00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define QTOPIA_INTERNAL_FSLP
00024
00025 #include "fileselector.h"
00026 #include "fileselector_p.h"
00027 #include "global.h"
00028 #include "resource.h"
00029 #include "config.h"
00030 #include "storage.h"
00031 #include "qpemenubar.h"
00032 #include <qcopchannel_qws.h>
00033 #include "lnkproperties.h"
00034 #include <qpe/qpeapplication.h>
00035 #include "categorymenu.h"
00036 #include "categoryselect.h"
00037 #include "mimetype.h"
00038 #include <qpe/categories.h>
00039
00040 #include <stdlib.h>
00041
00042 #include <qdir.h>
00043 #include <qwidget.h>
00044 #include <qpopupmenu.h>
00045 #include <qtoolbutton.h>
00046 #include <qpushbutton.h>
00047 #include <qheader.h>
00048 #include <qtooltip.h>
00049 #include <qwhatsthis.h>
00050
00051 class TypeCombo : public QComboBox
00052 {
00053 Q_OBJECT
00054 public:
00055 TypeCombo( QWidget *parent, const char *name=0 )
00056 : QComboBox( parent, name )
00057 {
00058 connect( this, SIGNAL(activated(int)), this, SLOT(selectType(int)) );
00059 }
00060
00061 void reread( DocLnkSet &files, const QString &filter );
00062
00063 signals:
00064 void selected( const QString & );
00065
00066 protected slots:
00067 void selectType( int idx ) {
00068 emit selected( typelist[idx] );
00069 }
00070
00071 protected:
00072 QStringList typelist;
00073 QString prev;
00074 };
00075
00076 void TypeCombo::reread( DocLnkSet &files, const QString &filter )
00077 {
00078 typelist.clear();
00079 QStringList filters = QStringList::split( ';', filter );
00080 int pos = filter.find( '/' );
00081
00082 if ( filters.count() == 1 && pos >= 0 && filter[pos+1] != '*' ) {
00083 typelist.append( filter );
00084 clear();
00085 QString minor = filter.mid( pos+1 );
00086 minor[0] = minor[0].upper();
00087 insertItem( tr("%1 files").arg(minor) );
00088 setCurrentItem(0);
00089 setEnabled( FALSE );
00090 return;
00091 }
00092
00093 QListIterator<DocLnk> dit( files.children() );
00094 for ( ; dit.current(); ++dit ) {
00095 if ( !typelist.contains( (*dit)->type() ) )
00096 typelist.append( (*dit)->type() );
00097 }
00098
00099 QStringList types;
00100 QStringList::ConstIterator it;
00101 for (it = typelist.begin(); it!=typelist.end(); ++it) {
00102 QString t = *it;
00103 if ( t.left(12) == "application/" ) {
00104 MimeType mt(t);
00105 const AppLnk* app = mt.application();
00106 if ( app )
00107 t = app->name();
00108 else
00109 t = t.mid(12);
00110 } else {
00111 QString major, minor;
00112 int pos = t.find( '/' );
00113 if ( pos >= 0 ) {
00114 major = t.left( pos );
00115 minor = t.mid( pos+1 );
00116 }
00117 if ( minor.find( "x-" ) == 0 )
00118 minor = minor.mid( 2 );
00119 minor[0] = minor[0].upper();
00120 major[0] = major[0].upper();
00121 if ( filters.count() > 1 )
00122 t = tr("%1 %2", "minor mimetype / major mimetype").arg(minor).arg(major);
00123 else
00124 t = minor;
00125 }
00126 types += tr("%1 files").arg(t);
00127 }
00128 for (it = filters.begin(); it!=filters.end(); ++it) {
00129 typelist.append( *it );
00130 int pos = (*it).find( '/' );
00131 if ( pos >= 0 ) {
00132 QString maj = (*it).left( pos );
00133 maj[0] = maj[0].upper();
00134 types << tr("All %1 files").arg(maj);
00135 }
00136 }
00137 if ( filters.count() > 1 ) {
00138 typelist.append( filter );
00139 types << tr("All files");
00140 }
00141 prev = currentText();
00142 clear();
00143 insertStringList(types);
00144 for (int i=0; i<count(); i++) {
00145 if ( text(i) == prev ) {
00146 setCurrentItem(i);
00147 break;
00148 }
00149 }
00150 if ( prev.isNull() )
00151 setCurrentItem(count()-1);
00152 setEnabled( TRUE );
00153 }
00154
00155
00156
00157
00158 FileSelectorItem::FileSelectorItem( QListView *parent, const DocLnk &f )
00159 : QListViewItem( parent ), fl( f )
00160 {
00161 setText( 0, f.name() );
00162 setPixmap( 0, f.pixmap() );
00163 }
00164
00165 FileSelectorItem::~FileSelectorItem()
00166 {
00167 }
00168
00169 FileSelectorView::FileSelectorView( QWidget *parent, const char *name )
00170 : QListView( parent, name )
00171 {
00172 setAllColumnsShowFocus( TRUE );
00173 addColumn( tr( "Name" ) );
00174 header()->hide();
00175 }
00176
00177 FileSelectorView::~FileSelectorView()
00178 {
00179 }
00180
00181 void FileSelectorView::keyPressEvent( QKeyEvent *e )
00182 {
00183 QString txt = e->text();
00184 if (e->key() == Key_Space)
00185 emit returnPressed( currentItem() );
00186 else if ( !txt.isNull() && txt[0] > ' ' && e->key() < 0x1000 )
00187 e->ignore();
00188 else
00189 QListView::keyPressEvent(e);
00190 }
00191
00192 class NewDocItem : public FileSelectorItem
00193 {
00194 public:
00195 NewDocItem( QListView *parent, const DocLnk &f )
00196 : FileSelectorItem( parent, f ) {
00197 setText( 0, QObject::tr("New Document") );
00198 QImage img( Resource::loadImage( "new" ) );
00199 QPixmap pm;
00200 pm = img.smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() );
00201 setPixmap( 0, pm );
00202 }
00203 QString key ( int, bool ) const {
00204 return QString("\n");
00205 }
00206
00207 void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) {
00208 QFont oldFont = p->font();
00209 QFont newFont = p->font();
00210 newFont.setWeight( QFont::Bold );
00211 p->setFont( newFont );
00212 FileSelectorItem::paintCell( p, cg, column, width, alignment );
00213 p->setFont( oldFont );
00214 }
00215
00216 int width( const QFontMetrics &fm, const QListView *v, int c ) const {
00217 return FileSelectorItem::width( fm, v, c )*4/3;
00218 }
00219 };
00220
00221
00222
00223 class FileSelectorPrivate
00224 {
00225 public:
00226 TypeCombo *typeCombo;
00227 CategorySelect *catSelect;
00228 QValueList<QRegExp> mimeFilters;
00229 int catId;
00230 bool showNew;
00231 NewDocItem *newDocItem;
00232 DocLnkSet files;
00233 QHBox *toolbar;
00234 };
00235
00281 FileSelector::FileSelector( const QString &f, QWidget *parent, const char *name, bool newVisible, bool closeVisible )
00282 : QVBox( parent, name ), filter( f )
00283 {
00284 setMargin( 0 );
00285 setSpacing( 0 );
00286
00287 d = new FileSelectorPrivate();
00288 d->newDocItem = 0;
00289 d->showNew = newVisible;
00290 d->catId = -2;
00291
00292 d->toolbar = new QHBox( this );
00293 d->toolbar->setBackgroundMode( PaletteButton );
00294 d->toolbar->setSpacing( 0 );
00295 d->toolbar->hide();
00296
00297 QWidget *spacer = new QWidget( d->toolbar );
00298 spacer->setBackgroundMode( PaletteButton );
00299
00300 QToolButton *tb = new QToolButton( d->toolbar );
00301 tb->setPixmap( Resource::loadPixmap( "close" ) );
00302 connect( tb, SIGNAL( clicked() ), this, SIGNAL( closeMe() ) );
00303 buttonClose = tb;
00304 tb->setFixedSize( 18, 20 );
00305 tb->setAutoRaise( TRUE );
00306 QToolTip::add( tb, tr( "Close the File Selector" ) );
00307 QPEMenuToolFocusManager::manager()->addWidget( tb );
00308
00309 view = new FileSelectorView( this, "fileview" );
00310 QPEApplication::setStylusOperation( view->viewport(), QPEApplication::RightOnHold );
00311 connect( view, SIGNAL( mouseButtonClicked(int,QListViewItem*,const QPoint&,int) ),
00312 this, SLOT( fileClicked(int,QListViewItem*,const QPoint&,int) ) );
00313 connect( view, SIGNAL( mouseButtonPressed(int,QListViewItem*,const QPoint&,int) ),
00314 this, SLOT( filePressed(int,QListViewItem*,const QPoint&,int) ) );
00315 connect( view, SIGNAL( returnPressed(QListViewItem*) ),
00316 this, SLOT( fileClicked(QListViewItem*) ) );
00317
00318 QHBox *hb = new QHBox( this );
00319
00320 d->typeCombo = new TypeCombo( hb );
00321 connect( d->typeCombo, SIGNAL(selected(const QString&)),
00322 this, SLOT(typeSelected(const QString&)) );
00323 QWhatsThis::add( d->typeCombo, tr("Show documents of this type") );
00324
00325 Categories c;
00326 c.load(categoryFileName());
00327 QArray<int> vl( 0 );
00328 d->catSelect = new CategorySelect( hb );
00329 d->catSelect->setRemoveCategoryEdit( TRUE );
00330 d->catSelect->setCategories( vl, "Document View", tr("Document View") );
00331 d->catSelect->setAllCategories( TRUE );
00332 connect( d->catSelect, SIGNAL(signalSelected(int)), this, SLOT(catSelected(int)) );
00333 QWhatsThis::add( d->catSelect, tr("Show documents in this category") );
00334
00335 setCloseVisible( closeVisible );
00336
00337 QCopChannel *channel = new QCopChannel( "QPE/Card", this );
00338 connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
00339 this, SLOT(cardMessage(const QCString&,const QByteArray&)) );
00340
00341 reread();
00342 updateWhatsThis();
00343 }
00344
00348 FileSelector::~FileSelector()
00349 {
00350 delete d;
00351 }
00352
00358 int FileSelector::fileCount()
00359 {
00360 return d->files.children().count();;
00361 }
00362
00369 void FileSelector::createNew()
00370 {
00371 DocLnk f;
00372 emit newSelected( f );
00373 emit closeMe();
00374 }
00375
00376 void FileSelector::fileClicked( int button, QListViewItem *i, const QPoint &, int )
00377 {
00378 if ( !i )
00379 return;
00380 if ( button == Qt::LeftButton ) {
00381 fileClicked( i );
00382 }
00383 }
00384
00385 void FileSelector::filePressed( int button, QListViewItem *i, const QPoint &, int )
00386 {
00387 if ( !i || i == d->newDocItem )
00388 return;
00389 if ( button == Qt::RightButton ) {
00390 DocLnk l = ((FileSelectorItem *)i)->file();
00391 LnkProperties prop( &l );
00392 prop.showMaximized();
00393 prop.exec();
00394 reread();
00395 }
00396 }
00397
00398 void FileSelector::fileClicked( QListViewItem *i )
00399 {
00400 if ( !i )
00401 return;
00402 if ( i == d->newDocItem ) {
00403 createNew();
00404 } else {
00405 emit fileSelected( ( (FileSelectorItem*)i )->file() );
00406 emit closeMe();
00407 }
00408 }
00409
00410 void FileSelector::typeSelected( const QString &type )
00411 {
00412 d->mimeFilters.clear();
00413 QStringList subFilter = QStringList::split(";", type);
00414 for( QStringList::Iterator it = subFilter.begin(); it != subFilter.end(); ++it )
00415 d->mimeFilters.append( QRegExp(*it, FALSE, TRUE) );
00416 updateView();
00417 }
00418
00419 void FileSelector::catSelected( int c )
00420 {
00421 d->catId = c;
00422 updateView();
00423 }
00424
00425 void FileSelector::cardMessage( const QCString &msg, const QByteArray &)
00426 {
00427 if ( msg == "mtabChanged()" )
00428 reread();
00429 }
00430
00431
00436 const DocLnk *FileSelector::selected()
00437 {
00438 FileSelectorItem *item = (FileSelectorItem *)view->selectedItem();
00439 if ( item && item != d->newDocItem )
00440 return new DocLnk( item->file() );
00441 return NULL;
00442 }
00443
00471 void FileSelector::setNewVisible( bool b )
00472 {
00473 if ( d->showNew != b ) {
00474 d->showNew = b;
00475 updateView();
00476 updateWhatsThis();
00477 }
00478 }
00479
00487 void FileSelector::setCloseVisible( bool b )
00488 {
00489 if ( b )
00490 d->toolbar->show();
00491 else
00492 d->toolbar->hide();
00493 }
00494
00498 void FileSelector::setTypeComboVisible( bool b ) {
00499 if ( b )
00500 d->typeCombo->show();
00501 else
00502 d->typeCombo->hide();
00503 }
00507 void FileSelector::setCategorySelectVisible( bool b ) {
00508 if ( b )
00509 d->catSelect->show();
00510 else
00511 d->catSelect->hide();
00512 }
00513
00517 void FileSelector::reread()
00518 {
00519 d->files.clear();
00520 Global::findDocuments(&d->files, filter);
00521 d->typeCombo->reread( d->files, filter );
00522 updateView();
00523 }
00524
00525 void FileSelector::updateView()
00526 {
00527 FileSelectorItem *item = (FileSelectorItem *)view->selectedItem();
00528 if ( item == d->newDocItem )
00529 item = 0;
00530 QString oldFile;
00531 if ( item )
00532 oldFile = item->file().file();
00533 view->clear();
00534 QListIterator<DocLnk> dit( d->files.children() );
00535 for ( ; dit.current(); ++dit ) {
00536 bool mimeMatch = FALSE;
00537 if ( d->mimeFilters.count() ) {
00538 QValueList<QRegExp>::Iterator it;
00539 for ( it = d->mimeFilters.begin(); it != d->mimeFilters.end(); ++it ) {
00540 if ( (*it).match((*dit)->type()) >= 0 ) {
00541 mimeMatch = TRUE;
00542 break;
00543 }
00544 }
00545 } else {
00546 mimeMatch = TRUE;
00547 }
00548 if ( mimeMatch &&
00549 (d->catId == -2 || (*dit)->categories().contains(d->catId) ||
00550 (d->catId == -1 && (*dit)->categories().isEmpty())) ) {
00551 item = new FileSelectorItem( view, **dit );
00552 if ( item->file().file() == oldFile )
00553 view->setCurrentItem( item );
00554 }
00555 }
00556
00557 if ( d->showNew )
00558 d->newDocItem = new NewDocItem( view, DocLnk() );
00559 else
00560 d->newDocItem = 0;
00561
00562 if ( !view->selectedItem() || view->childCount() == 1 ) {
00563 view->setCurrentItem( view->firstChild() );
00564 view->setSelected( view->firstChild(), TRUE );
00565 }
00566 }
00567
00568 void FileSelector::updateWhatsThis()
00569 {
00570 QWhatsThis::remove( this );
00571 QString text = tr("Click to select a document from the list");
00572 if ( d->showNew )
00573 text += tr(", or select <b>New Document</b> to create a new document.");
00574 text += tr("<br><br>Click and hold for document properties.");
00575 QWhatsThis::add( this, text );
00576 }
00577
00578 #include "fileselector.moc"
00579