summaryrefslogtreecommitdiffstats
path: root/krusader/Panel
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-22 18:58:28 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-22 18:58:28 +0000
commit83b9bf0e3bfb1d842b10b80bbe749095b2c661a1 (patch)
treeb05b1793361693ae88106648c2a953bed988f423 /krusader/Panel
downloadkrusader-83b9bf0e3bfb1d842b10b80bbe749095b2c661a1.tar.gz
krusader-83b9bf0e3bfb1d842b10b80bbe749095b2c661a1.zip
Added old KDE3 version of Krusader
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/krusader@1094427 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krusader/Panel')
-rw-r--r--krusader/Panel/Makefile.am29
-rw-r--r--krusader/Panel/krbriefview.cpp1461
-rw-r--r--krusader/Panel/krbriefview.h172
-rw-r--r--krusader/Panel/krbriefviewitem.cpp225
-rw-r--r--krusader/Panel/krbriefviewitem.h79
-rw-r--r--krusader/Panel/krcalcspacedialog.cpp187
-rw-r--r--krusader/Panel/krcalcspacedialog.h106
-rw-r--r--krusader/Panel/krcolorcache.cpp761
-rw-r--r--krusader/Panel/krcolorcache.h101
-rw-r--r--krusader/Panel/krdetailedview.cpp1587
-rw-r--r--krusader/Panel/krdetailedview.h180
-rw-r--r--krusader/Panel/krdetailedviewitem.cpp313
-rw-r--r--krusader/Panel/krdetailedviewitem.h73
-rw-r--r--krusader/Panel/krdrag.cpp103
-rw-r--r--krusader/Panel/krdrag.h62
-rw-r--r--krusader/Panel/krpopupmenu.cpp354
-rw-r--r--krusader/Panel/krpopupmenu.h77
-rw-r--r--krusader/Panel/krpreviewpopup.cpp68
-rw-r--r--krusader/Panel/krpreviewpopup.h48
-rw-r--r--krusader/Panel/krselectionmode.cpp61
-rw-r--r--krusader/Panel/krselectionmode.h97
-rw-r--r--krusader/Panel/krview.cpp332
-rw-r--r--krusader/Panel/krview.h245
-rw-r--r--krusader/Panel/krviewitem.cpp105
-rw-r--r--krusader/Panel/krviewitem.h76
-rw-r--r--krusader/Panel/listpanel.cpp1115
-rw-r--r--krusader/Panel/listpanel.h211
-rwxr-xr-xkrusader/Panel/panelfunc.cpp1186
-rw-r--r--krusader/Panel/panelfunc.h105
-rw-r--r--krusader/Panel/panelpopup.cpp400
-rw-r--r--krusader/Panel/panelpopup.h73
31 files changed, 9992 insertions, 0 deletions
diff --git a/krusader/Panel/Makefile.am b/krusader/Panel/Makefile.am
new file mode 100644
index 0000000..3317a9b
--- /dev/null
+++ b/krusader/Panel/Makefile.am
@@ -0,0 +1,29 @@
+if include_libkonq
+AM_CPPFLAGS = -D__LIBKONQ__
+endif
+
+
+noinst_LIBRARIES = libPanel.a
+
+INCLUDES = $(all_includes)
+
+libPanel_a_METASOURCES = AUTO
+
+libPanel_a_SOURCES = \
+ krcolorcache.cpp \
+ krcalcspacedialog.cpp \
+ krpopupmenu.cpp \
+ krpreviewpopup.cpp \
+ krview.cpp \
+ krviewitem.cpp \
+ krdetailedviewitem.cpp \
+ krdetailedview.cpp \
+ panelfunc.cpp \
+ listpanel.cpp \
+ panelpopup.cpp \
+ krdrag.cpp \
+ krselectionmode.cpp \
+ krbriefview.cpp \
+ krbriefviewitem.cpp
+
+
diff --git a/krusader/Panel/krbriefview.cpp b/krusader/Panel/krbriefview.cpp
new file mode 100644
index 0000000..1fe8a36
--- /dev/null
+++ b/krusader/Panel/krbriefview.cpp
@@ -0,0 +1,1461 @@
+/***************************************************************************
+ krbriefview.cpp
+ -------------------
+copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+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 "krbriefview.h"
+#include "krbriefviewitem.h"
+#include "krcolorcache.h"
+#include "krselectionmode.h"
+#include "../krusader.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../krslots.h"
+#include "../VFS/krarchandler.h"
+#include "../VFS/krquery.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include <qheader.h>
+#include <qtooltip.h>
+
+#define CANCEL_TWO_CLICK_RENAME {singleClicked = false;renameTimer.stop();}
+#define PROPS static_cast<KrBriefViewProperties*>(_properties)
+#define MAX_COLS 5
+#define VF getVfile()
+
+
+class KrBriefViewToolTip : public QToolTip
+{
+public:
+ KrBriefViewToolTip( KrBriefView *view, QWidget *parent );
+ void maybeTip( const QPoint &pos );
+
+ virtual ~KrBriefViewToolTip() {}
+private:
+ KrBriefView *view;
+};
+
+KrBriefViewToolTip::KrBriefViewToolTip( KrBriefView *lv, QWidget *parent )
+ : QToolTip( parent ), view( lv )
+{
+}
+
+void KrBriefViewToolTip::maybeTip( const QPoint &pos )
+{
+ QIconViewItem *item = view->findItem( view->viewportToContents( pos ) );
+
+ if ( !item )
+ return;
+
+ int width = QFontMetrics( view->font() ).width( item->text() ) + 4;
+
+ QRect r = item->rect();
+ r.setTopLeft( view->contentsToViewport( r.topLeft() ) );
+ if( width > item->textRect().width() )
+ tip( r, item->text() );
+}
+
+
+KrBriefView::KrBriefView( QHeader * headerIn, QWidget *parent, bool &left, KConfig *cfg, const char *name ):
+ KIconView(parent, name), KrView( cfg ), header( headerIn ), _currDragItem( 0 ),
+ currentlyRenamedItem( 0 ), pressedItem( 0 ), mouseEvent( 0 ) {
+ setWidget( this );
+ _nameInKConfig = QString( "KrBriefView" ) + QString( ( left ? "Left" : "Right" ) );
+ krConfig->setGroup("Private");
+ if (krConfig->readBoolEntry("Enable Input Method", true))
+ setInputMethodEnabled(true);
+ toolTip = new KrBriefViewToolTip( this, viewport() );
+}
+
+void KrBriefView::setup() {
+ lastSwushPosition = 0;
+
+ // 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( QIconViewItem* ) ), this, SLOT( slotExecuted( QIconViewItem* ) ) );
+ } else {
+ connect( this, SIGNAL( clicked( QIconViewItem* ) ), this, SLOT( slotClicked( QIconViewItem* ) ) );
+ connect( this, SIGNAL( doubleClicked( QIconViewItem* ) ), this, SLOT( slotDoubleClicked( QIconViewItem* ) ) );
+ }
+
+ // a change in the selection needs to update totals
+ connect( this, SIGNAL( onItem( QIconViewItem* ) ), this, SLOT( slotItemDescription( QIconViewItem* ) ) );
+ connect( this, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ),
+ this, SLOT( handleContextMenu( QIconViewItem*, const QPoint& ) ) );
+ connect( this, SIGNAL( rightButtonPressed(QIconViewItem*, const QPoint&)),
+ this, SLOT(slotRightButtonPressed(QIconViewItem*, const QPoint&)));
+ connect( this, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( setNameToMakeCurrent( QIconViewItem* ) ) );
+ connect( this, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( transformCurrentChanged( QIconViewItem* ) ) );
+ connect( this, SIGNAL( mouseButtonClicked ( int, QIconViewItem *, const QPoint & ) ),
+ this, SLOT( slotMouseClicked ( int, QIconViewItem *, const QPoint & ) ) );
+ connect( &KrColorCache::getColorCache(), SIGNAL( colorsRefreshed() ), this, SLOT( refreshColors() ) );
+
+ // add whatever columns are needed to the listview
+ krConfig->setGroup( nameInKConfig() );
+
+ // determine basic settings for the view
+ setAcceptDrops( true );
+ setItemsMovable( false );
+ setItemTextPos( QIconView::Right );
+ setArrangement( QIconView::TopToBottom );
+ setWordWrapIconText( false );
+ setSpacing( 0 );
+ horizontalScrollBar()->installEventFilter( this );
+
+ // allow in-place renaming
+
+ connect( this, SIGNAL( itemRenamed ( QIconViewItem * ) ),
+ this, SLOT( inplaceRenameFinished( QIconViewItem * ) ) );
+ connect( &renameTimer, SIGNAL( timeout() ), this, SLOT( renameCurrentItem() ) );
+ connect( &contextMenuTimer, SIGNAL (timeout()), this, SLOT (showContextMenu()));
+
+ setSelectionMode( QIconView::Extended );
+
+ setFocusPolicy( StrongFocus );
+ restoreSettings();
+ refreshColors();
+
+ CANCEL_TWO_CLICK_RENAME;
+
+ // setting the header
+ while( header->count() )
+ header->removeLabel( 0 );
+
+ header->addLabel( i18n( "Name" ) );
+ header->setStretchEnabled( true );
+
+ header->setSortIndicator( 0, sortDirection() ? Qt::Ascending : Qt::Descending );
+ connect( header, SIGNAL(clicked( int )), this, SLOT( changeSortOrder()));
+
+ header->installEventFilter( this );
+ header->show();
+}
+
+KrBriefView::~KrBriefView() {
+ delete _properties; _properties = 0;
+ delete _operator; _operator = 0;
+ if( mouseEvent )
+ delete mouseEvent;
+ mouseEvent = 0;
+ delete toolTip;
+}
+
+void KrBriefView::resizeEvent ( QResizeEvent * resEvent )
+{
+ QPoint pnt( contentsX(), contentsY() );
+ QRect viewportRect( pnt, resEvent->oldSize() );
+ bool visible = false;
+ if( currentItem() )
+ visible = viewportRect.contains( currentItem()->rect() );
+
+ KIconView::resizeEvent( resEvent );
+ redrawColumns();
+
+ if( visible && currentItem() )
+ ensureItemVisible( currentItem() );
+}
+
+void KrBriefView::redrawColumns()
+{
+ bool ascending = sortDirection();
+ setSorting( false, ascending );
+
+ setGridX( width() / PROPS->numberOfColumns );
+
+ // QT bug, it's important for recalculating the bounding rectangle
+ for( QIconViewItem * item = firstItem(); item; item = item->nextItem() )
+ {
+ QString txt = item->text();
+ item->setText( "" );
+ item->setText( txt );
+ }
+
+ setSorting( true, ascending );
+
+ arrangeItemsInGrid();
+}
+
+// if vfile passes the filter, create an item, otherwise, drop it
+KrViewItem *KrBriefView::preAddItem( vfile *vf ) {
+ 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 KrBriefViewItem( this, lastItem(), vf );
+}
+
+bool KrBriefView::preDelItem(KrViewItem *item) {
+ if( item ) {
+ KrBriefViewItem * viewItem = dynamic_cast<KrBriefViewItem*>( item );
+ if( viewItem == currentlyRenamedItem ) {
+ currentlyRenamedItem->cancelRename();
+ currentlyRenamedItem = 0;
+ }
+ }
+
+ return true;
+}
+
+void KrBriefView::addItems( vfs *v, bool addUpDir ) {
+ QIconViewItem * item = firstItem();
+ QIconViewItem * currentItem = item;
+
+ // add the up-dir arrow if needed
+ if ( addUpDir ) {
+ new KrBriefViewItem( this, ( QIconViewItem* ) 0L, ( vfile* ) 0L );
+ }
+
+
+ // text for updating the status bar
+ QString statusText = QString("%1/ ").arg( v->vfs_getOrigin().fileName() ) + i18n("Directory");
+
+ bool as = sortDirection();
+ setSorting( false, as ); // disable sorting
+
+ for ( vfile * vf = v->vfs_getFirstFile(); vf != 0 ; vf = v->vfs_getNextFile() ) {
+ 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
+ }
+ }
+
+ KrBriefViewItem *bvitem = new KrBriefViewItem( this, item, vf );
+ _dict.insert( vf->vfile_getName(), bvitem );
+ if ( isDir )
+ ++_numDirs;
+ else
+ _countSize += bvitem->VF->vfile_getSize();
+ ++_count;
+ // if the item should be current - make it so
+ if ( bvitem->name() == nameToMakeCurrent() )
+ {
+ currentItem = static_cast<QIconViewItem*>(bvitem);
+ statusText = bvitem->description();
+ }
+ }
+
+
+ // re-enable sorting
+ setSorting( true, as );
+ sort( as );
+
+ if ( !currentItem )
+ currentItem = firstItem();
+ KIconView::setCurrentItem( currentItem );
+ ensureItemVisible( currentItem );
+
+ op()->emitItemDescription( statusText );
+}
+
+void KrBriefView::delItem( const QString &name ) {
+ KrView::delItem( name );
+ arrangeItemsInGrid();
+}
+
+QString KrBriefView::getCurrentItem() const {
+ QIconViewItem * it = currentItem();
+ if ( !it )
+ return QString::null;
+ else
+ return dynamic_cast<KrViewItem*>( it ) ->name();
+}
+
+void KrBriefView::setCurrentItem( const QString& name ) {
+ KrBriefViewItem * it = dynamic_cast<KrBriefViewItem*>(_dict[ name ]);
+ if ( it )
+ KIconView::setCurrentItem( it );
+}
+
+void KrBriefView::clear() {
+ if( currentlyRenamedItem ) {
+ currentlyRenamedItem->cancelRename();
+ currentlyRenamedItem = 0;
+ }
+
+ op()->emitSelectionChanged(); /* to avoid rename crash at refresh */
+ KIconView::clear();
+ KrView::clear();
+}
+
+void KrBriefView::slotClicked( QIconViewItem *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 KrBriefView::slotDoubleClicked( QIconViewItem *item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ QString tmp = dynamic_cast<KrViewItem*>( item ) ->name();
+ op()->emitExecuted(tmp);
+}
+
+void KrBriefView::prepareForActive() {
+ KrView::prepareForActive();
+ setFocus();
+ slotItemDescription( currentItem() );
+}
+
+void KrBriefView::prepareForPassive() {
+ KrView::prepareForPassive();
+ CANCEL_TWO_CLICK_RENAME;
+ 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 KrBriefView::slotItemDescription( QIconViewItem * item ) {
+ KrViewItem * it = static_cast<KrBriefViewItem*>( item );
+ if ( !it )
+ return ;
+ QString desc = it->description();
+ op()->emitItemDescription(desc);
+}
+
+void KrBriefView::handleQuickSearchEvent( QKeyEvent * e ) {
+ switch ( e->key() ) {
+ case Key_Insert:
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 );
+ KIconView::keyPressEvent( & ev );
+ ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_Home:
+ {
+ QIconView::setCurrentItem( firstItem() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_End:
+ {
+ QIconView::setCurrentItem( firstItem() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Up, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ }
+}
+
+
+void KrBriefView::slotCurrentChanged( QIconViewItem * item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ _nameToMakeCurrent = static_cast<KrBriefViewItem*>( item ) ->name();
+}
+
+void KrBriefView::contentsMousePressEvent( QMouseEvent * e ) {
+ bool callDefaultHandler = true, processEvent = true, selectionChanged = false;
+ pressedItem = 0;
+
+ e = transformMouseEvent( e );
+
+ QIconViewItem * oldCurrent = currentItem();
+ QIconViewItem *newCurrent = findItem( 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(), true);
+ 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(), true);
+ 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();
+ setFocus();
+
+ 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->index();
+ int newPos = newCurrent->index();
+ QIconViewItem *top = 0, *bottom = 0;
+ if ( oldPos > newPos ) {
+ top = newCurrent;
+ bottom = oldCurrent;
+ } else {
+ top = oldCurrent;
+ bottom = newCurrent;
+ }
+ while( top )
+ {
+ if ( !top->isSelected() ) {
+ top->setSelected( true, true );
+ selectionChanged = true;
+ }
+ if ( top == bottom )
+ break;
+ top = top->nextItem();
+ }
+ QIconView::setCurrentItem( newCurrent );
+ callDefaultHandler = false;
+ }
+ if( e->state() & ShiftButton )
+ callDefaultHandler = false;
+ }
+
+ if (selectionChanged)
+ updateView(); // don't call triggerUpdate directly!
+
+ 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<KrBriefViewItem*>( newCurrent ) ->name();
+
+ KIconView::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 QIconView::contentsMousePressEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ QPoint vp = contentsToViewport( e->pos() );
+
+ if( !newCurrent ) {
+ emit pressed( pressedItem = newCurrent );
+ emit pressed( newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ emit mouseButtonPressed( e->button(), newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ // if (i != 0) // comment in, if click sould NOT select
+ // setSelected(i, FALSE);
+ if (newCurrent) QIconView::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 KrBriefView::contentsMouseReleaseEvent( QMouseEvent * e ) {
+ if (e->button() == RightButton)
+ contextMenuTimer.stop();
+
+ e = transformMouseEvent( e );
+
+ KIconView::contentsMouseReleaseEvent( e );
+
+ if( pressedItem ) {
+ QPoint vp = contentsToViewport( e->pos() );
+ QIconViewItem *newCurrent = findItem( e->pos() );
+
+ if( pressedItem == newCurrent ) {
+ // emitting the missing signals from QIconView::contentsMouseReleaseEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ if( !newCurrent ) {
+ emit clicked( newCurrent );
+ emit clicked( newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ emit mouseButtonClicked( e->button(), newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ pressedItem = 0;
+ }
+}
+
+void KrBriefView::contentsMouseMoveEvent ( QMouseEvent * e ) {
+ e = transformMouseEvent( e );
+
+ if ( ( singleClicked || renameTimer.isActive() ) && findItem( 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)
+ {
+ QIconViewItem *newItem = findItem( e->pos() );
+ e->accept();
+ if (newItem != lastSwushPosition && newItem)
+ {
+ // is the new item above or below the previous one?
+ QIconViewItem * above = newItem;
+ QIconViewItem * below = newItem;
+ for (;(above || below) && above != lastSwushPosition && below != lastSwushPosition;)
+ {
+ if (above)
+ above = above->nextItem();
+ if (below)
+ below = below->prevItem();
+ }
+ if (above && (above == lastSwushPosition))
+ {
+ for (; above != newItem; above = above->prevItem())
+ above->setSelected(swushSelects,true);
+ newItem->setSelected(swushSelects,true);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ else if (below && (below == lastSwushPosition))
+ {
+ for (; below != newItem; below = below->nextItem())
+ below->setSelected(swushSelects,true);
+ newItem->setSelected(swushSelects,true);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ contextMenuTimer.stop();
+ }
+ // emitting the missing signals from QIconView::contentsMouseMoveEvent();
+ if( newItem )
+ emit onItem( newItem );
+ else
+ emit onViewport();
+ }
+ else
+ KIconView::contentsMouseMoveEvent( e );
+}
+
+void KrBriefView::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ e = transformMouseEvent ( e );
+ KIconView::contentsMouseDoubleClickEvent( e );
+}
+
+void KrBriefView::handleContextMenu( QIconViewItem * it, const QPoint & pos ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+
+ if ( !it )
+ return ;
+ if ( static_cast<KrBriefViewItem*>( it ) ->
+ name() == ".." )
+ return ;
+ int i = KrSelectionMode::getSelectionHandler()->showContextMenu();
+ contextMenuPoint = QPoint( pos.x(), pos.y() );
+ if (i < 0)
+ showContextMenu();
+ else if (i > 0)
+ contextMenuTimer.start(i, true);
+}
+
+void KrBriefView::showContextMenu()
+{
+ if (lastSwushPosition)
+ lastSwushPosition->setSelected(true);
+ op()->emitContextMenu( contextMenuPoint );
+}
+
+KrViewItem *KrBriefView::getKrViewItemAt( const QPoint & vp ) {
+ return dynamic_cast<KrViewItem*>( KIconView::findItem( vp ) );
+}
+
+bool KrBriefView::acceptDrag( QDropEvent* ) const {
+ return true;
+}
+
+void KrBriefView::contentsDropEvent( QDropEvent * e ) {
+ _currDragItem = 0;
+ op()->emitGotDrop(e);
+ e->ignore();
+ KIconView::contentsDropEvent( e );
+}
+
+void KrBriefView::contentsDragMoveEvent( QDragMoveEvent * e ) {
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = getKrViewItemAt( e->pos() );
+ if( _currDragItem && !_currDragItem->VF->vfile_isDir() )
+ _currDragItem = 0;
+
+ KIconView::contentsDragMoveEvent( e );
+
+ if( _currDragItem != oldDragItem )
+ {
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+ if( _currDragItem )
+ dynamic_cast<KrBriefViewItem *>( _currDragItem )->repaint();
+ }
+}
+
+void KrBriefView::contentsDragLeaveEvent ( QDragLeaveEvent *e )
+{
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = 0;
+ KIconView::contentsDragLeaveEvent( e );
+
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+}
+
+void KrBriefView::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 ) )
+ KIconView::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 icon view will
+ // realize its new size after the key processing. The following line
+ // will resize the icon 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 KrBriefView::imEndEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMEndEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::imComposeEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMComposeEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::keyPressEvent( QKeyEvent * e ) {
+ if ( !e || !firstItem() )
+ 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()) {
+ QIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->prevItem();
+ if ( i ) {
+ QIconView::setCurrentItem( i );
+ QIconView::ensureItemVisible( i );
+ }
+ } else KIconView::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()){
+ QIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->nextItem();
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->nextItem() ); --page )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->prevItem() ); --page )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+Home */
+ {
+ clearSelection();
+ KIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ QIconViewItem * i = firstItem();
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_End: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+End */
+ {
+ clearSelection();
+ KIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ QIconViewItem *i = firstItem(), *j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ break;
+ }
+ } else KIconView::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 ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QIconViewItem *i = currentItem();
+ QIconViewItem *newCurrent = 0;
+
+ if ( !i ) break;
+
+ int minY = i->y() - i->height() / 2;
+ int minX = i->width() / 2 + i->x();
+
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+
+ while( i && i->x() <= minX )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->nextItem();
+ }
+
+ while( i && i->y() < minY )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->nextItem();
+ }
+
+ if( i )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ }
+
+ if( newCurrent )
+ {
+ QIconView::setCurrentItem( newCurrent );
+ QIconView::ensureItemVisible( newCurrent );
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Backspace : // Terminal Emulator bugfix
+ 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_Left :
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QIconViewItem *i = currentItem();
+ QIconViewItem *newCurrent = 0;
+
+ if ( !i ) break;
+
+ int maxY = i->y() + i->height() / 2;
+ int maxX = i->x() - i->width() / 2;
+
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+
+ while( i && i->x() >= maxX )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->prevItem();
+ }
+
+ while( i && i->y() > maxY )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->prevItem();
+ }
+ if( i )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ }
+
+ if( newCurrent )
+ {
+ QIconView::setCurrentItem( newCurrent );
+ QIconView::ensureItemVisible( newCurrent );
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+
+ case Key_Delete : // kill file
+ SLOTS->deleteFiles( e->state() == ShiftButton || e->state() == ControlButton );
+
+ break ;
+ case Key_Insert : {
+ {
+ QIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->insertMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ QIconView::setCurrentItem( i->nextItem() );
+ QIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_Space : {
+ {
+ QIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->spaceMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ QIconView::setCurrentItem( i->nextItem() );
+ QIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_A : // mark all
+ if ( e->state() == ControlButton ) {
+ KIconView::keyPressEvent( e );
+ updateView();
+ break;
+ }
+ default:
+ if ( e->key() == Key_Escape ) {
+ QIconView::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 ) )
+ KIconView::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 icon view will
+ // realize its new size after the key processing. The following line
+ // will resize the icon 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 );
+ }
+ KIconView::keyPressEvent( e );
+ }
+ }
+ // emit the new item description
+ slotItemDescription( currentItem() ); // actually send the QIconViewItem
+}
+// overridden to make sure EXTENTION won't be lost during rename
+void KrBriefView::rename( QIconViewItem * item ) {
+ currentlyRenamedItem = dynamic_cast< KrBriefViewItem * >( item );
+ currentlyRenamedItem->rename();
+ //TODO: renameLineEdit() ->selectAll();
+}
+
+void KrBriefView::renameCurrentItem() {
+ QString newName, fileName;
+
+ // handle inplace renaming, if possible
+
+ KrBriefViewItem *it = static_cast<KrBriefViewItem*>(getCurrentKrViewItem());
+ if ( it )
+ fileName = it->name();
+ else
+ return ; // quit if no current item available
+ // don't allow anyone to rename ..
+ if ( fileName == ".." )
+ return ;
+
+ rename( static_cast<QIconViewItem*>( it ) );
+ // if applicable, select only the name without extension
+/* TODO:
+ 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);
+ }*/
+}
+
+void KrBriefView::inplaceRenameFinished( QIconViewItem * it ) {
+ if ( !it ) { // major failure - call developers
+ krOut << "Major failure at inplaceRenameFinished(): item is null" << endl;
+ return;
+ }
+
+ KrBriefViewItem *item = dynamic_cast<KrBriefViewItem *>( it );
+ if( item->text() != item->name() )
+ op()->emitRenameItem( item->name(), item->text() );
+
+ currentlyRenamedItem = 0;
+ setFocus();
+}
+
+// TODO: move the whole quicksearch mess out of here and into krview
+void KrBriefView::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 KrBriefView::stopQuickSearch( QKeyEvent * e ) {
+ if( ACTIVE_PANEL && ACTIVE_PANEL->quickSearch ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ if ( e )
+ keyPressEvent( e );
+ }
+}
+
+void KrBriefView::setNameToMakeCurrent( QIconViewItem * it ) {
+ if (!it) return;
+ KrView::setNameToMakeCurrent( static_cast<KrBriefViewItem*>( it ) ->name() );
+}
+
+void KrBriefView::slotMouseClicked( int button, QIconViewItem * item, const QPoint& ) {
+ pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent
+ if ( button == Qt::MidButton )
+ emit middleButtonClicked( dynamic_cast<KrViewItem *>( item ) );
+}
+
+void KrBriefView::refreshColors() {
+ krConfig->setGroup("Colors");
+ bool kdeDefault = krConfig->readBoolEntry("KDE Default");
+ 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() );
+ } else {
+ // KDE default is choosen: set back the background color
+ setPaletteBackgroundColor( KGlobalSettings::baseColor() );
+ }
+ slotUpdate();
+}
+
+bool KrBriefView::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;
+ }
+ if( e->type() == QEvent::Wheel )
+ {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+ }
+ return KIconView::event( e );
+}
+
+
+bool KrBriefView::eventFilter( QObject * watched, QEvent * e )
+{
+ if( watched == horizontalScrollBar() )
+ {
+ if( e->type() == QEvent::Hide || e->type() == QEvent::Show )
+ {
+ bool res = KIconView::eventFilter( watched, e );
+ arrangeItemsInGrid();
+ return res;
+ }
+ }
+ else if( watched == header )
+ {
+ if( e->type() == QEvent::MouseButtonPress && ((QMouseEvent *)e )->button() == Qt::RightButton )
+ {
+ setColumnNr();
+ return TRUE;
+ }
+ return FALSE;
+ }
+ return KIconView::eventFilter( watched, e );
+}
+
+void KrBriefView::makeItemVisible( const KrViewItem *item ) {
+// qApp->processEvents(); // Please don't remove the comment. Causes crash if it is inserted!
+ ensureItemVisible( (QIconViewItem *)( static_cast<const KrBriefViewItem*>( item ) ) );
+}
+
+void KrBriefView::initOperator() {
+ _operator = new KrViewOperator(this, this);
+ // QIconView emits selection changed, so chain them to operator
+ connect(this, SIGNAL(selectionChanged()), _operator, SIGNAL(selectionChanged()));
+}
+
+void KrBriefView::initProperties() {
+ // TODO: move this to a general location, maybe KrViewProperties constructor ?
+ _properties = new KrBriefViewProperties;
+ _properties->filter = KrViewProperties::All;
+ _properties->filterMask = KRQuery( "*" );
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ _properties->displayIcons = _config->readBoolEntry( "With Icons", _WithIcons );
+ bool dirsByNameAlways = _config->readBoolEntry("Always sort dirs by name", false);
+ _properties->sortMode = static_cast<KrViewProperties::SortSpec>( KrViewProperties::Name |
+ KrViewProperties::Descending | KrViewProperties::DirsFirst |
+ (dirsByNameAlways ? KrViewProperties::AlwaysSortDirsByName : 0) );
+ if ( !_config->readBoolEntry( "Case Sensative Sort", _CaseSensativeSort ) )
+ _properties->sortMode = static_cast<KrViewProperties::SortSpec>( _properties->sortMode |
+ KrViewProperties::IgnoreCase );
+ _properties->humanReadableSize = krConfig->readBoolEntry("Human Readable Size", _HumanReadableSize);
+ _properties->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;
+ }
+ _properties->atomicExtensions = atomicExtensions;
+
+ _config->setGroup( nameInKConfig() );
+ PROPS->numberOfColumns = _config->readNumEntry( "Number Of Brief Columns", _NumberOfBriefColumns );
+ if( PROPS->numberOfColumns < 1 )
+ PROPS->numberOfColumns = 1;
+ else if( PROPS->numberOfColumns > MAX_COLS )
+ PROPS->numberOfColumns = MAX_COLS;
+}
+
+void KrBriefView::setColumnNr()
+{
+ KPopupMenu popup( this );
+ popup.insertTitle( i18n("Columns"));
+
+ int COL_ID = 14700;
+
+ for( int i=1; i <= MAX_COLS; i++ )
+ {
+ popup.insertItem( QString( "%1" ).arg( i ), COL_ID + i );
+ popup.setItemChecked( COL_ID + i, PROPS->numberOfColumns == i );
+ }
+
+ int result=popup.exec(QCursor::pos());
+
+ krConfig->setGroup( nameInKConfig() );
+
+ if( result > COL_ID && result <= COL_ID + MAX_COLS )
+ {
+ krConfig->writeEntry( "Number Of Brief Columns", result - COL_ID );
+ PROPS->numberOfColumns = result - COL_ID;
+ redrawColumns();
+ }
+}
+
+void KrBriefView::sortOrderChanged() {
+ ensureItemVisible(currentItem());
+
+ if( !_focused )
+ op()->emitNeedFocus();
+
+}
+
+void KrBriefView::updateView() {
+ arrangeItemsInGrid();
+ op()->emitSelectionChanged();
+}
+
+void KrBriefView::updateItem(KrViewItem* item) {
+ dynamic_cast<KrBriefViewItem*>(item)->repaintItem();
+}
+
+void KrBriefView::slotRightButtonPressed(QIconViewItem*, const QPoint& point) {
+ op()->emitEmptyContextMenu(point);
+}
+
+void KrBriefView::changeSortOrder()
+{
+ bool asc = !sortDirection();
+ header->setSortIndicator( 0, asc ? Qt::Ascending : Qt::Descending );
+ sort( asc );
+}
+
+QMouseEvent * KrBriefView::transformMouseEvent( QMouseEvent * e )
+{
+ if( findItem( e->pos() ) != 0 )
+ return e;
+
+ QIconViewItem *closestItem = 0;
+ int mouseX = e->pos().x(), mouseY = e->pos().y();
+ int closestDelta = 0x7FFFFFFF;
+
+ int minX = ( mouseX / gridX() ) * gridX();
+ int maxX = minX + gridX();
+
+ QIconViewItem *current = firstItem();
+ while( current )
+ {
+ if( current->x() >= minX && current->x() < maxX )
+ {
+ int delta = mouseY - current->y();
+ if( delta >= 0 && delta < closestDelta )
+ {
+ closestDelta = delta;
+ closestItem = current;
+ }
+ }
+ current = current->nextItem();
+ }
+
+ if( closestItem != 0 )
+ {
+ if( mouseX - closestItem->x() > gridX() )
+ closestItem = 0;
+ else if( mouseY - closestItem->y() > closestItem->height() )
+ closestItem = 0;
+ }
+
+ if( closestItem != 0 )
+ {
+ QRect rec = closestItem->textRect( false );
+ if( mouseX < rec.x() )
+ mouseX = rec.x();
+ if( mouseY < rec.y() )
+ mouseY = rec.y();
+ if( mouseX > rec.x() + rec.width() -1 )
+ mouseX = rec.x() + rec.width() -1;
+ if( mouseY > rec.y() + rec.height() -1 )
+ mouseY = rec.y() + rec.height() -1;
+ QPoint newPos( mouseX, mouseY );
+ QPoint glPos;
+ if( !e->globalPos().isNull() )
+ {
+ glPos = QPoint( mouseX - e->pos().x() + e->globalPos().x(),
+ mouseY - e->pos().y() + e->globalPos().y() );
+ }
+
+ if( mouseEvent )
+ delete mouseEvent;
+ return mouseEvent = new QMouseEvent( e->type(), newPos, glPos, e->button(), e->state() );
+ }
+
+ return e;
+}
+
+#include "krbriefview.moc"
diff --git a/krusader/Panel/krbriefview.h b/krusader/Panel/krbriefview.h
new file mode 100644
index 0000000..8ba27f4
--- /dev/null
+++ b/krusader/Panel/krbriefview.h
@@ -0,0 +1,172 @@
+/***************************************************************************
+ krbriefview.h
+ -------------------
+ copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+ 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
+
+ H e a d e r 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. *
+* *
+***************************************************************************/
+#ifndef KRBRIEFVIEW_H
+#define KRBRIEFVIEW_H
+
+#include "krview.h"
+#include "krviewitem.h"
+#include <kiconview.h>
+#include <qtimer.h>
+
+// extends KrViewProperties to add detailedview-only properties
+class KrBriefViewProperties: public KrViewProperties {
+public:
+ int numberOfColumns; // the number of columns in the view
+};
+
+class KrBriefViewItem;
+class QDragMoveEvent;
+class QToolTip;
+class QHeader;
+
+/**
+ * KrBriefView implements everthing and anything regarding a brief view in a filemananger.
+ * IT MUST USE KrViewItem as the children to it's *KIconView. KrBriefView and KrViewItem are
+ * tightly coupled and the view will not work with other kinds of items.
+ * Apart from this, the view is self-reliant and you can use the vast interface to get whatever
+ * information is necessery from it.
+ */
+class KrBriefView: public KIconView, public KrView {
+ friend class KrBriefViewItem;
+ Q_OBJECT
+public:
+ KrBriefView( QHeader *header, QWidget *parent, bool &left, KConfig *cfg = krConfig, const char *name = 0 );
+ virtual ~KrBriefView();
+ virtual inline KrViewItem *getFirst() { return dynamic_cast<KrViewItem*>( firstItem() ); }
+ virtual inline KrViewItem *getLast() { return dynamic_cast<KrViewItem*>( lastItem() ); }
+ virtual inline KrViewItem *getNext( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<QIconViewItem*>( current ) ->nextItem() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<QIconViewItem*>( current ) ->prevItem() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt(const QPoint &vp);
+ virtual inline KrViewItem *findItemByName(const QString &name) { return dynamic_cast<KrViewItem*>( findItem( name, Qt::ExactMatch ) ); }
+ virtual void addItems(vfs* v, bool addUpDir = true);
+ virtual void delItem(const QString &);
+ virtual QString getCurrentItem() const;
+ virtual void makeItemVisible(const KrViewItem * item );
+ virtual void setCurrentItem(const QString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item );
+ virtual void clear();
+ virtual void sort() { if( sortDirection() ) sortOrderChanged();KIconView::sort( true ); }
+ virtual void sort( bool ascending ) { if( sortDirection() != ascending ) sortOrderChanged();KIconView::sort( ascending ); }
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual void saveSettings() {}
+ virtual void restoreSettings() {}
+ virtual QString nameInKConfig() {return _nameInKConfig;}
+ virtual void resizeEvent ( QResizeEvent * );
+
+signals:
+ void middleButtonClicked( KrViewItem *item );
+ void currentChanged( KrViewItem *item );
+
+protected:
+ virtual void setup();
+ virtual void initProperties();
+ virtual void initOperator();
+ virtual KrViewItem *preAddItem(vfile * vf);
+ virtual bool preDelItem(KrViewItem * item );
+
+ void setColumnNr();
+ void redrawColumns();
+
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void imStartEvent( QIMEvent* e );
+ virtual void imEndEvent( QIMEvent *e );
+ virtual void imComposeEvent( QIMEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (QMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( QMouseEvent * e );
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e );
+ virtual bool acceptDrag( QDropEvent* e ) const;
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual void contentsDragLeaveEvent ( QDragLeaveEvent * );
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( QEvent *e );
+ virtual bool eventFilter( QObject * watched, QEvent * e );
+ QMouseEvent * transformMouseEvent( QMouseEvent * );
+
+protected slots:
+ void rename( QIconViewItem *item );
+ void slotClicked( QIconViewItem *item );
+ void slotDoubleClicked( QIconViewItem *item );
+ void slotItemDescription( QIconViewItem * );
+ void slotCurrentChanged( QIconViewItem *item );
+ void handleContextMenu( QIconViewItem*, const QPoint& );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( QIconViewItem *it );
+ void setNameToMakeCurrent( QIconViewItem *it );
+ void sortOrderChanged();
+ void slotRightButtonPressed(QIconViewItem*, const QPoint& point);
+ void transformCurrentChanged( QIconViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, QIconViewItem * item, const QPoint & pos );
+ inline void slotExecuted( QIconViewItem* i ) {
+ QString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const QString &, int = 0 );
+ void stopQuickSearch( QKeyEvent* );
+ void handleQuickSearchEvent( QKeyEvent* );
+ void changeSortOrder();
+
+
+signals:
+ void letsDrag(QStringList items, QPixmap icon);
+ void gotDrop(QDropEvent *);
+
+private:
+ QHeader * header;
+ bool swushSelects;
+ QPoint dragStartPos;
+ QIconViewItem *lastSwushPosition;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ QTime clickTime;
+ QIconViewItem *clickedItem;
+ QTimer renameTimer;
+ QTimer contextMenuTimer;
+ QPoint contextMenuPoint;
+ KrBriefViewItem *currentlyRenamedItem;
+ QIconViewItem *pressedItem;
+ QMouseEvent *mouseEvent;
+ QToolTip *toolTip;
+};
+
+#endif
diff --git a/krusader/Panel/krbriefviewitem.cpp b/krusader/Panel/krbriefviewitem.cpp
new file mode 100644
index 0000000..533090f
--- /dev/null
+++ b/krusader/Panel/krbriefviewitem.cpp
@@ -0,0 +1,225 @@
+#include "krbriefview.h"
+#include "krbriefviewitem.h"
+#include "../krusaderview.h"
+#include "../defaults.h"
+#include "../kicons.h"
+#include "listpanel.h"
+#include <kconfig.h>
+#include "krcolorcache.h"
+
+#include <qpainter.h>
+#include <qpointarray.h>
+
+#define PROPS _viewProperties
+#define VF getVfile()
+
+#ifdef FASTER
+int KrBriefViewItem::expHeight = 0;
+#endif // FASTER
+
+KrBriefViewItem::KrBriefViewItem(KrBriefView *parent, QIconViewItem *after, vfile *vf):
+ KIconViewItem(parent, after), KrViewItem(vf, parent->properties()) {
+#ifdef FASTER
+ initiated = false;
+ // get the expected height of an item - should be done only once
+ if (expHeight == 0) {
+ KConfigGroupSaver svr(krConfig, "Look&Feel");
+ expHeight = 2 + (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ }
+ if( PROPS->displayIcons )
+ itemIcon = QPixmap( expHeight, expHeight );
+#endif // FASTER
+
+ // there's a special case, where if _vf is null, then we've got the ".." (updir) item
+ // in that case, create a special vfile for that item, and delete it, if needed
+ if (!_vf) {
+ dummyVfile = true;
+ _vf = new vfile("..", 0, "drw-r--r--", 0, false, 0, 0, QString::null, QString::null, 0);
+
+ setText("..");
+ if ( PROPS->displayIcons )
+ setPixmap( FL_LOADICON( "up" ) );
+ setSelectable( false );
+ setDragEnabled( false );
+ setDropEnabled( false );
+#ifdef FASTER
+ initiated = true;
+#endif // FASTER
+ }
+
+ setRenameEnabled( false );
+ setDragEnabled( true );
+ setDropEnabled( true );
+ repaintItem();
+}
+
+
+int KrBriefViewItem::compare(QIconViewItem *i ) const {
+ bool ignoreCase = (PROPS->sortMode & KrViewProperties::IgnoreCase);
+
+ KrBriefViewItem *other = (KrBriefViewItem *)i;
+ int asc = iconView()->sortDirection() ? -1 : 1;
+
+ bool thisDir = VF->vfile_isDir();
+ bool otherDir = other->VF->vfile_isDir();
+
+ // handle directory sorting
+ if ( thisDir ){
+ if ( !otherDir ) return 1*asc;
+ } else if( otherDir ) return -1*asc;
+
+ if ( isDummy() ) return 1*asc;
+ if ( other->isDummy() ) return -1*asc;
+
+ QString text0 = name();
+ if (text0 == "..") return 1*asc;
+
+ QString itext0 = other->name();
+ if (itext0 == "..") return -1*asc;
+
+ if( ignoreCase )
+ {
+ text0 = text0.lower();
+ itext0 = itext0.lower();
+ }
+
+ if ( isHidden() ) {
+ if ( !other->isHidden() ) return 1*asc;
+ } else if ( other->isHidden() ) return -1*asc;
+
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(text0, itext0);
+ } else return QString::localeAwareCompare(text0,itext0);
+}
+
+void KrBriefViewItem::paintItem(QPainter *p, const QColorGroup &cg) {
+#ifdef FASTER
+ if (!initiated && !dummyVfile) {
+ // display an icon if needed
+ initiated = true;
+ if (PROPS->displayIcons)
+ itemIcon =KrView::getIcon(_vf);
+ }
+#endif
+
+ QColorGroup _cg(cg);
+
+ KrColorItemType colorItemType;
+ colorItemType.m_activePanel = (dynamic_cast<KrView *>(iconView()) == ACTIVE_PANEL->view);
+
+ int gridX = iconView()->gridX();
+ int xpos = x() / gridX;
+ int ypos = y() / height();
+
+ colorItemType.m_alternateBackgroundColor = (xpos & 1) ^ (ypos & 1) ;
+ colorItemType.m_currentItem = (iconView()->currentItem() == this);
+ colorItemType.m_selectedItem = isSelected();
+ if (VF->vfile_isSymLink())
+ {
+ if (_vf->vfile_getMime() == "Broken Link !" )
+ colorItemType.m_fileType = KrColorItemType::InvalidSymlink;
+ else
+ colorItemType.m_fileType = KrColorItemType::Symlink;
+ }
+ else if (VF->vfile_isDir())
+ colorItemType.m_fileType = KrColorItemType::Directory;
+ else if (VF->vfile_isExecutable())
+ colorItemType.m_fileType = KrColorItemType::Executable;
+ else
+ colorItemType.m_fileType = KrColorItemType::File;
+ KrColorCache::getColorCache().getColors(_cg, colorItemType);
+
+ if( _cg.background() != iconView()->paletteBackgroundColor() )
+ {
+ p->save();
+ p->setPen( Qt::NoPen );
+ p->setBrush( QBrush( _cg.background() ) );
+ p->drawRect( rect() );
+ p->restore();
+ }
+
+ QIconViewItem::paintItem(p, _cg);
+
+ paintFocus( p, cg );
+}
+
+void KrBriefViewItem::paintFocus(QPainter *p, const QColorGroup &cg) {
+ if ( ( iconView()->hasFocus() && this == iconView()->currentItem() ) ||
+ ((KrBriefView *)iconView())->_currDragItem == this )
+ {
+ p->save();
+ QPen pen( cg.shadow(), 0, Qt::DotLine );
+ p->setPen( pen );
+
+ // we manually draw the focus rect by points
+ QRect rec = rect();
+ QPointArray points( rec.right() - rec.left() + rec.bottom() - rec.top() + 4 );
+
+ int ndx = 0;
+ for( int x=rec.left(); x <= rec.right(); x+=2 )
+ {
+ points.setPoint( ndx++, x, rec.top() );
+ points.setPoint( ndx++, x, rec.bottom() );
+ }
+ for( int y=rec.top(); y <= rec.bottom(); y+=2 )
+ {
+ points.setPoint( ndx++, rec.left(), y );
+ points.setPoint( ndx++, rec.right(), y );
+ }
+
+ p->drawPoints( points );
+ p->restore();
+
+// --- That didn't work with all themes
+// iconView()->style().drawPrimitive(QStyle::PE_FocusRect, p,
+// QRect( rect().x(), rect().y(), rect().width(), rect().height() ), cg,
+// QStyle::Style_Default, cg.base() );
+ }
+}
+
+void KrBriefViewItem::itemHeightChanged() {
+#ifdef FASTER
+ expHeight = 0;
+#endif // FASTER
+}
+
+void KrBriefViewItem::repaintItem()
+{
+ if ( dummyVfile ) return;
+
+#ifndef FASTER
+ if (PROPS->displayIcons)
+ setPixmap(KrView::getIcon(_vf));
+#endif // FASTER
+ setText( _vf->vfile_getName() );
+}
+
+// for keeping the exact item heights...
+void KrBriefViewItem::calcRect ( const QString & text_ )
+{
+ KIconViewItem::calcRect( text_ );
+ QRect rec = rect();
+
+ int gridX = iconView()->gridX();
+ int minX = ( rec.x() / gridX ) * gridX;
+ rec.setX( minX );
+ rec.setWidth( gridX );
+ rec.setHeight( expHeight );
+ setItemRect( rec );
+
+ rec = pixmapRect();
+ if( rec.height() > expHeight )
+ {
+ rec.setHeight( expHeight );
+ setPixmapRect( rec );
+ }
+
+ rec = textRect();
+ if( rec.height() > expHeight )
+ {
+ rec.setHeight( expHeight );
+ setTextRect( rec );
+ }
+}
diff --git a/krusader/Panel/krbriefviewitem.h b/krusader/Panel/krbriefviewitem.h
new file mode 100644
index 0000000..e95c01b
--- /dev/null
+++ b/krusader/Panel/krbriefviewitem.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ krbriefviewitem.h
+ -------------------
+ copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+ 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
+
+ H e a d e r 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRBRIEFVIEWITEM_H
+#define KRBRIEFVIEWITEM_H
+
+#include "krviewitem.h"
+#include <sys/types.h>
+#include "../VFS/vfile.h"
+#include <kiconview.h>
+#include <qguardedptr.h>
+
+#define FASTER
+
+class QPixmap;
+class KrBriefView;
+
+class KrBriefViewItem : public KIconViewItem, public KrViewItem {
+friend class KrBriefView;
+friend class KrCalcSpaceDialog;
+public:
+ KrBriefViewItem(KrBriefView *parent, QIconViewItem *after, vfile *vf);
+ inline bool isSelected() const { return KIconViewItem::isSelected(); }
+ inline void setSelected(bool s) { KIconViewItem::setSelected(s); }
+ inline void cancelRename() { removeRenameBox(); }
+ int compare(QIconViewItem *i) const;
+ virtual void repaintItem();
+ static void itemHeightChanged(); // force the items to resize when icon/font size change
+ // TODO: virtual void setup(); // called when iconview needs to know the height of the item
+#ifdef FASTER
+ virtual QPixmap * pixmap() const {return const_cast<QPixmap *>(&itemIcon);}
+ virtual void setPixmap ( const QPixmap &icon ) { itemIcon = icon;}
+#endif
+
+protected:
+ virtual void paintItem(QPainter *p, const QColorGroup &cg);
+ virtual void paintFocus(QPainter *p, const QColorGroup &cg);
+ virtual void calcRect ( const QString & text_ = QString::null );
+
+private:
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+ QPixmap itemIcon;
+#endif // FASTER
+ // TODO:
+ static const QColor & setColorIfContrastIsSufficient(const QColor & /* background */, const QColor & /* color1 */, const QColor & /* color2 */ ) {static QColor col; return col;}
+
+// static int expHeight;
+};
+
+#endif
diff --git a/krusader/Panel/krcalcspacedialog.cpp b/krusader/Panel/krcalcspacedialog.cpp
new file mode 100644
index 0000000..aced7ed
--- /dev/null
+++ b/krusader/Panel/krcalcspacedialog.cpp
@@ -0,0 +1,187 @@
+/***************************************************************************
+ krcalcspacedialog.cpp - description
+ -------------------
+ begin : Fri Jan 2 2004
+ copyright : (C) 2004 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. *
+* *
+***************************************************************************/
+
+// Qt Includes
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qlabel.h>
+// KDE Includes
+#include <klocale.h>
+#include <kcursor.h>
+// Krusader Includes
+#include "krcalcspacedialog.h"
+#include "listpanel.h"
+#include "panelfunc.h"
+#include "../krusader.h"
+#include "../VFS/krpermhandler.h"
+
+/* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */
+KrCalcSpaceDialog::CalcThread::CalcThread(KrCalcSpaceDialog * parent, ListPanel * panel, const QStringList & items)
+ : m_totalSize(0), m_currentSize(0), m_totalFiles(0), m_totalDirs(0), m_items(items), m_files(panel->func->files()),
+ m_view(panel->view), m_parent(parent), m_threadInUse(true), m_stop(false) {}
+
+void KrCalcSpaceDialog::CalcThread::cleanUp(){
+ if (m_threadInUse || !finished())
+ m_synchronizeUsageAccess.unlock();
+ else{
+ m_synchronizeUsageAccess.unlock(); // prevents a resource leak
+ // otherwise: no one needs this instance any more: delete it
+ delete this;
+ }
+}
+
+void KrCalcSpaceDialog::CalcThread::deleteInstance(){
+ // synchronize to avoid race condition.
+ m_synchronizeUsageAccess.lock();
+ m_threadInUse = false;
+ cleanUp();
+}
+
+void KrCalcSpaceDialog::CalcThread::run(){
+ if ( !m_items.isEmpty() ) // if something to do: do the calculation
+ for ( QStringList::ConstIterator it = m_items.begin(); it != m_items.end(); ++it )
+ {
+ m_currentSize = 0;
+ m_files->vfs_calcSpace( *it, &m_currentSize, &m_totalFiles, &m_totalDirs , & m_stop);
+ if (m_stop)
+ break;
+ KrDetailedViewItem * viewItem = dynamic_cast<KrDetailedViewItem *>(m_view->findItemByName ( *it ) );
+ if (viewItem){
+ KrCalcSpaceDialog::setDirSize(viewItem, m_currentSize);
+ //viewItem->repaintItem(); // crash in KrDetailedViewItem::repaintItem(): setPixmap(_view->column(KrDetailedView::Name),KrView::getIcon(_vf))
+ }
+ m_totalSize += m_currentSize;
+ m_currentSize = 0;
+ }
+ // synchronize to avoid race condition.
+ m_synchronizeUsageAccess.lock();
+ cleanUp(); // this does not need the instance any more
+}
+
+void KrCalcSpaceDialog::CalcThread::stop(){
+ // cancel was pressed
+ m_stop = true;
+}
+
+KrCalcSpaceDialog::KrCalcSpaceDialog(QWidget *parent, ListPanel * files, const QStringList & items, bool autoclose) :
+ KDialogBase(parent, "KrCalcSpaceDialog", true, i18n("Calculate Occupied Space"), Ok|Cancel),
+ m_autoClose(autoclose), m_canceled(false), m_timerCounter(0){
+ // the dialog: The Ok button is hidden until it is needed
+ showButtonOK(false);
+ m_thread = new CalcThread(this, files, items);
+ m_pollTimer = new QTimer(this);
+ QWidget * mainWidget = new QWidget( this );
+ setMainWidget(mainWidget);
+ QVBoxLayout *topLayout = new QVBoxLayout( mainWidget, 0, spacingHint() );
+
+ m_label = new QLabel( "", mainWidget, "caption" );
+ showResult(); // fill m_label with something usefull
+ topLayout->addWidget( m_label );
+ topLayout->addStretch(10);
+}
+
+void KrCalcSpaceDialog::calculationFinished(){
+ // close dialog if auto close is true
+ if (m_autoClose){
+ done(0);
+ return;
+ }
+ // otherwise hide cancel and show ok button
+ showButtonCancel(false);
+ showButtonOK(true);
+ showResult(); // and show final result
+}
+
+/* This timer has two jobs: it polls the thread if it is finished. Polling is
+ better here as it might finish while the dialog builds up. Secondly it refreshes
+ the displayed result.
+ */
+void KrCalcSpaceDialog::timer(){
+ // thread finished?
+ if (m_thread->finished()){
+ // close dialog or switch buttons
+ calculationFinished();
+ m_pollTimer->stop(); // stop the polling. No longer needed
+ return;
+ }
+
+ // Every 10 pollings (1 second) refresh the displayed result
+ if (++m_timerCounter > 10){
+ m_timerCounter = 0;
+ showResult();
+ }
+}
+
+void KrCalcSpaceDialog::showResult(){
+ if (!m_thread) return;
+ QString msg;
+ QString fileName = ( ( m_thread->getItems().count() == 1 ) ? ( i18n( "Name: " ) + m_thread->getItems().first() + "\n" ) : QString( "" ) );
+ msg = fileName + i18n( "Total occupied space: %1").arg( KIO::convertSize( m_thread->getTotalSize() ) );
+ if (m_thread->getTotalSize() >= 1024)
+ msg += " (" + KRpermHandler::parseSize( m_thread->getTotalSize() ) + "bytes)";
+ msg += "\n";
+ msg += i18n("in %n directory", "in %n directories", m_thread->getTotalDirs() );
+ msg += " ";
+ msg += i18n("and %n file", "and %n files", m_thread->getTotalFiles() );
+ m_label->setText(msg);
+}
+
+void KrCalcSpaceDialog::slotCancel(){
+ m_thread->stop(); // notify teh thread to stop
+ m_canceled = true; // set the cancel flag
+ KDialogBase::slotCancel(); // close the dialog
+}
+
+KrCalcSpaceDialog::~KrCalcSpaceDialog(){
+ CalcThread * tmp = m_thread;
+ m_thread = 0; // do not access the thread anymore or core dump if smoe piece of code wrongly does
+ tmp->deleteInstance(); // Notify the thread, that the dialog does not need anymore.
+}
+
+void KrCalcSpaceDialog::exec(){
+ m_thread->start(); // start the thread
+ if (m_autoClose){ // autoclose
+ // set the cursor to busy mode and wait 3 seconds or until the thread finishes
+ krApp->setCursor( KCursor::waitCursor() );
+ bool result = m_thread->wait(3000);
+ krApp->setCursor( KCursor::arrowCursor() ); // return the cursor to normal mode
+ if (result) return;// thread finished: do not show the dialog
+ showResult(); // fill the invisible dialog with usefull data
+ }
+ // prepare and start the poll timer
+ connect(m_pollTimer, SIGNAL(timeout()), this, SLOT(timer()));
+ m_pollTimer->start(100);
+ KDialogBase::exec(); // show the dialog
+}
+/* --=={ End of patch by Heiner <h.eichmann@gmx.de> }==-- */
+
+
+#include "krcalcspacedialog.moc"
diff --git a/krusader/Panel/krcalcspacedialog.h b/krusader/Panel/krcalcspacedialog.h
new file mode 100644
index 0000000..fcdbdce
--- /dev/null
+++ b/krusader/Panel/krcalcspacedialog.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ krcalcspacedialog.h - description
+ -------------------
+ begin : Fri Jan 2 2004
+ copyright : (C) 2004 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
+
+ H e a d e r 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRCALCSPACEDIALOG_H
+#define KRCALCSPACEDIALOG_H
+
+/* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */
+
+// KDE Includes
+#include <kdialogbase.h>
+#include <kio/jobclasses.h>
+// Qt Includes
+#include <qthread.h>
+// Krusader Includes
+#include "../VFS/vfs.h"
+#include "krdetailedviewitem.h"
+class ListPanel;
+class KrView;
+
+
+/* Dialog calculating showing the number of files and directories and its total size
+ in a dialog. If wanted, the dialog appears after 3 seconds of calculation, to
+ avoid a short appearence if the result was found quickly. Computes teh result in
+ a different thread.
+ */
+class KrCalcSpaceDialog : public KDialogBase{
+ Q_OBJECT
+ /* Thread which does the actual calculation. Deletes itself, if no longer
+ needed. Creator must call finished(), if the thread is no longer needed.
+ */
+ class CalcThread : public QThread{
+ KIO::filesize_t m_totalSize, m_currentSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalDirs;
+ const QStringList m_items;
+ vfs * m_files;
+ KrView *m_view;
+ KrCalcSpaceDialog * m_parent;
+ QMutex m_synchronizeUsageAccess;
+ bool m_threadInUse; // true: caller needs the thread
+ bool m_stop;
+ void cleanUp(); // Deletes this, if possible
+ public:
+ KIO::filesize_t getTotalSize() const {return m_totalSize + m_currentSize;} // the result
+ unsigned long getTotalFiles() const {return m_totalFiles;} // the result
+ unsigned long getTotalDirs() const {return m_totalDirs;} // the result
+ const QStringList & getItems() const {return m_items;} // list of directories to calculate
+ CalcThread(KrCalcSpaceDialog * parent, ListPanel * panel, const QStringList & items);
+ void deleteInstance(); // thread is no longer needed.
+ void run(); // start calculation
+ void stop(); // stop it. Thread continues until vfs_calcSpace returns
+ } * m_thread;
+ friend class CalcThread;
+ class QTimer * m_pollTimer;
+ QLabel * m_label;
+ bool m_autoClose; // true: wait 3 sec. before showing the dialog. Close it, when done
+ bool m_canceled; // true: cancel was pressed
+ int m_timerCounter; // internal counter. The timer runs faster as the rehresh (see comment there)
+ void calculationFinished(); // called if the calulation is done
+ void showResult(); // show the current result in teh dialog
+ static void setDirSize(KrDetailedViewItem * viewItem, KIO::filesize_t size) {viewItem->setSize(size);}
+protected slots:
+ void timer(); // poll timer was fired
+ void slotCancel(); // cancel was pressed
+public:
+ // autoclose: wait 3 sec. before showing the dialog. Close it, when done
+ KrCalcSpaceDialog(QWidget *parent, ListPanel * panel, const QStringList & items, bool autoclose);
+ ~KrCalcSpaceDialog();
+ KIO::filesize_t getTotalSize() const {return m_thread->getTotalSize();} // the result
+ unsigned long getTotalFiles() const {return m_thread->getTotalFiles();} // the result
+ unsigned long getTotalDirs() const {return m_thread->getTotalDirs();} // the result
+ bool wasCanceled() const {return m_canceled;} // cancel was pressed; result is probably wrong
+public slots:
+ void exec(); // start calculation
+};
+/* End of patch by Heiner <h.eichmann@gmx.de> */
+
+#endif
diff --git a/krusader/Panel/krcolorcache.cpp b/krusader/Panel/krcolorcache.cpp
new file mode 100644
index 0000000..2c3351a
--- /dev/null
+++ b/krusader/Panel/krcolorcache.cpp
@@ -0,0 +1,761 @@
+/***************************************************************************
+ krcolorcache.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 "krcolorcache.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include <kglobalsettings.h>
+#include <qfile.h>
+
+
+// Macro: set target = col, if col is valid
+#define SETCOLOR(target, col) { if (col.isValid()) target = col; }
+
+/*
+Static class, which lists all allowed keywords for a quick access. Just call a method to initialize it.
+*/
+class KrColorSettingNames
+{
+ static QMap<QString, bool> s_colorNames;
+ static QMap<QString, bool> s_numNames;
+ static QMap<QString, bool> s_boolNames;
+ static void initialize();
+public:
+ static QValueList<QString> getColorNames();
+ static bool isColorNameValid(const QString & settingName);
+ static QValueList<QString> getNumNames();
+ static bool isNumNameValid(const QString & settingName);
+ static QValueList<QString> getBoolNames();
+ static bool isBoolNameValid(const QString & settingName);
+} krColorSettingNames;
+
+QMap<QString, bool> KrColorSettingNames::s_colorNames;
+QMap<QString, bool> KrColorSettingNames::s_numNames;
+QMap<QString, bool> KrColorSettingNames::s_boolNames;
+
+void KrColorSettingNames::initialize()
+{
+ if (!s_colorNames.empty())
+ return;
+ s_colorNames["Foreground"] = true;
+ s_colorNames["Inactive Foreground"] = true;
+ s_colorNames["Directory Foreground"] = true;
+ s_colorNames["Inactive Directory Foreground"] = true;
+ s_colorNames["Executable Foreground"] = true;
+ s_colorNames["Inactive Executable Foreground"] = true;
+ s_colorNames["Symlink Foreground"] = true;
+ s_colorNames["Inactive Symlink Foreground"] = true;
+ s_colorNames["Invalid Symlink Foreground"] = true;
+ s_colorNames["Inactive Invalid Symlink Foreground"] = true;
+ s_colorNames["Marked Foreground"] = true;
+ s_colorNames["Inactive Marked Foreground"] = true;
+ s_colorNames["Marked Background"] = true;
+ s_colorNames["Inactive Marked Background"] = true;
+ s_colorNames["Current Foreground"] = true;
+ s_colorNames["Inactive Current Foreground"] = true;
+ s_colorNames["Current Background"] = true;
+ s_colorNames["Inactive Current Background"] = true;
+ s_colorNames["Marked Current Foreground"] = true;
+ s_colorNames["Inactive Marked Current Foreground"] = true;
+ s_colorNames["Alternate Background"] = true;
+ s_colorNames["Inactive Alternate Background"] = true;
+ s_colorNames["Background"] = true;
+ s_colorNames["Inactive Background"] = true;
+ s_colorNames["Alternate Marked Background"] = true;
+ s_colorNames["Inactive Alternate Marked Background"] = true;
+ s_colorNames["Dim Target Color"] = true;
+
+ s_numNames["Dim Factor"] = true;
+
+ s_boolNames["KDE Default"] = true;
+ s_boolNames["Enable Alternate Background"] = true;
+ s_boolNames["Show Current Item Always"] = true;
+ s_boolNames["Dim Inactive Colors"] = true;
+}
+
+QValueList<QString> KrColorSettingNames::getColorNames()
+{
+ initialize();
+ return s_colorNames.keys();
+}
+
+bool KrColorSettingNames::isColorNameValid(const QString & settingName)
+{
+ initialize();
+ return s_colorNames.contains(settingName);
+}
+
+QValueList<QString> KrColorSettingNames::getNumNames()
+{
+ initialize();
+ return s_numNames.keys();
+}
+
+bool KrColorSettingNames::isNumNameValid(const QString & settingName)
+{
+ initialize();
+ return s_numNames.contains(settingName);
+}
+
+QValueList<QString> KrColorSettingNames::getBoolNames()
+{
+ initialize();
+ return s_boolNames.keys();
+}
+
+bool KrColorSettingNames::isBoolNameValid(const QString & settingName)
+{
+ initialize();
+ return s_boolNames.contains(settingName);
+}
+
+
+
+/*
+KrColorSettings implementation. Contains all properties in QMaps. loadFromConfig initializes them from krConfig.
+*/
+class KrColorSettingsImpl
+{
+ friend class KrColorSettings;
+ QMap<QString, QString> m_colorTextValues;
+ QMap<QString, QColor> m_colorValues;
+ QMap<QString, int> m_numValues;
+ QMap<QString, bool> m_boolValues;
+ void loadFromConfig();
+};
+
+void KrColorSettingsImpl::loadFromConfig()
+{
+ krConfig->setGroup("Colors");
+ QValueList<QString> names = KrColorSettingNames::getColorNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ m_colorTextValues[*it] = krConfig->readEntry(*it, "");
+ m_colorValues[*it] = krConfig->readColorEntry(*it);
+ }
+ names = KrColorSettingNames::getNumNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != QString::null)
+ m_numValues[*it] = krConfig->readNumEntry(*it);
+ }
+ names = KrColorSettingNames::getBoolNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != QString::null)
+ m_boolValues[*it] = krConfig->readBoolEntry(*it);
+ }
+}
+
+
+
+KrColorSettings::KrColorSettings()
+{
+ m_impl = new KrColorSettingsImpl();
+ m_impl->loadFromConfig();
+}
+
+KrColorSettings::KrColorSettings(const KrColorSettings & src)
+{
+ m_impl = new KrColorSettingsImpl();
+ operator =(src);
+}
+
+KrColorSettings::~KrColorSettings()
+{
+ delete m_impl;
+}
+
+const KrColorSettings & KrColorSettings::operator= (const KrColorSettings & src)
+{
+ if (this == & src)
+ return * this;
+ QValueList<QString> names = KrColorSettingNames::getColorNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ m_impl->m_colorTextValues[*it] = src.m_impl->m_colorTextValues[*it];
+ m_impl->m_colorValues[*it] = src.m_impl->m_colorValues[*it];
+ }
+ for ( QMap<QString, int>::Iterator it = src.m_impl->m_numValues.begin(); it != src.m_impl->m_numValues.end(); ++it )
+ {
+ m_impl->m_numValues[it.key()] = it.data();
+ }
+ for ( QMap<QString, bool>::Iterator it = src.m_impl->m_boolValues.begin(); it != src.m_impl->m_boolValues.end(); ++it )
+ {
+ m_impl->m_boolValues[it.key()] = it.data();
+ }
+ return * this;
+}
+
+QValueList<QString> KrColorSettings::getColorNames()
+{
+ return KrColorSettingNames::getColorNames();
+}
+
+bool KrColorSettings::isColorNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isColorNameValid(settingName);
+}
+
+bool KrColorSettings::setColorValue(const QString & settingName, const QColor & color)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorValues[settingName] = color;
+ return true;
+}
+
+QColor KrColorSettings::getColorValue(const QString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return QColor();
+ }
+ return m_impl->m_colorValues[settingName];
+}
+
+bool KrColorSettings::setColorTextValue(const QString & settingName, const QString & colorText)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorTextValues[settingName] = colorText;
+ return true;
+}
+
+QString KrColorSettings::getColorTextValue(const QString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return QString();
+ }
+ return m_impl->m_colorTextValues[settingName];
+}
+
+QValueList<QString> KrColorSettings::getNumNames()
+{
+ return KrColorSettingNames::getNumNames();
+}
+
+bool KrColorSettings::isNumNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isNumNameValid(settingName);
+}
+
+bool KrColorSettings::setNumValue(const QString & settingName, int value)
+{
+ if (!isNumNameValid(settingName))
+ {
+ krOut << "Invalid number setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_numValues[settingName] = value;
+ return true;
+}
+
+int KrColorSettings::getNumValue(const QString & settingName, int defaultValue) const
+{
+ if (!isNumNameValid(settingName))
+ {
+ krOut << "Invalid number setting name: " << settingName << endl;
+ return 0;
+ }
+ if (!m_impl->m_numValues.contains(settingName))
+ return defaultValue;
+ return m_impl->m_numValues[settingName];
+}
+
+QValueList<QString> KrColorSettings::getBoolNames()
+{
+ return KrColorSettingNames::getBoolNames();
+}
+
+bool KrColorSettings::isBoolNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isBoolNameValid(settingName);
+}
+
+bool KrColorSettings::setBoolValue(const QString & settingName, bool value)
+{
+ if (!isBoolNameValid(settingName))
+ {
+ krOut << "Invalid bool setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_boolValues[settingName] = value;
+ return true;
+}
+
+int KrColorSettings::getBoolValue(const QString & settingName, bool defaultValue) const
+{
+ if (!isBoolNameValid(settingName))
+ {
+ krOut << "Invalid bool setting name: " << settingName << endl;
+ return false;
+ }
+ if (!m_impl->m_boolValues.contains(settingName))
+ return defaultValue;
+ return m_impl->m_boolValues[settingName];
+}
+
+
+
+KrColorItemType::KrColorItemType()
+{
+ m_fileType = File;
+ m_alternateBackgroundColor = false;
+ m_activePanel = false;
+ m_currentItem = false;
+ m_selectedItem = false;
+}
+
+KrColorItemType::KrColorItemType(FileType type, bool alternateBackgroundColor, bool activePanel, bool currentItem, bool selectedItem)
+{
+ m_fileType = type;
+ m_alternateBackgroundColor = alternateBackgroundColor;
+ m_activePanel = activePanel;
+ m_currentItem = currentItem;
+ m_selectedItem = selectedItem;
+}
+
+KrColorItemType::KrColorItemType(const KrColorItemType & src)
+{
+ operator= (src);
+}
+
+const KrColorItemType & KrColorItemType::operator= (const KrColorItemType & src)
+{
+ if (this == & src)
+ return * this;
+ m_fileType = src.m_fileType;
+ m_alternateBackgroundColor = src.m_alternateBackgroundColor;
+ m_activePanel = src.m_activePanel;
+ m_currentItem = src.m_currentItem;
+ m_selectedItem = src.m_selectedItem;
+ return * this;
+}
+
+
+
+
+/*
+KrColorCache implementation. Contains the KrColorSettings used for teh calculation and the cache for the results.
+getColors is the only method to call. All other are taken from the previous versions.
+*/
+class KrColorCacheImpl
+{
+ friend class KrColorCache;
+ QMap<QString, QColorGroup> m_cachedColors;
+ KrColorSettings m_colorSettings;
+ QColorGroup getColors(const KrColorItemType & type) const;
+ static const QColor & setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2);
+ QColor getForegroundColor(bool isActive) const;
+ QColor getSpecialForegroundColor(const QString & type, bool isActive) const;
+ QColor getBackgroundColor(bool isActive) const;
+ QColor getAlternateBackgroundColor(bool isActive) const;
+ QColor getMarkedForegroundColor(bool isActive) const;
+ QColor getMarkedBackgroundColor(bool isActive) const;
+ QColor getAlternateMarkedBackgroundColor(bool isActive) const;
+ QColor getCurrentForegroundColor(bool isActive) const;
+ QColor getCurrentBackgroundColor(bool isActive) const;
+ QColor getCurrentMarkedForegroundColor(bool isActive) const;
+ QColor dimColor(QColor color, bool isBackgroundColor) const;
+};
+
+QColorGroup KrColorCacheImpl::getColors(const KrColorItemType & type) const
+{
+ QColorGroup result;
+ if (m_colorSettings.getBoolValue("KDE Default", _KDEDefaultColors))
+ {
+ // KDE default? Getcolors from KGlobalSettings.
+ bool enableAlternateBackground = m_colorSettings.getBoolValue("Enable Alternate Background", _AlternateBackground);
+ QColor background = enableAlternateBackground && type.m_alternateBackgroundColor ?
+ KGlobalSettings::alternateBackgroundColor()
+ : KGlobalSettings::baseColor();
+ result.setColor(QColorGroup::Base, background);
+ result.setColor(QColorGroup::Background, background);
+ result.setColor(QColorGroup::Text, KGlobalSettings::textColor());
+ result.setColor(QColorGroup::HighlightedText, KGlobalSettings::highlightedTextColor());
+ result.setColor(QColorGroup::Highlight, KGlobalSettings::highlightColor());
+ return result;
+ }
+ bool markCurrentAlways = m_colorSettings.getBoolValue("Show Current Item Always", _ShowCurrentItemAlways);
+ bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
+
+ // cache m_activePanel flag. If color dimming is turned on, it is set to true, as the inactive colors
+ // are calculated from the active ones at the end.
+ bool isActive = type.m_activePanel;
+ if (dimBackground)
+ isActive = true;
+
+ // First calculate fore- and background.
+ QColor background = type.m_alternateBackgroundColor ?
+ getAlternateBackgroundColor(isActive)
+ : getBackgroundColor(isActive);
+ QColor foreground;
+ switch(type.m_fileType)
+ {
+ case KrColorItemType::Directory :
+ foreground = getSpecialForegroundColor("Directory", isActive);
+ break;
+ case KrColorItemType::Executable :
+ foreground = getSpecialForegroundColor("Executable", isActive);
+ break;
+ case KrColorItemType::InvalidSymlink :
+ foreground = getSpecialForegroundColor("Invalid Symlink", isActive);
+ break;
+ case KrColorItemType::Symlink :
+ foreground = getSpecialForegroundColor("Symlink", isActive);
+ break;
+ default:
+ foreground = getForegroundColor(isActive);
+ }
+
+ // set the background color
+ result.setColor(QColorGroup::Base, background);
+ result.setColor(QColorGroup::Background, background);
+
+ // set the foreground color
+ result.setColor(QColorGroup::Text, foreground);
+
+ // now the color of a marked item
+ QColor markedBackground = type.m_alternateBackgroundColor ?
+ getAlternateMarkedBackgroundColor(isActive)
+ : getMarkedBackgroundColor(isActive);
+ QColor markedForeground = getMarkedForegroundColor(isActive);
+ if (!markedForeground.isValid()) // transparent
+ // choose fore- or background, depending on its contrast compared to markedBackground
+ markedForeground = setColorIfContrastIsSufficient(markedBackground, foreground, background);
+
+ // set it in the color group (different group color than normal foreground!)
+ result.setColor(QColorGroup::HighlightedText, markedForeground);
+ result.setColor(QColorGroup::Highlight, markedBackground);
+
+ // In case the current item is a selected one, set the fore- and background colors for the contrast calculation below
+ if (type.m_selectedItem)
+ {
+ background = markedBackground;
+ foreground = markedForeground;
+ }
+
+ // finally the current item
+ if (type.m_currentItem && (markCurrentAlways || isActive))
+ {
+ // if this is the current item AND the panels has the focus OR the current should be marked always
+ QColor currentBackground = getCurrentBackgroundColor(isActive);
+
+ if (!currentBackground.isValid()) // transparent
+ currentBackground = background;
+
+ // set the background
+ result.setColor(QColorGroup::Highlight, currentBackground);
+ result.setColor(QColorGroup::Base, currentBackground);
+ result.setColor(QColorGroup::Background, currentBackground);
+
+ QColor color;
+ if (type.m_selectedItem)
+ color = getCurrentMarkedForegroundColor(isActive);
+ if (!color.isValid()) // not used
+ {
+ color = getCurrentForegroundColor(isActive);
+ if (!color.isValid()) // transparent
+ // choose fore- or background, depending on its contrast compared to markedBackground
+ color = setColorIfContrastIsSufficient(currentBackground, foreground, background);
+ }
+
+ // set the foreground
+ result.setColor(QColorGroup::Text, color);
+ result.setColor(QColorGroup::HighlightedText, color);
+ }
+
+ if (dimBackground && !type.m_activePanel)
+ {
+ // if color dimming is choosen, dim the colors for the inactive panel
+ result.setColor(QColorGroup::Base, dimColor(result.base(), true));
+ result.setColor(QColorGroup::Background, dimColor(result.base(), true));
+ result.setColor(QColorGroup::Text, dimColor(result.text(), false));
+ result.setColor(QColorGroup::HighlightedText, dimColor(result.highlightedText(), false));
+ result.setColor(QColorGroup::Highlight, dimColor(result.highlight(), true));
+ }
+ return result;
+}
+
+const QColor & KrColorCacheImpl::setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2)
+{
+ #define sqr(x) ((x)*(x))
+ int contrast = sqr(color1.red() - background.red()) + sqr(color1.green() - background.green()) + sqr(color1.blue() - background.blue());
+
+ // if the contrast between background and color1 is too small, take color2 instead.
+ if (contrast < 1000)
+ return color2;
+ return color1;
+}
+
+QColor KrColorCacheImpl::getForegroundColor(bool isActive) const
+{
+ QColor color = KGlobalSettings::textColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Foreground"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Foreground"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getSpecialForegroundColor(const QString & type, bool isActive) const
+{
+ QString colorName = "Inactive " + type + " Foreground";
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Foreground")
+ return getForegroundColor(false);
+ QColor color = m_colorSettings.getColorValue(type + " Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue(colorName));
+ if (!color.isValid())
+ return getForegroundColor(isActive);
+ return color;
+}
+
+QColor KrColorCacheImpl::getBackgroundColor(bool isActive) const
+{
+ QColor color = KGlobalSettings::baseColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Background"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Background"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getAlternateBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background") == "")
+ return getAlternateBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ QColor color = isActive ?
+ m_colorSettings.getColorValue("Alternate Background")
+ : m_colorSettings.getColorValue("Inactive Alternate Background");
+ if (!color.isValid())
+ color = KGlobalSettings::alternateBackgroundColor();
+ if (!color.isValid())
+ color = KGlobalSettings::baseColor();
+ return color;
+}
+
+QColor KrColorCacheImpl::getMarkedForegroundColor(bool isActive) const
+{
+ QString colorName = isActive?"Marked Foreground":"Inactive Marked Foreground";
+ if (m_colorSettings.getColorTextValue(colorName) == "transparent")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return KGlobalSettings::highlightedTextColor();
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return getMarkedForegroundColor(true);
+ return m_colorSettings.getColorValue(colorName);
+}
+
+QColor KrColorCacheImpl::getMarkedBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "")
+ return KGlobalSettings::highlightColor();
+ if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background") == "")
+ return getMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Marked Background")
+ : m_colorSettings.getColorValue("Inactive Marked Background");
+}
+
+QColor KrColorCacheImpl::getAlternateMarkedBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background") == "Alternate Background")
+ return getAlternateBackgroundColor(true);
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background") == "")
+ return getMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "")
+ return getAlternateMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Alternate Background")
+ return getAlternateBackgroundColor(false);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Marked Background")
+ return getMarkedBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Alternate Marked Background")
+ : m_colorSettings.getColorValue("Inactive Alternate Marked Background");
+}
+
+QColor KrColorCacheImpl::getCurrentForegroundColor(bool isActive) const
+{
+ QColor color = m_colorSettings.getColorValue("Current Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Current Foreground"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getCurrentBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Current Background") == "")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue("Current Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background") == "")
+ return getCurrentBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Current Background")
+ : m_colorSettings.getColorValue("Inactive Current Background");
+}
+
+QColor KrColorCacheImpl::getCurrentMarkedForegroundColor(bool isActive) const
+{
+ QString colorName = isActive?"Marked Current Foreground":"Inactive Marked Current Foreground";
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "Marked Foreground")
+ return getMarkedForegroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return getCurrentMarkedForegroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Marked Foreground")
+ return getMarkedForegroundColor(false);
+ return m_colorSettings.getColorValue(colorName);
+}
+
+QColor KrColorCacheImpl::dimColor(QColor color, bool /* isBackgroundColor */) const
+{
+ krConfig->setGroup("Colors");
+ int dimFactor = m_colorSettings.getNumValue("Dim Factor", 100);
+ QColor targetColor = m_colorSettings.getColorValue("Dim Target Color");
+ if (!targetColor.isValid())
+ targetColor = QColor(255, 255, 255);
+ bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
+ bool dim = dimFactor >= 0 && dimFactor < 100 && dimBackground;
+ if (dim)
+ color = KrColorCache::dimColor(color, dimFactor, targetColor);
+ return color;
+}
+
+
+
+
+
+
+KrColorCache * KrColorCache::m_instance = 0;
+
+KrColorCache::KrColorCache()
+{
+ m_impl = new KrColorCacheImpl;
+}
+
+KrColorCache::~KrColorCache()
+{
+ delete m_impl;
+}
+
+KrColorCache & KrColorCache::getColorCache()
+{
+ if (!m_instance)
+ {
+ m_instance = new KrColorCache;
+ m_instance->refreshColors();
+ }
+ return * m_instance;
+}
+
+void KrColorCache::getColors(QColorGroup & result, const KrColorItemType & type) const
+{
+ // for the cache lookup: calculate a unique key from the type
+ char hashKey[128];
+ switch(type.m_fileType)
+ {
+ case KrColorItemType::Directory :
+ strcpy(hashKey, "Directory");
+ break;
+ case KrColorItemType::Executable :
+ strcpy(hashKey, "Executable");
+ break;
+ case KrColorItemType::InvalidSymlink :
+ strcpy(hashKey, "InvalidSymlink");
+ break;
+ case KrColorItemType::Symlink :
+ strcpy(hashKey, "Symlink");
+ break;
+ default:
+ strcpy(hashKey, "File");
+ }
+ if (type.m_activePanel)
+ strcat(hashKey, "-Active");
+ if (type.m_alternateBackgroundColor)
+ strcat(hashKey, "-Alternate");
+ if (type.m_currentItem)
+ strcat(hashKey, "-Current");
+ if (type.m_selectedItem)
+ strcat(hashKey, "-Selected");
+
+ // lookup in cache
+ if (!m_impl->m_cachedColors.contains(hashKey))
+ // not found: calculate color group and store it in cache
+ m_impl->m_cachedColors[hashKey] = m_impl->getColors(type);
+
+ // get color group from cache
+ const QColorGroup & col = m_impl->m_cachedColors[hashKey];
+
+ // copy colors in question to result color group
+ result.setColor(QColorGroup::Base, col.base());
+ result.setColor(QColorGroup::Background, col.base());
+ result.setColor(QColorGroup::Text, col.text());
+ result.setColor(QColorGroup::HighlightedText, col.highlightedText());
+ result.setColor(QColorGroup::Highlight, col.highlight());
+}
+
+QColor KrColorCache::dimColor(const QColor & color, int dim, const QColor & targetColor)
+{
+ return QColor((targetColor.red() * (100 - dim) + color.red() * dim) / 100,
+ (targetColor.green() * (100 - dim) + color.green() * dim) / 100,
+ (targetColor.blue() * (100 - dim) + color.blue() * dim) / 100);
+}
+
+void KrColorCache::refreshColors()
+{
+ m_impl->m_cachedColors.clear();
+ m_impl->m_colorSettings = KrColorSettings();
+ colorsRefreshed();
+}
+
+void KrColorCache::setColors(const KrColorSettings & colorSettings)
+{
+ m_impl->m_cachedColors.clear();
+ m_impl->m_colorSettings = colorSettings;
+ colorsRefreshed();
+}
+
+#include "krcolorcache.moc"
diff --git a/krusader/Panel/krcolorcache.h b/krusader/Panel/krcolorcache.h
new file mode 100644
index 0000000..a213319
--- /dev/null
+++ b/krusader/Panel/krcolorcache.h
@@ -0,0 +1,101 @@
+#ifndef KRCOLORCACHE_H
+#define KRCOLORCACHE_H
+
+#include <qobject.h>
+#include <qdict.h>
+
+/*
+Design goals: Color calculation is done on one place only. Configuration through krConfig OR through local settings.
+Calculation must be fast through cacheing.
+
+This implementation exposes 3 classes:
+
+KrColorSettings: holds the color settings from krConfig, which can be changed locally
+KrColorItemType: specifies the colors to be calculated
+KrColorCache: perfomes the color calculation and caches the result. Uses KrColorSettings for the calculation
+*/
+
+
+/*
+Copies all used color settings from krConfig into a local cache on creation. It contains 3 types of properties:
+color, numeric (int) and boolean. Color properties can have string or color values. Property values can be
+changed. These changes does not go into krConfig!
+
+is*Valid checks, if a protery name is valid
+get*Names returns a list of all allowed property names
+set*Value overwrites a property with a new value
+get*Value retunrs the current value
+
+For colors teh value can be returned as text or as color. If a text representation is not a valid color,
+setColorValue(QColor()) should be called.
+*/
+class KrColorSettings
+{
+ class KrColorSettingsImpl * m_impl;
+public:
+ KrColorSettings();
+ KrColorSettings(const KrColorSettings &);
+ ~KrColorSettings();
+ const KrColorSettings & operator= (const KrColorSettings &);
+
+ static bool isColorNameValid(const QString & settingName);
+ static QValueList<QString> getColorNames();
+ bool setColorValue(const QString & settingName, const QColor & color);
+ QColor getColorValue(const QString & settingName) const;
+ bool setColorTextValue(const QString & settingName, const QString & colorText);
+ QString getColorTextValue(const QString & settingName) const;
+
+ static bool isNumNameValid(const QString & settingName);
+ static QValueList<QString> getNumNames();
+ bool setNumValue(const QString & settingName, int value);
+ int getNumValue(const QString & settingName, int defaultValue = 0) const;
+
+ static bool isBoolNameValid(const QString & settingName);
+ static QValueList<QString> getBoolNames();
+ bool setBoolValue(const QString & settingName, bool value);
+ int getBoolValue(const QString & settingName, bool defaultValue = false) const;
+};
+
+/*
+A colletcion of properties which describe the color group to be calculated
+*/
+class KrColorItemType
+{
+public:
+ enum FileType {File, InvalidSymlink, Symlink, Directory, Executable};
+ FileType m_fileType;
+ bool m_alternateBackgroundColor, m_activePanel, m_currentItem, m_selectedItem;
+ KrColorItemType();
+ KrColorItemType(FileType type, bool alternateBackgroundColor, bool activePanel, bool currentItem, bool selectedItem);
+ KrColorItemType(const KrColorItemType &);
+ const KrColorItemType & operator= (const KrColorItemType &);
+};
+
+/*
+The color calculation. It bases on an internal KrColorSettings instance. Via setColors it can be changed.
+getColors does the color calculation. It sets the colors Base, Background, Text, HighlightedText and Highlight.
+All calculated values are cached. The cache is deleted on refreshColors and setColors, which also trigger
+colorsRefreshed. getColorCache returns a statis color cached for painting the panels. On the color cache
+setColors should NEVER be called!
+*/
+class KrColorCache : public QObject
+{
+ Q_OBJECT
+ static KrColorCache * m_instance;
+ class KrColorCacheImpl * m_impl;
+ KrColorCache(const KrColorCache &);
+ const KrColorCache & operator= (const KrColorCache &);
+public:
+ KrColorCache();
+ ~KrColorCache();
+ static KrColorCache & getColorCache();
+ void getColors(QColorGroup & result, const KrColorItemType & type) const;
+ static QColor dimColor(const QColor & color, int dim, const QColor & targetColor);
+public slots:
+ void refreshColors();
+ void setColors(const KrColorSettings &);
+signals:
+ void colorsRefreshed();
+};
+
+#endif
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"
diff --git a/krusader/Panel/krdetailedview.h b/krusader/Panel/krdetailedview.h
new file mode 100644
index 0000000..f0616fb
--- /dev/null
+++ b/krusader/Panel/krdetailedview.h
@@ -0,0 +1,180 @@
+/***************************************************************************
+ krdetailedview.h
+ -------------------
+ 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
+
+ H e a d e r 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. *
+* *
+***************************************************************************/
+#ifndef KRDETAILEDVIEW_H
+#define KRDETAILEDVIEW_H
+
+#include <klistview.h>
+#include <ksqueezedtextlabel.h>
+#include <klocale.h>
+#include <qwidget.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include "krview.h"
+#include "krviewitem.h"
+
+// extends KrViewProperties to add detailedview-only properties
+class KrDetailedViewProperties: public KrViewProperties {
+public:
+ enum ColumnType { Unused = -1, Name = 0x0, Extention = 0x1, Mime = 0x2, Size = 0x3, DateTime = 0x4,
+ Permissions = 0x5, KrPermissions = 0x6, Owner = 0x7, Group = 0x8 };
+ static const int MAX_COLUMNS = 9;
+ int column[ MAX_COLUMNS ]; // column[ColumnType] contains the number of the requested column.
+ // This is used by column() and whenever item uses text() or setText()
+ bool numericPermissions; // show full permission column as octal numbers
+
+ KrDetailedViewProperties() {
+ for ( int i = 0; i < MAX_COLUMNS; i++ ) column[i] = Unused;
+ filter = KrViewProperties::All;
+ filterMask = KRQuery( "*" );
+ }
+};
+
+
+class QDragMoveEvent;
+class KrRenameTimerObject;
+class ListPanel;
+class KrDetailedViewItem;
+
+/**
+ * KrDetailedView implements everthing and anything regarding a detailed view in a filemananger.
+ * IT MUST USE KrViewItem as the children to it's *KListView. KrDetailedView and KrViewItem are
+ * tightly coupled and the view will not work with other kinds of items.
+ * Apart from this, the view is self-reliant and you can use the vast interface to get whatever
+ * information is necessery from it.
+ */
+class KrDetailedView : public KListView, public KrView {
+ Q_OBJECT
+ friend class KrDetailedViewItem;
+
+public:
+ KrDetailedView( QWidget *parent, bool &left, KConfig *cfg = krConfig, const char *name = 0 );
+ virtual ~KrDetailedView();
+ virtual int column( KrDetailedViewProperties::ColumnType type );
+ virtual inline KrViewItem *getFirst() { return dynamic_cast<KrViewItem*>( firstChild() ); }
+ virtual inline KrViewItem *getLast() { return dynamic_cast<KrViewItem*>( lastChild() ); }
+ virtual inline KrViewItem *getNext( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<KListViewItem*>( current ) ->itemBelow() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<KListViewItem*>( current ) ->itemAbove() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt( const QPoint &vp );
+ virtual inline KrViewItem *findItemByName( const QString &name ) { return dynamic_cast<KrViewItem*>( findItem( name, 0 ) ); }
+ virtual void addItems( vfs *v, bool addUpDir = true );
+ virtual QString getCurrentItem() const;
+ virtual void makeItemVisible( const KrViewItem *item );
+ virtual void setCurrentItem( const QString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item);
+ virtual void clear();
+ virtual void sort() { KListView::sort(); }
+ virtual void setSortMode( KrViewProperties::SortSpec mode );
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual inline void saveSettings() { KListView::saveLayout( _config, nameInKConfig() ); }
+ virtual inline void restoreSettings() { KListView::restoreLayout( _config, nameInKConfig() ); }
+
+signals:
+ void middleButtonClicked( KrViewItem *item );
+ void currentChanged( KrViewItem *item );
+
+protected:
+ virtual void setup();
+ virtual void initProperties();
+ virtual void initOperator();
+ virtual KrViewItem *preAddItem(vfile *vf);
+ virtual bool preDelItem(KrViewItem *item);
+
+ void newColumn( KrDetailedViewProperties::ColumnType type );
+ void selectColumns();
+
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void imStartEvent( QIMEvent* e );
+ virtual void imEndEvent( QIMEvent *e );
+ virtual void imComposeEvent( QIMEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (QMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( QMouseEvent * e );
+ virtual void contentsWheelEvent( QWheelEvent *e );
+ virtual bool acceptDrag( QDropEvent* e ) const;
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item);
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( QEvent *e );
+ virtual bool eventFilter( QObject * watched, QEvent * e );
+
+protected slots:
+ void rename( QListViewItem *item, int c );
+ void slotClicked( QListViewItem *item );
+ void slotDoubleClicked( QListViewItem *item );
+ void slotItemDescription( QListViewItem *item );
+ void slotCurrentChanged( QListViewItem *item );
+ void handleContextMenu( QListViewItem*, const QPoint&, int );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( QListViewItem *it, int col );
+ void setNameToMakeCurrent( QListViewItem *it );
+ void sortOrderChanged(int);
+ void slotRightButtonPressed(QListViewItem*, const QPoint& point, int);
+ void slotSortOrderChanged(int col);
+ void transformCurrentChanged( QListViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, QListViewItem * item, const QPoint & pos, int c );
+ inline void slotExecuted( QListViewItem* i ) {
+ QString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const QString &, int = 0 );
+ void stopQuickSearch( QKeyEvent* );
+ void handleQuickSearchEvent( QKeyEvent* );
+
+private:
+ static QString ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ];
+ bool swushSelects;
+ QPoint dragStartPos;
+ QListViewItem *lastSwushPosition;
+ bool caseSensitiveSort;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ QTime clickTime;
+ QListViewItem *clickedItem;
+ QTimer renameTimer;
+ QTimer contextMenuTimer;
+ QPoint contextMenuPoint;
+ QListViewItem *currentlyRenamedItem;
+ QListViewItem *pressedItem;
+};
+
+#endif /* KRDETAILEDVIEW_H */
diff --git a/krusader/Panel/krdetailedviewitem.cpp b/krusader/Panel/krdetailedviewitem.cpp
new file mode 100644
index 0000000..4d37854
--- /dev/null
+++ b/krusader/Panel/krdetailedviewitem.cpp
@@ -0,0 +1,313 @@
+/***************************************************************************
+ krdetailedviewitem.cpp
+ -------------------
+ copyright : (C) 2000 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 "../krusader.h"
+#include "../defaults.h"
+#include "../kicons.h"
+#include "../krusaderview.h"
+#include "krdetailedviewitem.h"
+#include "krdetailedview.h"
+#include "krcolorcache.h"
+#include "listpanel.h"
+#include "../VFS/krpermhandler.h"
+#include <sys/types.h>
+#include <time.h>
+#include <qpainter.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <qpalette.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+
+#define COLUMN(X) static_cast<const KrDetailedViewProperties*>(_viewProperties)-> \
+ column[ KrDetailedViewProperties::X ]
+#define PROPS static_cast<const KrDetailedViewProperties*>(_viewProperties)
+#define PERM_BITMASK (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
+#define VF getVfile()
+
+#ifdef FASTER
+int KrDetailedViewItem::expHeight = 0;
+#endif // FASTER
+
+KrDetailedViewItem::KrDetailedViewItem(KrDetailedView *parent, QListViewItem *after, vfile *vf):
+ KListViewItem(parent, after), KrViewItem(vf, parent->properties()) {
+#ifdef FASTER
+ initiated = false;
+ // get the expected height of an item - should be done only once
+ if (expHeight == 0) {
+ KConfigGroupSaver svr(krConfig, "Look&Feel");
+ expHeight = 2 + (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ }
+
+#endif
+ // there's a special case, where if _vf is null, then we've got the ".." (updir) item
+ // in that case, create a special vfile for that item, and delete it, if needed
+ if (!_vf) {
+ dummyVfile = true;
+ _vf = new vfile("..", 0, "drw-r--r--", 0, false, 0, 0, QString::null, QString::null, 0);
+
+ setText(COLUMN(Name), "..");
+ setText(COLUMN(Size), i18n("<DIR>") );
+ if ( PROPS->displayIcons )
+ setPixmap( COLUMN(Name), FL_LOADICON( "up" ) );
+ setSelectable( false );
+#ifdef FASTER
+ initiated = true;
+#endif
+ }
+
+ repaintItem();
+}
+
+#ifdef FASTER
+void KrDetailedViewItem::setup() {
+ // idea: when not having pixmaps in the first place, the height of the item is smaller then with
+ // the pixmap. when the pixmap is inserted, the item resizes, thereby making ensureItemVisible()
+ // become 'confused' and stop working. therefore, we set the correct height here and avoid the issue
+ KListViewItem::setup();
+ setHeight(expHeight);
+}
+#endif
+
+void KrDetailedViewItem::repaintItem() {
+ if ( dummyVfile ) return;
+ QString tmp;
+ // set text in columns, according to what columns are available
+ int id = KrDetailedViewProperties::Unused;
+ if ((id = COLUMN(Mime)) != -1) {
+ tmp = KMimeType::mimeType(_vf->vfile_getMime())->comment();
+ setText( id, tmp );
+ }
+ if ((id = COLUMN(Size)) != -1) {
+ if (_vf->vfile_isDir() && _vf->vfile_getSize() <= 0) setText(id, i18n("<DIR>"));
+ else setText(id, PROPS->humanReadableSize ? KIO::convertSize(_vf->vfile_getSize())+" " :
+ KRpermHandler::parseSize(_vf->vfile_getSize())+" ");
+ }
+
+ if ((id = COLUMN(DateTime)) != -1)
+ setText(id, dateTime());
+ if ((id = COLUMN(KrPermissions)) != -1) {
+ // first, build the krusader permissions
+ tmp=QString::null;
+ switch (_vf->vfile_isReadable()){
+ case ALLOWED_PERM: tmp+='r'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ switch (_vf->vfile_isWriteable()){
+ case ALLOWED_PERM: tmp+='w'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ switch (_vf->vfile_isExecutable()){
+ case ALLOWED_PERM: tmp+='x'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ setText(id, tmp);
+ }
+ if ((id = COLUMN(Permissions) ) != -1) {
+ if (PROPS->numericPermissions) {
+ setText(id, tmp.sprintf("%.4o", _vf->vfile_getMode() & PERM_BITMASK));
+ } else setText(id, _vf->vfile_getPerm());
+ }
+ if ((id = COLUMN(Owner)) != -1) {
+ setText(id, _vf->vfile_getOwner());
+ }
+ if ((id = COLUMN(Group)) != -1) {
+ setText(id, _vf->vfile_getGroup());
+ }
+ // if we've got an extention column, clip the name accordingly
+ QString name = this->name(), ext = "";
+ if ((id = COLUMN(Extention)) != -1 && !_vf->vfile_isDir()) {
+ ext = this->extension();
+ name = this->name(false); // request name without extension
+ setText(id, ext);
+ }
+ setText(COLUMN(Name), name);
+#ifndef FASTER
+ // display an icon if needed
+ if (PROPS->displayIcons)
+ setPixmap(COLUMN(Name),KrView::getIcon(_vf));
+#endif
+}
+
+QString num2qstring(KIO::filesize_t num){
+ QString buf;
+ buf.sprintf("%025llu",num);
+ return buf;
+}
+
+void KrDetailedViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) {
+#ifdef FASTER
+ if (!initiated && !dummyVfile) {
+ // display an icon if needed
+ if (PROPS->displayIcons)
+ setPixmap(COLUMN(Name),KrView::getIcon(_vf));
+
+ initiated = true;
+ }
+#endif
+
+ QColorGroup _cg(cg);
+
+ // This is ugly! I had to dublicate KListViewItem::paintCell() code, as the
+ // KListViewItem::paintCell() overwrites my color settings. So KrDetailedViewItem::paintCell
+ // must dublicate the KListViewItem::paintCell() code, do the required color settings
+ // and call QListViewItem::paintCell() afterwards (the base class of KListViewItem).
+ // This tabooed in the object oriented heaven, but necessary here. Blame the KDE team for
+ // this really poor paintCell implementation!
+
+ const QPixmap *pm = listView()->viewport()->backgroundPixmap();
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm));
+ p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
+ }
+ else if (isAlternate())
+ if (listView()->viewport()->backgroundMode()==Qt::FixedColor)
+ _cg.setColor(QColorGroup::Background, static_cast< KListView* >(listView())->alternateBackground());
+ else
+ _cg.setColor(QColorGroup::Base, static_cast< KListView* >(listView())->alternateBackground());
+
+ // end of uglyness
+
+ KrColorItemType colorItemType;
+ colorItemType.m_activePanel = (dynamic_cast<KrView *>(listView()) == ACTIVE_PANEL->view);
+ colorItemType.m_alternateBackgroundColor = isAlternate();
+ colorItemType.m_currentItem = (listView()->currentItem() == this);
+ colorItemType.m_selectedItem = isSelected();
+ if (VF->vfile_isSymLink())
+ {
+ if (_vf->vfile_getMime() == "Broken Link !" )
+ colorItemType.m_fileType = KrColorItemType::InvalidSymlink;
+ else
+ colorItemType.m_fileType = KrColorItemType::Symlink;
+ }
+ else if (VF->vfile_isDir())
+ colorItemType.m_fileType = KrColorItemType::Directory;
+ else if (VF->vfile_isExecutable())
+ colorItemType.m_fileType = KrColorItemType::Executable;
+ else
+ colorItemType.m_fileType = KrColorItemType::File;
+ KrColorCache::getColorCache().getColors(_cg, colorItemType);
+ // center the <DIR> thing if needed
+ if(column != COLUMN(Size))
+ QListViewItem::paintCell(p, _cg, column, width, align);
+ else {
+ if (dummyVfile) {
+ QListViewItem::paintCell(p, _cg, column, width, Qt::AlignHCenter); // updir
+ } else {
+ if (_vf->vfile_isDir() && _vf->vfile_getSize()<=0)
+ QListViewItem::paintCell(p, _cg, column, width, Qt::AlignHCenter);
+ else QListViewItem::paintCell(p, _cg, column, width, align); // size
+ }
+ }
+}
+
+const QColor & KrDetailedViewItem::setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2)
+{
+ #define sqr(x) ((x)*(x))
+ int contrast = sqr(color1.red() - background.red()) + sqr(color1.green() - background.green()) + sqr(color1.blue() - background.blue());
+
+ // if the contrast between background and color1 is too small, take color2 instead.
+ if (contrast < 1000)
+ return color2;
+ return color1;
+}
+
+int KrDetailedViewItem::compare(QListViewItem *i,int col,bool ascending ) const {
+ bool ignoreCase = (PROPS->sortMode & KrViewProperties::IgnoreCase);
+ bool alwaysSortDirsByName = (PROPS->sortMode & KrViewProperties::AlwaysSortDirsByName);
+ int asc = ( ascending ? -1 : 1 );
+ KrDetailedViewItem *other = (KrDetailedViewItem *)(i);
+
+ bool thisDir = VF->vfile_isDir();
+ bool otherDir = other->VF->vfile_isDir();
+
+ // handle directory sorting
+ if ( thisDir ){
+ if ( !otherDir ) return 1*asc;
+ } else if( otherDir ) return -1*asc;
+
+ if ( isDummy() ) return 1*asc;
+ if ( other->isDummy() ) return -1*asc;
+
+ if (col == COLUMN(Name) ||
+ (alwaysSortDirsByName && thisDir && otherDir )) {
+ // localeAwareCompare doesn't handle names that start with a dot
+ QString text0 = name();
+ QString itext0 = other->name();
+
+ if( ignoreCase )
+ {
+ text0 = text0.lower();
+ itext0 = itext0.lower();
+ }
+
+ if ( isHidden() ) {
+ if ( !other->isHidden() ) return 1*asc;
+ } else if ( other->isHidden() ) return -1*asc;
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(text0, itext0);
+ } else return QString::localeAwareCompare(text0,itext0);
+ } else if (col == COLUMN(Size) ) {
+ if( VF->vfile_getSize() == other->VF->vfile_getSize() )
+ return 0;
+ return (VF->vfile_getSize() > other->VF->vfile_getSize() ? 1 : -1);
+ } else if (col == COLUMN(DateTime) ) {
+ if( VF->vfile_getTime_t() == other->VF->vfile_getTime_t() )
+ return 0;
+ return (VF->vfile_getTime_t() > other->VF->vfile_getTime_t() ? 1 : -1);
+ } else if (col == COLUMN(Permissions) && PROPS->numericPermissions) {
+ int thisPerm = VF->vfile_getMode() & PERM_BITMASK;
+ int otherPerm = other->VF->vfile_getMode() & PERM_BITMASK;
+ if( thisPerm == otherPerm )
+ return 0;
+ return ((thisPerm > otherPerm) ? 1 : -1);
+ } else {
+ QString e1 = (!ignoreCase ? text(col) : text(col).lower());
+ QString e2 = (!ignoreCase ? i->text(col) : i->text(col).lower());
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(e1, e2);
+ } else return QString::localeAwareCompare(e1, e2);
+ }
+}
+
+void KrDetailedViewItem::itemHeightChanged() {
+#ifdef FASTER
+ expHeight = 0;
+#endif
+}
diff --git a/krusader/Panel/krdetailedviewitem.h b/krusader/Panel/krdetailedviewitem.h
new file mode 100644
index 0000000..3ef9fcf
--- /dev/null
+++ b/krusader/Panel/krdetailedviewitem.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ krdetailedviewitem.h
+ -------------------
+ 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
+
+ H e a d e r 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRDETAILEDVIEWITEM_H
+#define KRDETAILEDVIEWITEM_H
+
+#include "krviewitem.h"
+#include <sys/types.h>
+#include "../VFS/vfile.h"
+#include <klistview.h>
+#include <qguardedptr.h>
+
+#define FASTER
+
+class QPixmap;
+class KrDetailedView;
+
+class KrDetailedViewItem : public KListViewItem, public KrViewItem {
+friend class KrDetailedView;
+friend class KrCalcSpaceDialog;
+public:
+ KrDetailedViewItem(KrDetailedView *parent, QListViewItem *after, vfile *vf);
+ inline bool isSelected() const { return KListViewItem::isSelected(); }
+ inline void setSelected(bool s) { KListViewItem::setSelected(s); }
+ int compare(QListViewItem *i,int col,bool ascending ) const;
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+ void repaintItem();
+ static void itemHeightChanged(); // force the items to resize when icon/font size change
+#ifdef FASTER
+ virtual void setup(); // called when listview needs to know the height of the item
+#endif
+
+protected:
+ // text() was made protected in order to catch every place where text(x) is used
+ // to gain unlawful information on the object
+ virtual inline QString text(int column) const { return KListViewItem::text(column); }
+
+private:
+ static const QColor & setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2);
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+#endif
+};
+
+#endif
diff --git a/krusader/Panel/krdrag.cpp b/krusader/Panel/krdrag.cpp
new file mode 100644
index 0000000..5e80b36
--- /dev/null
+++ b/krusader/Panel/krdrag.cpp
@@ -0,0 +1,103 @@
+/***************************************************************************
+ krdrag.cpp
+ -------------------
+copyright : (C) 2003 by Heiner Eichmann
+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
+
+ H e a d e r 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 "krdrag.h"
+#include <kurldrag.h>
+
+KRDrag * KRDrag::newDrag( const KURL::List & urls, bool move, QWidget * dragSource, const char* name )
+{
+ // See KURLDrag::newDrag
+ QStrList uris;
+ KURL::List::ConstIterator uit = urls.begin();
+ KURL::List::ConstIterator uEnd = urls.end();
+ // Get each URL encoded in utf8 - and since we get it in escaped
+ // form on top of that, .latin1() is fine.
+ for ( ; uit != uEnd ; ++uit )
+ uris.append( KURLDrag::urlToString( *uit ).latin1() );
+ return new KRDrag( uris, move, dragSource, name );
+}
+
+KRDrag::KRDrag( const QStrList & urls, bool move, QWidget * dragSource, const char* name )
+ : QUriDrag( urls, dragSource, name ),
+ m_bCutSelection( move ), m_urls( urls )
+{}
+
+const char* KRDrag::format( int i ) const
+{
+ if ( i == 0 )
+ return "text/uri-list";
+ else if ( i == 1 )
+ return "application/x-kde-cutselection";
+ else if ( i == 2 )
+ return "text/plain";
+ else return 0;
+}
+
+QByteArray KRDrag::encodedData( const char* mime ) const
+{
+ QByteArray a;
+ QCString mimetype( mime );
+ if ( mimetype == "text/uri-list" )
+ return QUriDrag::encodedData( mime );
+ else if ( mimetype == "application/x-kde-cutselection" ) {
+ QCString s ( m_bCutSelection ? "1" : "0" );
+ a.resize( s.length() + 1 ); // trailing zero
+ memcpy( a.data(), s.data(), s.length() + 1 );
+ }
+ else if ( mimetype == "text/plain" )
+ {
+ QStringList uris;
+ for (QStrListIterator it(m_urls); *it; ++it)
+ uris.append(KURLDrag::stringToUrl(*it).prettyURL());
+ QCString s = uris.join( "\n" ).local8Bit();
+ if( uris.count() > 1 )
+ s.append( "\n" );
+ a.resize( s.length() + 1 ); // trailing zero
+ memcpy( a.data(), s.data(), s.length() + 1 );
+ }
+ return a;
+}
+
+//
+
+// Used for KonqIconDrag too
+
+bool KRDrag::decodeIsCutSelection( const QMimeSource *e )
+{
+ QByteArray a = e->encodedData( "application/x-kde-cutselection" );
+ if ( a.isEmpty() )
+ return false;
+ else
+ {
+ return (a.at(0) == '1'); // true if "1", or similar
+ }
+ }
+
+#include "krdrag.moc"
diff --git a/krusader/Panel/krdrag.h b/krusader/Panel/krdrag.h
new file mode 100644
index 0000000..1aa264f
--- /dev/null
+++ b/krusader/Panel/krdrag.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ krdrag.h
+ -------------------
+copyright : (C) 2003 by Heiner Eichmann
+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
+
+ H e a d e r 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. *
+* *
+***************************************************************************/
+
+#ifndef KRDRAG_H
+#define KRDRAG_H
+
+#include <qdragobject.h>
+#include <kurl.h>
+
+class KRDrag : public QUriDrag
+{
+ Q_OBJECT
+public:
+ static KRDrag * newDrag( const KURL::List & urls, bool move, QWidget * dragSource = 0, const char* name = 0 );
+
+protected:
+ KRDrag( const QStrList & urls, bool move, QWidget * dragSource, const char* name );
+
+public:
+ virtual ~KRDrag() {}
+
+ virtual const char* format( int i ) const;
+ virtual QByteArray encodedData( const char* mime ) const;
+
+ void setMoveSelection( bool move ) { m_bCutSelection = move; }
+
+ // Returns true if the data was cut (used for KonqIconDrag too)
+ static bool decodeIsCutSelection( const QMimeSource *e );
+
+protected:
+ bool m_bCutSelection;
+ QStrList m_urls;
+};
+
+#endif /* KRDRAG_H */
diff --git a/krusader/Panel/krpopupmenu.cpp b/krusader/Panel/krpopupmenu.cpp
new file mode 100644
index 0000000..fda6296
--- /dev/null
+++ b/krusader/Panel/krpopupmenu.cpp
@@ -0,0 +1,354 @@
+/***************************************************************************
+ krpopupmenu.cpp - description
+ -------------------
+ begin : Tue Aug 26 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <klocale.h>
+#include <kprocess.h>
+#include <kshred.h>
+#include <krun.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include "../krservices.h"
+#include "../defaults.h"
+#include "../MountMan/kmountman.h"
+#include "../krslots.h"
+#include "krpopupmenu.h"
+#include "krview.h"
+#include "krviewitem.h"
+#include "panelfunc.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+
+void KrPopupMenu::run(const QPoint &pos, ListPanel *panel) {
+ KrPopupMenu menu(panel);
+ int result = menu.exec(pos);
+ menu.performAction(result);
+}
+
+KrPopupMenu::KrPopupMenu(ListPanel *thePanel, QWidget *parent) : KPopupMenu(parent), panel(thePanel), empty(false),
+ multipleSelections(false),actions(0) {
+#ifdef __LIBKONQ__
+ konqMenu = 0;
+#endif
+
+ panel->view->getSelectedKrViewItems( &items );
+ if ( items.empty() ) {
+ addCreateNewMenu();
+ insertSeparator();
+ addEmptyMenuEntries();
+ return;
+ } else if ( items.size() > 1 ) multipleSelections = true;
+
+ item = items.first();
+ vfile *vf = panel->func->getVFile(item);
+
+ // ------------ the OPEN option - open prefered service
+ insertItem( i18n("Open/Run"), OPEN_ID );
+ if ( !multipleSelections ) { // meaningful only if one file is selected
+ changeItem( OPEN_ID, item->icon(), vf->vfile_isExecutable() && !vf->vfile_isDir() ? i18n("Run") : i18n("Open") );
+ // open in a new tab (if folder)
+ if ( vf->vfile_isDir() ) {
+ insertItem( i18n( "Open in New Tab" ), OPEN_TAB_ID );
+ changeItem( OPEN_TAB_ID, krLoader->loadIcon( "tab_new", KIcon::Panel ), i18n( "Open in New Tab" ) );
+ }
+ insertSeparator();
+ }
+
+ // ------------- Preview - normal vfs only ?
+ if ( panel->func->files()->vfs_getType() == vfs::NORMAL ) {
+ // create the preview popup
+ QStringList names;
+ panel->getSelectedNames( &names );
+ preview.setUrls( panel->func->files() ->vfs_getFiles( &names ) );
+ insertItem( i18n("Preview"), &preview, PREVIEW_ID );
+ }
+
+ // -------------- Open with: try to find-out which apps can open the file
+ // this too, is meaningful only if one file is selected or if all the files
+ // have the same mimetype !
+ QString mime = panel->func->getVFile(item)->vfile_getMime();
+ // check if all the list have the same mimetype
+ for ( unsigned int i = 1; i < items.size(); ++i ) {
+ if ( panel->func->getVFile(( *items.at( i ) )) ->vfile_getMime() != mime ) {
+ mime = QString::null;
+ break;
+ }
+ }
+ if ( !mime.isEmpty() ) {
+ offers = KServiceTypeProfile::offers( mime );
+ for ( unsigned int i = 0; i < offers.count(); ++i ) {
+ KService::Ptr service = offers[ i ].service();
+ if ( service->isValid() && service->type() == "Application" ) {
+ openWith.insertItem( service->name(), SERVICE_LIST_ID + i );
+ openWith.changeItem( SERVICE_LIST_ID + i, service->pixmap( KIcon::Small ), service->name() );
+ }
+ }
+ openWith.insertSeparator();
+ if ( vf->vfile_isDir() )
+ openWith.insertItem( krLoader->loadIcon( "konsole", KIcon::Small ), i18n( "Terminal" ), OPEN_TERM_ID );
+ openWith.insertItem( i18n( "Other..." ), CHOOSE_ID );
+ insertItem( QPixmap(), &openWith, OPEN_WITH_ID );
+ changeItem( OPEN_WITH_ID, i18n( "Open With" ) );
+ insertSeparator();
+ }
+
+ // --------------- user actions
+ insertItem( i18n("User Actions"), new UserActionPopupMenu( panel->func->files()->vfs_getFile( item->name() ).url() ) );
+ _items.setAutoDelete( true );
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ vfile *file = panel->func->files()->vfs_search(((*it)->name()));
+ KURL url = file->vfile_getUrl();
+ _items.append( new KFileItem( url, file->vfile_getMime(), file->vfile_getMode() ) );
+ }
+
+#ifdef __LIBKONQ__
+ // -------------- konqueror menu
+ actions = new KActionCollection(this);
+ konqMenu = new KonqPopupMenu( KonqBookmarkManager::self(), _items, panel->func->files()->vfs_getOrigin(), *actions, 0, this,
+ KonqPopupMenu::NoFlags, KParts::BrowserExtension::DefaultPopupItems );
+ insertItem( QPixmap(), konqMenu, KONQ_MENU_ID );
+ changeItem( KONQ_MENU_ID, i18n( "Konqueror Menu" ) );
+#endif
+
+ // ------------- 'create new' submenu
+ addCreateNewMenu();
+ insertSeparator();
+
+ // ---------- COPY
+ insertItem( i18n( "Copy..." ), COPY_ID );
+ if ( panel->func->files() ->vfs_isWritable() ) {
+ // ------- MOVE
+ insertItem( i18n( "Move..." ), MOVE_ID );
+ // ------- RENAME - only one file
+ if ( !multipleSelections )
+ insertItem( i18n( "Rename" ), RENAME_ID );
+
+ // -------- MOVE TO TRASH
+ KConfigGroupSaver saver(krConfig, "General");
+ bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
+ if( trash )
+ insertItem( i18n( "Move to Trash" ), TRASH_ID );
+ // -------- DELETE
+ insertItem( i18n( "Delete" ), DELETE_ID );
+ // -------- SHRED - only one file
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL &&
+ !vf->vfile_isDir() && !multipleSelections )
+ insertItem( i18n( "Shred" ), SHRED_ID );
+ }
+
+ // ---------- link handling
+ // create new shortcut or redirect links - only on local directories:
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL ) {
+ insertSeparator();
+ linkPopup.insertItem( i18n( "New Symlink..." ), NEW_SYMLINK_ID );
+ linkPopup.insertItem( i18n( "New Hardlink..." ), NEW_LINK_ID );
+ if ( panel->func->getVFile(item)->vfile_isSymLink() )
+ linkPopup.insertItem( i18n( "Redirect Link..." ), REDIRECT_LINK_ID);
+ insertItem( QPixmap(), &linkPopup, LINK_HANDLING_ID );
+ changeItem( LINK_HANDLING_ID, i18n( "Link Handling" ) );
+ }
+ insertSeparator();
+
+ // ---------- calculate space
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL && ( vf->vfile_isDir() || multipleSelections ) )
+ krCalculate->plug( this );
+
+ // ---------- mount/umount/eject
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL && vf->vfile_isDir() && !multipleSelections ) {
+ if ( krMtMan.getStatus( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) == KMountMan::MOUNTED )
+ insertItem( i18n( "Unmount" ), UNMOUNT_ID );
+ else if ( krMtMan.getStatus( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) == KMountMan::NOT_MOUNTED )
+ insertItem( i18n( "Mount" ), MOUNT_ID );
+ if ( krMtMan.ejectable( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) )
+ insertItem( i18n( "Eject" ), EJECT_ID );
+ }
+
+ // --------- send by mail
+ if ( Krusader::supportedTools().contains( "MAIL" ) && !vf->vfile_isDir() ) {
+ insertItem( i18n( "Send by Email" ), SEND_BY_EMAIL_ID );
+ }
+
+ // --------- synchronize
+ if ( panel->view->numSelected() ) {
+ insertItem( i18n( "Synchronize Selected Files..." ), SYNC_SELECTED_ID );
+ }
+
+ // --------- copy/paste
+ insertSeparator();
+ insertItem( i18n( "Copy to Clipboard" ), COPY_CLIP_ID );
+ if ( panel->func->files() ->vfs_isWritable() )
+ {
+ insertItem( i18n( "Cut to Clipboard" ), MOVE_CLIP_ID );
+ insertItem( i18n( "Paste from Clipboard" ), PASTE_CLIP_ID );
+ }
+ insertSeparator();
+
+ // --------- properties
+ krProperties->plug( this );
+}
+
+KrPopupMenu::~KrPopupMenu() {
+ if (actions) delete actions;
+#ifdef __LIBKONQ__
+ if (konqMenu) delete konqMenu;
+#endif
+}
+
+void KrPopupMenu::addEmptyMenuEntries() {
+ insertItem( i18n( "Paste from Clipboard" ), PASTE_CLIP_ID );
+}
+
+void KrPopupMenu::addCreateNewMenu() {
+ createNewPopup.insertItem( krLoader->loadIcon( "folder", KIcon::Small ), i18n("Folder..."), MKDIR_ID);
+ createNewPopup.insertItem( krLoader->loadIcon( "txt", KIcon::Small ), i18n("Text File..."), NEW_TEXT_FILE_ID);
+
+ insertItem( QPixmap(), &createNewPopup, CREATE_NEW_ID);
+ changeItem( CREATE_NEW_ID, i18n( "Create New" ) );
+
+}
+
+void KrPopupMenu::performAction(int id) {
+ KURL u;
+ KURL::List lst;
+
+ switch ( id ) {
+ case - 1 : // the user clicked outside of the menu
+ return ;
+ case OPEN_TAB_ID :
+ // assuming only 1 file is selected (otherwise we won't get here)
+ ( ACTIVE_PANEL == LEFT_PANEL ? LEFT_MNG : RIGHT_MNG )->
+ slotNewTab( panel->func->files()->vfs_getFile( item->name() ).url() );
+ break;
+ case OPEN_ID :
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ u = panel->func->files()->vfs_getFile( ( *it ) ->name() );
+ KRun::runURL( u, panel->func->getVFile(item)->vfile_getMime() );
+ }
+ break;
+ case COPY_ID :
+ panel->func->copyFiles();
+ break;
+ case MOVE_ID :
+ panel->func->moveFiles();
+ break;
+ case RENAME_ID :
+ SLOTS->rename();
+ break;
+ case TRASH_ID :
+ panel->func->deleteFiles( false );
+ break;
+ case DELETE_ID :
+ panel->func->deleteFiles( true );
+ break;
+ case EJECT_ID :
+ KMountMan::eject( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case SHRED_ID :
+ if ( KMessageBox::warningContinueCancel( krApp,
+ i18n("<qt>Do you really want to shred <b>%1</b>? Once shred, the file is gone forever!</qt>").arg(item->name()),
+ QString::null, KStdGuiItem::cont(), "Shred" ) == KMessageBox::Continue )
+ KShred::shred( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case OPEN_KONQ_ID :
+ kapp->startServiceByDesktopName( "konqueror", panel->func->files() ->vfs_getFile( item->name() ).url() );
+ break;
+ case CHOOSE_ID : // open-with dialog
+ u = panel->func->files() ->vfs_getFile( item->name() );
+ lst.append( u );
+ KRun::displayOpenWithDialog( lst );
+ break;
+ case MOUNT_ID :
+ krMtMan.mount( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case NEW_LINK_ID :
+ panel->func->krlink( false );
+ break;
+ case NEW_SYMLINK_ID :
+ panel->func->krlink( true );
+ break;
+ case REDIRECT_LINK_ID :
+ panel->func->redirectLink();
+ break;
+ case UNMOUNT_ID :
+ krMtMan.unmount( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case COPY_CLIP_ID :
+ panel->func->copyToClipboard();
+ break;
+ case MOVE_CLIP_ID :
+ panel->func->copyToClipboard( true );
+ break;
+ case PASTE_CLIP_ID :
+ panel->func->pasteFromClipboard();
+ break;
+ case SEND_BY_EMAIL_ID :
+ SLOTS->sendFileByEmail( panel->func->files() ->vfs_getFile( item->name() ).url() );
+ break;
+ case MKDIR_ID :
+ SLOTS->mkdir();
+ break;
+ case NEW_TEXT_FILE_ID:
+ SLOTS->editDlg();
+ break;
+ case SYNC_SELECTED_ID :
+ {
+ QStringList selectedNames;
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it )
+ selectedNames.append( ( *it ) ->name() );
+ if( panel->otherPanel->view->numSelected() ) {
+ KrViewItemList otherItems;
+ panel->otherPanel->view->getSelectedKrViewItems( &otherItems );
+
+ for ( KrViewItemList::Iterator it2 = otherItems.begin(); it2 != otherItems.end(); ++it2 ) {
+ QString name = ( *it2 ) ->name();
+ if( !selectedNames.contains( name ) )
+ selectedNames.append( name );
+ }
+ }
+ SLOTS->slotSynchronizeDirs( selectedNames );
+ }
+ break;
+ case OPEN_TERM_ID :
+ QString save = getcwd( 0, 0 );
+ chdir( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ).local8Bit() );
+ KProcess proc;
+ {
+ KConfigGroupSaver saver(krConfig, "General");
+ QString term = krConfig->readEntry( "Terminal", _Terminal );
+ proc << KrServices::separateArgs( term );
+ if ( !panel->func->getVFile(item)->vfile_isDir() ) proc << "-e" << item->name();
+ if ( term.contains( "konsole" ) ) { /* KDE 3.2 bug (konsole is killed by pressing Ctrl+C) */
+ /* Please remove the patch if the bug is corrected */
+ proc << "&";
+ proc.setUseShell( true );
+ }
+ if ( !proc.start( KProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "Can't open \"%1\"" ).arg(term) );
+ } // group-saver is blown out of scope here
+ chdir( save.local8Bit() );
+ break;
+ }
+
+ // check if something from the open-with-offered-services was selected
+ if ( id >= SERVICE_LIST_ID ) {
+ QStringList names;
+ panel->getSelectedNames( &names );
+ KRun::run( *( offers[ id - SERVICE_LIST_ID ].service() ),
+ *( panel->func->files() ->vfs_getFiles( &names ) ) );
+ }
+}
+
+#include "krpopupmenu.moc"
diff --git a/krusader/Panel/krpopupmenu.h b/krusader/Panel/krpopupmenu.h
new file mode 100644
index 0000000..13157b4
--- /dev/null
+++ b/krusader/Panel/krpopupmenu.h
@@ -0,0 +1,77 @@
+#ifndef KRPOPUPMENU_H
+#define KRPOPUPMENU_H
+
+#include <kpopupmenu.h>
+#include <kurl.h>
+#include <kuserprofile.h>
+#include "listpanel.h"
+#include "krpreviewpopup.h"
+#include "../UserAction/useractionpopupmenu.h"
+#ifdef __LIBKONQ__
+#include <konq_popupmenu.h>
+#include <konqbookmarkmanager.h>
+#endif
+
+// should be renamed to KrContextMenu or similar
+class KrPopupMenu : public KPopupMenu {
+ Q_OBJECT
+public:
+ static void run(const QPoint &pos, ListPanel *panel);
+
+protected:
+ KrPopupMenu(ListPanel *thePanel, QWidget *parent=0);
+ ~KrPopupMenu();
+ void performAction(int id);
+ void addEmptyMenuEntries(); // adds the choices for a menu without selected items
+ void addCreateNewMenu(); // adds a "create new" submenu
+
+ enum ID {
+ OPEN_ID,
+ OPEN_WITH_ID,
+ OPEN_KONQ_ID,
+ OPEN_TERM_ID,
+ OPEN_TAB_ID,
+ PREVIEW_ID,
+ KONQ_MENU_ID,
+ CHOOSE_ID,
+ DELETE_ID,
+ COPY_ID,
+ MOVE_ID,
+ RENAME_ID,
+ PROPERTIES_ID,
+ MOUNT_ID,
+ UNMOUNT_ID,
+ TRASH_ID,
+ SHRED_ID,
+ NEW_LINK_ID,
+ NEW_SYMLINK_ID,
+ REDIRECT_LINK_ID,
+ SYNC_SELECTED_ID,
+ SEND_BY_EMAIL_ID,
+ LINK_HANDLING_ID,
+ EJECT_ID,
+ COPY_CLIP_ID,
+ MOVE_CLIP_ID,
+ PASTE_CLIP_ID,
+ MKDIR_ID,
+ NEW_TEXT_FILE_ID,
+ CREATE_NEW_ID,
+ SERVICE_LIST_ID // ALWAYS KEEP THIS ONE LAST!!!
+ };
+
+private:
+ ListPanel *panel;
+ bool empty, multipleSelections;
+ KPopupMenu openWith, linkPopup, createNewPopup;
+ KrPreviewPopup preview;
+ KActionCollection *actions;
+ KrViewItemList items; // list of selected items
+ KrViewItem *item; // the (first) selected item
+ KFileItemList _items;
+ QValueList<KServiceOffer> offers;
+#ifdef __LIBKONQ__
+ KonqPopupMenu *konqMenu;
+#endif
+};
+
+#endif
diff --git a/krusader/Panel/krpreviewpopup.cpp b/krusader/Panel/krpreviewpopup.cpp
new file mode 100644
index 0000000..53f4afd
--- /dev/null
+++ b/krusader/Panel/krpreviewpopup.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ krpreviewpopup.cpp - description
+ -------------------
+ begin : Sun Dec 29 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <kio/previewjob.h>
+#include "krpreviewpopup.h"
+#include <kdebug.h>
+#include <klocale.h>
+#include <keditcl.h>
+#include "../KViewer/krviewer.h"
+#include "../krusader.h"
+
+KrPreviewPopup::KrPreviewPopup(): id(1),noPreview(true){
+ connect(this,SIGNAL(activated(int)),this,SLOT(view(int)));
+}
+
+void KrPreviewPopup::setUrls(const KURL::List* urls){
+ //insertItem(i18n("Configure preview"),0);
+ insertItem(i18n("Preview not available"),0);
+
+ KIO::PreviewJob* pjob;
+ QStringList plugins = KIO::PreviewJob::availablePlugins();
+
+ for( unsigned int i=0; i< urls->count(); ++i){
+ KFileItem* kfi = new KFileItem(KFileItem::Unknown,KFileItem::Unknown,*(urls->at(i)));
+ files.append(kfi);
+ }
+
+ pjob = new KIO::PreviewJob(files,200,200,200,1,true,true,0);
+ connect(pjob,SIGNAL(gotPreview(const KFileItem*,const QPixmap&)),
+ this,SLOT(addPreview(const KFileItem*,const QPixmap&)));
+}
+
+KrPreviewPopup::~KrPreviewPopup(){}
+
+void KrPreviewPopup::addPreview(const KFileItem* file,const QPixmap& preview){
+ if(noPreview){
+ removeItem(0);
+ noPreview = false;
+ }
+ insertItem(preview,id);
+ insertItem(file->text(),id++);
+ insertSeparator();
+ availablePreviews.append(file->url());
+}
+
+void KrPreviewPopup::view(int id){
+ if( id==0 ) return;
+ else {
+ KURL url = *(availablePreviews.at(id-1));
+ KrViewer::view(url);
+ }
+}
+
+#include "krpreviewpopup.moc"
diff --git a/krusader/Panel/krpreviewpopup.h b/krusader/Panel/krpreviewpopup.h
new file mode 100644
index 0000000..91b852c
--- /dev/null
+++ b/krusader/Panel/krpreviewpopup.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ krpreviewpopup.h - description
+ -------------------
+ begin : Sun Dec 29 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRPREVIEWPOPUP_H
+#define KRPREVIEWPOPUP_H
+
+#include <qpopupmenu.h>
+#include <qpixmap.h>
+#include <kfileitem.h>
+#include <kurl.h>
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrPreviewPopup : public QPopupMenu {
+ Q_OBJECT
+public:
+ KrPreviewPopup();
+ ~KrPreviewPopup();
+
+ void setUrls(const KURL::List* urls);
+public slots:
+ void addPreview(const KFileItem* file,const QPixmap& preview);
+ void view(int id);
+
+protected:
+ KFileItemList files;
+ int id;
+ bool noPreview;
+ KURL::List availablePreviews;
+};
+
+#endif
diff --git a/krusader/Panel/krselectionmode.cpp b/krusader/Panel/krselectionmode.cpp
new file mode 100644
index 0000000..02d95b1
--- /dev/null
+++ b/krusader/Panel/krselectionmode.cpp
@@ -0,0 +1,61 @@
+#include "krselectionmode.h"
+#include "../krusader.h"
+#include "../defaults.h"
+
+static KrSelectionMode *__currentSelectionMode = 0; // uninitiated, at first
+
+
+KonqSelectionMode konqSelectionMode;
+OriginalSelectionMode originalSelectionMode;
+TCSelectionMode tcSelectionMode;
+UserSelectionMode userSelectionMode;
+
+KrSelectionMode* KrSelectionMode::getSelectionHandler()
+{
+ if (__currentSelectionMode) { // don't check krConfig every time
+ return __currentSelectionMode;
+ } else { // nothing yet, set the correct one
+ krConfig->setGroup( "Look&Feel" );
+ QString mode = krConfig->readEntry("Mouse Selection", "");
+ switch (mode.toInt()) {
+ case 0:
+ __currentSelectionMode = &originalSelectionMode;
+ break;
+ case 1:
+ __currentSelectionMode = &konqSelectionMode;
+ break;
+ case 2:
+ __currentSelectionMode = &tcSelectionMode;
+ break;
+ case 3:
+ __currentSelectionMode = &userSelectionMode;
+ userSelectionMode.init();
+ break;
+ default:
+ break;
+ }
+ // init and return
+ __currentSelectionMode->init();
+ return __currentSelectionMode;
+ }
+}
+
+void KrSelectionMode::resetSelectionHandler() {
+ __currentSelectionMode = 0;
+}
+
+void UserSelectionMode::init() {
+ krConfig->setGroup("Custom Selection Mode");
+ _useQTSelection = krConfig->readBoolEntry("QT Selection", _QtSelection);
+ _leftButtonSelects = krConfig->readBoolEntry("Left Selects", _LeftSelects);
+ _leftButtonPreservesSelection = krConfig->readBoolEntry("Left Preserves", _LeftPreserves);
+ _shiftCtrlLeftButtonSelects = krConfig->readBoolEntry("ShiftCtrl Left Selects", _ShiftCtrlLeft);
+ _rightButtonSelects = krConfig->readBoolEntry("Right Selects", _RightSelects);
+ _rightButtonPreservesSelection = krConfig->readBoolEntry("Right Preserves", _RightPreserves);
+ _shiftCtrlRightButtonSelects = krConfig->readBoolEntry("ShiftCtrl Right Selects", _ShiftCtrlRight);
+ _spaceMovesDown = krConfig->readBoolEntry("Space Moves Down", _SpaceMovesDown);
+ _spaceCalculatesDiskSpace = krConfig->readBoolEntry("Space Calc Space", _SpaceCalcSpace);
+ _insertMovesDown = krConfig->readBoolEntry("Insert Moves Down", _InsertMovesDown);
+ _showContextMenu = (krConfig->readBoolEntry("Immediate Context Menu", _ImmediateContextMenu) ? -1 : 500);
+}
+
diff --git a/krusader/Panel/krselectionmode.h b/krusader/Panel/krselectionmode.h
new file mode 100644
index 0000000..4f9de2e
--- /dev/null
+++ b/krusader/Panel/krselectionmode.h
@@ -0,0 +1,97 @@
+#ifndef KR_SELECTION_MODE_H
+#define KR_SELECTION_MODE_H
+
+/**
+ Every selection mode inherits this class, and has to implement init().
+ Usage:
+ KrSelectionMode::getSelectionHandler()->whateverFunctionYouNeed()
+
+ \note You can call KrSelectionMode::resetSelectionHandler() if you want the
+ selection mode to be re-read. This is useful after a configuration where you
+ changed the selection mode. calling resetSelectionHandler() will cause the next
+ call to getSelectionHandler() to (possibly) select a different mode.
+*/
+class KrSelectionMode {
+public:
+ static KrSelectionMode * getSelectionHandler();
+ static void resetSelectionHandler();
+
+ virtual void init() = 0; // everyone must implement this in order to be a selection mode
+ inline bool useQTSelection() { return _useQTSelection; }
+ inline bool spaceMovesDown() { return _spaceMovesDown; }
+ inline bool insertMovesDown() { return _insertMovesDown; }
+ inline bool spaceCalculatesDiskSpace() { return _spaceCalculatesDiskSpace; }
+ inline bool rightButtonSelects() { return _rightButtonSelects; }
+ inline bool leftButtonSelects() { return _leftButtonSelects; }
+ inline bool rightButtonPreservesSelection() { return _rightButtonPreservesSelection; }
+ inline bool leftButtonPreservesSelection() { return _leftButtonPreservesSelection; }
+ inline bool shiftCtrlRightButtonSelects() { return _shiftCtrlRightButtonSelects; }
+ inline bool shiftCtrlLeftButtonSelects() { return _shiftCtrlLeftButtonSelects; }
+ inline int showContextMenu() { return _showContextMenu; } // 0: no, -1: yes, n>0: after n milliseconds
+
+ virtual ~KrSelectionMode() {}
+
+protected:
+ bool _useQTSelection, _spaceMovesDown, _insertMovesDown, _spaceCalculatesDiskSpace;
+ bool _rightButtonSelects, _leftButtonSelects, _rightButtonPreservesSelection;
+ bool _leftButtonPreservesSelection, _shiftCtrlRightButtonSelects, _shiftCtrlLeftButtonSelects;
+ int _showContextMenu;
+};
+
+class KonqSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = true;
+ _spaceMovesDown = false;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = false;
+ _rightButtonSelects = true;
+ _leftButtonSelects = true;
+ _rightButtonPreservesSelection = false;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = false;
+ _showContextMenu = -1;
+ }
+};
+
+class OriginalSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = false;
+ _spaceMovesDown = true;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = true;
+ _rightButtonSelects = true;
+ _leftButtonSelects = true;
+ _rightButtonPreservesSelection = false;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = false;
+ _showContextMenu = -1;
+ }
+};
+
+class TCSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = false;
+ _spaceMovesDown = false;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = true;
+ _rightButtonSelects = true;
+ _leftButtonSelects = false;
+ _rightButtonPreservesSelection = true;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = true;
+ _showContextMenu = 500;
+ }
+};
+
+class UserSelectionMode: public KrSelectionMode {
+public:
+ void init();
+};
+
+#endif // KR_SELECTION_MODE_H
diff --git a/krusader/Panel/krview.cpp b/krusader/Panel/krview.cpp
new file mode 100644
index 0000000..c44bcb6
--- /dev/null
+++ b/krusader/Panel/krview.cpp
@@ -0,0 +1,332 @@
+/***************************************************************************
+ krview.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 "krview.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../VFS/krpermhandler.h"
+#include "krviewitem.h"
+#include <qnamespace.h>
+#include <qpixmapcache.h>
+#include <qdir.h>
+#include <qbitmap.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+
+
+#define VF getVfile()
+
+
+// ----------------------------- operator
+KrViewOperator::KrViewOperator(KrView *view, QWidget *widget): _view(view), _widget(widget) {
+}
+
+KrViewOperator::~KrViewOperator() {
+}
+
+void KrViewOperator::startDrag() {
+ QStringList items;
+ _view->getSelectedItems( &items );
+ if ( items.empty() )
+ return ; // don't drag an empty thing
+ QPixmap px;
+ if ( items.count() > 1 )
+ px = FL_LOADICON( "queue" ); // how much are we dragging
+ else
+ px = _view->getCurrentKrViewItem() ->icon();
+ emit letsDrag( items, px );
+}
+
+// ----------------------------- krview
+
+KrView::KrView( KConfig *cfg ) : _config( cfg ), _widget(0), _nameToMakeCurrent( QString::null ), _nameToMakeCurrentIfAdded( QString::null ),
+_numSelected( 0 ), _count( 0 ), _numDirs( 0 ), _countSize( 0 ), _selectedSize( 0 ), _properties(0), _focused( false ), _nameInKConfig(QString::null) {
+}
+
+KrView::~KrView() {
+ if (_properties)
+ qFatal("A class inheriting KrView didn't delete _properties!");
+ if (_operator)
+ qFatal("A class inheriting KrView didn't delete _operator!");
+}
+
+void KrView::init() {
+ // sanity checks:
+ if (_nameInKConfig.isEmpty())
+ qFatal("_nameInKConfig must be set during construction of KrView inheritors");
+ if (!_widget)
+ qFatal("_widget must be set during construction of KrView inheritors");
+ // ok, continue
+ initProperties();
+ initOperator();
+ setup();
+}
+
+QPixmap KrView::getIcon( vfile *vf /*, KRListItem::cmpColor color*/ ) {
+ //krConfig->setGroup("Advanced");
+ //////////////////////////////
+ QPixmap icon;
+ QString icon_name = vf->vfile_getIcon();
+ //QPixmapCache::setCacheLimit( krConfig->readNumEntry("Icon Cache Size",_IconCacheSize) );
+
+ if( icon_name.isNull() )
+ icon_name="";
+
+ // first try the cache
+ if ( !QPixmapCache::find( icon_name, icon ) ) {
+ icon = FL_LOADICON( icon_name );
+ // insert it into the cache
+ QPixmapCache::insert( icon_name, icon );
+ }
+ // if it's a symlink - add an arrow overlay
+ if ( vf->vfile_isSymLink() ) {
+ QPixmap link( link_xpm );
+ bitBlt ( &icon, 0, icon.height() - 11, &link, 0, 21, 10, 11, Qt::CopyROP, false );
+ icon.setMask( icon.createHeuristicMask( false ) );
+ }
+
+ return icon;
+}
+
+/**
+ * this function ADDs a list of selected item names into 'names'.
+ * it assumes the list is ready and doesn't initialize it, or clears it
+ */
+void KrView::getItemsByMask( QString mask, QStringList* names, bool dirs, bool files ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( ( it->name() == ".." ) || !QDir::match( mask, it->name() ) ) continue;
+ // if we got here, than the item fits the mask
+ if ( it->getVfile()->vfile_isDir() && !dirs ) continue; // do we need to skip folders?
+ if ( !it->getVfile()->vfile_isDir() && !files ) continue; // do we need to skip files
+ names->append( it->name() );
+ }
+}
+
+/**
+ * this function ADDs a list of selected item names into 'names'.
+ * it assumes the list is ready and doesn't initialize it, or clears it
+ */
+void KrView::getSelectedItems( QStringList *names ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) )
+ if ( it->isSelected() && ( it->name() != ".." ) ) names->append( it->name() );
+
+ // if all else fails, take the current item
+ QString item = getCurrentItem();
+ if ( names->empty() && item!=QString::null && item!=".." ) names->append( item );
+}
+
+void KrView::getSelectedKrViewItems( KrViewItemList *items ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) )
+ if ( it->isSelected() && ( it->name() != ".." ) ) items->append( it );
+
+ // if all else fails, take the current item
+ QString item = getCurrentItem();
+ if ( items->empty() && item!=QString::null && item!=".." ) items->append( getCurrentKrViewItem() );
+}
+
+QString KrView::statistics() {
+ _countSize = _numSelected = _selectedSize = 0;
+
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ){
+ if ( it->isSelected() ) {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ if (it->getVfile()->vfile_getSize() > 0)
+ _countSize += it->getVfile()->vfile_getSize();
+ }
+ QString tmp = QString(i18n("%1 out of %2, %3 (%4) out of %5 (%6)"))
+ .arg( _numSelected ).arg( _count ).arg( KIO::convertSize( _selectedSize ) )
+ .arg( KRpermHandler::parseSize(_selectedSize) )
+ .arg( KIO::convertSize( _countSize ) ).arg( KRpermHandler::parseSize(_countSize) );
+ // notify if we're running a filtered view
+ if (filter() != KrViewProperties::All)
+ tmp = ">> [ " + filterMask().nameFilter() + " ] "+tmp;
+ return tmp;
+}
+
+void KrView::changeSelection( const KRQuery& filter, bool select, bool includeDirs ) {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ bool markDirs = _config->readBoolEntry( "Mark Dirs", _MarkDirs ) || includeDirs;
+
+ KrViewItem *temp = getCurrentKrViewItem();
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( it->name() == ".." ) continue;
+ if ( it->getVfile()->vfile_isDir() && !markDirs ) continue;
+
+ vfile * file = it->getMutableVfile(); // filter::match calls getMimetype which isn't const
+ if( file == 0 ) continue;
+
+ if( filter.match( file ) ) {
+ // we're increasing/decreasing the number of selected files
+ if ( select ) {
+ if ( !it->isSelected() ) {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ } else {
+ if ( it->isSelected() ) {
+ --_numSelected;
+ _selectedSize -= it->getVfile()->vfile_getSize();
+ }
+ }
+ it->setSelected( select );
+ }
+ }
+ updateView();
+ makeItemVisible( temp );
+}
+
+void KrView::invertSelection() {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" /*nameInKConfig()*/ );
+ bool markDirs = _config->readBoolEntry( "Mark Dirs", _MarkDirs );
+
+ KrViewItem *temp = getCurrentKrViewItem();
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( it->name() == ".." ) continue;
+ if ( it->getVfile()->vfile_isDir() && !markDirs && !it->isSelected() ) continue;
+ if ( it->isSelected() ) {
+ --_numSelected;
+ _selectedSize -= it->getVfile()->vfile_getSize();
+ } else {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ it->setSelected( !it->isSelected() );
+ }
+ updateView();
+ makeItemVisible( temp );
+}
+
+QString KrView::firstUnmarkedBelowCurrent() {
+ KrViewItem * iterator = getNext( getCurrentKrViewItem() );
+ while ( iterator && iterator->isSelected() )
+ iterator = getNext( iterator );
+ if ( !iterator ) {
+ iterator = getPrev( getCurrentKrViewItem() );
+ while ( iterator && iterator->isSelected() )
+ iterator = getPrev( iterator );
+ }
+ if ( !iterator ) return QString::null;
+ return iterator->name();
+}
+
+void KrView::delItem(const QString &name) {
+ KrViewItem * it = _dict[ name ];
+ if ( !it ) {
+ krOut << "got signal deletedVfile(" << name << ") but can't find KrViewItem" << endl;
+ return;
+ }
+ if (!preDelItem(it)) return; // do not delete this after all
+
+ // remove from dict
+ if (it->VF->vfile_isDir()) {
+ --_numDirs;
+ } else {
+ _countSize -= it->VF->vfile_getSize();
+ }
+ --_count;
+ _dict.remove( name );
+ delete it;
+ op()->emitSelectionChanged();
+}
+
+KrViewItem *KrView::addItem( vfile *vf ) {
+ KrViewItem *item = preAddItem(vf);
+ if (!item) return 0; // don't add it after all
+
+ // add to dictionary
+ _dict.insert( vf->vfile_getName(), item );
+ if ( vf->vfile_isDir() )
+ ++_numDirs;
+ else _countSize += vf->vfile_getSize();
+ ++_count;
+
+ if (item->name() == nameToMakeCurrent() ) {
+ setCurrentItem(item->name()); // dictionary based - quick
+ makeItemVisible( item );
+ }
+ if (item->name() == nameToMakeCurrentIfAdded() ) {
+ setCurrentItem(item->name());
+ setNameToMakeCurrentIfAdded(QString::null);
+ makeItemVisible( item );
+ }
+
+
+ op()->emitSelectionChanged();
+ return item;
+}
+
+void KrView::updateItem(vfile *vf) {
+ // since we're deleting the item, make sure we keep
+ // it's properties first and repair it later
+ KrViewItem * it = _dict[ vf->vfile_getName() ];
+ if ( !it ) {
+ krOut << "got signal updatedVfile(" << vf->vfile_getName() << ") but can't find KrViewItem" << endl;
+ } else {
+ bool selected = it->isSelected();
+ bool current = ( getCurrentKrViewItem() == it );
+ delItem( vf->vfile_getName() );
+ KrViewItem *updatedItem = addItem( vf );
+ // restore settings
+ ( _dict[ vf->vfile_getName() ] ) ->setSelected( selected );
+ if ( current ) {
+ setCurrentItem( vf->vfile_getName() );
+ makeItemVisible( updatedItem );
+ }
+ }
+ op()->emitSelectionChanged();
+}
+
+void KrView::clear() {
+ _count = _numSelected = _numDirs = _selectedSize = _countSize = 0;
+ _dict.clear();
+}
+
+// good old dialog box
+void KrView::renameCurrentItem() {
+ QString newName, fileName;
+
+ KrViewItem *it = getCurrentKrViewItem();
+ if ( it ) fileName = it->name();
+ else return ; // quit if no current item available
+
+ // don't allow anyone to rename ..
+ if ( fileName == ".." ) return ;
+
+ bool ok = false;
+ newName = KInputDialog::getText( i18n( "Rename" ), i18n( "Rename " ) + fileName + i18n( " to:" ),
+ fileName, &ok, krApp );
+ // if the user canceled - quit
+ if ( !ok || newName == fileName )
+ return ;
+ op()->emitRenameItem(it->name(), newName);
+}
+
diff --git a/krusader/Panel/krview.h b/krusader/Panel/krview.h
new file mode 100644
index 0000000..a7c0932
--- /dev/null
+++ b/krusader/Panel/krview.h
@@ -0,0 +1,245 @@
+/***************************************************************************
+ krview.h
+ -------------------
+ 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
+
+ H e a d e r 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. *
+ * *
+ ***************************************************************************/
+#ifndef KRVIEW_H
+#define KRVIEW_H
+
+#include <qpixmap.h>
+#include <qvariant.h>
+#include <qdict.h>
+#include "../krusader.h"
+#include "../VFS/vfile.h"
+#include "../VFS/vfs.h"
+#include "../VFS/krquery.h"
+
+#include <kdebug.h>
+
+class KrView;
+class KrViewItem;
+typedef QValueList<KrViewItem*> KrViewItemList;
+
+// KrViewProperties
+// This class is an interface class between KrView and KrViewItem
+// In order for KrViewItem to be as independant as possible, KrView holds
+// an instance of this class, and fills it with the correct data. A reference
+// to this should be given to each KrViewItem, which then queries it for
+// information regarding how things should be displayed in the current view.
+//
+// Every property that the item needs to know about the view must be here!
+class KrViewProperties {
+public:
+ enum SortSpec { Name=0x1, Ext=0x2, Size=0x4, Type=0x8, Modified=0x10, Permissions=0x20,
+ KrPermissions=0x40, Owner=0x80, Group=0x100, Descending=0x200,
+ DirsFirst=0x400, IgnoreCase=0x800, AlwaysSortDirsByName=0x1000 };
+ enum FilterSpec { Dirs=0x1, Files=0x2, All=0x3, Custom=0x4, ApplyToDirs=0x8 };
+
+ bool displayIcons; // true if icons should be displayed in this view
+ SortSpec sortMode; // sort specifications
+ FilterSpec filter; // what items to show (all, custom, exec)
+ KRQuery filterMask; // what items to show (*.cpp, *.h etc)
+ bool localeAwareCompareIsCaseSensitive; // mostly, it is not! depends on LC_COLLATE
+ bool humanReadableSize; // display size as KB, MB or just as a long number
+ QStringList atomicExtensions; // list of strings, which will be treated as one extension. Must start with a dot.
+};
+
+// operator can handle two ways of doing things:
+// 1. if the view is a widget (inherits krview and klistview for example)
+// 2. if the view HAS A widget (a krview-son has a member of klistview)
+// this is done by specifying the view and the widget in the constructor,
+// even if they are actually the same object (specify it twice in that case)
+class KrViewOperator: public QObject {
+ Q_OBJECT
+public:
+ KrViewOperator(KrView *view, QWidget *widget);
+ ~KrViewOperator();
+ KrView *view() const { return _view; }
+ QWidget *widget() const { return _widget; }
+ void startDrag();
+
+ void emitSelectionChanged() { emit selectionChanged(); }
+ void emitGotDrop(QDropEvent *e) { emit gotDrop(e); }
+ void emitLetsDrag(QStringList items, QPixmap icon ) { emit letsDrag(items, icon); }
+ void emitItemDescription(QString &desc) { emit itemDescription(desc); }
+ void emitContextMenu(const QPoint &point) { emit contextMenu(point); }
+ void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); }
+ void emitRenameItem(const QString &oldName, const QString &newName) { emit renameItem(oldName, newName); }
+ void emitExecuted( QString &name ) { emit executed(name); }
+ void emitNeedFocus() { emit needFocus(); }
+
+signals:
+ void selectionChanged();
+ void gotDrop( QDropEvent *e );
+ void letsDrag( QStringList items, QPixmap icon );
+ void itemDescription( QString &desc );
+ void contextMenu( const QPoint &point );
+ void emptyContextMenu( const QPoint& point );
+ void renameItem( const QString &oldName, const QString &newName );
+ void executed( QString &name );
+ void needFocus();
+
+
+protected:
+ // never delete those
+ KrView *_view;
+ QWidget *_widget;
+};
+
+/****************************************************************************
+ * READ THIS FIRST: Using the view
+ *
+ * You always hold a pointer to KrView, thus you can only use functions declared
+ * in this class. If you need something else, either this class is missing something
+ * or you are ;-) Using a true name (like dynamic_cast<KrDetailedViewItem*>) should be
+ * needed only when doing new(), or connect() - see example in listpanel.cpp
+ *
+ * The functions you'd usually want:
+ * 1) getSelectedItems - returns all selected items, or (if none) the current item.
+ * it never returns anything which includes the "..", and thus can return an empty list!
+ * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems
+ * 3) getCurrentItem, setCurrentItem - work with QString
+ * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and
+ * used to iterate through a list of items. note that getNext and getPrev accept a pointer
+ * to the current item (used in detailedview for safe iterating), thus your loop should be:
+ * for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; }
+ * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString
+ *
+ * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!!
+ */
+class KrView {
+friend class KrViewItem;
+public:
+ // instantiating a new view
+ // 1. new KrView
+ // 2. view->init()
+ // notes: constructor does as little as possible, setup() does the rest. esp, note that
+ // if you need something from operator or properties, move it into setup()
+ virtual void init();
+
+protected:
+ virtual void initProperties() { qFatal("Please implement your own initProperties() method"); }
+ virtual void initOperator() { qFatal("Please implement your own initOperator() method"); }
+ virtual void setup() { qFatal("Please implement your own setup() method"); }
+
+ ///////////////////////////////////////////////////////
+ // Every view must implement the following functions //
+ ///////////////////////////////////////////////////////
+public:
+ virtual KrViewItem *getFirst() = 0;
+ virtual KrViewItem *getLast() = 0;
+ virtual KrViewItem *getNext(KrViewItem *current) = 0;
+ virtual KrViewItem *getPrev(KrViewItem *current) = 0;
+ virtual KrViewItem *getCurrentKrViewItem() = 0;
+ virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0;
+ virtual KrViewItem *findItemByName(const QString &name) = 0;
+ virtual void addItems(vfs* v, bool addUpDir = true) = 0; // kill me, kill me now
+ virtual QString getCurrentItem() const = 0;
+ virtual void setCurrentItem(const QString& name) = 0;
+ virtual void makeItemVisible(const KrViewItem *item) = 0;
+ virtual void clear();
+ virtual void updateView() = 0;
+ virtual void updateItem(KrViewItem* item) = 0;
+ virtual void sort() = 0;
+ virtual void saveSettings() = 0;
+ virtual void restoreSettings() = 0;
+ virtual void prepareForActive() { _focused = true; }
+ virtual void prepareForPassive() { _focused = false; }
+ virtual void renameCurrentItem(); // Rename current item. returns immediatly
+ virtual QString nameInKConfig() const { return _nameInKConfig; }
+
+protected:
+ virtual KrViewItem *preAddItem(vfile *vf) = 0;
+ virtual bool preDelItem(KrViewItem *item) = 0;
+
+public:
+ //////////////////////////////////////////////////////
+ // the following functions are already implemented, //
+ // and normally - should NOT be re-implemented. //
+ //////////////////////////////////////////////////////
+ virtual KrViewItem *addItem(vfile *vf);
+ virtual void updateItem(vfile *vf);
+ virtual void delItem(const QString &name);
+ virtual uint numSelected() const { return _numSelected; }
+ virtual KIO::filesize_t selectedSize() const { return _selectedSize; }
+ virtual uint numFiles() const { return _count-_numDirs; }
+ virtual uint numDirs() const { return _numDirs; }
+ virtual uint count() const { return _count; }
+ virtual KIO::filesize_t countSize() const { return _countSize; }
+ virtual void getSelectedItems(QStringList* names);
+ virtual void getItemsByMask(QString mask, QStringList* names, bool dirs = true, bool files = true);
+ virtual void getSelectedKrViewItems(KrViewItemList *items);
+ virtual void selectAllIncludingDirs() { changeSelection( KRQuery( "*" ), true, true); }
+ virtual void select( const KRQuery& filter = KRQuery( "*" ) ) { changeSelection(filter, true); }
+ virtual void unselect(const KRQuery& filter = KRQuery( "*" ) ) { changeSelection(filter, false); }
+ virtual void invertSelection();
+ virtual QString nameToMakeCurrent() const { return _nameToMakeCurrent; }
+ virtual void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; }
+ virtual QString nameToMakeCurrentIfAdded() const { return _nameToMakeCurrentIfAdded; }
+ virtual void setNameToMakeCurrentIfAdded(const QString name) { _nameToMakeCurrentIfAdded = name; }
+ virtual QString firstUnmarkedBelowCurrent();
+ virtual QString statistics();
+ virtual const KrViewProperties* properties() const { return _properties; }
+ virtual KrViewOperator* op() const { return _operator; }
+
+ /////////////////////////////////////////////////////////////
+ // the following functions have a default and minimalistic //
+ // implementation, and may be re-implemented if needed //
+ /////////////////////////////////////////////////////////////
+ virtual void setSortMode(KrViewProperties::SortSpec mode) { _properties->sortMode = mode; }
+ virtual KrViewProperties::SortSpec sortMode() const { return _properties->sortMode; }
+ virtual void setFilter(KrViewProperties::FilterSpec filter) { _properties->filter = filter; }
+ virtual KrViewProperties::FilterSpec filter() const { return _properties->filter; }
+ virtual void setFilterMask( KRQuery mask ) { _properties->filterMask = mask; }
+ virtual const KRQuery& filterMask() const { return _properties->filterMask; }
+ inline QWidget *widget() { return _widget; }
+ inline void setWidget(QWidget *w) { _widget = w; }
+
+ // todo: what about selection modes ???
+ virtual ~KrView();
+protected:
+ KrView(KConfig *cfg = krConfig);
+ static QPixmap getIcon(vfile *vf);
+ void changeSelection(const KRQuery& filter, bool select, bool includeDirs = false);
+
+
+protected:
+ KConfig *_config;
+ QWidget *_widget;
+ QString _nameToMakeCurrent;
+ QString _nameToMakeCurrentIfAdded;
+ uint _numSelected, _count, _numDirs;
+ KIO::filesize_t _countSize, _selectedSize;
+ bool _left;
+ KrViewProperties *_properties;
+ KrViewOperator *_operator;
+ QDict<KrViewItem> _dict;
+ bool _focused;
+ QString _nameInKConfig;
+};
+
+#endif /* KRVIEW_H */
diff --git a/krusader/Panel/krviewitem.cpp b/krusader/Panel/krviewitem.cpp
new file mode 100644
index 0000000..28500d4
--- /dev/null
+++ b/krusader/Panel/krviewitem.cpp
@@ -0,0 +1,105 @@
+#include "krviewitem.h"
+#include "../VFS/krpermhandler.h"
+#include <klocale.h>
+#include <kmimetype.h>
+#include <sys/types.h>
+#include <time.h>
+#include <stdlib.h>
+
+#define PROPS static_cast<const KrViewProperties*>(_viewProperties)
+
+QString atomicExtensions[] = {
+ ".tar.gz",
+ ".tar.bz2",
+ ".moc.cpp"
+};
+
+KrViewItem::KrViewItem(vfile *vf, const KrViewProperties* properties):
+ _vf(vf), dummyVfile(false), _viewProperties(properties), _hasExtension(false), _hidden(false), _extension("") {
+ if (vf) {
+ // check if the file has an extension
+ const QString& vfName = vf->vfile_getName();
+ int loc = vfName.findRev('.');
+ if (loc>0) { // avoid mishandling of .bashrc and friend
+ // check if it has one of the predefined 'atomic extensions'
+ for (QStringList::const_iterator i = PROPS->atomicExtensions.begin(); i != PROPS->atomicExtensions.end(); ++i) {
+ if (vfName.endsWith(*i)){
+ loc = vfName.length() - (*i).length();
+ break;
+ }
+ }
+ _name = vfName.left(loc);
+ _extension = vfName.mid(loc+1);
+ _hasExtension=true;
+ }
+
+ if( vfName.startsWith(".") )
+ _hidden = true;
+ }
+}
+
+const QString& KrViewItem::name(bool withExtension) const {
+ if (!withExtension && _hasExtension) return _name;
+ else return _vf->vfile_getName();
+}
+
+QString KrViewItem::description() const {
+ if (dummyVfile) return i18n("Climb up the directory tree");
+ // else is implied
+ QString text = _vf->vfile_getName();
+ QString comment = KMimeType::mimeType(_vf->vfile_getMime())->comment(text, false);
+ QString myLinkDest = _vf->vfile_getSymDest();
+ KIO::filesize_t mySize = _vf->vfile_getSize();
+
+ QString text2 = text.copy();
+ mode_t m_fileMode = _vf->vfile_getMode();
+
+ if (_vf->vfile_isSymLink() ){
+ QString tmp;
+ if ( comment.isEmpty() ) tmp = i18n ( "Symbolic Link" ) ;
+ else if( _vf->vfile_getMime() == "Broken Link !" ) tmp = i18n("(broken link !)");
+ else tmp = i18n("%1 (Link)").arg(comment);
+
+ text += "->";
+ text += myLinkDest;
+ text += " ";
+ text += tmp;
+ } else if ( S_ISREG( m_fileMode ) ){
+ text = QString("%1 (%2)").arg(text2).arg( PROPS->humanReadableSize ?
+ KRpermHandler::parseSize(_vf->vfile_getSize()) : KIO::convertSize( mySize ) );
+ text += " ";
+ text += comment;
+ } else if ( S_ISDIR ( m_fileMode ) ){
+ text += "/ ";
+ text += comment;
+ } else {
+ text += " ";
+ text += comment;
+ }
+ return text;
+}
+
+QString KrViewItem::dateTime() const {
+ // convert the time_t to struct tm
+ time_t time = _vf->vfile_getTime_t();
+ struct tm* t=localtime((time_t *)&time);
+
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ return KGlobal::locale()->formatDateTime(tmp);
+}
+
+QPixmap KrViewItem::icon() {
+#if 0
+ QPixmap *p;
+
+ // This is bad - very bad. the function must return a valid reference,
+ // This is an interface flow - shie please fix it with a function that return QPixmap*
+ // this way we can return 0 - and do our error checking...
+
+ // shie answers: why? what's the difference? if we return an empty pixmap, others can use it as it
+ // is, without worrying or needing to do error checking. empty pixmap displays nothing
+#endif
+ if (dummyVfile || !_viewProperties->displayIcons)
+ return QPixmap();
+ else return KrView::getIcon(_vf);
+}
diff --git a/krusader/Panel/krviewitem.h b/krusader/Panel/krviewitem.h
new file mode 100644
index 0000000..2294b28
--- /dev/null
+++ b/krusader/Panel/krviewitem.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ krviewitem.h
+ -------------------
+ 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
+
+ H e a d e r 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. *
+* *
+***************************************************************************/
+#ifndef KRVIEWITEM_H
+#define KRVIEWITEM_H
+
+#include <sys/types.h>
+#include <kio/global.h>
+#include "../VFS/vfile.h"
+#include "krview.h"
+
+class QString;
+class QPixmap;
+
+class KrViewItem {
+ friend class KrView;
+
+public:
+ virtual const QString& name(bool withExtension=true) const;
+ virtual inline bool hasExtension() const { return _hasExtension; }
+ virtual inline const QString& extension() const { return _extension; }
+ virtual QString dateTime() const;
+ virtual QString description() const;
+ virtual bool isSelected() const = 0;
+ virtual void setSelected( bool s ) = 0;
+ virtual QPixmap icon();
+
+ KrViewItem(vfile *vf, const KrViewProperties* properties);
+ virtual ~KrViewItem() { if (dummyVfile) delete _vf; }
+
+ // DON'T USE THOSE OUTSIDE THE VIEWS!!!
+ inline const vfile* getVfile() const { return _vf; }
+ inline vfile* getMutableVfile() { return _vf; }
+ inline bool isDummy() const { return dummyVfile; }
+ inline bool isHidden() const { return _hidden; }
+
+protected:
+ // used INTERNALLY when calculation of dir size changes the displayed size of the item
+ inline void setSize(KIO::filesize_t size) { _vf->vfile_setSize(size); }
+
+ vfile* _vf; // each view item holds a pointer to a corrosponding vfile for fast access
+ bool dummyVfile; // used in case our item represents the ".." (updir) item
+ const KrViewProperties* _viewProperties;
+ bool _hasExtension;
+ bool _hidden;
+ QString _name;
+ QString _extension;
+};
+
+#endif
diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp
new file mode 100644
index 0000000..5972eaf
--- /dev/null
+++ b/krusader/Panel/listpanel.cpp
@@ -0,0 +1,1115 @@
+/***************************************************************************
+ listpanel.cpp
+ -------------------
+copyright : (C) 2000 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 <unistd.h>
+#include <sys/param.h>
+// QT includes
+#include <qbitmap.h>
+#include <qwhatsthis.h>
+#include <qstringlist.h>
+#include <qstrlist.h>
+#include <kurldrag.h>
+#include <qheader.h>
+#include <qtimer.h>
+#include <qregexp.h>
+#include <qsplitter.h>
+// KDE includes
+#include <kpopupmenu.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <ktrader.h>
+#include <kopenwith.h>
+#include <kuserprofile.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <qtooltip.h>
+#include <kdeversion.h>
+#include <qimage.h>
+#include <qtabbar.h>
+#include <kdebug.h>
+#include <kurlrequester.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+
+// Krusader includes
+#include "../krusader.h"
+#include "../krslots.h"
+#include "panelfunc.h"
+#include "../kicons.h"
+#include "../VFS/krpermhandler.h"
+#include "listpanel.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../MountMan/kmountman.h"
+#include "../Dialogs/krdialogs.h"
+#include "../BookMan/krbookmarkbutton.h"
+#include "../Dialogs/krspwidgets.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include "../GUI/kcmdline.h"
+#include "../Dialogs/percentalsplitter.h"
+#include "krdetailedview.h"
+#include "krbriefview.h"
+#include "krpreviewpopup.h"
+#include "../GUI/dirhistorybutton.h"
+#include "../GUI/dirhistoryqueue.h"
+#include "../GUI/mediabutton.h"
+#include "../GUI/syncbrowsebutton.h"
+#include "../krservices.h"
+#include "panelpopup.h"
+#include "../UserAction/useractionpopupmenu.h"
+#include "../Dialogs/popularurls.h"
+#include "krpopupmenu.h"
+
+#ifdef __LIBKONQ__
+#include <konq_popupmenu.h>
+#include <konqbookmarkmanager.h>
+#endif
+
+typedef QValueList<KServiceOffer> OfferList;
+
+#define URL(X) KURL::fromPathOrURL(X)
+
+/////////////////////////////////////////////////////
+// The list panel constructor //
+/////////////////////////////////////////////////////
+ListPanel::ListPanel( QString typeIn, QWidget *parent, bool &left, const char *name ) :
+ QWidget( parent, name ), panelType( typeIn ), colorMask( 255 ), compareMode( false ), currDragItem( 0 ), statsAgent( 0 ),
+ quickSearch( 0 ), cdRootButton( 0 ), cdUpButton( 0 ), popupBtn(0), popup(0),inlineRefreshJob(0), _left( left ) {
+
+ func = new ListPanelFunc( this );
+ setAcceptDrops( true );
+ layout = new QGridLayout( this, 3, 3 );
+
+ mediaButton = new MediaButton( this, "mediaButton" );
+ connect( mediaButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( mediaButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+
+ status = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ status->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ status->setBackgroundMode( PaletteBackground );
+ status->setFrameStyle( QFrame::Box | QFrame::Raised );
+ status->setLineWidth( 1 ); // a nice 3D touch :-)
+ status->setText( "" ); // needed for initialization code!
+ status->enableDrops( true );
+ int sheight = QFontMetrics( status->font() ).height() + 4;
+ status->setMaximumHeight( sheight );
+ QWhatsThis::add
+ ( status, i18n( "The statusbar displays information about the FILESYSTEM "
+ "which holds your current directory: Total size, free space, "
+ "type of filesystem, etc." ) );
+ connect( status, SIGNAL( clicked() ), this, SLOT( slotFocusOnMe() ) );
+ connect( status, SIGNAL( dropped( QDropEvent *) ), this, SLOT( handleDropOnStatus(QDropEvent *) ) );
+
+ // ... create the history button
+ dirHistoryQueue = new DirHistoryQueue( this );
+ historyButton = new DirHistoryButton( dirHistoryQueue, this, "historyButton" );
+ connect( historyButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( historyButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+
+ bookmarksButton = new KrBookmarkButton(this);
+ connect( bookmarksButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( bookmarksButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+ QWhatsThis::add
+ ( bookmarksButton, i18n( "Open menu with bookmarks. You can also add "
+ "current location to the list, edit bookmarks "
+ "or add subfolder to the list." ) );
+
+ QHBoxLayout *totalsLayout = new QHBoxLayout;
+ totals = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ totals->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ totals->setFrameStyle( QFrame::Box | QFrame::Raised );
+ totals->setBackgroundMode( PaletteBackground );
+ totals->setLineWidth( 1 ); // a nice 3D touch :-)
+ totals->setMaximumHeight( sheight );
+ totals->enableDrops( true );
+ QWhatsThis::add
+ ( totals, i18n( "The totals bar shows how many files exist, "
+ "how many selected and the bytes math" ) );
+ connect( totals, SIGNAL( clicked() ), this, SLOT( slotFocusOnMe() ) );
+ connect( totals, SIGNAL( dropped( QDropEvent *) ), this, SLOT( handleDropOnTotals(QDropEvent *) ) );
+
+ // a cancel button for the inplace refresh mechanism
+ inlineRefreshCancelButton = new KPushButton(this);
+ inlineRefreshCancelButton->setFixedSize( 22, 20 );
+ inlineRefreshCancelButton->setPixmap(krLoader->loadIcon("cancel", KIcon::Toolbar, 16));
+ connect(inlineRefreshCancelButton, SIGNAL(clicked()), this, SLOT(inlineRefreshCancel()));
+
+ // a quick button to open the popup panel
+ popupBtn = new QToolButton( this, "popupbtn" );
+ popupBtn->setFixedSize( 22, 20 );
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", KIcon::Toolbar, 16));
+ connect(popupBtn, SIGNAL(clicked()), this, SLOT(togglePanelPopup()));
+ QToolTip::add( popupBtn, i18n( "Open the popup panel" ) );
+ totalsLayout->addWidget(totals);
+ totalsLayout->addWidget(inlineRefreshCancelButton); inlineRefreshCancelButton->hide();
+ totalsLayout->addWidget(popupBtn);
+
+ quickSearch = new KrQuickSearch( this );
+ krConfig->setGroup( "Look&Feel" );
+ quickSearch->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ quickSearch->setFrameStyle( QFrame::Box | QFrame::Raised );
+ quickSearch->setLineWidth( 1 ); // a nice 3D touch :-)
+ quickSearch->setMaximumHeight( sheight );
+
+ QHBox * hbox = new QHBox( this );
+
+ // clear-origin button
+ bool clearButton = krConfig->readBoolEntry("Clear Location Bar Visible", _ClearLocation);
+ if (clearButton){
+ clearOrigin = new QToolButton(hbox, "clearorigin");
+ clearOrigin->setPixmap(krLoader->loadIcon("locationbar_erase", KIcon::Toolbar, 16));
+ QToolTip::add( clearOrigin, i18n( "Clear the location bar" ) );
+ }
+
+ QuickNavLineEdit *qnle = new QuickNavLineEdit(this);
+ origin = new KURLRequester( qnle, hbox );
+ QPixmap pixMap = origin->button() ->iconSet() ->pixmap( QIconSet::Small, QIconSet::Normal );
+ origin->button() ->setFixedSize( pixMap.width() + 4, pixMap.height() + 4 );
+ QWhatsThis::add
+ ( origin, i18n( "Use superb KDE file dialog to choose location. " ) );
+ origin->setShowLocalProtocol( false );
+ origin->lineEdit() ->setURLDropsEnabled( true );
+ origin->lineEdit() ->installEventFilter( this );
+ QWhatsThis::add
+ ( origin->lineEdit(), i18n( "Name of directory where you are. You can also "
+ "enter name of desired location to move there. "
+ "Use of Net protocols like ftp or fish is possible." ) );
+ origin->setMode( KFile::Directory | KFile::ExistingOnly );
+ connect( origin, SIGNAL( returnPressed( const QString& ) ), func, SLOT( openUrl( const QString& ) ) );
+ connect( origin, SIGNAL( returnPressed( const QString& ) ), this, SLOT( slotFocusOnMe() ) );
+ connect( origin, SIGNAL( urlSelected( const QString& ) ), func, SLOT( openUrl( const QString& ) ) );
+ connect( origin, SIGNAL( urlSelected( const QString& ) ), this, SLOT( slotFocusOnMe() ) );
+
+ // this is here on purpose, do not move up!
+ if (clearButton) {
+ clearOrigin->setFixedSize( 20, origin->button() ->height() );
+ connect(clearOrigin, SIGNAL(clicked()), origin->lineEdit(), SLOT(clear()));
+ connect(clearOrigin, SIGNAL(clicked()), origin->lineEdit(), SLOT(setFocus()));
+ }
+ //
+
+ cdOtherButton = new QToolButton( hbox, "cdOtherButton" );
+ cdOtherButton->setFixedSize( 20, origin->button() ->height() );
+ cdOtherButton->setText( i18n( "=" ) );
+ QToolTip::add( cdOtherButton, i18n( "Equal" ) );
+ connect( cdOtherButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDOther() ) );
+
+ cdUpButton = new QToolButton( hbox, "cdUpButton" );
+ cdUpButton->setFixedSize( 20, origin->button() ->height() );
+ cdUpButton->setText( i18n( ".." ) );
+ QToolTip::add( cdUpButton, i18n( "Up" ) );
+ connect( cdUpButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDup() ) );
+
+ cdHomeButton = new QToolButton( hbox, "cdHomeButton" );
+ cdHomeButton->setFixedSize( 20, origin->button() ->height() );
+ cdHomeButton->setText( i18n( "~" ) );
+ QToolTip::add( cdHomeButton, i18n( "Home" ) );
+ connect( cdHomeButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDHome() ) );
+
+ cdRootButton = new QToolButton( hbox, "cdRootButton" );
+ cdRootButton->setFixedSize( 20, origin->button() ->height() );
+ cdRootButton->setText( i18n( "/" ) );
+ QToolTip::add( cdRootButton, i18n( "Root" ) );
+ connect( cdRootButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDRoot() ) );
+
+ // ... creates the button for sync-browsing
+ syncBrowseButton = new SyncBrowseButton( hbox );
+
+ setPanelToolbar();
+
+ header = new QHeader( this );
+ header->hide();
+
+ // create a splitter to hold the view and the popup
+ splt = new PercentalSplitter(this);
+ splt->setChildrenCollapsible(true);
+ splt->setOrientation(QObject::Vertical);
+
+ createView();
+
+ // make sure that a focus/path change reflects in the command line and activePanel
+ connect( this, SIGNAL( cmdLineUpdate( QString ) ), SLOTS, SLOT( slotCurrentChanged( QString ) ) );
+ connect( this, SIGNAL( activePanelChanged( ListPanel * ) ), SLOTS, SLOT( slotSetActivePanel( ListPanel * ) ) );
+
+ // add a popup
+ popup = new PanelPopup(splt, left);
+ connect(popup, SIGNAL(selection(const KURL&)), SLOTS, SLOT(refresh(const KURL&)));
+ connect(popup, SIGNAL(hideMe()), this, SLOT(togglePanelPopup()));
+ popup->hide();
+
+ // finish the layout
+ layout->addMultiCellWidget( hbox, 0, 0, 0, 3 );
+ layout->addWidget( mediaButton, 1, 0 );
+ layout->addWidget( status, 1, 1 );
+ layout->addWidget( historyButton, 1, 2 );
+ layout->addWidget( bookmarksButton, 1, 3 );
+ layout->addMultiCellWidget( header, 2, 2, 0, 3 );
+ layout->addMultiCellWidget( splt, 3, 3, 0, 3 );
+ layout->addMultiCellWidget( quickSearch, 4, 4, 0, 3 );
+ quickSearch->hide();
+ layout->addMultiCellLayout( totalsLayout, 5, 5, 0, 3 );
+ //filter = ALL;
+}
+
+void ListPanel::createView()
+{
+ header->hide();
+ if( panelType == "Brief" )
+ {
+ view = new KrBriefView( header, splt, _left, krConfig );
+ view->init();
+
+ connect( dynamic_cast<KrBriefView*>( view ), SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrBriefView*>( view ), SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, SLOT( updatePopupPanel( KrViewItem* ) ) );
+
+ // connect quicksearch
+ connect( quickSearch, SIGNAL( textChanged( const QString& ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( quickSearch( const QString& ) ) );
+ connect( quickSearch, SIGNAL( otherMatching( const QString&, int ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( quickSearch( const QString& , int ) ) );
+ connect( quickSearch, SIGNAL( stop( QKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( stopQuickSearch( QKeyEvent* ) ) );
+ connect( quickSearch, SIGNAL( process( QKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( handleQuickSearchEvent( QKeyEvent* ) ) );
+ } else { /* Detailed */
+ panelType = "Detailed";
+ view = new KrDetailedView( splt, _left, krConfig );
+ view->init();
+ connect( dynamic_cast<KrDetailedView*>( view ), SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrDetailedView*>( view ), SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, SLOT( updatePopupPanel( KrViewItem * ) ) );
+ // connect quicksearch
+ connect( quickSearch, SIGNAL( textChanged( const QString& ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( quickSearch( const QString& ) ) );
+ connect( quickSearch, SIGNAL( otherMatching( const QString&, int ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( quickSearch( const QString& , int ) ) );
+ connect( quickSearch, SIGNAL( stop( QKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( stopQuickSearch( QKeyEvent* ) ) );
+ connect( quickSearch, SIGNAL( process( QKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( handleQuickSearchEvent( QKeyEvent* ) ) );
+ }
+
+ connect( view->op(), SIGNAL( renameItem( const QString &, const QString & ) ),
+ func, SLOT( rename( const QString &, const QString & ) ) );
+ connect( view->op(), SIGNAL( executed( QString& ) ), func, SLOT( execute( QString& ) ) );
+ connect( view->op(), SIGNAL( needFocus() ), this, SLOT( slotFocusOnMe() ) );
+ connect( view->op(), SIGNAL( selectionChanged() ), this, SLOT( slotUpdateTotals() ) );
+ connect( view->op(), SIGNAL( itemDescription( QString& ) ), krApp, SLOT( statusBarUpdate( QString& ) ) );
+ connect( view->op(), SIGNAL( contextMenu( const QPoint & ) ), this, SLOT( popRightClickMenu( const QPoint & ) ) );
+ connect( view->op(), SIGNAL( emptyContextMenu( const QPoint &) ),
+ this, SLOT( popEmptyRightClickMenu( const QPoint & ) ) );
+ connect( view->op(), SIGNAL( letsDrag( QStringList, QPixmap ) ), this, SLOT( startDragging( QStringList, QPixmap ) ) );
+ connect( view->op(), SIGNAL( gotDrop( QDropEvent * ) ), this, SLOT( handleDropOnView( QDropEvent * ) ) );
+}
+
+void ListPanel::changeType( const QString & type )
+{
+ if( panelType != type )
+ {
+ panelType = type;
+ delete view;
+ createView();
+
+ slotStartUpdate();
+
+ if( panelType == "Brief" )
+ dynamic_cast<KrBriefView*>( view )->show();
+ else /* Detailed */
+ dynamic_cast<KrDetailedView*>( view )->show();
+ }
+}
+
+ListPanel::~ListPanel() {
+ delete func;
+ delete view;
+ delete status;
+ delete bookmarksButton;
+ delete totals;
+ delete quickSearch;
+ delete origin;
+ delete cdRootButton;
+ delete cdHomeButton;
+ delete cdUpButton;
+ delete cdOtherButton;
+ delete syncBrowseButton;
+ delete layout;
+}
+
+int ListPanel::getProperties()
+{
+ int props = 0;
+ if( syncBrowseButton->state() == SYNCBROWSE_CD )
+ props |= PROP_SYNC_BUTTON_ON;
+ return props;
+}
+
+void ListPanel::setProperties( int prop )
+{
+ if( prop & PROP_SYNC_BUTTON_ON )
+ syncBrowseButton->setOn( true );
+ else
+ syncBrowseButton->setOn( false );
+}
+
+bool ListPanel::eventFilter ( QObject * watched, QEvent * e ) {
+ if( e->type() == QEvent::KeyPress && origin->lineEdit() == watched ) {
+ QKeyEvent *ke = (QKeyEvent *)e;
+
+ if( ( ke->key() == Key_Down ) && ( ke->state() == ControlButton ) ) {
+ slotFocusOnMe();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void ListPanel::togglePanelPopup() {
+ if (popup->isHidden()) {
+ if (popupSizes.count() > 0) {
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(popupSizes);
+ } else { // on the first time, resize to 50%
+ QValueList<int> lst;
+ lst << height()/2 << height()/2;
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(lst);
+ }
+
+ popup->show();
+ popupBtn->setPixmap(krLoader->loadIcon("1downarrow", KIcon::Toolbar, 16));
+ QToolTip::add( popupBtn, i18n( "Close the popup panel" ) );
+ } else {
+ popupSizes.clear();
+ popupSizes = dynamic_cast<QSplitter*>(popup->parent())->sizes();
+ popup->hide();
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", KIcon::Toolbar, 16));
+ QToolTip::add( popupBtn, i18n( "Open the popup panel" ) );
+
+ QValueList<int> lst;
+ lst << height() << 0;
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(lst);
+ if( ACTIVE_PANEL )
+ ACTIVE_PANEL->slotFocusOnMe();
+ }
+}
+
+KURL ListPanel::virtualPath() const {
+ return func->files()->vfs_getOrigin();
+}
+
+QString ListPanel::realPath() const {
+ return _realPath.path();
+}
+
+
+void ListPanel::setPanelToolbar() {
+ krConfig->setGroup( "Look&Feel" );
+
+ bool panelToolBarVisible = krConfig->readBoolEntry( "Panel Toolbar visible", _PanelToolBar );
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Root Button Visible", _cdRoot ) ) )
+ cdRootButton->show();
+ else
+ cdRootButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Home Button Visible", _cdHome ) ) )
+ cdHomeButton->show();
+ else
+ cdHomeButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Up Button Visible", _cdUp ) ) )
+ cdUpButton->show();
+ else
+ cdUpButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Equal Button Visible", _cdOther ) ) )
+ cdOtherButton->show();
+ else
+ cdOtherButton->hide();
+
+ if ( !panelToolBarVisible || ( krConfig->readBoolEntry( "Open Button Visible", _Open ) ) )
+ origin->button() ->show();
+ else
+ origin->button() ->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "SyncBrowse Button Visible", _syncBrowseButton ) ) )
+ syncBrowseButton->show();
+ else
+ syncBrowseButton->hide();
+}
+
+void ListPanel::slotUpdateTotals() {
+ totals->setText( view->statistics() );
+}
+
+void ListPanel::slotFocusAndCDOther() {
+ slotFocusOnMe();
+ func->openUrl( otherPanel->func->files() ->vfs_getOrigin() );
+
+}
+
+void ListPanel::slotFocusAndCDHome() {
+ slotFocusOnMe();
+ func->openUrl( QString( "~" ), QString::null );
+}
+
+void ListPanel::slotFocusAndCDup() {
+ slotFocusOnMe();
+ func->dirUp();
+}
+
+void ListPanel::slotFocusAndCDRoot() {
+ slotFocusOnMe();
+ func->openUrl( QString( "/" ), QString::null );
+}
+
+void ListPanel::select( KRQuery query, bool select) {
+ if ( !query.isNull() ) {
+ if ( select )
+ view->select( query );
+ else
+ view->unselect( query );
+ }
+}
+
+void ListPanel::select( bool select, bool all ) {
+ if ( all )
+ {
+ if ( select )
+ view->select( KRQuery( "*" ) );
+ else
+ view->unselect( KRQuery( "*" ) );
+ }
+ else {
+ KRQuery query = KRSpWidgets::getMask( ( select ? i18n( " Select Files " ) : i18n( " Unselect Files " ) ) );
+ // if the user canceled - quit
+ if ( query.isNull() )
+ return ;
+ if ( select )
+ view->select( query );
+ else
+ view->unselect( query );
+ }
+}
+
+void ListPanel::invertSelection() {
+ view->invertSelection();
+}
+
+void ListPanel::compareDirs() {
+ krConfig->setGroup( "Private" );
+ int compareMode = krConfig->readNumEntry( "Compare Mode", 0 );
+ krConfig->setGroup( "Look&Feel" );
+ bool selectDirs = krConfig->readBoolEntry( "Mark Dirs", false );
+
+ KrViewItem *item, *otherItem;
+
+ for( item = view->getFirst(); item != 0; item = view->getNext( item ) )
+ {
+ if( item->name() == ".." )
+ continue;
+
+ for( otherItem = otherPanel->view->getFirst(); otherItem != 0 && otherItem->name() != item->name() ;
+ otherItem = otherPanel->view->getNext( otherItem ) );
+
+ bool isSingle = ( otherItem == 0 ), isDifferent = false, isNewer = false;
+
+ if( func->getVFile(item)->vfile_isDir() && !selectDirs )
+ {
+ item->setSelected( false );
+ continue;
+ }
+
+ if( otherItem )
+ {
+ if( !func->getVFile(item)->vfile_isDir() )
+ isDifferent = ITEM2VFILE(otherPanel,otherItem)->vfile_getSize() != func->getVFile(item)->vfile_getSize();
+ isNewer = func->getVFile(item)->vfile_getTime_t() > ITEM2VFILE(otherPanel, otherItem)->vfile_getTime_t();
+ }
+
+ switch( compareMode )
+ {
+ case 0:
+ item->setSelected( isNewer || isSingle );
+ break;
+ case 1:
+ item->setSelected( isNewer );
+ break;
+ case 2:
+ item->setSelected( isSingle );
+ break;
+ case 3:
+ item->setSelected( isDifferent || isSingle );
+ break;
+ case 4:
+ item->setSelected( isDifferent );
+ break;
+ }
+ }
+
+ view->updateView();
+}
+
+void ListPanel::slotFocusOnMe() {
+ // give this VFS the focus (the path bar)
+ // we start by calling the KVFS function
+ krConfig->setGroup( "Look&Feel" );
+
+ // take care of the 'otherpanel'
+ QPalette q( otherPanel->status->palette() );
+ q.setColor( QColorGroup::Foreground, KGlobalSettings::textColor() );
+ q.setColor( QColorGroup::Background, KGlobalSettings::baseColor() );
+
+ otherPanel->status->setPalette( q );
+ otherPanel->totals->setPalette( q );
+ otherPanel->view->prepareForPassive();
+
+ // now, take care of this panel
+ QPalette p( status->palette() );
+ p.setColor( QColorGroup::Foreground, KGlobalSettings::highlightedTextColor() );
+ p.setColor( QColorGroup::Background, KGlobalSettings::highlightColor() );
+ status->setPalette( p );
+ totals->setPalette( p );
+
+ view->prepareForActive();
+ emit cmdLineUpdate( realPath() );
+ emit activePanelChanged( this );
+
+ func->refreshActions();
+
+ Krusader::actDetailedView->setEnabled( panelType != "Detailed" ); // enable/disable the detailed view action
+ Krusader::actBriefView->setEnabled( panelType != "Brief" ); // enable/disable the brief view action
+
+ if( panelType == "Brief" )
+ {
+ KrBriefView * v = dynamic_cast<KrBriefView *>( view );
+ if ( v )
+ v->refreshColors();
+ }
+ else /* detailed */
+ {
+ KrDetailedView * v = dynamic_cast<KrDetailedView *>( view );
+ if ( v )
+ v->refreshColors();
+ }
+
+ if( otherPanel->panelType == "Brief" )
+ {
+ KrBriefView * v = dynamic_cast<KrBriefView *>( otherPanel->view );
+ if ( v )
+ v->refreshColors();
+ }
+ else /* detailed */
+ {
+ KrDetailedView *v = dynamic_cast<KrDetailedView *>( otherPanel->view );
+ if ( v )
+ v->refreshColors();
+ }
+}
+
+// this is used to start the panel, AFTER setOther() has been used
+//////////////////////////////////////////////////////////////////
+void ListPanel::start( KURL url, bool immediate ) {
+ KURL virt;
+
+ virt = url;
+
+ if ( !virt.isValid() )
+ virt = URL("/");
+ if( virt.isLocalFile() ) _realPath = virt;
+ else _realPath = URL("/");
+
+ if( immediate )
+ func->immediateOpenUrl( virt );
+ else
+ func->openUrl( virt );
+
+ slotFocusOnMe();
+ setJumpBack( virt );
+}
+
+void ListPanel::slotStartUpdate() {
+ while ( func->inRefresh )
+ ; // wait until the last refresh finish
+ func->inRefresh = true; // make sure the next refresh wait for this one
+ if (inlineRefreshJob)
+ inlineRefreshListResult(0);
+
+ if( this == ACTIVE_PANEL ){
+ slotFocusOnMe();
+ }
+
+ setCursor( KCursor::workingCursor() );
+ view->clear();
+
+ if ( func->files() ->vfs_getType() == vfs::NORMAL )
+ _realPath = virtualPath();
+ this->origin->setURL( vfs::pathOrURL( virtualPath() ) );
+ emit pathChanged( this );
+ emit cmdLineUpdate( realPath() ); // update the command line
+
+ slotGetStats( virtualPath() );
+ slotUpdate();
+ if ( compareMode ) {
+ otherPanel->view->clear();
+ otherPanel->slotUpdate();
+ }
+ // return cursor to normal arrow
+ setCursor( KCursor::arrowCursor() );
+ slotUpdateTotals();
+ krApp->popularUrls->addUrl(virtualPath());
+}
+
+void ListPanel::slotUpdate() {
+ // if we are not at the root add the ".." entery
+ QString protocol = func->files() ->vfs_getOrigin().protocol();
+ bool isFtp = ( protocol == "ftp" || protocol == "smb" || protocol == "sftp" || protocol == "fish" );
+
+ QString origin = virtualPath().prettyURL(-1);
+ if ( origin.right( 1 ) != "/" && !( ( func->files() ->vfs_getType() == vfs::FTP ) && isFtp &&
+ origin.find( '/', origin.find( ":/" ) + 3 ) == -1 ) ) {
+ view->addItems( func->files() );
+ } else
+ view->addItems( func->files(), false );
+
+ func->inRefresh = false;
+}
+
+
+void ListPanel::slotGetStats( const KURL& url ) {
+ if ( !url.isLocalFile() ) {
+ status->setText( i18n( "No space information on non-local filesystems" ) );
+ return ;
+ }
+
+ // check for special filesystems;
+ QString path = url.path(); // must be local url
+ if ( path.left(4) == "/dev") {
+ status->setText(i18n( "No space information on [dev]" ));
+ return;
+ }
+#if defined(BSD)
+ if ( path.left( 5 ) == "/procfs" ) { // /procfs is a special case - no volume information
+ status->setText(i18n( "No space information on [procfs]" ));
+ return;
+ }
+#else
+ if ( path.left( 5 ) == "/proc" ) { // /proc is a special case - no volume information
+ status->setText(i18n( "No space information on [proc]" ));
+ return;
+ }
+#endif
+
+ status->setText( i18n( "Mt.Man: working ..." ) );
+ statsAgent = KDiskFreeSp::findUsageInfo( path );
+ connect( statsAgent, SIGNAL( foundMountPoint( const QString &, unsigned long, unsigned long, unsigned long ) ),
+ this, SLOT( gotStats( const QString &, unsigned long, unsigned long, unsigned long ) ) );
+}
+
+void ListPanel::gotStats( const QString &mountPoint, unsigned long kBSize,
+ unsigned long, unsigned long kBAvail ) {
+ int perc = 0;
+ if (kBSize != 0) { // make sure that if totalsize==0, then perc=0
+ perc = (int)(((float)kBAvail / (float)kBSize)*100.0);
+ }
+ // mount point information - find it in the list first
+ KMountPoint::List lst = KMountPoint::currentMountPoints();
+ QString fstype = i18n("unknown");
+ for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) {
+ if ((*it)->mountPoint() == mountPoint) {
+ fstype = (*it)->mountType();
+ break;
+ }
+ }
+
+ QString stats = i18n( "%1 free out of %2 (%3%) on %4 [ (%5) ]" )
+ .arg( KIO::convertSizeFromKB( kBAvail ) )
+ .arg( KIO::convertSizeFromKB( kBSize ) ).arg( perc )
+ .arg( mountPoint ).arg( fstype );
+ status->setText( stats );
+}
+
+void ListPanel::handleDropOnTotals( QDropEvent *e ) {
+ handleDropOnView( e, totals );
+}
+
+void ListPanel::handleDropOnStatus( QDropEvent *e ) {
+ handleDropOnView( e, status );
+}
+
+void ListPanel::handleDropOnView( QDropEvent *e, QWidget *widget ) {
+ // if copyToPanel is true, then we call a simple vfs_addfiles
+ bool copyToDirInPanel = false;
+ bool dragFromOtherPanel = false;
+ bool dragFromThisPanel = false;
+ bool isWritable = func->files() ->vfs_isWritable();
+
+ vfs* tempFiles = func->files();
+ vfile *file;
+ KrViewItem *i = 0;
+ if( widget == 0 )
+ {
+ i = view->getKrViewItemAt( e->pos() );
+ widget = this;
+ }
+
+ if ( e->source() == otherPanel )
+ dragFromOtherPanel = true;
+ if ( e->source() == this )
+ dragFromThisPanel = true;
+
+ if ( i ) {
+ file = func->files() ->vfs_search( i->name() );
+
+ if ( !file ) { // trying to drop on the ".."
+ copyToDirInPanel = true;
+ } else {
+ if ( file->vfile_isDir() ) {
+ copyToDirInPanel = true;
+ isWritable = file->vfile_isWriteable();
+ if ( isWritable ) {
+ // keep the folder_open icon until we're finished, do it only
+ // if the folder is writeable, to avoid flicker
+ }
+ } else
+ if ( e->source() == this )
+ return ; // no dragging onto ourselves
+ }
+ } else // if dragged from this panel onto an empty spot in the panel...
+ if ( dragFromThisPanel ) { // leave!
+ e->ignore();
+ return ;
+ }
+
+ if ( !isWritable && getuid() != 0 ) {
+ e->ignore();
+ KMessageBox::sorry( 0, i18n( "Can't drop here, no write permissions." ) );
+ return ;
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // decode the data
+ KURL::List URLs;
+ if ( !KURLDrag::decode( e, URLs ) ) {
+ e->ignore(); // not for us to handle!
+ return ;
+ }
+
+ bool isLocal = true;
+ for( unsigned u = 0; u != URLs.count(); u++ )
+ if( !URLs[ u ].isLocalFile() ) {
+ isLocal = false;
+ break;
+ }
+
+ KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy;
+
+ // the KURL::List is finished, let's go
+ // --> display the COPY/MOVE/LINK menu
+ QPopupMenu popup( this );
+ popup.insertItem( i18n( "Copy Here" ), 1 );
+ if ( func->files() ->vfs_isWritable() )
+ popup.insertItem( i18n( "Move Here" ), 2 );
+ if ( func->files() ->vfs_getType() == vfs::NORMAL &&
+ isLocal )
+ popup.insertItem( i18n( "Link Here" ), 3 );
+ popup.insertItem( i18n( "Cancel" ), 4 );
+ QPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( tmp );
+ switch ( result ) {
+ case 1 :
+ mode = KIO::CopyJob::Copy;
+ break;
+ case 2 :
+ mode = KIO::CopyJob::Move;
+ break;
+ case 3 :
+ mode = KIO::CopyJob::Link;
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+
+ QString dir = "";
+ if ( copyToDirInPanel ) {
+ dir = i->name();
+ }
+ QWidget *notify = ( !e->source() ? 0 : e->source() );
+ tempFiles->vfs_addFiles( &URLs, mode, notify, dir );
+}
+
+void ListPanel::startDragging( QStringList names, QPixmap px ) {
+ KURL::List * urls = func->files() ->vfs_getFiles( &names );
+
+ if ( urls->isEmpty() ) { // avoid draging empty urls
+ delete urls;
+ return ;
+ }
+
+ KURLDrag *d = new KURLDrag(*urls, this);
+ d->setPixmap( px, QPoint( -7, 0 ) );
+ d->dragCopy();
+
+ delete urls; // free memory
+}
+
+// pops a right-click menu for items
+void ListPanel::popRightClickMenu( const QPoint &loc ) {
+ // run it, on the mouse location
+ int j = QFontMetrics( font() ).height() * 2;
+ KrPopupMenu::run(QPoint( loc.x() + 5, loc.y() + j ), this);
+}
+
+void ListPanel::popEmptyRightClickMenu( const QPoint &loc ) {
+ KrPopupMenu::run(loc, this);
+}
+
+void ListPanel::setFilter( KrViewProperties::FilterSpec f ) {
+ switch ( f ) {
+ case KrViewProperties::All :
+ //case KrView::EXEC:
+ break;
+ case KrViewProperties::Custom :
+ filterMask = KRSpWidgets::getMask( i18n( " Select Files " ) );
+ // if the user canceled - quit
+ if ( filterMask.isNull() )
+ return;
+ view->setFilterMask( filterMask );
+ break;
+ default:
+ return ;
+ }
+ view->setFilter( f ); // do that in any case
+ func->files()->vfs_invalidate();
+ func->refresh();
+}
+
+QString ListPanel::getCurrentName() {
+ QString name = view->getCurrentItem();
+ if ( name != ".." )
+ return name;
+ else
+ return QString::null;
+}
+
+void ListPanel::prepareToDelete() {
+ view->setNameToMakeCurrent( view->firstUnmarkedBelowCurrent() );
+}
+
+void ListPanel::keyPressEvent( QKeyEvent *e ) {
+ switch ( e->key() ) {
+ case Key_Enter :
+ case Key_Return :
+ if ( e->state() & ControlButton ) {
+ if (e->state() & AltButton) {
+ vfile *vf = func->files()->vfs_search(view->getCurrentKrViewItem()->name());
+ if (vf && vf->vfile_isDir()) SLOTS->newTab(vf->vfile_getUrl());
+ } else {
+ SLOTS->insertFileName( ( e->state() & ShiftButton ) != 0 );
+ }
+ } else e->ignore();
+ break;
+ case Key_Right :
+ case Key_Left :
+ if ( e->state() == ControlButton ) {
+ // user pressed CTRL+Right/Left - refresh other panel to the selected path if it's a
+ // directory otherwise as this one
+ if ( ( _left && e->key() == Key_Right ) || ( !_left && e->key() == Key_Left ) ) {
+ KURL newPath;
+ KrViewItem *it = view->getCurrentKrViewItem();
+
+ if( it->name() == ".." ) {
+ newPath = func->files()->vfs_getOrigin().upURL();
+ } else {
+ vfile *v = func->getVFile( it );
+ if ( v && v->vfile_isDir() && v->vfile_getName() != ".." ) {
+ newPath = v->vfile_getUrl();
+ } else {
+ newPath = func->files() ->vfs_getOrigin();
+ }
+ }
+ otherPanel->func->openUrl( newPath );
+ } else func->openUrl( otherPanel->func->files() ->vfs_getOrigin() );
+ return ;
+ } else
+ e->ignore();
+ break;
+
+ case Key_Down :
+ if ( e->state() == ControlButton ) { // give the keyboard focus to the command line
+ if ( MAIN_VIEW->cmdLine->isVisible() )
+ MAIN_VIEW->cmdLineFocus();
+ else
+ MAIN_VIEW->focusTerminalEmulator();
+ return ;
+ } else if ( e->state() == ( ControlButton | ShiftButton ) ) { // give the keyboard focus to TE
+ MAIN_VIEW->focusTerminalEmulator();
+ } else
+ e->ignore();
+ break;
+
+ case Key_Up :
+ if ( e->state() == ControlButton ) { // give the keyboard focus to the command line
+ origin->lineEdit()->setFocus();
+ return ;
+ } else
+ e->ignore();
+ break;
+
+ default:
+ // if we got this, it means that the view is not doing
+ // the quick search thing, so send the characters to the commandline, if normal key
+ if ( e->state() == NoButton )
+ MAIN_VIEW->cmdLine->addText( e->text() );
+
+ //e->ignore();
+ }
+}
+
+void ListPanel::slotItemAdded(vfile *vf) {
+ view->addItem(vf);
+}
+
+void ListPanel::slotItemDeleted(const QString& name) {
+ view->delItem(name);
+}
+
+void ListPanel::slotItemUpdated(vfile *vf) {
+ view->updateItem(vf);
+}
+
+void ListPanel::slotCleared() {
+ view->clear();
+}
+
+void ListPanel::showEvent( QShowEvent *e ) {
+ panelActive();
+ QWidget::showEvent(e);
+}
+
+void ListPanel::hideEvent( QHideEvent *e ) {
+ panelInactive();
+ QWidget::hideEvent(e);
+}
+
+void ListPanel::panelActive() {
+ // don't refresh when not active (ie: hidden, application isn't focussed ...)
+ func->files()->vfs_enableRefresh(true);
+}
+
+void ListPanel::panelInactive() {
+ func->files()->vfs_enableRefresh(false);
+}
+
+void ListPanel::slotJobStarted(KIO::Job* job) {
+ // disable the parts of the panel we don't want touched
+ //static_cast<KrDetailedView*>(view)->setEnabled(false);
+ status->setEnabled(false);
+ origin->setEnabled(false);
+ cdRootButton->setEnabled(false);
+ cdHomeButton->setEnabled(false);
+ cdUpButton->setEnabled(false);
+ cdOtherButton->setEnabled(false);
+ popupBtn->setEnabled(false);
+ popup->setEnabled(false);
+ bookmarksButton->setEnabled(false);
+ historyButton->setEnabled(false);
+ syncBrowseButton->setEnabled(false);
+
+ // connect to the job interface to provide in-panel refresh notification
+ connect( job, SIGNAL( infoMessage( KIO::Job*, const QString & ) ),
+ SLOT( inlineRefreshInfoMessage( KIO::Job*, const QString & ) ) );
+ connect( job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
+ SLOT( inlineRefreshPercent( KIO::Job*, unsigned long ) ) );
+ connect(job,SIGNAL(result(KIO::Job*)),
+ this,SLOT(inlineRefreshListResult(KIO::Job*)));
+ connect(job,SIGNAL(canceled(KIO::Job*)),
+ this,SLOT(inlineRefreshListResult(KIO::Job*)));
+
+ inlineRefreshJob = job;
+
+ totals->setText(i18n(">> Reading..."));
+ inlineRefreshCancelButton->show();
+}
+
+void ListPanel::inlineRefreshCancel() {
+ if (inlineRefreshJob) {
+ inlineRefreshJob->kill(false);
+ inlineRefreshJob = 0;
+ }
+}
+
+void ListPanel::inlineRefreshPercent( KIO::Job*, unsigned long perc) {
+ QString msg = QString(">> %1: %2 % complete...").arg(i18n("Reading")).arg(perc);
+ totals->setText(msg);
+}
+
+void ListPanel::inlineRefreshInfoMessage( KIO::Job*, const QString &msg ) {
+ totals->setText(">> " + i18n("Reading: ") + msg);
+}
+
+void ListPanel::inlineRefreshListResult(KIO::Job*) {
+ inlineRefreshJob = 0;
+ // reenable everything
+ //static_cast<KrDetailedView*>(view)->setEnabled(true);
+ status->setEnabled(true);
+ origin->setEnabled(true);
+ cdRootButton->setEnabled(true);
+ cdHomeButton->setEnabled(true);
+ cdUpButton->setEnabled(true);
+ cdOtherButton->setEnabled(true);
+ popupBtn->setEnabled(true);
+ popup->setEnabled(true);
+ bookmarksButton->setEnabled(true);
+ historyButton->setEnabled(true);
+ syncBrowseButton->setEnabled(true);
+
+ inlineRefreshCancelButton->hide();
+}
+
+void ListPanel::jumpBack() {
+ func->openUrl( _jumpBackURL );
+}
+
+void ListPanel::setJumpBack( KURL url ) {
+ _jumpBackURL = url;
+}
+
+#include "listpanel.moc"
diff --git a/krusader/Panel/listpanel.h b/krusader/Panel/listpanel.h
new file mode 100644
index 0000000..088fdfd
--- /dev/null
+++ b/krusader/Panel/listpanel.h
@@ -0,0 +1,211 @@
+/***************************************************************************
+ listpanel.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 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
+
+ H e a d e r 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. *
+* *
+***************************************************************************/
+
+
+#ifndef LISTPANEL_H
+#define LISTPANEL_H
+
+#include <kpropsdlg.h>
+#include <kfileitem.h>
+#include <kurl.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qtoolbutton.h>
+#include <qpopupmenu.h>
+#include <qdir.h>
+#include <qpixmapcache.h>
+#include <qiconset.h>
+#include <qptrstack.h>
+#include <qtextbrowser.h>
+#include <keditcl.h>
+#include <klineedit.h>
+#include <qguardedptr.h>
+#include "krview.h"
+#include "../Dialogs/krsqueezedtextlabel.h"
+
+// use our version of it, until kde fixes theirs
+#include "../MountMan/kdiskfreesp.h"
+
+#define PROP_SYNC_BUTTON_ON 1
+
+class vfs;
+class vfile;
+class KRdirWatch;
+class KrView;
+class KURLRequester;
+class BookmarksButton;
+class KrQuickSearch;
+class DirHistoryButton;
+class DirHistoryQueue;
+class MediaButton;
+class PanelPopup;
+class SyncBrowseButton;
+class KrBookmarkButton;
+class KPushButton;
+class ListPanelFunc;
+class QHeader;
+
+class ListPanel : public QWidget {
+ friend class ListPanelFunc;
+ Q_OBJECT
+public:
+ #define ITEM2VFILE(PANEL_PTR, KRVIEWITEM) PANEL_PTR->func->files()->vfs_search(KRVIEWITEM->name())
+ #define NAME2VFILE(PANEL_PTR, STRING_NAME) PANEL_PTR->func->files()->vfs_search(STRING_NAME)
+ // constructor create the panel, but DOESN'T fill it with data, use start()
+ ListPanel( QString panelType, QWidget *parent, bool &left, const char *name = 0 );
+ ~ListPanel();
+ void start( KURL url = KURL(), bool immediate = false );
+
+ const QString & getType() { return panelType; }
+ void changeType( const QString & );
+
+ KURL virtualPath() const;
+ QString realPath() const;
+ QString getCurrentName();
+ void getSelectedNames( QStringList* fileNames ) {
+ view->getSelectedItems( fileNames );
+ }
+ void setPanelToolbar();
+ bool isLeft() {return _left;}
+ void jumpBack();
+ void setJumpBack( KURL url );
+
+ int getProperties();
+ void setProperties( int );
+
+public slots:
+ void gotStats( const QString &mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail); // displays filesystem status
+ void popRightClickMenu( const QPoint& );
+ void popEmptyRightClickMenu( const QPoint & );
+ void select( KRQuery query, bool select);
+ void select( bool, bool ); // see doc in ListPanel
+ void invertSelection(); // see doc in ListPanel
+ void compareDirs();
+ void slotFocusOnMe(); // give this VFS the focus (the path bar)
+ void slotUpdate(); // when the vfs finish to update...
+ void slotUpdateTotals();
+ void slotStartUpdate(); // internal
+ void slotGetStats( const KURL& url ); // get the disk-free stats
+ void setFilter( KrViewProperties::FilterSpec f );
+ void slotFocusAndCDRoot();
+ void slotFocusAndCDHome();
+ void slotFocusAndCDup();
+ void slotFocusAndCDOther();
+ void togglePanelPopup();
+ // for signals from vfs' dirwatch
+ void slotItemAdded(vfile *vf);
+ void slotItemDeleted(const QString& name);
+ void slotItemUpdated(vfile *vf);
+ void slotCleared();
+ void panelActive(); // called when the panel becomes active
+ void panelInactive(); // called when panel becomes inactive
+
+
+ ///////////////////////// service functions - called internally ////////////////////////
+ inline void setOther( ListPanel *panel ) {
+ otherPanel = panel;
+ }
+ void prepareToDelete(); // internal use only
+
+protected:
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void showEvent( QShowEvent * );
+ virtual void hideEvent( QHideEvent * );
+ virtual bool eventFilter ( QObject * watched, QEvent * e );
+
+ void createView();
+
+protected slots:
+ void handleDropOnView(QDropEvent *, QWidget *destWidget=0); // handles drops on the view only
+ void handleDropOnTotals( QDropEvent * ); // handles drops on the totals line
+ void handleDropOnStatus( QDropEvent * ); // handles drops on the status line
+ void startDragging( QStringList, QPixmap );
+ // those handle the in-panel refresh notifications
+ void slotJobStarted(KIO::Job* job);
+ void inlineRefreshInfoMessage( KIO::Job* job, const QString &msg );
+ void inlineRefreshListResult(KIO::Job* job);
+ void inlineRefreshPercent( KIO::Job*, unsigned long );
+ void inlineRefreshCancel();
+
+signals:
+ void signalStatus( QString msg ); // emmited when we need to update the status bar
+ void cmdLineUpdate( QString p ); // emitted when we need to update the command line
+ void pathChanged( ListPanel *panel );
+ void activePanelChanged( ListPanel *p ); // emitted when the user changes panels
+ void finishedDragging(); // currently
+
+public:
+ QString panelType;
+ ListPanelFunc *func;
+ KrView *view;
+ ListPanel *otherPanel;
+ int colorMask;
+ bool compareMode;
+ //FilterSpec filter;
+ KRQuery filterMask;
+ QPixmap currDragPix;
+ QListViewItem *currDragItem;
+ KDiskFreeSp* statsAgent;
+ KrSqueezedTextLabel *status, *totals;
+ KrQuickSearch *quickSearch;
+ KURLRequester *origin;
+ QGridLayout *layout;
+ QToolButton *cdRootButton;
+ QToolButton *cdHomeButton;
+ QToolButton *cdUpButton;
+ QToolButton *cdOtherButton;
+ QToolButton *popupBtn;
+ QToolButton *clearOrigin;
+ PanelPopup *popup;
+ KrBookmarkButton *bookmarksButton;
+ DirHistoryQueue* dirHistoryQueue;
+ DirHistoryButton* historyButton;
+ MediaButton *mediaButton;
+ SyncBrowseButton *syncBrowseButton;
+ KPushButton *inlineRefreshCancelButton;
+ KIO::Job *inlineRefreshJob;
+ QSplitter *splt;
+ QHeader * header;
+
+protected:
+ KURL _realPath; // named with _ to keep realPath() compatability
+ KURL _jumpBackURL;
+
+
+private:
+ bool &_left;
+ QValueList<int> popupSizes;
+};
+
+#endif
diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp
new file mode 100755
index 0000000..735a0cf
--- /dev/null
+++ b/krusader/Panel/panelfunc.cpp
@@ -0,0 +1,1186 @@
+/***************************************************************************
+ panelfunc.cpp
+ -------------------
+copyright : (C) 2000 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 <unistd.h>
+// Qt Includes
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qeventloop.h>
+#include <qclipboard.h>
+// KDE Includes
+#include <klocale.h>
+#include <kprocess.h>
+#include <kpropertiesdialog.h>
+#include <kopenwith.h>
+#include <kmessagebox.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kurl.h>
+#include <krun.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <ktempdir.h>
+#include <kurlrequester.h>
+#include <kprocio.h>
+#include <kdesktopfile.h>
+// Krusader Includes
+#include "panelfunc.h"
+#include "krcalcspacedialog.h"
+#include "krdetailedview.h"
+#include "../krusader.h"
+#include "../krslots.h"
+#include "../defaults.h"
+#include "../VFS/vfile.h"
+#include "../VFS/vfs.h"
+#include "../VFS/virt_vfs.h"
+#include "../VFS/krarchandler.h"
+#include "../VFS/krpermhandler.h"
+#include "../VFS/krvfshandler.h"
+#include "../VFS/preservingcopyjob.h"
+#include "../VFS/virtualcopyjob.h"
+#include "../Dialogs/packgui.h"
+#include "../Dialogs/krdialogs.h"
+#include "../Dialogs/krpleasewait.h"
+#include "../Dialogs/krspwidgets.h"
+#include "../Dialogs/checksumdlg.h"
+#include "../KViewer/krviewer.h"
+#include "../resources.h"
+#include "../krservices.h"
+#include "../GUI/syncbrowsebutton.h"
+#include "../Queue/queue_mgr.h"
+#include "krdrag.h"
+#include <kurldrag.h>
+
+//////////////////////////////////////////////////////////
+////// ---------- List Panel ------------- ////////
+//////////////////////////////////////////////////////////
+
+ListPanelFunc::ListPanelFunc( ListPanel *parent ) :
+panel( parent ), inRefresh( false ), vfsP( 0 ) {
+ urlStack.push( "file:/" );
+ connect( &delayTimer, SIGNAL( timeout() ), this, SLOT( doOpenUrl() ) );
+}
+
+void ListPanelFunc::openUrl( const QString& url, const QString& nameToMakeCurrent ) {
+ openUrl( vfs::fromPathOrURL(
+ // KURLRequester is buggy: it should return a string containing "/home/shie/downloads"
+ // but it returns "~/downloads" which is parsed incorrectly by vfs::fromPathOrURL.
+ // replacedPath should replace ONLY $HOME and environment variables
+ panel->origin->completionObject()->replacedPath(url) )
+ , nameToMakeCurrent );
+}
+
+void ListPanelFunc::immediateOpenUrl( const KURL& urlIn ) {
+ KURL url = urlIn;
+ url.cleanPath();
+
+ // check for special cases first - don't refresh here !
+ // you may call openUrl or vfs_refresh()
+ if ( !url.isValid() ) {
+ if ( url.url() == "~" ) {
+ return openUrl( QDir::homeDirPath() );
+ } else if ( !url.url().startsWith( "/" ) ) {
+ // possible relative URL - translate to full URL
+ url = files() ->vfs_getOrigin();
+ url.addPath( urlIn.url() );
+ //kdDebug()<< urlIn.url() << "," << url.url() <<endl;
+ } else {
+ panel->slotStartUpdate(); // refresh the panel
+ return ;
+ }
+ }
+
+ // if we are not refreshing to current URL
+ bool is_equal_url = files() ->vfs_getOrigin().equals( url, true );
+
+ if ( !is_equal_url ) {
+ // change the cursor to busy
+ panel->setCursor( KCursor::waitCursor() );
+ }
+
+ if ( !nameToMakeCurrent.isEmpty() ) {
+ panel->view->setNameToMakeCurrent( nameToMakeCurrent );
+ // if the url we're refreshing into is the current one, then the
+ // partial url will not generate the needed signals to actually allow the
+ // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch)
+ if ( is_equal_url ) {
+ panel->view->setCurrentItem( nameToMakeCurrent );
+ panel->view->makeItemVisible( panel->view->getCurrentKrViewItem() );
+ }
+ }
+
+ vfs* v = 0;
+ if ( !urlStack.top().equals( url ) )
+ urlStack.push( url );
+ // count home many urls is in the stack, so later on, we'll know if the refresh was a success
+ uint stackSize = urlStack.size();
+ bool refreshFailed = true; // assume the worst
+ while ( true ) {
+ KURL u = urlStack.pop();
+ //u.adjustPath(-1); // remove trailing "/"
+ u.cleanPath(); // Resolves "." and ".." components in path.
+ v = KrVfsHandler::getVfs( u, panel, files() );
+ if ( !v )
+ continue; //this should not happen !
+ if ( v != vfsP ) {
+ if( vfsP->vfs_canDelete() )
+ delete vfsP;
+ else {
+ connect( vfsP, SIGNAL( deleteAllowed() ), vfsP, SLOT( deleteLater() ) );
+ vfsP->vfs_requestDelete();
+ }
+ vfsP = v; // v != 0 so this is safe
+ } else {
+ if( vfsP->vfs_isBusy() )
+ {
+ delayURL = url; /* this function is useful for FTP url-s and bookmarks */
+ delayTimer.start( 100, true ); /* if vfs is busy try refreshing later */
+ return;
+ }
+ }
+ connect( files(), SIGNAL(startJob(KIO::Job* )),
+ panel, SLOT(slotJobStarted(KIO::Job* )));
+ if ( vfsP->vfs_refresh( u ) ) {
+ break; // we have a valid refreshed URL now
+ }
+ if ( vfsP == 0 ) // the object was deleted during vfs_refresh? Hoping the best...
+ return;
+ // prevent repeated error messages
+ if ( vfsP->vfs_isDeleting() )
+ break;
+ vfsP->vfs_setQuiet( true );
+ }
+ vfsP->vfs_setQuiet( false );
+
+ // if we popped exactly 1 url from the stack, it means the url we were
+ // given was refreshed successfully.
+ if (stackSize == urlStack.size() + 1)
+ refreshFailed = false;
+
+ // update the urls stack
+ if ( !files() ->vfs_getOrigin().equals( urlStack.top() ) ) {
+ urlStack.push( files() ->vfs_getOrigin() );
+ }
+ // disconnect older signals
+ disconnect( files(), SIGNAL( addedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), SIGNAL( updatedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), SIGNAL( deletedVfile( const QString& ) ), 0, 0 );
+ disconnect( files(), SIGNAL( cleared() ), 0, 0 );
+ // connect to the vfs's dirwatch signals
+ connect( files(), SIGNAL( addedVfile( vfile* ) ),
+ panel, SLOT( slotItemAdded( vfile* ) ) );
+ connect( files(), SIGNAL( updatedVfile( vfile* ) ),
+ panel, SLOT( slotItemUpdated( vfile* ) ) );
+ connect( files(), SIGNAL( deletedVfile( const QString& ) ),
+ panel, SLOT( slotItemDeleted( const QString& ) ) );
+ connect( files(), SIGNAL( cleared() ),
+ panel, SLOT( slotCleared() ) );
+
+ // on local file system change the working directory
+ if ( files() ->vfs_getType() == vfs::NORMAL )
+ chdir( files() ->vfs_getOrigin().path().local8Bit() );
+
+ // see if the open url operation failed, and if so,
+ // put the attempted url in the origin bar and let the user change it
+ if (refreshFailed) {
+ panel->origin->setURL(urlIn.prettyURL());
+ panel->origin->setFocus();
+ }
+}
+
+void ListPanelFunc::openUrl( const KURL& url, const QString& nameToMakeCurrent ) {
+ panel->inlineRefreshCancel();
+ // first the other dir, then the active! Else the focus changes and the other becomes active
+ if ( panel->syncBrowseButton->state() == SYNCBROWSE_CD ) {
+ // prevents that the sync-browsing circles itself to death
+ static bool inSync = false;
+ if( ! inSync ){
+ inSync = true;
+ //do sync-browse stuff....
+ KURL otherDir = OTHER_PANEL->virtualPath();
+ OTHER_FUNC->files() ->vfs_setQuiet( true );
+ // the trailing slash is nessesary because krusader provides Dir's without it
+ // we can't use openUrl because the delay don't allow a check if the panel has realy changed!
+ OTHER_FUNC->immediateOpenUrl( KURL::relativeURL( panel->virtualPath().url() + "/", url.url() ) );
+ OTHER_FUNC->files() ->vfs_setQuiet( false );
+ // now we need to test ACTIVE_PANEL because the openURL has changed the active panel!!
+ if ( ACTIVE_PANEL->virtualPath().equals( otherDir ) ) {
+ // deactivating the sync-browse if syncbrowse not possible
+ panel->syncBrowseButton->setOn( false );
+ }
+ inSync = false;
+ }
+ }
+ this->nameToMakeCurrent = nameToMakeCurrent;
+ delayURL = url; /* this function is useful for FTP url-s and bookmarks */
+ delayTimer.start( 0, true ); /* to avoid qApp->processEvents() deadlock situaltion */
+}
+
+void ListPanelFunc::refresh() {
+ openUrl(panel->virtualPath()); // re-read the files
+}
+
+void ListPanelFunc::doOpenUrl() {
+ immediateOpenUrl( delayURL );
+}
+
+void ListPanelFunc::goBack() {
+ if ( urlStack.isEmpty() )
+ return ;
+
+ if ( urlStack.top().equals( files() ->vfs_getOrigin() ) )
+ urlStack.pop();
+ openUrl( urlStack.top(), files() ->vfs_getOrigin().fileName() );
+
+ if ( urlStack.isEmpty() )
+ krBack->setEnabled( false );
+}
+
+void ListPanelFunc::redirectLink() {
+ if ( files() ->vfs_getType() != vfs::NORMAL ) {
+ KMessageBox::sorry( krApp, i18n( "You can edit links only on local file systems" ) );
+ return ;
+ }
+
+ vfile *vf = files() ->vfs_search( panel->getCurrentName() );
+ if ( !vf )
+ return ;
+
+ QString file = files() ->vfs_getFile( vf->vfile_getName() ).path( -1 );
+ QString currentLink = vf->vfile_getSymDest();
+ if ( currentLink.isEmpty() ) {
+ KMessageBox::sorry( krApp, i18n( "The current file is not a link, so I can't redirect it." ) );
+ return ;
+ }
+
+ // ask the user for a new destination
+ bool ok = false;
+ QString newLink =
+ KInputDialog::getText( i18n( "Link Redirection" ),
+ i18n( "Please enter the new link destination:" ), currentLink, &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || newLink == currentLink )
+ return ;
+ // delete the current link
+ if ( unlink( file.local8Bit() ) == -1 ) {
+ KMessageBox::sorry( krApp, i18n( "Can't remove old link: " ) + file );
+ return ;
+ }
+ // try to create a new symlink
+ if ( symlink( newLink.local8Bit(), file.local8Bit() ) == -1 ) {
+ KMessageBox:: /* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */sorry( krApp, i18n( "Failed to create a new link: " ) + file );
+ return ;
+ }
+}
+
+void ListPanelFunc::krlink( bool sym ) {
+ if ( files() ->vfs_getType() != vfs::NORMAL ) {
+ KMessageBox::sorry( krApp, i18n( "You can create links only on local file systems" ) );
+ return ;
+ }
+
+ QString name = panel->getCurrentName();
+
+ // ask the new link name..
+ bool ok = false;
+ QString linkName =
+ KInputDialog::getText( i18n( "New link" ), i18n( "Create a new link to: " ) + name, name, &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || linkName == name )
+ return ;
+
+ // if the name is already taken - quit
+ if ( files() ->vfs_search( linkName ) != 0 ) {
+ KMessageBox::sorry( krApp, i18n( "A directory or a file with this name already exists." ) );
+ return ;
+ }
+
+ if ( linkName.left( 1 ) != "/" )
+ linkName = files() ->vfs_workingDir() + "/" + linkName;
+
+ if ( linkName.contains( "/" ) )
+ name = files() ->vfs_getFile( name ).path( -1 );
+
+ if ( sym ) {
+ if ( symlink( name.local8Bit(), linkName.local8Bit() ) == -1 )
+ KMessageBox::sorry( krApp, i18n( "Failed to create a new symlink: " ) + linkName +
+ i18n( " To: " ) + name );
+ } else {
+ if ( link( name.local8Bit(), linkName.local8Bit() ) == -1 )
+ KMessageBox::sorry( krApp, i18n( "Failed to create a new link: " ) + linkName +
+ i18n( " To: " ) + name );
+ }
+}
+
+void ListPanelFunc::view() {
+ QString fileName = panel->getCurrentName();
+ if ( fileName.isNull() )
+ return ;
+
+ // if we're trying to view a directory, just exit
+ vfile * vf = files() ->vfs_search( fileName );
+ if ( !vf || vf->vfile_isDir() )
+ return ;
+ if ( !vf->vfile_isReadable() ) {
+ KMessageBox::sorry( 0, i18n( "No permissions to view this file." ) );
+ return ;
+ }
+ // call KViewer.
+ KrViewer::view( files() ->vfs_getFile( fileName ) );
+ // nothing more to it!
+}
+
+void ListPanelFunc::terminal() {
+ QString save = getcwd( 0, 0 );
+ chdir( panel->realPath().local8Bit() );
+
+ KProcess proc;
+ krConfig->setGroup( "General" );
+ QString term = krConfig->readEntry( "Terminal", _Terminal );
+ proc << KrServices::separateArgs( term );
+
+ if ( term.contains( "konsole" ) ) /* KDE 3.2 bug (konsole is killed by pressing Ctrl+C) */
+ { /* Please remove the patch if the bug is corrected */
+ proc << "&";
+ proc.setUseShell( true );
+ }
+
+ if ( !proc.start( KProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "<qt>Can't open <b>%1</b></qt>" ).arg(term) );
+
+ chdir( save.local8Bit() );
+}
+
+void ListPanelFunc::editFile() {
+ QString name = panel->getCurrentName();
+ if ( name.isNull() )
+ return ;
+
+ if ( files() ->vfs_search( name ) ->vfile_isDir() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't edit a directory" ) );
+ return ;
+ }
+
+ if ( !files() ->vfs_search( name ) ->vfile_isReadable() ) {
+ KMessageBox::sorry( 0, i18n( "No permissions to edit this file." ) );
+ return ;
+ }
+
+ KrViewer::edit( files() ->vfs_getFile( name ) );
+}
+
+void ListPanelFunc::moveFiles() {
+ PreserveMode pmode = PM_DEFAULT;
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL dest = panel->otherPanel->virtualPath();
+ KURL virtualBaseURL;
+
+ QString destProtocol = dest.protocol();
+ if ( destProtocol == "krarc" || destProtocol == "tar" || destProtocol == "zip" ) {
+ KMessageBox::sorry( krApp, i18n( "Moving into archive is disabled" ) );
+ return ;
+ }
+
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Move", _ConfirmMove ) ) {
+ bool preserveAttrs = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ QString s;
+
+ if( fileNames.count() == 1 )
+ s = i18n("Move %1 to:").arg(fileNames.first());
+ else
+ s = i18n("Move %n file to:", "Move %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ virtualBaseURL = getVirtualBaseURL();
+ dest = KChooseDir::getDir(s, dest, panel->virtualPath(), preserveAttrs, virtualBaseURL);
+ if ( dest.isEmpty() ) return ; // the user canceled
+ if( preserveAttrs )
+ pmode = PM_PRESERVE_ATTR;
+ else
+ pmode = PM_NONE;
+ }
+
+ if ( fileNames.isEmpty() )
+ return ; // nothing to copy
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+
+ // after the delete return the cursor to the first unmarked
+ // file above the current item;
+ panel->prepareToDelete();
+
+ if( !virtualBaseURL.isEmpty() ) {
+ // keep the directory structure for virtual paths
+ VirtualCopyJob *vjob = new VirtualCopyJob( &fileNames, files(), dest, virtualBaseURL, pmode, KIO::CopyJob::Move, false, true );
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+ }
+ // if we are not moving to the other panel :
+ else if ( !dest.equals( panel->otherPanel->virtualPath(), true ) ) {
+ // you can rename only *one* file not a batch,
+ // so a batch dest must alwayes be a directory
+ if ( fileNames.count() > 1 ) dest.adjustPath(1);
+ KIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, KIO::CopyJob::Move, false, true );
+ job->setAutoErrorHandlingEnabled( true );
+ // refresh our panel when done
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ // and if needed the other panel as well
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( job, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+
+ } else { // let the other panel do the dirty job
+ //check if copy is supported
+ if ( !otherFunc() ->files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't move files to this file system" ) );
+ return ;
+ }
+ // finally..
+ otherFunc() ->files() ->vfs_addFiles( fileUrls, KIO::CopyJob::Move, files(), "", pmode );
+ }
+}
+
+// called from SLOTS to begin the renaming process
+void ListPanelFunc::rename() {
+ panel->view->renameCurrentItem();
+}
+
+// called by signal itemRenamed() from the view to complete the renaming process
+void ListPanelFunc::rename( const QString &oldname, const QString &newname ) {
+ if ( oldname == newname )
+ return ; // do nothing
+ panel->view->setNameToMakeCurrentIfAdded( newname );
+ // as always - the vfs do the job
+ files() ->vfs_rename( oldname, newname );
+}
+
+void ListPanelFunc::mkdir() {
+ // ask the new dir name..
+ bool ok = false;
+ QString dirName =
+ KInputDialog::getText( i18n( "New directory" ), i18n( "Directory's name:" ), "", &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || dirName.isEmpty() )
+ return ;
+
+ QStringList dirTree = QStringList::split( "/", dirName );
+
+ for ( QStringList::Iterator it = dirTree.begin(); it != dirTree.end(); ++it ) {
+ // check if the name is already taken
+ if ( files() ->vfs_search( *it ) ) {
+ // if it is the last dir to be created - quit
+ if ( *it == dirTree.last() ) {
+ KMessageBox::sorry( krApp, i18n( "A directory or a file with this name already exists." ) );
+ return ;
+ }
+ // else go into this dir
+ else {
+ immediateOpenUrl( *it );
+ continue;
+ }
+ }
+
+ panel->view->setNameToMakeCurrent( *it );
+ // as always - the vfs do the job
+ files() ->vfs_mkdir( *it );
+ if ( dirTree.count() > 1 )
+ immediateOpenUrl( *it );
+ } // for
+}
+
+KURL ListPanelFunc::getVirtualBaseURL() {
+ if( files()->vfs_getType() != vfs::VIRT || otherFunc()->files()->vfs_getType() == vfs::VIRT )
+ return KURL();
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+ if( fileUrls->count() == 0 )
+ return KURL();
+
+ KURL base = (*fileUrls)[ 0 ].upURL();
+
+ if( base.protocol() == "virt" ) // is it a virtual subfolder?
+ return KURL(); // --> cannot keep the directory structure
+
+ for( unsigned i=1; i < fileUrls->count(); i++ ) {
+ if( base.isParentOf( (*fileUrls)[ i ] ) )
+ continue;
+ if( base.protocol() != (*fileUrls)[ i ].protocol() )
+ return KURL();
+
+ do {
+ KURL oldBase = base;
+ base = base.upURL();
+ if( oldBase.equals( base, true ) )
+ return KURL();
+ if( base.isParentOf( (*fileUrls)[ i ] ) )
+ break;
+ }while( true );
+ }
+ return base;
+}
+
+void ListPanelFunc::copyFiles() {
+ PreserveMode pmode = PM_DEFAULT;
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL dest = panel->otherPanel->virtualPath();
+ KURL virtualBaseURL;
+
+ // confirm copy
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Copy", _ConfirmCopy ) ) {
+ bool preserveAttrs = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ QString s;
+
+ if( fileNames.count() == 1 )
+ s = i18n("Copy %1 to:").arg(fileNames.first());
+ else
+ s = i18n("Copy %n file to:", "Copy %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ virtualBaseURL = getVirtualBaseURL();
+ dest = KChooseDir::getDir(s, dest, panel->virtualPath(), preserveAttrs, virtualBaseURL );
+ if ( dest.isEmpty() ) return ; // the user canceled
+ if( preserveAttrs )
+ pmode = PM_PRESERVE_ATTR;
+ else
+ pmode = PM_NONE;
+ }
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+
+ if( !virtualBaseURL.isEmpty() ) {
+ // keep the directory structure for virtual paths
+ VirtualCopyJob *vjob = new VirtualCopyJob( &fileNames, files(), dest, virtualBaseURL, pmode, KIO::CopyJob::Copy, false, true );
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+ }
+ // if we are not copying to the other panel :
+ else if ( !dest.equals( panel->otherPanel->virtualPath(), true ) ) {
+ // you can rename only *one* file not a batch,
+ // so a batch dest must alwayes be a directory
+ if ( fileNames.count() > 1 ) dest.adjustPath(1);
+ KIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, KIO::CopyJob::Copy, false, true );
+ job->setAutoErrorHandlingEnabled( true );
+ if ( dest.equals( panel->virtualPath(), true ) ||
+ dest.upURL().equals( panel->virtualPath(), true ) )
+ // refresh our panel when done
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ // let the other panel do the dirty job
+ } else {
+ //check if copy is supported
+ if ( !otherFunc() ->files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't copy files to this file system" ) );
+ return ;
+ }
+ // finally..
+ otherFunc() ->files() ->vfs_addFiles( fileUrls, KIO::CopyJob::Copy, 0, "", pmode );
+ }
+}
+
+void ListPanelFunc::deleteFiles(bool reallyDelete) {
+ // check that the you have write perm
+ if ( !files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You do not have write permission to this directory" ) );
+ return ;
+ }
+
+ // first get the selected file names list
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ;
+
+ krConfig->setGroup( "General" );
+ bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
+ // now ask the user if he want to delete:
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Delete", _ConfirmDelete ) ) {
+ QString s, b;
+
+ if ( !reallyDelete && trash && files() ->vfs_getType() == vfs::NORMAL ) {
+ s = i18n( "Do you really want to move this item to the trash?", "Do you really want to move these %n items to the trash?", fileNames.count() );
+ b = i18n( "&Trash" );
+ } else if( files() ->vfs_getType() == vfs::VIRT && files()->vfs_getOrigin().equals( KURL("virt:/"), true ) ) {
+ s = i18n( "Do you really want to delete this virtual item (physical files stay untouched)?", "Do you really want to delete these virtual items (physical files stay untouched)?", fileNames.count() );
+ b = i18n( "&Delete" );
+ } else if( files() ->vfs_getType() == vfs::VIRT ) {
+ s = i18n( "<qt>Do you really want to delete this item <b>physically</b> (not just removing it from the virtual items)?</qt>", "<qt>Do you really want to delete these %n items <b>physically</b> (not just removing them from the virtual items)?</qt>", fileNames.count() );
+ b = i18n( "&Delete" );
+ } else {
+ s = i18n( "Do you really want to delete this item?", "Do you really want to delete these %n items?", fileNames.count() );
+ b = i18n( "&Delete" );
+ }
+
+ // show message
+ // note: i'm using continue and not yes/no because the yes/no has cancel as default button
+ if ( KMessageBox::warningContinueCancelList( krApp, s, fileNames,
+ i18n( "Warning" ), b ) != KMessageBox::Continue )
+ return ;
+ }
+ //we want to warn the user about non empty dir
+ // and files he don't have permission to delete
+ krConfig->setGroup( "Advanced" );
+ bool emptyDirVerify = krConfig->readBoolEntry( "Confirm Unempty Dir", _ConfirmUnemptyDir );
+ emptyDirVerify = ( ( emptyDirVerify ) && ( files() ->vfs_getType() == vfs::NORMAL ) );
+
+ QDir dir;
+ for ( QStringList::Iterator name = fileNames.begin(); name != fileNames.end(); ) {
+ vfile * vf = files() ->vfs_search( *name );
+
+ // verify non-empty dirs delete... (only for normal vfs)
+ if ( emptyDirVerify && vf->vfile_isDir() && !vf->vfile_isSymLink() ) {
+ dir.setPath( panel->virtualPath().path() + "/" + ( *name ) );
+ if ( dir.entryList(QDir::All | QDir::System | QDir::Hidden ).count() > 2 ) {
+ switch ( KMessageBox::warningYesNoCancel( krApp,
+ i18n( "<qt><p>Directory <b>%1</b> is not empty!</p><p>Skip this one or Delete All?</p></qt>" ).arg(*name),
+ QString::null, i18n( "&Skip" ), i18n( "&Delete All" ) ) ) {
+ case KMessageBox::Cancel :
+ return ;
+ case KMessageBox::No :
+ emptyDirVerify = false;
+ break;
+ case KMessageBox::Yes :
+ name = fileNames.remove( name );
+ continue;
+ }
+ }
+ }
+ ++name;
+ }
+
+ if ( fileNames.count() == 0 )
+ return ; // nothing to delete
+
+ // after the delete return the cursor to the first unmarked
+ // file above the current item;
+ panel->prepareToDelete();
+
+ // let the vfs do the job...
+ if (reallyDelete) {
+ // if reallyDelete, then make sure nothing gets moved to trash
+ krConfig->setGroup("General");
+ krConfig->writeEntry( "Move To Trash", false );
+ }
+ files() ->vfs_delFiles( &fileNames );
+ if (reallyDelete) {
+ krConfig->setGroup("General");
+ krConfig->writeEntry( "Move To Trash", trash);
+ }
+}
+
+// this is done when you double click on a file
+void ListPanelFunc::execute( QString& name ) {
+ if ( name == ".." ) {
+ dirUp();
+ return ;
+ }
+
+ vfile *vf = files() ->vfs_search( name );
+ if ( vf == 0 )
+ return ;
+
+ KURL origin = files() ->vfs_getOrigin();
+
+ QString protocol = origin.isLocalFile() ? KrServices::registerdProtocol( vf->vfile_getMime() ) : "";
+
+ if ( protocol == "tar" || protocol == "krarc" ) {
+ bool encrypted;
+ QString type = KRarcHandler::getType( encrypted, vf->vfile_getUrl().path(), vf->vfile_getMime(), false );
+ if ( !KRarcHandler::arcHandled( type ) ) // if the specified archive is disabled delete the protocol
+ protocol = "";
+ }
+
+ if ( vf->vfile_isDir() ) {
+ origin = files() ->vfs_getFile( name );
+ panel->view->setNameToMakeCurrent( QString::null );
+ openUrl( origin );
+ } else if ( !protocol.isEmpty() ) {
+ KURL path = files() ->vfs_getFile( vf->vfile_getName() );
+ path.setProtocol( protocol );
+ openUrl( path );
+ } else {
+ KURL url = files() ->vfs_getFile( name );
+ KFileItem kfi( vf->vfile_getEntry(), url,true );
+ kfi.run();
+ }
+}
+
+void ListPanelFunc::dirUp() {
+ openUrl( files() ->vfs_getOrigin().upURL(), files() ->vfs_getOrigin().fileName() );
+}
+
+void ListPanelFunc::pack() {
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ if ( fileNames.count() == 0 )
+ return ; // nothing to pack
+
+ // choose the default name
+ QString defaultName = panel->virtualPath().fileName();
+ if ( defaultName == "" )
+ defaultName = "pack";
+ if ( fileNames.count() == 1 )
+ defaultName = fileNames.first();
+ // ask the user for archive name and packer
+ new PackGUI( defaultName, vfs::pathOrURL( panel->otherPanel->virtualPath(), -1 ), fileNames.count(), fileNames.first() );
+ if ( PackGUI::type == QString::null )
+ return ; // the user canceled
+
+ // check for partial URLs
+ if( !PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith("/") ){
+ PackGUI::destination = panel->virtualPath().prettyURL()+"/"+PackGUI::destination;
+ }
+
+ QString destDir = PackGUI::destination;
+ if( !destDir.endsWith( "/" ) )
+ destDir += "/";
+
+ bool packToOtherPanel = ( destDir == panel->otherPanel->virtualPath().prettyURL(1) );
+
+ // on remote URL-s first pack into a temp file then copy to its right place
+ KURL destURL = vfs::fromPathOrURL( destDir + PackGUI::filename + "." + PackGUI::type );
+ KTempFile *tempDestFile = 0;
+ QString arcFile;
+ if ( destURL.isLocalFile() )
+ arcFile = destURL.path();
+ else if( destURL.protocol() == "virt" ) {
+ KMessageBox::error( krApp, i18n( "Cannot pack files onto a virtual destination!" ) );
+ return;
+ }
+ else {
+ tempDestFile = new KTempFile( QString::null, "." + PackGUI::type );
+ tempDestFile->setAutoDelete( true );
+ arcFile = tempDestFile->name();
+ QFile::remove
+ ( arcFile );
+ }
+
+ if ( QFileInfo( arcFile ).exists() ) {
+ QString msg = i18n( "<qt><p>The archive <b>%1.%2</b> already exists. Do you want to overwrite it?</p><p>All data in the previous archive will be lost!</p></qt>").arg(PackGUI::filename).arg(PackGUI::type);
+ if( PackGUI::type == "zip" ) {
+ msg = i18n( "<qt><p>The archive <b>%1.%2</b> already exists. Do you want to overwrite it?</p><p>Zip will replace identically named entries in the zip archive or add entries for new names.</p></qt>").arg(PackGUI::filename).arg(PackGUI::type);
+ }
+ if ( KMessageBox::warningContinueCancel( krApp,msg,QString::null,i18n( "&Overwrite" ))
+ == KMessageBox::Cancel )
+ return ; // stop operation
+ }
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Counting files to pack" ), 0, true );
+
+ // get the files to be packed:
+ files() ->vfs_getFiles( &fileNames );
+
+ KIO::filesize_t totalSize = 0;
+ unsigned long totalDirs = 0, totalFiles = 0;
+ if( !calcSpace( fileNames, totalSize, totalFiles, totalDirs ) )
+ return;
+
+ // download remote URL-s if necessary
+ QString arcDir;
+ KTempDir *tempDir = 0;
+
+ if ( files() ->vfs_getOrigin().isLocalFile() )
+ arcDir = files() ->vfs_workingDir();
+ else {
+ tempDir = new KTempDir();
+ tempDir->setAutoDelete( true );
+ arcDir = tempDir->name();
+ KURL::List *urlList = files() ->vfs_getFiles( &fileNames );
+ KIO::NetAccess::dircopy( *urlList, vfs::fromPathOrURL( arcDir ), 0 );
+ delete urlList;
+ }
+
+ // pack the files
+ // we must chdir() first because we supply *names* not URL's
+ QString save = getcwd( 0, 0 );
+ chdir( arcDir.local8Bit() );
+ KRarcHandler::pack( fileNames, PackGUI::type, arcFile, totalFiles + totalDirs, PackGUI::extraProps );
+ chdir( save.local8Bit() );
+
+ // delete the temporary directory if created
+ if ( tempDir )
+ delete tempDir;
+
+ // copy from the temp file to it's right place
+ if ( tempDestFile ) {
+ KIO::NetAccess::file_move( vfs::fromPathOrURL( arcFile ), destURL );
+ delete tempDestFile;
+ }
+
+ if ( packToOtherPanel )
+ panel->otherPanel->func->refresh();
+}
+
+void ListPanelFunc::testArchive() {
+ QString arcName = panel->getCurrentName();
+ if ( arcName.isNull() )
+ return ;
+ if ( arcName == ".." )
+ return ; // safety
+
+ KURL arcURL = files() ->vfs_getFile( arcName );
+ QString url = QString::null;
+
+ // download the file if it's on a remote filesystem
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", QString( arcName ) );
+ if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ return ;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ QString type = KRarcHandler::getType( encrypted, url, mime );
+
+ // check we that archive is supported
+ if ( !KRarcHandler::arcSupported( type ) ) {
+ KMessageBox::sorry( krApp, i18n( "%1, unknown archive type." ).arg( arcName ) );
+ return ;
+ }
+
+ QString password = encrypted ? KRarcHandler::getPassword( url ) : QString::null;
+
+ // test the archive
+ if ( KRarcHandler::test( url, type, password ) )
+ KMessageBox::information( krApp, i18n( "%1, test passed." ).arg( arcName ) );
+ else
+ KMessageBox::error( krApp, i18n( "%1, test failed!" ).arg( arcName ) );
+
+ // remove the downloaded file if necessary
+ if ( url != arcURL.path( -1 ) )
+ QFile( url ).remove();
+}
+
+void ListPanelFunc::unpack() {
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ QString s;
+ if(fileNames.count() == 1)
+ s = i18n("Unpack %1 to:").arg(fileNames[0]);
+ else
+ s = i18n("Unpack %n file to:", "Unpack %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ KURL dest = KChooseDir::getDir(s, panel->otherPanel->virtualPath(), panel->virtualPath());
+ if ( dest.isEmpty() ) return ; // the user canceled
+
+ bool packToOtherPanel = ( dest.equals( panel->otherPanel->virtualPath(), true ) );
+
+ for ( unsigned int i = 0; i < fileNames.count(); ++i ) {
+ QString arcName = fileNames[ i ];
+ if ( arcName.isNull() )
+ return ;
+ if ( arcName == ".." )
+ return ; // safety
+
+ // download the file if it's on a remote filesystem
+ KURL arcURL = files() ->vfs_getFile( arcName );
+ QString url = QString::null;
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", QString( arcName ) );
+ if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ continue;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ // if the destination is in remote directory use temporary one instead
+ dest.adjustPath(1);
+ KURL originalDestURL;
+ KTempDir *tempDir = 0;
+
+ if ( !dest.isLocalFile() ) {
+ originalDestURL = dest;
+ tempDir = new KTempDir();
+ tempDir->setAutoDelete( true );
+ dest = tempDir->name();
+ }
+
+ // determining the type
+ QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ QString type = KRarcHandler::getType( encrypted, url, mime );
+
+ // check we that archive is supported
+ if ( !KRarcHandler::arcSupported( type ) ) {
+ KMessageBox::sorry( krApp, i18n( "%1, unknown archive type" ).arg( arcName ) );
+ continue;
+ }
+
+ QString password = encrypted ? KRarcHandler::getPassword( url ) : QString::null;
+
+ // unpack the files
+ KRarcHandler::unpack( url, type, password, dest.path( -1 ) );
+
+ // remove the downloaded file if necessary
+ if ( url != arcURL.path( -1 ) )
+ QFile( url ).remove();
+
+ // copy files to the destination directory at remote files
+ if ( tempDir ) {
+ QStringList nameList = QDir( dest.path( -1 ) ).entryList();
+ KURL::List urlList;
+ for ( unsigned int i = 0; i != nameList.count(); i++ )
+ if ( nameList[ i ] != "." && nameList[ i ] != ".." )
+ urlList.append( vfs::fromPathOrURL( dest.path( 1 ) + nameList[ i ] ) );
+ if ( urlList.count() > 0 )
+ KIO::NetAccess::dircopy( urlList, originalDestURL, 0 );
+ delete tempDir;
+ }
+ }
+ if ( packToOtherPanel )
+ panel->otherPanel->func->refresh();
+}
+
+// a small ugly function, used to prevent duplication of EVERY line of
+// code (maybe except 3) from createChecksum and matchChecksum
+static void checksum_wrapper(ListPanel *panel, QStringList& args, bool &folders) {
+ KrViewItemList items;
+ panel->view->getSelectedKrViewItems( &items );
+ if ( items.isEmpty() ) return ; // nothing to do
+ // determine if we need recursive mode (md5deep)
+ folders=false;
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ if (panel->func->getVFile(*it)->vfile_isDir()) {
+ folders = true;
+ args << (*it)->name();
+ } else args << (*it)->name();
+ }
+}
+
+void ListPanelFunc::createChecksum() {
+ QStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ CreateChecksumDlg dlg(args, folders, panel->realPath());
+}
+
+void ListPanelFunc::matchChecksum() {
+ QStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ QValueList<vfile*> checksumFiles = files()->vfs_search(
+ KRQuery(MatchChecksumDlg::checksumTypesFilter)
+ );
+ MatchChecksumDlg dlg(args, folders, panel->realPath(),
+ (checksumFiles.size()==1 ? checksumFiles[0]->vfile_getUrl().prettyURL() : QString::null));
+}
+
+void ListPanelFunc::calcSpace() {
+ QStringList items;
+ panel->view->getSelectedItems( &items );
+ if ( items.isEmpty() ) {
+ panel->view->selectAllIncludingDirs();
+ panel->view->getSelectedItems( &items );
+ if ( items.isEmpty() )
+ return ; // nothing to do
+ }
+
+ KrCalcSpaceDialog calc( krApp, panel, items, false );
+ calc.exec();
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) {
+ KrViewItem *viewItem = panel->view->findItemByName( *it );
+ if ( viewItem )
+ panel->view->updateItem(viewItem);
+ }
+ panel->slotUpdateTotals();
+}
+
+bool ListPanelFunc::calcSpace( const QStringList & items, KIO::filesize_t & totalSize, unsigned long & totalFiles, unsigned long & totalDirs ) {
+ KrCalcSpaceDialog calc( krApp, panel, items, true );
+ calc.exec();
+ totalSize = calc.getTotalSize();
+ totalFiles = calc.getTotalFiles();
+ totalDirs = calc.getTotalDirs();
+ return !calc.wasCanceled();
+}
+
+void ListPanelFunc::FTPDisconnect() {
+ // you can disconnect only if connected !
+ if ( files() ->vfs_getType() == vfs::FTP ) {
+ krFTPDiss->setEnabled( false );
+ panel->view->setNameToMakeCurrent( QString::null );
+ openUrl( panel->realPath() ); // open the last local URL
+ }
+}
+
+void ListPanelFunc::newFTPconnection() {
+ KURL url = KRSpWidgets::newFTP();
+ // if the user canceled - quit
+ if ( url.isEmpty() )
+ return ;
+
+ krFTPDiss->setEnabled( true );
+ openUrl( url );
+}
+
+void ListPanelFunc::properties() {
+ QStringList names;
+ panel->getSelectedNames( &names );
+ if ( names.isEmpty() )
+ return ; // no names...
+ KFileItemList fi;
+ fi.setAutoDelete( true );
+
+ for ( unsigned int i = 0 ; i < names.count() ; ++i ) {
+ vfile* vf = files() ->vfs_search( names[ i ] );
+ if ( !vf )
+ continue;
+ KURL url = files()->vfs_getFile( names[i] );
+ fi.append( new KFileItem( vf->vfile_getEntry(), url ) );
+ }
+
+ if ( fi.isEmpty() )
+ return ;
+
+ // Show the properties dialog
+ KPropertiesDialog *dlg = new KPropertiesDialog( fi );
+ connect( dlg, SIGNAL( applied() ), SLOTS, SLOT( refresh() ) );
+}
+
+void ListPanelFunc::refreshActions() {
+ vfs::VFS_TYPE vfsType = files() ->vfs_getType();
+
+ // set up actions
+ krMultiRename->setEnabled( vfsType == vfs::NORMAL ); // batch rename
+ //krProperties ->setEnabled( vfsType == vfs::NORMAL || vfsType == vfs::FTP ); // file properties
+ krFTPDiss ->setEnabled( vfsType == vfs::FTP ); // disconnect an FTP session
+ krCreateCS->setEnabled( vfsType == vfs::NORMAL );
+ /*
+ krUnpack->setEnabled(true); // unpack archive
+ krTest->setEnabled(true); // test archive
+ krSelect->setEnabled(true); // select a group by filter
+ krSelectAll->setEnabled(true); // select all files
+ krUnselect->setEnabled(true); // unselect by filter
+ krUnselectAll->setEnabled( true); // remove all selections
+ krInvert->setEnabled(true); // invert the selection
+ krFTPConnect->setEnabled(true); // connect to an ftp
+ krFTPNew->setEnabled(true); // create a new connection
+ krAllFiles->setEnabled(true); // show all files in list
+ krCustomFiles->setEnabled(true); // show a custom set of files
+ krBack->setEnabled(func->canGoBack()); // go back
+ krRoot->setEnabled(true); // go all the way up
+ krExecFiles->setEnabled(true); // show only executables
+ */
+}
+
+ListPanelFunc::~ListPanelFunc() {
+ if( !vfsP ) {
+ if( vfsP->vfs_canDelete() )
+ delete vfsP;
+ else {
+ connect( vfsP, SIGNAL( deleteAllowed() ), vfsP, SLOT( deleteLater() ) );
+ vfsP->vfs_requestDelete();
+ }
+ }
+ vfsP = 0;
+}
+
+vfs* ListPanelFunc::files() {
+ if ( !vfsP )
+ vfsP = KrVfsHandler::getVfs( "/", panel, 0 );
+ return vfsP;
+}
+
+
+void ListPanelFunc::copyToClipboard( bool move ) {
+ if( files()->vfs_getOrigin().equals( KURL("virt:/"), true ) ) {
+ if( move )
+ KMessageBox::error( krApp, i18n( "Cannot cut a virtual URL collection to the clipboard!" ) );
+ else
+ KMessageBox::error( krApp, i18n( "Cannot copy a virtual URL collection onto the clipboard!" ) );
+ return;
+ }
+
+ QStringList fileNames;
+
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+ if ( fileUrls ) {
+ KRDrag * urlData = KRDrag::newDrag( *fileUrls, move, krApp->mainView, "krusader" );
+ QApplication::clipboard() ->setData( urlData );
+
+ if( move && files()->vfs_getType() == vfs::VIRT )
+ ( static_cast<virt_vfs*>( files() ) )->vfs_removeFiles( &fileNames );
+
+ delete fileUrls;
+ }
+}
+
+void ListPanelFunc::pasteFromClipboard() {
+ QClipboard * cb = QApplication::clipboard();
+ QMimeSource * data = cb->data();
+ KURL::List urls;
+ if ( KURLDrag::canDecode( data ) ) {
+ KURLDrag::decode( data, urls );
+ bool cutSelection = KRDrag::decodeIsCutSelection( data );
+
+ KURL destUrl = panel->virtualPath();
+
+ files()->vfs_addFiles( &urls, cutSelection ? KIO::CopyJob::Move : KIO::CopyJob::Copy, otherFunc()->files(),
+ "", PM_DEFAULT );
+ }
+}
+
+#include "panelfunc.moc"
diff --git a/krusader/Panel/panelfunc.h b/krusader/Panel/panelfunc.h
new file mode 100644
index 0000000..1274e11
--- /dev/null
+++ b/krusader/Panel/panelfunc.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+ panelfunc.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 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
+
+ H e a d e r 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. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef PANELFUNC_H
+#define PANELFUNC_H
+#include "listpanel.h"
+#include "krviewitem.h"
+#include <qobject.h>
+#include <qvaluestack.h>
+#include <qtimer.h>
+
+class ListPanelFunc : public QObject{
+friend class ListPanel;
+ Q_OBJECT
+public slots:
+ inline vfile* getVFile(KrViewItem *item) { return files()->vfs_search(item->name()); }
+ inline vfile* getVFile(const QString& name) { return files()->vfs_search(name); }
+ void execute(QString&);
+ void openUrl(const KURL& path, const QString& nameToMakeCurrent = QString::null);
+ void openUrl(const QString& path, const QString& nameToMakeCurrent = QString::null);
+ void immediateOpenUrl( const KURL& path);
+ void doOpenUrl();
+ void refresh();
+ void rename(const QString &oldname, const QString &newname);
+
+public:
+ ListPanelFunc(class ListPanel *parent);
+ ~ListPanelFunc();
+
+ vfs* files(); // return a pointer to the vfs
+
+ void refreshActions();
+ void redirectLink();
+ void krlink(bool sym);
+ void goBack();
+ void dirUp();
+ void properties();
+ void terminal();
+ void editFile();
+ void view();
+ void rename();
+ void mkdir();
+ void moveFiles();
+ void pack();
+ void unpack();
+ void testArchive();
+ void copyFiles();
+ void deleteFiles(bool reallyDelete=false);
+ void calcSpace(); // calculate the occupied space and show it in a dialog
+ void createChecksum();
+ void matchChecksum();
+ void copyToClipboard( bool move=false );
+ void pasteFromClipboard();
+
+ // calculate the occupied space. A dialog appears, if calculation lasts more than 3 seconds
+ // and disappears, if the calculation is done. Returns true, if the result is ok and false
+ // otherwise (Cancel was pressed).
+ bool calcSpace(const QStringList & items,KIO::filesize_t & totalSize,unsigned long & totalFiles,unsigned long & totalDirs);
+ void FTPDisconnect();
+ void newFTPconnection();
+ inline ListPanelFunc* otherFunc(){ return panel->otherPanel->func; }
+
+private:
+ KURL getVirtualBaseURL();
+
+protected:
+ ListPanel* panel; // our ListPanel
+ QValueStack<KURL> urlStack; // Path stack for the "back" button
+ bool inRefresh; // true when we are in refresh()
+ vfs* vfsP; // pointer to vfs.
+ QTimer delayTimer;
+ KURL delayURL;
+ QString nameToMakeCurrent;
+};
+
+#endif
diff --git a/krusader/Panel/panelpopup.cpp b/krusader/Panel/panelpopup.cpp
new file mode 100644
index 0000000..deaec38
--- /dev/null
+++ b/krusader/Panel/panelpopup.cpp
@@ -0,0 +1,400 @@
+#include "../krusader.h"
+#include "panelpopup.h"
+#include "../kicons.h"
+#include "../Dialogs/krsqueezedtextlabel.h"
+#include "../defaults.h"
+#include "../krslots.h"
+#include "panelfunc.h"
+#include <qtooltip.h>
+#include <qbuttongroup.h>
+#include <qtoolbutton.h>
+#include <kfiletreeview.h>
+#include <klocale.h>
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qheader.h>
+#include <krview.h>
+#include <krviewitem.h>
+#include <klineedit.h>
+#include <kio/jobclasses.h>
+#include "../KViewer/kimagefilepreview.h"
+#include "../KViewer/panelviewer.h"
+#include "../KViewer/diskusageviewer.h"
+
+PanelPopup::PanelPopup( QSplitter *parent, bool left ) : QWidget( parent ),
+ _left( left ), _hidden(true), stack( 0 ), viewer( 0 ), pjob( 0 ), splitterSizes() {
+ splitter = parent;
+ QGridLayout * layout = new QGridLayout(this, 1, 1);
+
+ // loading the splitter sizes
+ krConfig->setGroup( "Private" );
+ if( left )
+ splitterSizes = krConfig->readIntListEntry( "Left PanelPopup Splitter Sizes" );
+ else
+ splitterSizes = krConfig->readIntListEntry( "Right PanelPopup Splitter Sizes" );
+
+ if( splitterSizes.count() < 2 ) {
+ splitterSizes.clear();
+ splitterSizes.push_back( 100 );
+ splitterSizes.push_back( 100 );
+ }
+
+ // create the label+buttons setup
+ dataLine = new KrSqueezedTextLabel(this);
+ dataLine->setText("blah blah");
+ connect( dataLine, SIGNAL( clicked() ), this, SLOT( setFocus() ) );
+ krConfig->setGroup( "Look&Feel" );
+ dataLine->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // --- hack: setup colors to be the same as an inactive panel
+ dataLine->setBackgroundMode( PaletteBackground );
+ QPalette q( dataLine->palette() );
+ q.setColor( QColorGroup::Foreground, KGlobalSettings::textColor() );
+ q.setColor( QColorGroup::Background, KGlobalSettings::baseColor() );
+ dataLine->setPalette( q );
+ dataLine->setFrameStyle( QFrame::Box | QFrame::Raised );
+ dataLine->setLineWidth( 1 ); // a nice 3D touch :-)
+ int sheight = QFontMetrics( dataLine->font() ).height() + 4;
+ dataLine->setMaximumHeight( sheight );
+
+ btns = new QButtonGroup(this);
+ btns->setExclusive(true);
+ btns->hide(); // it should be invisible
+ connect(btns, SIGNAL(clicked(int)), this, SLOT(tabSelected(int)));
+
+ treeBtn = new QToolButton(this);
+ QToolTip::add(treeBtn, i18n("Tree Panel: a tree view of the local file system"));
+ treeBtn->setPixmap(krLoader->loadIcon( "view_tree", KIcon::Toolbar, 16 ));
+ treeBtn->setFixedSize(20, 20);
+ treeBtn->setToggleButton(true);
+ btns->insert(treeBtn, Tree);
+
+
+ previewBtn = new QToolButton(this);
+ QToolTip::add(previewBtn, i18n("Preview Panel: display a preview of the current file"));
+ previewBtn->setPixmap(krLoader->loadIcon( "thumbnail", KIcon::Toolbar, 16 ));
+ previewBtn->setFixedSize(20, 20);
+ previewBtn->setToggleButton(true);
+ btns->insert(previewBtn, Preview);
+
+ quickBtn = new QToolButton(this);
+ QToolTip::add(quickBtn, i18n("Quick Panel: quick way to perform actions"));
+ quickBtn->setPixmap(krLoader->loadIcon( "misc", KIcon::Toolbar, 16 ));
+ quickBtn->setFixedSize(20, 20);
+ quickBtn->setToggleButton(true);
+ btns->insert(quickBtn, QuickPanel);
+
+ viewerBtn = new QToolButton(this);
+ QToolTip::add(viewerBtn, i18n("View Panel: view the current file"));
+ viewerBtn->setPixmap(krLoader->loadIcon( "viewmag", KIcon::Toolbar, 16 ));
+ viewerBtn->setFixedSize(20, 20);
+ viewerBtn->setToggleButton(true);
+ btns->insert(viewerBtn, View);
+
+ duBtn = new QToolButton(this);
+ QToolTip::add(duBtn, i18n("Disk Usage Panel: view the usage of a directory"));
+ duBtn->setPixmap(krLoader->loadIcon( "kr_diskusage", KIcon::Toolbar, 16 ));
+ duBtn->setFixedSize(20, 20);
+ duBtn->setToggleButton(true);
+ btns->insert(duBtn, DskUsage);
+
+ layout->addWidget(dataLine,0,0);
+ layout->addWidget(treeBtn,0,1);
+ layout->addWidget(previewBtn,0,2);
+ layout->addWidget(quickBtn,0,3);
+ layout->addWidget(viewerBtn,0,4);
+ layout->addWidget(duBtn,0,5);
+
+ // create a widget stack on which to put the parts
+ stack = new QWidgetStack( this );
+
+ // create the tree part ----------
+ tree = new KFileTreeView( stack );
+ tree->setAcceptDrops(true);
+ connect(tree, SIGNAL(dropped (QWidget *, QDropEvent *, KURL::List &, KURL &)),
+ this, SLOT(slotDroppedOnTree(QWidget *, QDropEvent *, KURL::List&, KURL& )));
+ stack->addWidget( tree, Tree );
+ tree->addColumn( "" );
+ // add ~
+ tree->addBranch( QDir::home().absPath(), i18n("Home"));
+ tree->setDirOnlyMode( tree->branch(i18n("Home")), true);
+ tree->branch(i18n("Home"))->setChildRecurse(false);
+ // add /
+ tree->addBranch( "/", i18n( "Root" ) );
+ tree->setDirOnlyMode( tree->branch( i18n( "Root" ) ), true );
+ tree->setShowFolderOpenPixmap(true);
+ tree->branch( i18n( "Root" ) ) ->setChildRecurse(false);
+ tree->branch( i18n( "Root" ) ) ->setOpen( true );
+ tree->header() ->setHidden( true );
+ connect(tree, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(treeSelection(QListViewItem*)));
+ // start listing the tree
+ tree->branch( i18n( "Root" ) ) ->root();
+ tree->branch( i18n( "Home" ) ) ->root();
+
+ // create the quickview part ------
+ viewer = new KrusaderImageFilePreview(stack);
+ stack->addWidget( viewer, Preview );
+
+ // create the panelview
+
+ panelviewer = new PanelViewer(stack);
+ stack->addWidget(panelviewer, View);
+ connect(panelviewer, SIGNAL(openURLRequest(const KURL &)), this, SLOT(handleOpenURLRequest(const KURL &)));
+
+ // create the disk usage view
+
+ diskusage = new DiskUsageViewer( stack );
+ diskusage->setStatusLabel( dataLine, i18n("Disk Usage: ") );
+ stack->addWidget( diskusage, DskUsage );
+ connect(diskusage, SIGNAL(openURLRequest(const KURL &)), this, SLOT(handleOpenURLRequest(const KURL &)));
+
+ // create the quick-panel part ----
+
+ QWidget *quickPanel = new QWidget(stack);
+ QGridLayout *qlayout = new QGridLayout(quickPanel);
+ // --- quick select
+ QLabel *selectLabel = new QLabel(i18n("Quick Select"), quickPanel);
+ quickSelectCombo = new KComboBox( quickPanel );
+ quickSelectCombo->setEditable( true );
+ krConfig->setGroup( "Private" );
+ QStrList lst;
+ int i = krConfig->readListEntry( "Predefined Selections", lst );
+ if ( i > 0 )
+ quickSelectCombo->insertStrList( lst );
+ quickSelectCombo->setCurrentText( "*" );
+ quickSelectCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ) );
+
+ connect(quickSelectCombo, SIGNAL(returnPressed(const QString& )),
+ this, SLOT(quickSelect(const QString& )));
+
+ QToolButton *qselectBtn = new QToolButton(quickPanel);
+ qselectBtn->setPixmap(krLoader->loadIcon( "kr_selectall", KIcon::Toolbar, 16 ));
+ qselectBtn->setFixedSize(20, 20);
+ QToolTip::add( qselectBtn, i18n("apply the selection") );
+ connect(qselectBtn, SIGNAL(clicked()), this, SLOT(quickSelect()));
+
+ QToolButton *qstoreBtn = new QToolButton(quickPanel);
+ qstoreBtn->setPixmap(krLoader->loadIcon( "filesave", KIcon::Toolbar, 16 ));
+ qstoreBtn->setFixedSize(20, 20);
+ QToolTip::add( qstoreBtn, i18n("store the current selection") );
+ connect(qstoreBtn, SIGNAL(clicked()), this, SLOT(quickSelectStore()));
+
+ QToolButton *qsettingsBtn = new QToolButton(quickPanel);
+ qsettingsBtn->setPixmap(krLoader->loadIcon( "configure", KIcon::Toolbar, 16 ));
+ qsettingsBtn->setFixedSize(20, 20);
+ QToolTip::add( qsettingsBtn, i18n("select group dialog") );
+ connect(qsettingsBtn, SIGNAL(clicked()), krSelect, SLOT(activate()));
+
+ qlayout->addWidget(selectLabel,0,0);
+ qlayout->addWidget(quickSelectCombo,0,1);
+ qlayout->addWidget(qselectBtn,0,2);
+ qlayout->addWidget(qstoreBtn,0,3);
+ qlayout->addWidget(qsettingsBtn,0,4);
+ stack->addWidget(quickPanel, QuickPanel);
+
+ // -------- finish the layout (General one)
+ layout->addMultiCellWidget(stack,1,1,0,5);
+
+ // set the wanted widget
+ // ugly: are we left or right?
+ int id;
+ krConfig->setGroup("Startup");
+ if (left) {
+ id = krConfig->readNumEntry("Left Panel Popup", _LeftPanelPopup);
+ } else {
+ id = krConfig->readNumEntry("Right Panel Popup", _RightPanelPopup);
+ }
+ btns->setButton(id);
+
+ hide(); // for not to open the 3rd hand tool at start (selecting the last used tab)
+ tabSelected(id);
+}
+
+PanelPopup::~PanelPopup() {}
+
+void PanelPopup::show() {
+ QWidget::show();
+ if( _hidden )
+ splitter->setSizes( splitterSizes );
+ _hidden = false;
+ tabSelected( stack->id(stack->visibleWidget()) );
+}
+
+
+void PanelPopup::hide() {
+ if( !_hidden )
+ splitterSizes = splitter->sizes();
+ QWidget::hide();
+ _hidden = true;
+ if (stack->id(stack->visibleWidget()) == View) panelviewer->closeURL();
+ if (stack->id(stack->visibleWidget()) == DskUsage) diskusage->closeURL();
+}
+
+void PanelPopup::setFocus() {
+ switch ( stack->id( stack->visibleWidget() ) ) {
+ case Preview:
+ if( !isHidden() )
+ viewer->setFocus();
+ break;
+ case View:
+ if( !isHidden() && panelviewer->part() && panelviewer->part()->widget() )
+ panelviewer->part()->widget()->setFocus();
+ break;
+ case DskUsage:
+ if( !isHidden() && diskusage->getWidget() && diskusage->getWidget()->visibleWidget() )
+ diskusage->getWidget()->visibleWidget()->setFocus();
+ break;
+ case Tree:
+ if( !isHidden() )
+ tree->setFocus();
+ break;
+ case QuickPanel:
+ if( !isHidden() )
+ quickSelectCombo->setFocus();
+ break;
+ }
+}
+
+void PanelPopup::saveSizes() {
+ krConfig->setGroup( "Private" );
+
+ if( !isHidden() )
+ splitterSizes = splitter->sizes();
+
+ if( _left )
+ krConfig->writeEntry( "Left PanelPopup Splitter Sizes", splitterSizes );
+ else
+ krConfig->writeEntry( "Right PanelPopup Splitter Sizes", splitterSizes );
+}
+
+void PanelPopup::handleOpenURLRequest(const KURL &url) {
+ if (KMimeType::findByURL(url.url())->name() == "inode/directory") ACTIVE_PANEL->func->openUrl(url);
+}
+
+
+void PanelPopup::tabSelected( int id ) {
+ KURL url = "";
+ if ( ACTIVE_PANEL && ACTIVE_PANEL->func && ACTIVE_PANEL->func->files() && ACTIVE_PANEL->view ) {
+ url = ACTIVE_PANEL->func->files()->vfs_getFile( ACTIVE_PANEL->view->getCurrentItem());
+ }
+
+ stack->raiseWidget( id );
+
+ // if tab is tree, set something logical in the data line
+ switch (id) {
+ case Tree:
+ dataLine->setText( i18n("Tree:") );
+ if( !isHidden() )
+ tree->setFocus();
+ break;
+ case Preview:
+ dataLine->setText( i18n("Preview:") );
+ update(url);
+ break;
+ case QuickPanel:
+ dataLine->setText( i18n("Quick Select:") );
+ if( !isHidden() )
+ quickSelectCombo->setFocus();
+ break;
+ case View:
+ dataLine->setText( i18n("View:") );
+ update(url);
+ if( !isHidden() && panelviewer->part() && panelviewer->part()->widget() )
+ panelviewer->part()->widget()->setFocus();
+ break;
+ case DskUsage:
+ dataLine->setText( i18n("Disk Usage:") );
+ update(url);
+ if( !isHidden() && diskusage->getWidget() && diskusage->getWidget()->visibleWidget() )
+ diskusage->getWidget()->visibleWidget()->setFocus();
+ break;
+ }
+ if (id != View) panelviewer->closeURL();
+}
+
+// decide which part to update, if at all
+void PanelPopup::update( KURL url ) {
+ if ( isHidden() || url.url()=="" ) return ; // failsafe
+
+ KFileItemList lst;
+
+ switch ( stack->id( stack->visibleWidget() ) ) {
+ case Preview:
+ viewer->showPreview(url);
+ dataLine->setText( i18n("Preview: ")+url.fileName() );
+ break;
+ case View:
+ panelviewer->openURL(url);
+ dataLine->setText( i18n("View: ")+url.fileName() );
+ break;
+ case DskUsage:
+ if( url.fileName() == ".." )
+ url.setFileName( "" );
+ if (KMimeType::findByURL(url.url())->name() != "inode/directory")
+ url = url.upURL();
+ dataLine->setText( i18n("Disk Usage: ")+url.fileName() );
+ diskusage->openURL(url);
+ break;
+ case Tree: // nothing to do
+ break;
+ }
+}
+
+// ------------------- tree
+
+void PanelPopup::treeSelection(QListViewItem*) {
+ emit selection(tree->currentURL());
+ //emit hideMe();
+}
+
+// ------------------- quick panel
+
+void PanelPopup::quickSelect() {
+ SLOTS->markGroup(quickSelectCombo->currentText(), true);
+}
+
+void PanelPopup::quickSelect(const QString &mask) {
+ SLOTS->markGroup(mask, true);
+}
+
+void PanelPopup::quickSelectStore() {
+ krConfig->setGroup( "Private" );
+ QStringList lst = krConfig->readListEntry( "Predefined Selections" );
+ if ( lst.find(quickSelectCombo->currentText()) == lst.end() )
+ lst.append( quickSelectCombo->currentText() );
+ krConfig->writeEntry( "Predefined Selections", lst );
+}
+
+void PanelPopup::slotDroppedOnTree(QWidget *widget, QDropEvent *e, KURL::List &lst, KURL &) {
+ // KFileTreeView is buggy: when dropped, it might not give us the correct
+ // destination, but actually, it's parent. workaround: don't use
+ // the destination in the signal, but take the current item
+ KURL dest = tree->currentURL();
+
+ // ask the user what to do: copy, move or link?
+ QPopupMenu popup( this );
+ popup.insertItem( i18n( "Copy Here" ), 1 );
+ popup.insertItem( i18n( "Move Here" ), 2 );
+ popup.insertItem( i18n( "Link Here" ), 3 );
+ popup.insertItem( i18n( "Cancel" ), 4 );
+ QPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( QCursor::pos() );
+
+ KIO::CopyJob *job;
+ switch ( result ) {
+ case 1 :
+ job = KIO::copy(lst, dest, true);
+ break;
+ case 2 :
+ job = KIO::move(lst, dest, true);
+ break;
+ case 3 :
+ job = KIO::link(lst, dest, true);
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+}
+
+#include "panelpopup.moc"
diff --git a/krusader/Panel/panelpopup.h b/krusader/Panel/panelpopup.h
new file mode 100644
index 0000000..3c09a0b
--- /dev/null
+++ b/krusader/Panel/panelpopup.h
@@ -0,0 +1,73 @@
+#ifndef _PANELPOPUP_H
+#define _PANELPOPUP_H
+
+#include <qwidget.h>
+#include <qwidgetstack.h>
+#include <qpixmap.h>
+#include <qvaluelist.h>
+#include <kfileitem.h>
+#include <qguardedptr.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+class QButtonGroup;
+class QLabel;
+class QListViewItem;
+class QSplitter;
+class KFileTreeView;
+class QToolButton;
+class KrSqueezedTextLabel;
+class KLineEdit;
+class KComboBox;
+class KrusaderImageFilePreview;
+class PanelViewer;
+class DiskUsageViewer;
+
+class PanelPopup: public QWidget {
+ Q_OBJECT
+ enum Parts { Tree, Preview, QuickPanel, View, DskUsage, Last=0xFF };
+public:
+ PanelPopup( QSplitter *splitter, bool left );
+ ~PanelPopup();
+ inline int currentPage() const { return stack->id(stack->visibleWidget()); }
+
+ void saveSizes();
+
+public slots:
+ void update(KURL url);
+ void show();
+ void hide();
+
+signals:
+ void selection(const KURL &url);
+ void hideMe();
+
+protected slots:
+ virtual void setFocus();
+ void tabSelected(int id);
+ void treeSelection(QListViewItem*);
+ void slotDroppedOnTree(QWidget *widget, QDropEvent *e, KURL::List &lst, KURL &);
+ void handleOpenURLRequest(const KURL &url);
+ void quickSelect();
+ void quickSelect(const QString &);
+ void quickSelectStore();
+
+protected:
+ bool _left;
+ bool _hidden;
+ QWidgetStack *stack;
+ KrusaderImageFilePreview *viewer;
+ KrSqueezedTextLabel *dataLine;
+ QGuardedPtr<KIO::PreviewJob> pjob;
+ KFileTreeView *tree;
+ QToolButton *treeBtn, *previewBtn, *quickBtn, *viewerBtn, *duBtn;
+ QButtonGroup *btns;
+ KLineEdit *quickFilter;
+ KComboBox *quickSelectCombo;
+ PanelViewer *panelviewer;
+ DiskUsageViewer *diskusage;
+ QValueList<int> splitterSizes;
+ QSplitter *splitter;
+};
+
+#endif // _PANELPOPUP_H