filebrowser.cpp

来自「Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3」· C++ 代码 · 共 1,050 行 · 第 1/2 页

CPP
1,050
字号
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define QTOPIA_INTERNAL_FILEOPERATIONS#include "inlineedit.h"#include "filebrowser.h"#include <qtopia/resource.h>#include <qtopia/config.h>#include <qtopia/global.h>#include <qtopia/mimetype.h>#include <qtopia/applnk.h>#include <qtopia/services.h>#include <qtopia/qcopenvelope_qws.h>#ifdef QWS#include <qcopchannel_qws.h>#endif#include <qmessagebox.h>#include <qdir.h>#include <qregexp.h>#include <qheader.h>#include <qtopia/qpetoolbar.h>#include <qpopupmenu.h>#include <qtopia/qpemenubar.h>#include <qaction.h>#include <qstringlist.h>#include <qcursor.h>#include <qmultilineedit.h>#include <qfont.h>#include <qtooltip.h>#if defined(Q_OS_LINUX) || defined(_OS_LINUX_)#include <unistd.h>#endif#include <stdlib.h>#include <sys/stat.h>static int fileViewInstances = 0;static QPixmap	*pmLockedFolder;static QPixmap	*pmFolder;static QPixmap	*pmLocked;static QPixmap	*pmLibrary;static QPixmap	*pmUnknown;////  FileItem//FileItem::FileItem( QListView * parent, const QFileInfo & fi )    : QListViewItem( parent ),      fileInfo( fi ){    QDate d = fi.lastModified().date();    setText( 0, fi.fileName() );#ifndef QTOPIA_PHONE    setText( 1, sizeString( fi.size() ) + " " );    setText( 2, QString().sprintf("%4d-%02d-%02d",d.year(), d.month(), d.day() ) );#endif    MimeType mt(fi.filePath());#ifndef QTOPIA_PHONE    if( fi.isDir() )	setText( 3, "directory" );    else if( isLib() )	setText( 3, "library" );    else	setText( 3, mt.description() );#endif    QPixmap pm;    if( fi.isDir() ){	if( !QDir( fi.filePath() ).isReadable() )	    pm = *pmLockedFolder;	else	    pm = *pmFolder;    }    else if( !fi.isReadable() )	pm = *pmLocked;    else if( isLib() )	pm = *pmLibrary;    else	pm = mt.pixmap();    if ( pm.isNull() )	pm = *pmUnknown;    setPixmap(0,pm);}QString FileItem::sizeString( unsigned int s ){    double size = s;    if ( size > 1024 * 1024 * 1024 )		return QString().sprintf( "%.1f", size / ( 1024 * 1024 * 1024 ) ) + "G";    else if ( size > 1024 * 1024 )		return QString().sprintf( "%.1f", size / ( 1024 * 1024 ) ) + "M";    else if ( size > 1024 )		return QString().sprintf( "%.1f", size / ( 1024 ) ) + "K";    else		return QString::number( size ) + "B";}QString FileItem::key( int column, bool ascending ) const{    QString tmp;    ascending = ascending;    if( (column == 0) && fileInfo.isDir() ){ // Sort by name		// We want the directories to appear at the top of the list		tmp = (char) 0;		return (tmp + text( column ).lower());    }    else if( column == 2 ) { // Sort by date		QDateTime epoch( QDate( 1980, 1, 1 ) );        tmp.sprintf( "%08d", epoch.secsTo( fileInfo.lastModified() ) );		return tmp;    }    else if( column == 1 ) { // Sort by size		return tmp.sprintf( "%08d", fileInfo.size() );    }    return text( column ).lower();}bool FileItem::isLib(){    // This is of course not foolproof    if( !qstrncmp("lib", fileInfo.baseName(), 3) &&		( fileInfo.extension().contains( "so" ) ||		  fileInfo.extension().contains( "a" ) ) )		return TRUE;    else		return FALSE;}int FileItem::launch(){    //    // If this item is in $QPEDIR/Documents, pass it's    // associated .desktop file along to the third party rather    // than itself, to avoid double referencing the same file from    // separate .desktop files.    //    QString	file_to_launch = fileInfo.filePath();    MimeType	mt(fileInfo.filePath());    QString	fname_desktop(file_to_launch);    if (file_to_launch.contains(QDir::homeDirPath() + "/Documents")) {	int	idx;	idx = fname_desktop.findRev('.');           // fix suffix	if (idx != -1) {	    fname_desktop.truncate(idx);	}	fname_desktop += ".desktop";	idx = fname_desktop.findRev('/');           // take filename only	if (idx != -1) {	    fname_desktop = fname_desktop.right(fname_desktop.length() - idx);	}	fname_desktop = QDir::homeDirPath() + "/Documents/" + mt.id() +	       fname_desktop;    }    if (!QFile::exists(fname_desktop)) {	//	// We're trying to open a file that lives in $QPEDIR/Documents	// but doesn't have an associated .desktop.  Something bad has	// happened to get into this state; revert back to opening the	// file we were originally asked for.	//	fname_desktop = fileInfo.filePath();    }    QString type = mt.id();    if (isExecutable() && type.contains("application/octet-stream") ) {        int cpid = fork();                switch (cpid){            case -1:	        QMessageBox::warning( 0, QObject::tr( "File Manager" ),                        QObject::tr( "<qt>Cannot fork this process.</qt>" ), QObject::tr( "&OK" ) );                break;            case 0:                qDebug("Filebrowser: executing " + file_to_launch);                execl(file_to_launch, file_to_launch, 0);                break;            default:                //parent                break;        }    } else {        Config cfg(Service::appConfig("Open/"+type),Config::File);        cfg.setGroup("Standard");        if ( cfg.readNumEntry("Version") > 100 ) {	    // Use Open service            QCopEnvelope e(Service::channel("Open/"+type), "openFile(QString)");	    e << fname_desktop;        } else {	    // Use setDocument()	    DocLnk doc( fname_desktop, FALSE );	    doc.execute();        }    }    listView()->clearSelection();    return 1;}bool FileItem::rename( const QString & name ){    QString oldpath, newpath;    if ( name.isEmpty() )		return FALSE;    if ( name.contains( QRegExp("[/\\$\"\'\\*\\?]") ) )		return FALSE;    oldpath = fileInfo.filePath();    newpath = fileInfo.dirPath() + "/" + name;    if ( ::rename( oldpath.local8Bit().data(), newpath.local8Bit().data() ) != 0 )		return FALSE;    else		return TRUE;}////  FileView//FileView::FileView( const QString & dir, QWidget * parent,					const char * name )    : QListView( parent, name ),      menuTimer( this ),      le( NULL ),      itemToRename( NULL ){    setFrameStyle( NoFrame );    addColumn( "Name" );#ifndef QTOPIA_PHONE    addColumn( "Date" );    addColumn( "Size" );    addColumn( "Type" );#endif    setMultiSelection( TRUE );    header()->hide();#ifndef QTOPIA_PHONE    setColumnWidthMode( 0, Manual );    setColumnWidthMode( 3, Manual );    // right align yize column    setColumnAlignment( 1, AlignRight );#else    setColumnWidthMode( 0, Maximum );#endif    if ( fileViewInstances++ == 0 )	scaleIcons();    generateDir( dir );    connect( this, SIGNAL( clicked(QListViewItem*)),			 SLOT( itemClicked(QListViewItem*)) );    connect( this, SIGNAL( doubleClicked(QListViewItem*)),			 SLOT( itemDblClicked(QListViewItem*)) );    connect( this, SIGNAL( selectionChanged() ), SLOT( cancelMenuTimer() ) );    connect( &menuTimer, SIGNAL( timeout() ), SLOT( showFileMenu() ) );}FileView::~FileView(void){    if ( --fileViewInstances == 0 ) {	delete pmLockedFolder;	delete pmFolder;	delete pmLocked;	delete pmLibrary;	delete pmUnknown;    }}void FileView::resizeEvent( QResizeEvent *e ){#ifndef QTOPIA_PHONE    setColumnWidth( 0, width() - 2 * lineWidth() - 20 - columnWidth( 1 ) - columnWidth( 2 ) );    // hide type column, we use it for "sort by type" only    setColumnWidth( 3, 0 );    QListView::resizeEvent( e );#else    Q_UNUSED(e);#endif}void FileView::updateDir(){    generateDir( currentDir );}void FileView::setDir( const QString & dir ){    if ( dir.startsWith( "/dev" ) ) {	menuTimer.stop();	QMessageBox::warning( this, tr( "File Manager" ),			      tr( "<qt>Can't show /dev directory.</qt>" ), tr( "&OK" ) );	return;    }    dirHistory += currentDir;    generateDir( dir );}void FileView::generateDir( const QString & dir ){    QDir d( dir );    if( d.exists() && !d.isReadable() ) return;    //currentDir = d.canonicalPath();    currentDir = d.path(); // store symlinks    d.setFilter( QDir::Dirs | QDir::Files );    d.setSorting( QDir::Name | QDir::DirsFirst | QDir::IgnoreCase |				  QDir::Reversed );    const QFileInfoList * list = d.entryInfoList();    QFileInfoListIterator it( *list );    QFileInfo *fi;    clear();    while( (fi = it.current()) ){		if( (fi->fileName() == ".") || (fi->fileName() == "..") ){			++it;			continue;		}		(void) new FileItem( (QListView *) this, *fi );		++it;    }    emit dirChanged();}void FileView::rename(){    itemToRename = (FileItem *) currentItem();    const QPixmap * pm;    int pmw;    if( itemToRename == NULL ) return;    if( ( pm = itemToRename->pixmap( 0 ) ) == NULL )		pmw = 0;    else		pmw = pm->width();    ensureItemVisible( itemToRename );    horizontalScrollBar()->setValue( 0 );    horizontalScrollBar()->setEnabled( FALSE );    verticalScrollBar()->setEnabled( FALSE );    selected = isSelected( itemToRename );    setSelected( itemToRename, FALSE );    if( le == NULL ){	le = new InlineEdit( this );	le->setFrame( FALSE );#ifndef QTOPIA_PHONE	connect( le, SIGNAL( lostFocus() ), SLOT( endRenaming() ) );#endif	connect(le, SIGNAL(returnPressed()), this, SLOT(endRenaming()));    }    QRect r = itemRect( itemToRename );    r.setTop( r.top() + frameWidth() + 1 );    r.setLeft( r.left() + frameWidth() + pmw );    r.setBottom( r.bottom() + frameWidth() );    r.setWidth( columnWidth( 0 ) - pmw );    le->setGeometry( r );    le->setText( itemToRename->text( 0 ) );    le->selectAll();    le->show();    le->setFocus();}void FileView::endRenaming(){    if( le && itemToRename ) {	le->hide();	setSelected( itemToRename, selected );	if (itemToRename) {	    if( !itemToRename->rename( le->text() ) ){		QMessageBox::warning( this, tr( "Rename file" ),		    tr( "Rename failed!" ), tr( "&OK" ) );	    } else {		updateDir();	    }	    itemToRename = NULL;	    horizontalScrollBar()->setEnabled( TRUE );	    verticalScrollBar()->setEnabled( TRUE );	}    }}void FileView::copy(){    endRenaming();    // dont keep cut files any longer than necessary    // ##### a better inmplementation might be to rename the CUT file    // ##### to ".QPE-FILEBROWSER-MOVING" rather than copying it.    QString sysCmd = QString("rm -rf %1qpemoving").arg(Global::tempDir());    system ( sysCmd.local8Bit().data() );    FileItem * i;    if((i = (FileItem *) firstChild()) == 0) return;    flist.clear();    while( i ){		if( i->isSelected() /*&& !i->isDir()*/ ){			flist += i->getFilePath();		}		i = (FileItem *) i->nextSibling();    }}void FileView::paste(){    int i, err;    QString cmd, dest, basename, cd = currentDir;    if(cd == "/") cd = "";    for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it ) {		basename = (*it).mid((*it).findRev("/") + 1, (*it).length());		dest = cd + "/" + basename;		if( QFile( dest ).exists() ){			i = 1;			dest = cd + "/" + tr("Copy of %1").arg(basename);			while( QFile( dest ).exists() ){				dest = cd + "/" + tr("Copy (%1) of %2","number,filename").				    arg(i++).arg(basename);			}		}		//		// Copy a directory recursively using the "cp" command -		// may have to be changed		//		if( QFileInfo( (*it) ).isDir() ){			cmd = "/bin/cp -fpR \"" + (*it) +"\" " + "\"" + dest + "\"";			err = system( cmd.local8Bit().data() );		} else if( !copyFile( dest, (*it) ) ){			err = -1;		} else {			err = 0;		}		if ( err != 0 ) {			QMessageBox::warning( this, tr("Paste file"), tr("Paste failed!"),								  tr("OK") );			break;		} else {			updateDir();			QListViewItem * i = firstChild();			basename = dest.mid( dest.findRev("/") + 1, dest.length() );			while( i ){				if( i->text(0) == basename ){					setCurrentItem( i );					ensureItemVisible( i );					break;				}				i = i->nextSibling();			}		}    }}bool FileView::copyFile( const QString & dest, const QString & src ){    char bf[ 50000 ];    int  bytesRead;    bool success = TRUE;    struct stat status;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?