00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "launcherview.h"
00029
00030
00031 #include <opie2/odebug.h>
00032 #include <opie2/oresource.h>
00033 #include <qpe/config.h>
00034 #include <qtopia/qpeapplication.h>
00035 #include <qtopia/private/categories.h>
00036 #include <qtopia/categoryselect.h>
00037 #include <qtopia/mimetype.h>
00038 using namespace Opie::Core;
00039
00040 #include <qpe/qcopenvelope_qws.h>
00041
00042
00043 #include <qtimer.h>
00044 #include <qfileinfo.h>
00045 #include <qiconview.h>
00046 #include <qobjectlist.h>
00047
00048
00049
00050 #define BRIGHTEN_BUSY_ICON
00051
00052
00053 #define BOUNCE_BUSY_ICON
00054
00055 typedef QMap<QString,QPixmap>::Iterator pixiter;
00056
00057 class BgPixmap
00058 {
00059 public:
00060 BgPixmap( const QPixmap &p ) : pm(p), ref(1) {}
00061 QPixmap pm;
00062 int ref;
00063 };
00064
00065
00066 static QMap<QString,BgPixmap*> *bgCache = 0;
00067
00068 static void cleanup_cache()
00069 {
00070 QMap<QString,BgPixmap*>::Iterator it = bgCache->begin();
00071 while ( it != bgCache->end() ) {
00072 QMap<QString,BgPixmap*>::Iterator curr = it;
00073 ++it;
00074 delete (*curr);
00075 bgCache->remove( curr );
00076 }
00077 delete bgCache;
00078 bgCache = 0;
00079 }
00080
00081
00082 class LauncherItem : public QIconViewItem
00083 {
00084 public:
00085 enum iconstate_t {
00086 BASE_ICON,
00087 WAITING_ICON,
00088 EYE_ICON
00089 };
00090
00091 LauncherItem( QIconView *parent, AppLnk* applnk, bool bigIcon=TRUE );
00092 ~LauncherItem();
00093
00094 AppLnk *appLnk() const { return app; }
00095 AppLnk *takeAppLnk() { AppLnk* r=app; app=0; return r; }
00096
00097 void animateIcon();
00098 void resetIcon();
00099 bool isEyeImage()const{return m_EyeImage;}
00100
00101 virtual int compare ( QIconViewItem * i ) const;
00102 void paintItem( QPainter *p, const QColorGroup &cg );
00103
00104 void setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; }
00105 void setEyePixmap(const QPixmap&aIcon);
00106 virtual QPixmap*pixmap()const;
00107
00108 protected:
00109 bool isBigIcon;
00110 int iteration;
00111 AppLnk* app;
00112
00113 private:
00114 void paintAnimatedIcon( QPainter *p );
00115 BusyIndicatorType busyType;
00116 int psize;
00117 bool m_EyeImage;
00118 iconstate_t m_EyeImageSet;
00119 };
00120
00121 static bool s_IgnoreNextPix = false;
00122
00123 LauncherItem::LauncherItem( QIconView *parent, AppLnk *applnk, bool bigIcon )
00124 : QIconViewItem( parent, applnk->name(),
00125 bigIcon ? applnk->bigPixmap() :applnk->pixmap() ),
00126 isBigIcon( bigIcon ),
00127 iteration(0),
00128 app(applnk),
00129 psize( (bigIcon ? applnk->bigPixmap().width() :applnk->pixmap().width() ) ),
00130 m_EyeImage(false),
00131 m_EyeImageSet(BASE_ICON)
00132 {
00133 if (applnk->type().lower().startsWith("image/") && applnk->exec().contains("opie-eye",false)) {
00134 m_EyeImage = true;
00135 QMap<QString,QPixmap>::Iterator it = LauncherIconView::sm_EyeCache->find(applnk->file());
00136 if (it != LauncherIconView::sm_EyeCache->end()) {
00137 m_EyeImageSet = EYE_ICON;
00138 setPixmap(*it);
00139 }
00140 }
00141 }
00142
00143 LauncherItem::~LauncherItem()
00144 {
00145 LauncherIconView* liv = (LauncherIconView*)iconView();
00146 if ( liv->busyItem() == this )
00147 liv->setBusy(FALSE);
00148 delete app;
00149 }
00150
00151 QPixmap*LauncherItem::pixmap()const
00152 {
00153 if (m_EyeImage && m_EyeImageSet == BASE_ICON && s_IgnoreNextPix==false) {
00154 LauncherIconView* liv = (LauncherIconView*)iconView();
00155 liv->requestEyePix(this);
00156 }
00157 return QIconViewItem::pixmap();
00158 }
00159
00160 int LauncherItem::compare ( QIconViewItem * i ) const
00161 {
00162 LauncherIconView* view = (LauncherIconView*)iconView();
00163 return view->compare(app,((LauncherItem *)i)->appLnk());
00164 }
00165
00166 void LauncherItem::paintItem( QPainter *p, const QColorGroup &cg )
00167 {
00168 LauncherIconView* liv = (LauncherIconView*)iconView();
00169 QBrush oldBrush( liv->itemTextBackground() );
00170 QColorGroup mycg( cg );
00171 if ( liv->currentItem() == this ) {
00172 liv->setItemTextBackground( cg.brush( QColorGroup::Highlight ) );
00173 mycg.setColor( QColorGroup::Text, cg.color( QColorGroup::HighlightedText ) );
00174 }
00175
00176 QIconViewItem::paintItem(p,mycg);
00177
00178
00179 if ( liv->busyItem() == this )
00180 paintAnimatedIcon(p);
00181
00182 if ( liv->currentItem() == this )
00183 liv->setItemTextBackground( oldBrush );
00184 }
00185
00186 void LauncherItem::paintAnimatedIcon( QPainter *p )
00187 {
00188 LauncherIconView* liv = (LauncherIconView*)iconView();
00189 int pic = iteration % 16;
00190 int w = pixmap()->width(), h = pixmap()->height();
00191 QPixmap dblBuf( w, h + 4 );
00192 QPainter p2( &dblBuf );
00193 int x1, y1;
00194 if ( liv->itemTextPos() == QIconView::Bottom ) {
00195 x1 = x() + (width() - w) / 2 - liv->contentsX();
00196 y1 = y() - liv->contentsY();
00197 } else {
00198 x1 = x() - liv->contentsX();
00199 y1 = y() + (height() - h) / 2 - liv->contentsY();
00200 }
00201 y1 -= 2;
00202 p2.translate(-x1,-y1);
00203 liv->drawBackground( &p2, QRect(x1,y1,w,h+4) );
00204 int bounceY = 2;
00205 #ifdef BOUNCE_BUSY_ICON
00206 if ( busyType == BIT_Animated ) {
00207 bounceY = 4 - ((iteration+2)%8);
00208 bounceY = bounceY < 0 ? -bounceY : bounceY;
00209 }
00210 #endif
00211 p2.drawPixmap( x1, y1 + bounceY, *pixmap() );
00212 #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
00213 p2.drawPixmap( x1, y1 + bounceY, liv->busyPixmap(), w * pic, 0, w, h );
00214 #else
00215 Q_UNUSED( pic )
00216 #endif
00217 p->drawPixmap( x1, y1, dblBuf );
00218 }
00219
00220 void LauncherItem::animateIcon()
00221 {
00222 LauncherIconView* liv = (LauncherIconView*)iconView();
00223
00224 if ( liv->busyItem() != this || !app )
00225 return;
00226
00227
00228 if ( iteration == 0 ) {
00229 QPixmap src;
00230 pixiter it;
00231 if (isEyeImage() && (it=LauncherIconView::sm_EyeCache->find(appLnk()->file()))!=LauncherIconView::sm_EyeCache->end()) {
00232 src = (*it);
00233 } else {
00234 src = ((isBigIcon ? app->bigPixmap() : app->pixmap()));
00235 }
00236 QImage img = src.convertToImage();
00237 QRgb *rgb;
00238 int count;
00239 if ( img.depth() == 32 ) {
00240 rgb = (QRgb*)img.bits();
00241 count = img.bytesPerLine()/sizeof(QRgb)*img.height();
00242 } else {
00243 rgb = img.colorTable();
00244 count = img.numColors();
00245 }
00246 for ( int r = 0; r < count; r++, rgb++ ) {
00247 #if defined(BRIGHTEN_BUSY_ICON)
00248 QColor c(*rgb);
00249 int h, s, v;
00250 c.hsv(&h,&s,&v);
00251 c.setHsv(h,QMAX(s-24,0),QMIN(v+48,255));
00252 *rgb = qRgba(c.red(),c.green(),c.blue(),qAlpha(*rgb));
00253 #elif defined(ALPHA_FADE_BUSY_ICON)
00254 *rgb = qRgba(qRed(*rgb),qGreen(*rgb),qBlue(*rgb),qAlpha(*rgb)/2);
00255 #endif
00256 }
00257 src.convertFromImage( img );
00258 setPixmap( src );
00259 }
00260
00261 iteration++;
00262
00263
00264 QPainter p( liv->viewport() );
00265 paintAnimatedIcon( &p );
00266 }
00267
00268 void LauncherItem::resetIcon()
00269 {
00270 iteration = 0;
00271 if (isEyeImage()) {
00272 QMap<QString,QPixmap>::Iterator it = LauncherIconView::sm_EyeCache->find(appLnk()->file());
00273 if (it != LauncherIconView::sm_EyeCache->end()) {
00274 setPixmap(*it);
00275 return;
00276 }
00277 }
00278 setPixmap(isBigIcon ? app->bigPixmap() : app->pixmap());
00279 }
00280
00281 void LauncherItem::setEyePixmap(const QPixmap&aIcon)
00282 {
00283 if (!isEyeImage()) return;
00284 setPixmap(aIcon);
00285 m_EyeImageSet = EYE_ICON;
00286 }
00287
00288
00289
00290
00291
00292 QMap<QString,QPixmap>* LauncherIconView::sm_EyeCache=0;
00293
00294 LauncherIconView::LauncherIconView( QWidget* parent, const char* name )
00295 : QIconView(parent,name),tf(""),cf(0),bsy(0),busyTimer(0),bigIcns(TRUE),bgColor(white),numColumns(0)
00296 {
00297 m_EyeCallBack = 0;
00298 if (!sm_EyeCache) sm_EyeCache = new QMap<QString,QPixmap>();
00299 sortmeth = Name;
00300 hidden.setAutoDelete(TRUE);
00301 ike = FALSE;
00302 calculateGrid( Bottom );
00303 connect(&m_eyeTimer,SIGNAL(timeout()),this,SLOT(stopEyeTimer()));
00304 Config config( "Launcher" );
00305 config.setGroup( "GUI" );
00306 setStaticBackgroundPicture( config.readBoolEntry( "StaticBackground", true ) );
00307 }
00308
00309 LauncherIconView::~LauncherIconView()
00310 {
00311 odebug << "LauncherIconView::~LauncherIconView()" << oendl;
00312 #if 0 // debuggery
00313 QListIterator<AppLnk> it(hidden);
00314 AppLnk* l;
00315 while ((l=it.current())) {
00316 ++it;
00317
00318 }
00319 #endif
00320 }
00321
00322 void LauncherIconView::unsetPalette()
00323 {
00324 s_IgnoreNextPix = true;
00325 QIconView::unsetPalette();
00326 s_IgnoreNextPix = false;
00327 }
00328
00329 void LauncherIconView::setPalette(const QPalette & palette)
00330 {
00331 s_IgnoreNextPix = true;
00332 QIconView::setPalette(palette);
00333 s_IgnoreNextPix = false;
00334 }
00335
00336 void LauncherIconView::setStaticBackgroundPicture( bool enable )
00337 {
00338 staticBackground = enable;
00339 if ( staticBackground )
00340 {
00341 setStaticBackground( true );
00342 verticalScrollBar()->setTracking( false );
00343 }
00344 else
00345 {
00346 setStaticBackground( false );
00347 verticalScrollBar()->setTracking( true );
00348 }
00349 }
00350
00351 int LauncherIconView::compare(const AppLnk* a, const AppLnk* b)
00352 {
00353 switch (sortmeth) {
00354 case Name:
00355 return a->name().lower().compare(b->name().lower());
00356 case Date: {
00357 QFileInfo fa(a->linkFileKnown() ? a->linkFile() : a->file());
00358 QFileInfo fb(b->linkFileKnown() ? b->linkFile() : b->file());
00359 return fa.lastModified().secsTo(fb.lastModified());
00360 }
00361 case Type:
00362 return a->type().compare(b->type());
00363 }
00364 return 0;
00365 }
00366
00367 void LauncherIconView::setSortMethod( SortMethod m )
00368 {
00369 if ( sortmeth != m ) {
00370 sortmeth = m;
00371 sort();
00372 }
00373 }
00374
00375 void LauncherIconView::setCategoryFilter( int catfilter, bool resort )
00376 {
00377 if ( catfilter == -2 )
00378 cf = 0;
00379 else
00380 cf = catfilter;
00381 hideOrShowItems(resort);
00382 }
00383
00384 void LauncherIconView::setTypeFilter(const QString& typefilter, bool resort)
00385 {
00386 tf = QRegExp(typefilter,FALSE,TRUE);
00387 hideOrShowItems(resort);
00388 }
00389
00390 void LauncherIconView::setItemTextPos( ItemTextPos pos )
00391 {
00392 calculateGrid( pos );
00393 QIconView::setItemTextPos( pos );
00394 }
00395
00396 void LauncherIconView::drawBackground( QPainter *p, const QRect &r )
00397 {
00398 if ( bgPixmap.isNull() )
00399 {
00400 p->fillRect( r, bgColor );
00401 }
00402 else
00403 {
00404 if ( staticBackground )
00405 {
00406 p->drawTiledPixmap( r, bgPixmap, QPoint( r.x() % bgPixmap.width(), r.y() % bgPixmap.height() ) );
00407 }
00408 else
00409 {
00410 p->drawTiledPixmap( r, bgPixmap, QPoint( (r.x() + contentsX()) % bgPixmap.width(),
00411 (r.y() + contentsY()) % bgPixmap.height() ) );
00412 }
00413 }
00414 }
00415
00416 void LauncherIconView::addCatsAndMimes(AppLnk* app)
00417 {
00418
00419
00420
00421
00422 QString maj=app->type();
00423 int sl=maj.find('/');
00424 if (sl>=0) {
00425 QString k;
00426 k = maj.left(12) == "application/" ? maj : maj.left(sl);
00427 mimes.replace(k,(void*)1);
00428 }
00429 }
00430
00431 void LauncherIconView::setBusy(bool on)
00432 {
00433 #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
00434 if ( busyPix.isNull() ) {
00435 int size = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize();
00436 busyPix.convertFromImage( OResource::loadImage( "busy", OResource::NoScale ).smoothScale( size * 16, size ) );
00437 }
00438 #endif
00439
00440 if ( on ) {
00441 busyTimer = startTimer( 100 );
00442 } else {
00443 if ( busyTimer ) {
00444 killTimer( busyTimer );
00445 busyTimer = 0;
00446 }
00447 }
00448
00449 LauncherItem *c = on ? (LauncherItem*)currentItem() : 0;
00450
00451 if ( bsy != c ) {
00452 LauncherItem *oldBusy = bsy;
00453 bsy = c;
00454 if ( oldBusy ) {
00455 oldBusy->resetIcon();
00456 }
00457 if ( bsy ) {
00458 bsy->setBusyIndicatorType( busyType ) ;
00459 bsy->animateIcon();
00460 }
00461 }
00462 }
00463
00464 void LauncherIconView::clear()
00465 {
00466 mimes.clear();
00467 cats.clear();
00468 QIconView::clear();
00469 hidden.clear();
00470 }
00471
00472 QStringList LauncherIconView::mimeTypes() const
00473 {
00474 QStringList r;
00475 QDictIterator<void> it(mimes);
00476 while (it.current()) {
00477 r.append(it.currentKey());
00478 ++it;
00479 }
00480 r.sort();
00481 return r;
00482 }
00483
00484 LauncherItem*LauncherIconView::findDocItem(const QString&fname)
00485 {
00486 LauncherItem* item = (LauncherItem*)firstItem();
00487 while (item) {
00488 if (item->appLnk()->file()==fname) {
00489 break;
00490 }
00491 item = (LauncherItem*)item->nextItem();
00492 }
00493 return item;
00494 }
00495
00496 void LauncherIconView::setEyePixmap(const QPixmap&aPixmap,const QString&aFile,int width)
00497 {
00498 int s = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize();
00499 if (s!=width) return;
00500 LauncherItem*item = findDocItem(aFile);
00501 if (!item||!item->isEyeImage()) return;
00502 (*sm_EyeCache)[aFile]=aPixmap;
00503 item->setEyePixmap(aPixmap);
00504 }
00505
00506 void LauncherIconView::checkCallback()
00507 {
00508 if (!m_EyeCallBack) {
00509 m_EyeCallBack = new LauncherThumbReceiver();
00510 connect(m_EyeCallBack,SIGNAL(sig_Thumbnail(const QPixmap&,const QString&,int)),
00511 this,SLOT(setEyePixmap(const QPixmap&,const QString&,int)));
00512 m_eyeTimer.changeInterval(600000);
00513 }
00514 }
00515
00516 void LauncherIconView::addCheckItem(AppLnk* app)
00517 {
00518 LauncherItem*item = new LauncherItem( this, app, bigIcns );
00519 if (item->isEyeImage()) {
00520 checkCallback();
00521 }
00522 }
00523
00524 void LauncherIconView::requestEyePix(const LauncherItem*item)
00525 {
00526 if (!item) return;
00527 if (item->isEyeImage()) {
00528 checkCallback();
00529 int s = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize();
00530 m_EyeCallBack->requestThumb(item->appLnk()->file(),s,s);
00531 }
00532 }
00533
00534 void LauncherIconView::stopEyeTimer()
00535 {
00536 if (m_EyeCallBack) {
00537 disconnect(m_EyeCallBack,SIGNAL(sig_Thumbnail(const QPixmap&,const QString&,int)),
00538 this,SLOT(setEyePixmap(const QPixmap&,const QString&,int)));
00539 delete m_EyeCallBack;
00540 m_EyeCallBack=0;
00541 }
00542 m_eyeTimer.stop();
00543 }
00544
00545 void LauncherIconView::updateCategoriesAndMimeTypes()
00546 {
00547 mimes.clear();
00548 cats.clear();
00549 LauncherItem* item = (LauncherItem*)firstItem();
00550 while (item) {
00551 addCatsAndMimes(item->appLnk());
00552 item = (LauncherItem*)item->nextItem();
00553 }
00554 QListIterator<AppLnk> it(hidden);
00555 AppLnk* l;
00556 while ((l=it.current())) {
00557 addCatsAndMimes(l);
00558 ++it;
00559 }
00560 }
00561
00562 void LauncherIconView::hideOrShowItems(bool resort)
00563 {
00564 viewport()->setUpdatesEnabled( FALSE );
00565 hidden.setAutoDelete(FALSE);
00566 QList<AppLnk> links=hidden;
00567 hidden.clear();
00568 hidden.setAutoDelete(TRUE);
00569 LauncherItem* item = (LauncherItem*)firstItem();
00570 while (item) {
00571 links.append(item->takeAppLnk());
00572 item = (LauncherItem*)item->nextItem();
00573 }
00574 clear();
00575 QListIterator<AppLnk> it(links);
00576 AppLnk* l;
00577 while ((l=it.current())) {
00578 addItem(l,FALSE);
00579 ++it;
00580 }
00581 if ( resort && !autoArrange() )
00582 sort();
00583 viewport()->setUpdatesEnabled( TRUE );
00584 }
00585
00586 bool LauncherIconView::removeLink(const QString& linkfile,bool removeCache)
00587 {
00588 LauncherItem* item = (LauncherItem*)firstItem();
00589 AppLnk* l;
00590 bool did = FALSE;
00591 DocLnk dl(linkfile);
00592 while (item) {
00593 l = item->appLnk();
00594 LauncherItem *nextItem = (LauncherItem *)item->nextItem();
00595 if ( l->linkFileKnown() && l->linkFile() == linkfile || l->fileKnown() &&
00596 ( l->file() == linkfile || dl.isValid() && dl.file() == l->file() ) ) {
00597 if (removeCache) sm_EyeCache->remove(l->file());
00598 delete item;
00599 did = TRUE;
00600 }
00601 item = nextItem;
00602 }
00603 QListIterator<AppLnk> it(hidden);
00604 while ((l=it.current())) {
00605 ++it;
00606 if ( l->linkFileKnown() && l->linkFile() == linkfile
00607 || l->file() == linkfile
00608 || dl.isValid() && dl.file() == l->file() ) {
00609 hidden.removeRef(l);
00610 did = TRUE;
00611 }
00612 }
00613 return did;
00614 }
00615
00616 void LauncherIconView::addItem(AppLnk* app, bool resort)
00617 {
00618 addCatsAndMimes(app);
00619 if ( (tf.isEmpty() || tf.match(app->type()) >= 0)
00620 && (cf == 0 || app->categories().contains(cf)
00621 || cf == -1 && app->categories().count() == 0 ) ) {
00622 addCheckItem(app);
00623 } else {
00624 hidden.append(app);
00625 }
00626 if ( resort ){
00627 sort();
00628 }
00629 }
00630
00631 void LauncherIconView::changeItem(const AppLnk&old,AppLnk*nlink)
00632 {
00633 QString oldfile = old.file();
00634 QString newfile = nlink->file();
00635
00636 if (newfile != oldfile) {
00637 QMap<QString,QPixmap>::Iterator it = sm_EyeCache->find(oldfile);
00638 if (it != sm_EyeCache->end()) {
00639 (*sm_EyeCache)[newfile]=(*it);
00640 }
00641 removeLink(old.linkFile());
00642 } else {
00643 removeLink(old.linkFile(),false);
00644 }
00645 addItem(nlink,false);
00646 }
00647
00648 void LauncherIconView::timerEvent( QTimerEvent *te )
00649 {
00650 if ( te->timerId() == busyTimer ) {
00651 if ( bsy )
00652 bsy->animateIcon();
00653 } else {
00654 QIconView::timerEvent( te );
00655 }
00656 }
00657
00658 void LauncherIconView::setBigIcons( bool bi )
00659 {
00660 sm_EyeCache->clear();
00661 bigIcns = bi;
00662 #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
00663 busyPix.resize(0,0);
00664 #endif
00665 }
00666
00667 QIconViewItem* LauncherIconView::busyItem() const
00668 {
00669 return bsy;
00670 }
00671
00672 void LauncherIconView::setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; }
00673
00674 void LauncherIconView::calculateGrid( ItemTextPos pos )
00675 {
00676 int dw = QApplication::desktop()->width();
00677 int viewerWidth = dw-style().scrollBarExtent().width();
00678 if ( pos == Bottom ) {
00679 if( !numColumns ) {
00680 if ( viewerWidth <= 200 ) numColumns = 2;
00681 else if ( viewerWidth >= 400 ) numColumns = viewerWidth/96;
00682 else numColumns = 3;
00683 }
00684 setSpacing( 4 );
00685 setGridX( (viewerWidth-(numColumns+1)*spacing())/numColumns );
00686 setGridY( fontMetrics().height()*2+24 );
00687 } else {
00688 if( !numColumns ) {
00689 if ( viewerWidth < 150 ) numColumns = 1;
00690 else if ( viewerWidth >= 400 ) numColumns = viewerWidth/150;
00691 else numColumns = 2;
00692 }
00693 setSpacing( 2 );
00694 setGridX( (viewerWidth-(numColumns+1)*spacing())/numColumns );
00695 setGridY( fontMetrics().height()+2 );
00696 }
00697 }
00698
00699 void LauncherIconView::styleChange( QStyle &old )
00700 {
00701 QIconView::styleChange( old );
00702 calculateGrid( itemTextPos() );
00703 }
00704
00705 void LauncherIconView::keyPressEvent(QKeyEvent* e)
00706 {
00707 ike = TRUE;
00708 if ( e->key() == Key_F33 || e->key() == Key_Space ) {
00709 if ( (e->state() & ShiftButton) )
00710 emit mouseButtonPressed(ShiftButton, currentItem(), QPoint() );
00711 else
00712 returnPressed(currentItem());
00713 }
00714
00715 QIconView::keyPressEvent(e);
00716 ike = FALSE;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 LauncherView::LauncherView( QWidget* parent, const char* name, WFlags fl )
00726 : QVBox( parent, name, fl )
00727 {
00728 catmb = 0;
00729 icons = new LauncherIconView( this );
00730 setFocusProxy(icons);
00731 QPEApplication::setStylusOperation( icons->viewport(), QPEApplication::RightOnHold );
00732
00733 icons->setItemsMovable( FALSE );
00734 icons->setAutoArrange( TRUE );
00735 icons->setSorting( TRUE );
00736 icons->setFrameStyle( QFrame::NoFrame );
00737 icons->setMargin( 0 );
00738 icons->setSelectionMode( QIconView::NoSelection );
00739 icons->setBackgroundMode( PaletteBase );
00740 icons->setResizeMode( QIconView::Adjust );
00741 vmode = (ViewMode)-1;
00742 setViewMode( Icon );
00743
00744 connect( icons, SIGNAL(mouseButtonClicked(int,QIconViewItem*,const QPoint&)),
00745 SLOT(itemClicked(int,QIconViewItem*)) );
00746 connect( icons, SIGNAL(selectionChanged()),
00747 SLOT(selectionChanged()) );
00748 connect( icons, SIGNAL(returnPressed(QIconViewItem*)),
00749 SLOT(returnPressed(QIconViewItem*)) );
00750 connect( icons, SIGNAL(mouseButtonPressed(int,QIconViewItem*,const QPoint&)),
00751 SLOT(itemPressed(int,QIconViewItem*)) );
00752
00753 tools = 0;
00754 setBackgroundType( Ruled, QString::null );
00755 }
00756
00757 LauncherView::~LauncherView()
00758 {
00759 if ( bgCache && bgCache->contains( bgName ) )
00760 (*bgCache)[bgName]->ref--;
00761 }
00762
00763
00764 bool LauncherView::bsy=FALSE;
00765
00766 void LauncherView::setBusy(bool on)
00767 {
00768 icons->setBusy(on);
00769 }
00770
00771 void LauncherView::setBusyIndicatorType( const QString& type ) {
00772 if ( type. lower ( ) == "animated" )
00773 icons->setBusyIndicatorType( BIT_Animated ) ;
00774 else
00775 icons->setBusyIndicatorType( BIT_Normal ) ;
00776 }
00777
00778 void LauncherView::hideIcons()
00779 {
00780 icons->hide();
00781 }
00782
00783 void LauncherView::setToolsEnabled(bool y)
00784 {
00785 if ( !y != !tools ) {
00786 if ( y ) {
00787 tools = new QHBox(this);
00788
00789 typemb = new QComboBox(tools);
00790 QSizePolicy p = typemb->sizePolicy();
00791 p.setHorData(QSizePolicy::Expanding);
00792 typemb->setSizePolicy(p);
00793
00794 updateTools();
00795 tools->show();
00796 } else {
00797 delete tools;
00798 tools = 0;
00799 }
00800 }
00801 }
00802
00803 void LauncherView::updateTools()
00804 {
00805 disconnect( typemb, SIGNAL(activated(int)),
00806 this, SLOT(showType(int)) );
00807 if ( catmb ) {
00808 disconnect( catmb, SIGNAL(signalSelected(int)),this,SLOT(showCategory(int)));
00809 }
00810
00811
00812 icons->updateCategoriesAndMimeTypes();
00813
00814 QString prev;
00815
00816
00817 QStringList types;
00818 typelist = icons->mimeTypes();
00819 for (QStringList::ConstIterator it = typelist.begin(); it!=typelist.end(); ++it) {
00820 QString t = *it;
00821 if ( t.left(12) == "application/" ) {
00822 MimeType mt(t);
00823 const AppLnk* app = mt.application();
00824 if ( app )
00825 t = app->name();
00826 else
00827 t = t.mid(12);
00828 } else {
00829 t[0] = t[0].upper();
00830 }
00831 types += t;
00832 }
00833 types << tr("All types");
00834 prev = typemb->currentText();
00835 typemb->clear();
00836 typemb->insertStringList(types);
00837 for (int i=0; i<typemb->count(); i++) {
00838 if ( typemb->text(i) == prev ) {
00839 typemb->setCurrentItem(i);
00840 break;
00841 }
00842 }
00843 if ( prev.isNull() ) {
00844 typemb->setCurrentItem(typemb->count()-1);
00845 }
00846
00847 int pcat = catmb ? catmb->currentCategory() : -2;
00848 if ( !catmb ) {
00849 catmb = new CategorySelect(tools);
00850 } else if (pcat!=-2) {
00851
00852 }
00853 Categories cats( 0 );
00854 cats.load( categoryFileName() );
00855 QArray<int> vl( 0 );
00856 catmb->setCategories( vl, "Document View",
00857 tr("Document View") );
00858 catmb->setRemoveCategoryEdit( TRUE );
00859 catmb->setAllCategories( TRUE );
00860 catmb->setCurrentCategory(pcat);
00861
00862
00863 if ( typemb->currentText() != prev )
00864 showType( typemb->currentItem() );
00865
00866 connect(typemb, SIGNAL(activated(int)), this, SLOT(showType(int)));
00867 connect(catmb, SIGNAL(signalSelected(int)), this, SLOT(showCategory(int)));
00868 }
00869
00870 void LauncherView::sortBy(int s)
00871 {
00872 icons->setSortMethod((LauncherIconView::SortMethod)s);
00873 }
00874
00875 void LauncherView::showType(int t)
00876 {
00877 if ( t >= (int)typelist.count() ) {
00878 icons->setTypeFilter("",TRUE);
00879 } else {
00880 QString ty = typelist[t];
00881 if ( !ty.contains('/') )
00882 ty += "/*";
00883 icons->setTypeFilter(ty,TRUE);
00884 }
00885 }
00886
00887 void LauncherView::showCategory( int c )
00888 {
00889 icons->setCategoryFilter( c, TRUE );
00890 }
00891
00892 void LauncherView::setViewMode( ViewMode m )
00893 {
00894 odebug << "LauncherView::setViewMode( ViewMode m )" << oendl;
00895 if ( vmode != m ) {
00896 bool bigIcons = m == Icon;
00897 icons->viewport()->setUpdatesEnabled( FALSE );
00898 icons->setBigIcons( bigIcons );
00899 switch ( m ) {
00900 case List:
00901 icons->setItemTextPos( QIconView::Right );
00902 break;
00903 case Icon:
00904 icons->setItemTextPos( QIconView::Bottom );
00905 break;
00906 }
00907 icons->hideOrShowItems( FALSE );
00908 icons->viewport()->setUpdatesEnabled( TRUE );
00909 vmode = m;
00910 }
00911 }
00912
00913
00914
00915
00916 QImage LauncherView::loadBackgroundImage(QString &bgName)
00917 {
00918 QImageIO imgio;
00919 QSize ds = qApp->desktop()->size();
00920 bool further_scaling = TRUE;
00921
00922 imgio.setFileName( bgName );
00923 imgio.setParameters("GetHeaderInformation");
00924
00925 if (imgio.read() == FALSE) {
00926 return imgio.image();
00927 }
00928
00929 if (imgio.image().width() < ds.width() &&
00930 imgio.image().height() < ds.height()) {
00931 further_scaling = FALSE;
00932 }
00933
00934 if (!imgio.image().bits()) {
00935
00936
00937
00938 QString param( "Scale( %1, %2, ScaleMin )" );
00939 imgio.setParameters(further_scaling ?
00940 param.arg(ds.width()).arg(ds.height()).latin1() :
00941 "");
00942 imgio.read();
00943 } else {
00944 if (further_scaling) {
00945 int t1 = imgio.image().width() * ds.height();
00946 int t2 = imgio.image().height() * ds.width();
00947 int dsth = ds.height();
00948 int dstw = ds.width();
00949
00950 if (t1 > t2) {
00951 dsth = t2 / imgio.image().width();
00952 } else {
00953 dstw = t1 / imgio.image().height();
00954 }
00955
00956
00957
00958
00959 return imgio.image().smoothScale(dstw, dsth);
00960 }
00961 }
00962
00963 return imgio.image();
00964 }
00965
00966 void LauncherView::setBackgroundType( BackgroundType t, const QString &val )
00967 {
00968 if ( !bgCache ) {
00969 bgCache = new QMap<QString,BgPixmap*>;
00970 qAddPostRoutine( cleanup_cache );
00971 }
00972
00973 if ( bgCache->contains( bgName ) )
00974 (*bgCache)[bgName]->ref--;
00975 bgName = "";
00976
00977 QPixmap bg;
00978
00979 switch ( t ) {
00980 case Ruled: {
00981 bgName = QString("Ruled_%1").arg(colorGroup().background().name());
00982 if ( bgCache->contains( bgName ) ) {
00983 (*bgCache)[bgName]->ref++;
00984 bg = (*bgCache)[bgName]->pm;
00985 } else {
00986 bg.resize( width(), 9 );
00987 QPainter painter( &bg );
00988 for ( int i = 0; i < 3; i++ ) {
00989 painter.setPen( white );
00990 painter.drawLine( 0, i*3, width()-1, i*3 );
00991 painter.drawLine( 0, i*3+1, width()-1, i*3+1 );
00992 painter.setPen( colorGroup().background().light(105) );
00993 painter.drawLine( 0, i*3+2, width()-1, i*3+2 );
00994 }
00995 painter.end();
00996 bgCache->insert( bgName, new BgPixmap(bg) );
00997 }
00998 break;
00999 }
01000
01001 case Image:
01002 if (!val.isEmpty()) {
01003 bgName = val;
01004 if ( bgCache->contains( bgName ) ) {
01005 (*bgCache)[bgName]->ref++;
01006 bg = (*bgCache)[bgName]->pm;
01007 } else {
01008 QString imgFile = bgName;
01009 bool tile = FALSE;
01010 if ( imgFile[0]!='/' || !QFile::exists(imgFile) ) {
01011 imgFile = OResource::findPixmap( imgFile );
01012 tile = TRUE;
01013 }
01014 QImage img = loadBackgroundImage(imgFile);
01015
01016
01017 if ( img.depth() == 1 )
01018 img = img.convertDepth(8);
01019 img.setAlphaBuffer(FALSE);
01020 bg.convertFromImage(img);
01021 bgCache->insert( bgName, new BgPixmap(bg) );
01022 }
01023 }
01024 break;
01025
01026 case SolidColor:
01027 default:
01028 break;
01029 }
01030
01031 const QObjectList *list = queryList( "QWidget", 0, FALSE );
01032 QObject *obj;
01033 for ( QObjectListIt it( *list ); (obj=it.current()); ++it ) {
01034 if ( obj->isWidgetType() ) {
01035 QWidget *w = (QWidget*)obj;
01036 w->setBackgroundPixmap( bg );
01037 if ( bgName.isEmpty() ) {
01038
01039 if ( val.isEmpty() )
01040 w->setBackgroundColor( colorGroup().base() );
01041 else
01042 w->setBackgroundColor( val );
01043 } else {
01044
01045 w->setBackgroundOrigin( ParentOrigin );
01046 }
01047 }
01048 }
01049 delete list;
01050
01051 bgType = t;
01052 icons->viewport()->update();
01053
01054 QTimer::singleShot( 1000, this, SLOT(flushBgCache()) );
01055 }
01056
01057 void LauncherView::setColNumber( int num )
01058 {
01059 icons->setColNumber( num );
01060 }
01061
01062 void LauncherIconView::setColNumber( int num )
01063 {
01064 numColumns = num;
01065 calculateGrid( Bottom );
01066 }
01067
01068 void LauncherView::setTextColor( const QColor &tc )
01069 {
01070 textCol = tc;
01071 QColorGroup cg = icons->colorGroup();
01072 cg.setColor( QColorGroup::Text, tc );
01073 icons->setPalette( QPalette(cg,cg,cg) );
01074 icons->viewport()->update();
01075 }
01076
01077 void LauncherView::setViewFont( const QFont &f )
01078 {
01079 icons->setFont( f );
01080 icons->hideOrShowItems( FALSE );
01081 }
01082
01083 void LauncherView::clearViewFont()
01084 {
01085 icons->unsetFont();
01086 icons->hideOrShowItems( FALSE );
01087 }
01088
01089 void LauncherView::resizeEvent(QResizeEvent *e)
01090 {
01091
01092 QVBox::resizeEvent( e );
01093
01094
01095 sort();
01096 }
01097
01098 void LauncherView::selectionChanged()
01099 {
01100 QIconViewItem* item = icons->currentItem();
01101 if ( item && item->isSelected() ) {
01102 AppLnk *appLnk = ((LauncherItem *)item)->appLnk();
01103 if ( icons->inKeyEvent() )
01104 emit clicked( appLnk );
01105 item->setSelected(FALSE);
01106 }
01107 }
01108
01109 void LauncherView::returnPressed( QIconViewItem *item )
01110 {
01111 if ( item ) {
01112 AppLnk *appLnk = ((LauncherItem *)item)->appLnk();
01113 emit clicked( appLnk );
01114 }
01115 }
01116
01117 void LauncherView::itemClicked( int btn, QIconViewItem *item )
01118 {
01119 if ( item ) {
01120 AppLnk *appLnk = ((LauncherItem *)item)->appLnk();
01121 if ( btn == LeftButton ) {
01122
01123 icons->setCurrentItem( item );
01124 emit clicked( appLnk );
01125 }
01126 item->setSelected(FALSE);
01127 }
01128 }
01129
01130 void LauncherView::itemPressed( int btn, QIconViewItem *item )
01131 {
01132 if ( item ) {
01133 AppLnk *appLnk = ((LauncherItem *)item)->appLnk();
01134 if ( btn == RightButton )
01135 emit rightPressed( appLnk );
01136 else if ( btn == ShiftButton )
01137 emit rightPressed( appLnk );
01138 item->setSelected(FALSE);
01139 }
01140 }
01141
01142 void LauncherView::removeAllItems()
01143 {
01144 odebug << "LauncherView::removeAllItems()" << oendl;
01145 if (LauncherIconView::sm_EyeCache) LauncherIconView::sm_EyeCache->clear();
01146 icons->clear();
01147 }
01148
01149 bool LauncherView::removeLink(const QString& linkfile)
01150 {
01151 return icons->removeLink(linkfile);
01152 }
01153
01154 void LauncherView::addItem(AppLnk* app, bool resort)
01155 {
01156 icons->addItem(app,resort);
01157 }
01158
01159 void LauncherView::changeItem(const AppLnk&old,AppLnk*nlink)
01160 {
01161 icons->changeItem(old,nlink);
01162 }
01163
01164 void LauncherView::setSortEnabled( bool v )
01165 {
01166 icons->setSorting( v );
01167 if ( v )
01168 sort();
01169 }
01170
01171 void LauncherView::setUpdatesEnabled( bool u )
01172 {
01173 icons->setUpdatesEnabled( u );
01174 }
01175
01176 void LauncherView::sort()
01177 {
01178 icons->sort();
01179 }
01180
01181 void LauncherView::paletteChange( const QPalette &p )
01182 {
01183 icons->unsetPalette();
01184 QVBox::paletteChange( p );
01185 if ( bgType == Ruled )
01186 setBackgroundType( Ruled, QString::null );
01187 QColorGroup cg = icons->colorGroup();
01188 cg.setColor( QColorGroup::Text, textCol );
01189 icons->setPalette( QPalette(cg,cg,cg) );
01190 }
01191
01192 void LauncherView::fontChanged(const QFont&)
01193 {
01194 odebug << "LauncherView::fontChanged()" << oendl;
01195 icons->hideOrShowItems( FALSE );
01196 }
01197
01198 void LauncherView::relayout(void)
01199 {
01200 icons->hideOrShowItems(FALSE);
01201 }
01202
01203 void LauncherView::flushBgCache()
01204 {
01205 if ( !bgCache )
01206 return;
01207
01208 QMap<QString,BgPixmap*>::Iterator it = bgCache->begin();
01209 while ( it != bgCache->end() ) {
01210 QMap<QString,BgPixmap*>::Iterator curr = it;
01211 ++it;
01212 if ( (*curr)->ref == 0 ) {
01213 delete (*curr);
01214 bgCache->remove( curr );
01215 }
01216 }
01217 }
01218
01219
01220
01221
01222
01223
01224 QDataStream &operator>>( QDataStream& s, PixmapInfo& inf ) {
01225 s >> inf.file >> inf.pixmap >> inf.width >> inf.height;
01226 return s;
01227 }
01228
01229 QDataStream &operator<<( QDataStream& s, const PixmapInfo& inf) {
01230 return s << inf.file << inf.width << inf.height;
01231 }
01232
01233 LauncherThumbReceiver::LauncherThumbReceiver()
01234 :QObject(),requestTimer(this)
01235 {
01236
01237 connect(&requestTimer,SIGNAL(timeout()),SLOT(sendRequest()));
01238 QCopChannel * chan = new QCopChannel( "QPE/opie-eye",this );
01239 connect(chan, SIGNAL(received(const QCString&,const QByteArray&)),
01240 this, SLOT(recieve(const QCString&,const QByteArray&)) );
01241
01242 {
01243 QCopEnvelope( "QPE/Application/opie-eye_slave", "refUp()" );
01244 }
01245 }
01246
01247 LauncherThumbReceiver::~LauncherThumbReceiver()
01248 {
01249 {
01250 QCopEnvelope( "QPE/Application/opie-eye_slave", "refDown()" );
01251 }
01252 }
01253
01254 void LauncherThumbReceiver::recieve( const QCString&str, const QByteArray&at )
01255 {
01256 PixmapInfos pixinfos;
01257 QDataStream stream( at, IO_ReadOnly );
01258
01259
01260 if ( str == "pixmapsHandled(PixmapList)" )
01261 stream >> pixinfos;
01262
01263 for ( PixmapInfos::Iterator it = pixinfos.begin(); it != pixinfos.end(); ++it ) {
01264 emit sig_Thumbnail((*it).pixmap,(*it).file,(*it).width);
01265 }
01266 }
01267
01268 void LauncherThumbReceiver::requestThumb(const QString&file,int width,int height)
01269 {
01270 PixmapInfo rItem;
01271 rItem.file = file;
01272 rItem.width = width;
01273 rItem.height = height;
01274 m_inThumbNail.append(rItem);
01275 if (!requestTimer.isActive()) {
01276 requestTimer.start(100,true);
01277 }
01278 }
01279
01280 void LauncherThumbReceiver::sendRequest()
01281 {
01282 if (m_inThumbNail.count()>0) {
01283 QCopEnvelope env("QPE/opie-eye_slave", "pixmapInfos(PixmapInfos)" );
01284 env << m_inThumbNail;
01285 m_inThumbNail.clear();
01286 }
01287 }