diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2025-08-28 22:44:34 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2025-08-31 23:30:34 +0900 |
commit | f9abd9d505434c9244c03eac708e29a0ca042f6b (patch) | |
tree | 30a197ab4c413849188bc131ff859212e636c821 /src/app/Panel/listpanel.cpp | |
parent | 14d42d284de233f9937becf3fc9ee0dabede3b21 (diff) | |
download | krusader-r14.1.x.tar.gz krusader-r14.1.x.zip |
Restructure source foldersr14.1.x
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
(cherry picked from commit 086012dcad8a976a0dabbb7cbc20c9cb612cdfa9)
Diffstat (limited to 'src/app/Panel/listpanel.cpp')
-rw-r--r-- | src/app/Panel/listpanel.cpp | 1115 |
1 files changed, 1115 insertions, 0 deletions
diff --git a/src/app/Panel/listpanel.cpp b/src/app/Panel/listpanel.cpp new file mode 100644 index 0000000..8d444df --- /dev/null +++ b/src/app/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> +// TQt includes +#include <tqbitmap.h> +#include <tqwhatsthis.h> +#include <tqstringlist.h> +#include <tqstrlist.h> +#include <kurldrag.h> +#include <tqheader.h> +#include <tqtimer.h> +#include <tqregexp.h> +#include <tqsplitter.h> +// TDE includes +#include <tdepopupmenu.h> +#include <kprocess.h> +#include <tdemessagebox.h> +#include <tdelocale.h> +#include <kmimetype.h> +#include <kurl.h> +#include <ktrader.h> +#include <kopenwith.h> +#include <kuserprofile.h> +#include <kiconloader.h> +#include <kcursor.h> +#include <tdemessagebox.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tqtooltip.h> +#include <tdeversion.h> +#include <tqimage.h> +#include <tqtabbar.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 TQValueList<KServiceOffer> OfferList; + +#define URL(X) KURL::fromPathOrURL(X) + +///////////////////////////////////////////////////// +// The list panel constructor // +///////////////////////////////////////////////////// +ListPanel::ListPanel( TQString typeIn, TQWidget *parent, bool &left, const char *name ) : + TQWidget( 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 TQGridLayout( this, 3, 3 ); + + mediaButton = new MediaButton( this, "mediaButton" ); + connect( mediaButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( mediaButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) ); + + status = new KrSqueezedTextLabel( this ); + krConfig->setGroup( "Look&Feel" ); + status->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) ); + status->setBackgroundMode( PaletteBackground ); + status->setFrameStyle( TQFrame::Box | TQFrame::Raised ); + status->setLineWidth( 1 ); // a nice 3D touch :-) + status->setText( "" ); // needed for initialization code! + status->enableDrops( true ); + int sheight = TQFontMetrics( status->font() ).height() + 4; + status->setMaximumHeight( sheight ); + TQWhatsThis::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, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( status, TQ_SIGNAL( dropped( TQDropEvent *) ), this, TQ_SLOT( handleDropOnStatus(TQDropEvent *) ) ); + + // ... create the history button + dirHistoryQueue = new DirHistoryQueue( this ); + historyButton = new DirHistoryButton( dirHistoryQueue, this, "historyButton" ); + connect( historyButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( historyButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) ); + + bookmarksButton = new KrBookmarkButton(this); + connect( bookmarksButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( bookmarksButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) ); + TQWhatsThis::add + ( bookmarksButton, i18n( "Open menu with bookmarks. You can also add " + "current location to the list, edit bookmarks " + "or add subfolder to the list." ) ); + + TQHBoxLayout *totalsLayout = new TQHBoxLayout; + totals = new KrSqueezedTextLabel( this ); + krConfig->setGroup( "Look&Feel" ); + totals->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) ); + totals->setFrameStyle( TQFrame::Box | TQFrame::Raised ); + totals->setBackgroundMode( PaletteBackground ); + totals->setLineWidth( 1 ); // a nice 3D touch :-) + totals->setMaximumHeight( sheight ); + totals->enableDrops( true ); + TQWhatsThis::add + ( totals, i18n( "The totals bar shows how many files exist, " + "how many selected and the bytes math" ) ); + connect( totals, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( totals, TQ_SIGNAL( dropped( TQDropEvent *) ), this, TQ_SLOT( handleDropOnTotals(TQDropEvent *) ) ); + + // a cancel button for the inplace refresh mechanism + inlineRefreshCancelButton = new KPushButton(this); + inlineRefreshCancelButton->setFixedSize( 22, 20 ); + inlineRefreshCancelButton->setPixmap(krLoader->loadIcon("cancel", TDEIcon::Toolbar, 16)); + connect(inlineRefreshCancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(inlineRefreshCancel())); + + // a quick button to open the popup panel + popupBtn = new TQToolButton( this, "popupbtn" ); + popupBtn->setFixedSize( 22, 20 ); + popupBtn->setPixmap(krLoader->loadIcon("1uparrow", TDEIcon::Toolbar, 16)); + connect(popupBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(togglePanelPopup())); + TQToolTip::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( TQFrame::Box | TQFrame::Raised ); + quickSearch->setLineWidth( 1 ); // a nice 3D touch :-) + quickSearch->setMaximumHeight( sheight ); + + TQHBox * hbox = new TQHBox( this ); + + // clear-origin button + bool clearButton = krConfig->readBoolEntry("Clear Location Bar Visible", _ClearLocation); + if (clearButton){ + clearOrigin = new TQToolButton(hbox, "clearorigin"); + clearOrigin->setPixmap(krLoader->loadIcon("locationbar_erase", TDEIcon::Toolbar, 16)); + TQToolTip::add( clearOrigin, i18n( "Clear the location bar" ) ); + } + + QuickNavLineEdit *qnle = new QuickNavLineEdit(this); + origin = new KURLRequester( qnle, hbox ); + TQPixmap pixMap = origin->button() ->iconSet() ->pixmap( TQIconSet::Small, TQIconSet::Normal ); + origin->button() ->setFixedSize( pixMap.width() + 4, pixMap.height() + 4 ); + TQWhatsThis::add + ( origin, i18n( "Use superb TDE file dialog to choose location. " ) ); + origin->setShowLocalProtocol( false ); + origin->lineEdit() ->setURLDropsEnabled( true ); + origin->lineEdit() ->installEventFilter( this ); + TQWhatsThis::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, TQ_SIGNAL( returnPressed( const TQString& ) ), func, TQ_SLOT( openUrl( const TQString& ) ) ); + connect( origin, TQ_SIGNAL( returnPressed( const TQString& ) ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( origin, TQ_SIGNAL( urlSelected( const TQString& ) ), func, TQ_SLOT( openUrl( const TQString& ) ) ); + connect( origin, TQ_SIGNAL( urlSelected( const TQString& ) ), this, TQ_SLOT( slotFocusOnMe() ) ); + + // this is here on purpose, do not move up! + if (clearButton) { + clearOrigin->setFixedSize( 20, origin->button() ->height() ); + connect(clearOrigin, TQ_SIGNAL(clicked()), origin->lineEdit(), TQ_SLOT(clear())); + connect(clearOrigin, TQ_SIGNAL(clicked()), origin->lineEdit(), TQ_SLOT(setFocus())); + } + // + + cdOtherButton = new TQToolButton( hbox, "cdOtherButton" ); + cdOtherButton->setFixedSize( 20, origin->button() ->height() ); + cdOtherButton->setText( i18n( "=" ) ); + TQToolTip::add( cdOtherButton, i18n( "Equal" ) ); + connect( cdOtherButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDOther() ) ); + + cdUpButton = new TQToolButton( hbox, "cdUpButton" ); + cdUpButton->setFixedSize( 20, origin->button() ->height() ); + cdUpButton->setText( i18n( ".." ) ); + TQToolTip::add( cdUpButton, i18n( "Up" ) ); + connect( cdUpButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDup() ) ); + + cdHomeButton = new TQToolButton( hbox, "cdHomeButton" ); + cdHomeButton->setFixedSize( 20, origin->button() ->height() ); + cdHomeButton->setText( i18n( "~" ) ); + TQToolTip::add( cdHomeButton, i18n( "Home" ) ); + connect( cdHomeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDHome() ) ); + + cdRootButton = new TQToolButton( hbox, "cdRootButton" ); + cdRootButton->setFixedSize( 20, origin->button() ->height() ); + cdRootButton->setText( i18n( "/" ) ); + TQToolTip::add( cdRootButton, i18n( "Root" ) ); + connect( cdRootButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDRoot() ) ); + + // ... creates the button for sync-browsing + syncBrowseButton = new SyncBrowseButton( hbox ); + + setPanelToolbar(); + + header = new TQHeader( this ); + header->hide(); + + // create a splitter to hold the view and the popup + splt = new PercentalSplitter(this); + splt->setChildrenCollapsible(true); + splt->setOrientation(TQt::Vertical); + + createView(); + + // make sure that a focus/path change reflects in the command line and activePanel + connect( this, TQ_SIGNAL( cmdLineUpdate( TQString ) ), SLOTS, TQ_SLOT( slotCurrentChanged( TQString ) ) ); + connect( this, TQ_SIGNAL( activePanelChanged( ListPanel * ) ), SLOTS, TQ_SLOT( slotSetActivePanel( ListPanel * ) ) ); + + // add a popup + popup = new PanelPopup(splt, left); + connect(popup, TQ_SIGNAL(selection(const KURL&)), SLOTS, TQ_SLOT(refresh(const KURL&))); + connect(popup, TQ_SIGNAL(hideMe()), this, TQ_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 ), TQ_SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, TQ_SLOT( newTab( KrViewItem * ) ) ); + connect( dynamic_cast<KrBriefView*>( view ), TQ_SIGNAL( currentChanged( KrViewItem * ) ), + SLOTS, TQ_SLOT( updatePopupPanel( KrViewItem* ) ) ); + + // connect quicksearch + connect( quickSearch, TQ_SIGNAL( textChanged( const TQString& ) ), + dynamic_cast<KrBriefView*>( view ), TQ_SLOT( quickSearch( const TQString& ) ) ); + connect( quickSearch, TQ_SIGNAL( otherMatching( const TQString&, int ) ), + dynamic_cast<KrBriefView*>( view ), TQ_SLOT( quickSearch( const TQString& , int ) ) ); + connect( quickSearch, TQ_SIGNAL( stop( TQKeyEvent* ) ), + dynamic_cast<KrBriefView*>( view ), TQ_SLOT( stopQuickSearch( TQKeyEvent* ) ) ); + connect( quickSearch, TQ_SIGNAL( process( TQKeyEvent* ) ), + dynamic_cast<KrBriefView*>( view ), TQ_SLOT( handleQuickSearchEvent( TQKeyEvent* ) ) ); + } else { /* Detailed */ + panelType = "Detailed"; + view = new KrDetailedView( splt, _left, krConfig ); + view->init(); + connect( dynamic_cast<KrDetailedView*>( view ), TQ_SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, TQ_SLOT( newTab( KrViewItem * ) ) ); + connect( dynamic_cast<KrDetailedView*>( view ), TQ_SIGNAL( currentChanged( KrViewItem * ) ), + SLOTS, TQ_SLOT( updatePopupPanel( KrViewItem * ) ) ); + // connect quicksearch + connect( quickSearch, TQ_SIGNAL( textChanged( const TQString& ) ), + dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( quickSearch( const TQString& ) ) ); + connect( quickSearch, TQ_SIGNAL( otherMatching( const TQString&, int ) ), + dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( quickSearch( const TQString& , int ) ) ); + connect( quickSearch, TQ_SIGNAL( stop( TQKeyEvent* ) ), + dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( stopQuickSearch( TQKeyEvent* ) ) ); + connect( quickSearch, TQ_SIGNAL( process( TQKeyEvent* ) ), + dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( handleQuickSearchEvent( TQKeyEvent* ) ) ); + } + + connect( view->op(), TQ_SIGNAL( renameItem( const TQString &, const TQString & ) ), + func, TQ_SLOT( rename( const TQString &, const TQString & ) ) ); + connect( view->op(), TQ_SIGNAL( executed( TQString& ) ), func, TQ_SLOT( execute( TQString& ) ) ); + connect( view->op(), TQ_SIGNAL( needFocus() ), this, TQ_SLOT( slotFocusOnMe() ) ); + connect( view->op(), TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotUpdateTotals() ) ); + connect( view->op(), TQ_SIGNAL( itemDescription( TQString& ) ), krApp, TQ_SLOT( statusBarUpdate( TQString& ) ) ); + connect( view->op(), TQ_SIGNAL( contextMenu( const TQPoint & ) ), this, TQ_SLOT( popRightClickMenu( const TQPoint & ) ) ); + connect( view->op(), TQ_SIGNAL( emptyContextMenu( const TQPoint &) ), + this, TQ_SLOT( popEmptyRightClickMenu( const TQPoint & ) ) ); + connect( view->op(), TQ_SIGNAL( letsDrag( TQStringList, TQPixmap ) ), this, TQ_SLOT( startDragging( TQStringList, TQPixmap ) ) ); + connect( view->op(), TQ_SIGNAL( gotDrop( TQDropEvent * ) ), this, TQ_SLOT( handleDropOnView( TQDropEvent * ) ) ); +} + +void ListPanel::changeType( const TQString & 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 ( TQObject * watched, TQEvent * e ) { + if( e->type() == TQEvent::KeyPress && origin->lineEdit() == watched ) { + TQKeyEvent *ke = (TQKeyEvent *)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<TQSplitter*>(popup->parent())->setSizes(popupSizes); + } else { // on the first time, resize to 50% + TQValueList<int> lst; + lst << height()/2 << height()/2; + dynamic_cast<TQSplitter*>(popup->parent())->setSizes(lst); + } + + popup->show(); + popupBtn->setPixmap(krLoader->loadIcon("1downarrow", TDEIcon::Toolbar, 16)); + TQToolTip::add( popupBtn, i18n( "Close the popup panel" ) ); + } else { + popupSizes.clear(); + popupSizes = dynamic_cast<TQSplitter*>(popup->parent())->sizes(); + popup->hide(); + popupBtn->setPixmap(krLoader->loadIcon("1uparrow", TDEIcon::Toolbar, 16)); + TQToolTip::add( popupBtn, i18n( "Open the popup panel" ) ); + + TQValueList<int> lst; + lst << height() << 0; + dynamic_cast<TQSplitter*>(popup->parent())->setSizes(lst); + if( ACTIVE_PANEL ) + ACTIVE_PANEL->slotFocusOnMe(); + } +} + +KURL ListPanel::virtualPath() const { + return func->files()->vfs_getOrigin(); +} + +TQString 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( TQString( "~" ), TQString() ); +} + +void ListPanel::slotFocusAndCDup() { + slotFocusOnMe(); + func->dirUp(); +} + +void ListPanel::slotFocusAndCDRoot() { + slotFocusOnMe(); + func->openUrl( TQString( "/" ), TQString() ); +} + +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' + TQPalette q( otherPanel->status->palette() ); + q.setColor( TQColorGroup::Foreground, TDEGlobalSettings::textColor() ); + q.setColor( TQColorGroup::Background, TDEGlobalSettings::baseColor() ); + + otherPanel->status->setPalette( q ); + otherPanel->totals->setPalette( q ); + otherPanel->view->prepareForPassive(); + + // now, take care of this panel + TQPalette p( status->palette() ); + p.setColor( TQColorGroup::Foreground, TDEGlobalSettings::highlightedTextColor() ); + p.setColor( TQColorGroup::Background, TDEGlobalSettings::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 + TQString protocol = func->files() ->vfs_getOrigin().protocol(); + bool isFtp = ( protocol == "ftp" || protocol == "smb" || protocol == "sftp" || protocol == "fish" ); + + TQString 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; + TQString 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, TQ_SIGNAL( foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ) ), + this, TQ_SLOT( gotStats( const TQString &, unsigned long, unsigned long, unsigned long ) ) ); +} + +void ListPanel::gotStats( const TQString &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(); + TQString fstype = i18n("unknown"); + for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) { + if ((*it)->mountPoint() == mountPoint) { + fstype = (*it)->mountType(); + break; + } + } + + TQString stats = i18n( "%1 free out of %2 (%3%) on %4 [ (%5) ]" ) + .arg( TDEIO::convertSizeFromKB( kBAvail ) ) + .arg( TDEIO::convertSizeFromKB( kBSize ) ).arg( perc ) + .arg( mountPoint ).arg( fstype ); + status->setText( stats ); +} + +void ListPanel::handleDropOnTotals( TQDropEvent *e ) { + handleDropOnView( e, totals ); +} + +void ListPanel::handleDropOnStatus( TQDropEvent *e ) { + handleDropOnView( e, status ); +} + +void ListPanel::handleDropOnView( TQDropEvent *e, TQWidget *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; + } + + TDEIO::CopyJob::CopyMode mode = TDEIO::CopyJob::Copy; + + // the KURL::List is finished, let's go + // --> display the COPY/MOVE/LINK menu + TQPopupMenu 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 ); + TQPoint tmp = widget->mapToGlobal( e->pos() ); + int result = popup.exec( tmp ); + switch ( result ) { + case 1 : + mode = TDEIO::CopyJob::Copy; + break; + case 2 : + mode = TDEIO::CopyJob::Move; + break; + case 3 : + mode = TDEIO::CopyJob::Link; + break; + case - 1 : // user pressed outside the menu + case 4: + return ; // cancel was pressed; + } + + TQString dir = ""; + if ( copyToDirInPanel ) { + dir = i->name(); + } + TQWidget *notify = ( !e->source() ? 0 : e->source() ); + tempFiles->vfs_addFiles( &URLs, mode, notify, dir ); +} + +void ListPanel::startDragging( TQStringList names, TQPixmap 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, TQPoint( -7, 0 ) ); + d->dragCopy(); + + delete urls; // free memory +} + +// pops a right-click menu for items +void ListPanel::popRightClickMenu( const TQPoint &loc ) { + // run it, on the mouse location + int j = TQFontMetrics( font() ).height() * 2; + KrPopupMenu::run(TQPoint( loc.x() + 5, loc.y() + j ), this); +} + +void ListPanel::popEmptyRightClickMenu( const TQPoint &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(); +} + +TQString ListPanel::getCurrentName() { + TQString name = view->getCurrentItem(); + if ( name != ".." ) + return name; + else + return TQString(); +} + +void ListPanel::prepareToDelete() { + view->setNameToMakeCurrent( view->firstUnmarkedBelowCurrent() ); +} + +void ListPanel::keyPressEvent( TQKeyEvent *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() == TQt::NoButton ) + MAIN_VIEW->cmdLine->addText( e->text() ); + + //e->ignore(); + } +} + +void ListPanel::slotItemAdded(vfile *vf) { + view->addItem(vf); +} + +void ListPanel::slotItemDeleted(const TQString& name) { + view->delItem(name); +} + +void ListPanel::slotItemUpdated(vfile *vf) { + view->updateItem(vf); +} + +void ListPanel::slotCleared() { + view->clear(); +} + +void ListPanel::showEvent( TQShowEvent *e ) { + panelActive(); + TQWidget::showEvent(e); +} + +void ListPanel::hideEvent( TQHideEvent *e ) { + panelInactive(); + TQWidget::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(TDEIO::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, TQ_SIGNAL( infoMessage( TDEIO::Job*, const TQString & ) ), + TQ_SLOT( inlineRefreshInfoMessage( TDEIO::Job*, const TQString & ) ) ); + connect( job, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ), + TQ_SLOT( inlineRefreshPercent( TDEIO::Job*, unsigned long ) ) ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)), + this,TQ_SLOT(inlineRefreshListResult(TDEIO::Job*))); + connect(job,TQ_SIGNAL(canceled(TDEIO::Job*)), + this,TQ_SLOT(inlineRefreshListResult(TDEIO::Job*))); + + inlineRefreshJob = job; + + totals->setText(i18n(">> Reading...")); + inlineRefreshCancelButton->show(); +} + +void ListPanel::inlineRefreshCancel() { + if (inlineRefreshJob) { + inlineRefreshJob->kill(false); + inlineRefreshJob = 0; + } +} + +void ListPanel::inlineRefreshPercent( TDEIO::Job*, unsigned long perc) { + TQString msg = TQString(">> %1: %2 % complete...").arg(i18n("Reading")).arg(perc); + totals->setText(msg); +} + +void ListPanel::inlineRefreshInfoMessage( TDEIO::Job*, const TQString &msg ) { + totals->setText(">> " + i18n("Reading: ") + msg); +} + +void ListPanel::inlineRefreshListResult(TDEIO::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" |