KuickShow – image/slideshow viewer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

464 lines
12 KiB

/* This file is part of the KDE project
Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
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, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <tqkeycode.h>
#include <tdeversion.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kpropertiesdialog.h>
#include <kurlcompletion.h>
#include "filefinder.h"
#include "filewidget.h"
#include "kuickdata.h"
#include "kuickshow.h"
#ifdef KeyPress
#undef KeyPress
#endif
FileWidget::FileWidget( const KURL& url, TQWidget *parent, const char *name )
: KDirOperator( url, parent, name ),
m_validCompletion( false ),
m_fileFinder( 0L )
{
setEnableDirHighlighting( true );
#if TDE_VERSION >= 310
setViewConfig( TDEGlobal::config(), "Filebrowser" );
#endif
readConfig( TDEGlobal::config(), "Filebrowser" );
setView( KFile::Default );
// setOnlyDoubleClickSelectsFiles( true );
reloadConfiguration();
completionObject()->setCompletionMode( TDEGlobalSettings::CompletionAuto );
dirCompletionObject()->setCompletionMode( TDEGlobalSettings::CompletionAuto);
slotViewChanged();
connect( this, TQT_SIGNAL( viewChanged( KFileView * )),
TQT_SLOT( slotViewChanged() ));
connect( dirLister(), TQT_SIGNAL( clear() ), TQT_SLOT( slotItemsCleared() ));
connect( dirLister(), TQT_SIGNAL( deleteItem( KFileItem * ) ),
TQT_SLOT( slotItemDeleted( KFileItem *) ));
connect( this, TQT_SIGNAL( fileHighlighted( const KFileItem * )),
TQT_SLOT( slotHighlighted( const KFileItem * )));
connect( this, TQT_SIGNAL(urlEntered(const KURL&)),
TQT_SLOT( slotURLEntered( const KURL& )));
// should actually be KDirOperator's job!
connect( this, TQT_SIGNAL( finishedLoading() ), TQT_SLOT( slotFinishedLoading() ));
}
FileWidget::~FileWidget()
{
delete m_fileFinder;
}
void FileWidget::initActions()
{
int index = 0;
KActionCollection *coll = actionCollection();
KActionSeparator *sep = new KActionSeparator( coll, "kuicksep" );
KActionMenu *menu = static_cast<KActionMenu*>( coll->action("popupMenu") );
menu->insert( coll->action("kuick_showInOtherWindow"), index++ );
menu->insert( coll->action("kuick_showInSameWindow"), index++ );
menu->insert( coll->action("kuick_showFullscreen"), index++ );
menu->insert( sep, index++ );
// support for older tdelibs, remove somewhen...
if ( coll->action("kuick_delete") )
menu->insert( coll->action("kuick_delete"), 9 );
// properties dialog is now in tdefile, but not at the right position,
// so we move it to the real bottom
menu->remove( coll->action( "properties" ) );
TQPopupMenu *pMenu = menu->popupMenu();
int lastItemId = pMenu->idAt( pMenu->count() - 1 );
TQMenuItem *mItem = pMenu->findItem( lastItemId );
if ( mItem && !mItem->isSeparator() )
menu->insert( sep );
// those at the bottom
menu->insert( coll->action("kuick_print") );
menu->insert( sep );
menu->insert( coll->action("properties") );
}
void FileWidget::reloadConfiguration()
{
if ( kdata->fileFilter != nameFilter() ) {
// At first, our list must have folders
TQStringList mimes;
mimes.append("inode/directory");
// Then, all the images!
KMimeType::List l = KMimeType::allMimeTypes();
for (KMimeType::List::iterator it = l.begin(); it != l.end(); ++it)
if ((*it)->name().startsWith( "image/" ))
mimes.append( (*it)->name() );
// Ok, show what we've done
setMimeFilter (mimes);
updateDir();
}
}
bool FileWidget::hasFiles() const
{
return (numFiles() > 0);
}
void FileWidget::activatedMenu( const KFileItem *item, const TQPoint& pos )
{
bool image = isImage( item );
actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
actionCollection()->action("kuick_print")->setEnabled( image );
actionCollection()->action("properties")->setEnabled( item );
bool hasSelection = (item != 0L);
if ( actionCollection()->action("kuick_delete") )
actionCollection()->action("kuick_delete")->setEnabled( hasSelection );
KDirOperator::activatedMenu( item, pos );
}
void FileWidget::findCompletion( const TQString& text )
{
if ( text.at(0) == '/' || text.at(0) == '~' ||
text.find('/') != -1 ) {
TQString t = m_fileFinder->completion()->makeCompletion( text );
if (m_fileFinder->completionMode() == TDEGlobalSettings::CompletionPopup ||
m_fileFinder->completionMode() == TDEGlobalSettings::CompletionPopupAuto)
m_fileFinder->setCompletedItems(
m_fileFinder->completion()->allMatches() );
else
if ( !t.isNull() )
m_fileFinder->setCompletedText( t );
return;
}
TQString file = makeDirCompletion( text );
if ( file.isNull() )
file = makeCompletion( text );
m_validCompletion = !file.isNull();
if ( m_validCompletion )
KDirOperator::setCurrentItem( file );
}
bool FileWidget::eventFilter( TQObject *o, TQEvent *e )
{
if ( e->type() == TQEvent::KeyPress ) {
TQKeyEvent *k = TQT_TQKEYEVENT( e );
if ( (k->state() & (ControlButton | AltButton)) == 0 ) {
int key = k->key();
if ( actionCollection()->action("delete")->shortcut().contains( key ) )
{
k->accept();
KFileItem *item = getCurrentItem( false );
if ( item ) {
KFileItemList list;
list.append( item );
del( list, (k->state() & ShiftButton) == 0 );
}
return true;
}
const TQString& text = k->text();
if ( !text.isEmpty() && text.unicode()->isPrint() ) {
k->accept();
if ( !m_fileFinder ) {
m_fileFinder = new FileFinder( this, "file finder" );
connect( m_fileFinder, TQT_SIGNAL( completion(const TQString&)),
TQT_SLOT( findCompletion( const TQString& )));
connect( m_fileFinder,
TQT_SIGNAL( enterDir( const TQString& ) ),
TQT_SLOT( slotReturnPressed( const TQString& )));
m_fileFinder->move( width() - m_fileFinder->width(),
height() - m_fileFinder->height() );
}
bool first = m_fileFinder->isHidden();
m_fileFinder->setText( text );
m_fileFinder->raise();
m_fileFinder->show();
m_fileFinder->setFocus();
if ( first )
findCompletion( text );
return true;
}
}
k->ignore();
}
return KDirOperator::eventFilter( o, e );
}
// TDEIO::NetAccess::stat() does NOT give us the right mimetype, while
// TDEIO::NetAccess::mimetype() does. So we have this hacklet to tell
// showImage that the KFileItem is really an image.
#define IS_IMAGE 5
#define MY_TYPE 55
bool FileWidget::isImage( const KFileItem *item )
{
// return item && !item->isDir();
if ( item )
{
return item->isReadable() && item->mimetype().startsWith( "image/") ||
item->extraData( (void*) MY_TYPE ) == (void*) IS_IMAGE;
}
return false;
}
void FileWidget::setImage( KFileItem& item, bool enable )
{
if ( enable )
item.setExtraData( (void*) MY_TYPE, (void*) IS_IMAGE );
else
item.removeExtraData( (void*) MY_TYPE );
}
KFileItem * FileWidget::gotoFirstImage()
{
KFileItemListIterator it( *(fileView()->items()) );
while ( it.current() ) {
if ( isImage( it.current() ) ) {
setCurrentItem( it.current() );
return it.current();
}
++it;
}
return 0L;
}
KFileItem * FileWidget::gotoLastImage()
{
KFileItemListIterator it( *(fileView()->items()) );
it.toLast();
while ( it.current() ) {
if ( isImage( it.current() ) ) {
setCurrentItem( it.current() );
return it.current();
}
--it;
}
return 0L;
}
KFileItem * FileWidget::getNext( bool go )
{
KFileItem *item = getItem( Next, true );
if ( item ) {
if ( go )
setCurrentItem( item );
return item;
}
return 0L;
}
KFileItem * FileWidget::getPrevious( bool go )
{
KFileItem *item = getItem( Previous, true );
if ( item ) {
if ( go )
setCurrentItem( item );
return item;
}
return 0L;
}
// returns 0L when there is no previous/next item/image
// this sucks! Use KFileView::currentFileItem() when implemented
KFileItem * FileWidget::getItem( WhichItem which, bool onlyImage ) const
{
KFileItemListIterator it( *(fileView()->items()) );
while ( it.current() ) { // find the iterator to the current item
if ( it.current()->url() == m_currentURL )
break;
++it;
}
if ( it.current() ) {
switch ( which ) {
case Previous: {
--it;
while ( it.current() ) {
if ( isImage( it.current() ) || !onlyImage )
return it.current();
--it;
}
return 0L; // no previous item / image
}
case Next: {
++it;
while ( it.current() ) {
if ( isImage( it.current() ) || !onlyImage )
return it.current();
++it;
}
return 0L; // no further item / image
}
case Current:
default:
return it.current();
}
}
return 0L;
}
void FileWidget::slotViewChanged()
{
fileView()->widget()->installEventFilter( this );
}
void FileWidget::slotItemsCleared()
{
m_currentURL = TQString();
}
void FileWidget::slotItemDeleted( KFileItem *item )
{
KFileItem *current = getCurrentItem( false );
if ( item != current ) {
return; // all ok, we already have a new current item
}
KFileItem *next = getNext();
if ( !next )
next = getPrevious();
if ( next )
m_currentURL = next->url().url();
}
void FileWidget::slotHighlighted( const KFileItem *item )
{
m_currentURL = item->url().url();
}
void FileWidget::slotReturnPressed( const TQString& t )
{
// we need a / at the end, otherwise replacedPath() will cut off the dir,
// assuming it is a filename
TQString text = t;
if ( text.at( text.length()-1 ) != '/' )
text += '/';
if ( text.at(0) == '/' || text.at(0) == '~' ) {
TQString dir = m_fileFinder->completion()->replacedPath( text );
KURL url;
url.setPath( dir );
setURL( url, true );
}
else if ( text.find('/') != (int) text.length() -1 ) { // relative path
TQString dir = m_fileFinder->completion()->replacedPath( text );
KURL u( url(), dir );
setURL( u, true );
}
else if ( m_validCompletion ) {
KFileItem *item = getCurrentItem( true );
if ( item ) {
if ( item->isDir() )
setURL( item->url(), true );
else
emit fileSelected( item );
}
}
}
void FileWidget::setCurrentItem( const KFileItem *item )
{
if ( item ) {
fileView()->setCurrentItem( item );
fileView()->ensureItemVisible( item );
}
}
void FileWidget::setInitialItem( const TQString& filename )
{
m_initialName = filename;
}
void FileWidget::slotURLEntered( const KURL& url )
{
if ( m_fileFinder )
m_fileFinder->completion()->setDir( url.path() );
}
void FileWidget::slotFinishedLoading()
{
KFileItem *current = getCurrentItem( false );
if ( !m_initialName.isEmpty() )
setCurrentItem( m_initialName );
else if ( !current )
setCurrentItem( view()->items()->getFirst() );
m_initialName = TQString();
emit finished();
}
TQSize FileWidget::sizeHint() const
{
return TQSize( 300, 300 );
}
void FileWidget::resizeEvent( TQResizeEvent *e )
{
KDirOperator::resizeEvent( e );
if ( m_fileFinder )
m_fileFinder->move( width() - m_fileFinder->width(),
height() - m_fileFinder->height() );
}
#include "filewidget.moc"