From 245dcac2f79d7409f80da37f9c6c47fff70dc949 Mon Sep 17 00:00:00 2001
From: zecke <zecke>
Date: Thu, 28 Aug 2003 14:37:27 +0000
Subject: -Make it compile

-apply Opie patches
-prepare BusyIndicator changes
-add QCOP method for showing the desktop and going to the next tab
---
(limited to 'core/launcher/launcherview.cpp')

diff --git a/core/launcher/launcherview.cpp b/core/launcher/launcherview.cpp
index 7117e0b..85163b6 100644
--- a/core/launcher/launcherview.cpp
+++ b/core/launcher/launcherview.cpp
@@ -20,15 +20,15 @@
 
 #include "launcherview.h"
 
-#include <qpe/qpeapplication.h>
-#include <qpe/applnk.h>
-#include <qpe/qpedebug.h>
-#include <qpe/categories.h>
-#include <qpe/categoryselect.h>
-#include <qpe/menubutton.h>
-#include <qpe/mimetype.h>
-#include <qpe/resource.h>
-#include <qpe/qpetoolbar.h>
+#include <qtopia/qpeapplication.h>
+#include <qtopia/applnk.h>
+#include <qtopia/qpedebug.h>
+#include <qtopia/private/categories.h>
+#include <qtopia/categoryselect.h>
+#include <qtopia/menubutton.h>
+#include <qtopia/mimetype.h>
+#include <qtopia/resource.h>
+#include <qtopia/qpetoolbar.h>
 //#include <qtopia/private/palmtoprecord.h>
 
 #include <qtimer.h>
@@ -38,12 +38,21 @@
 #include <qfileinfo.h>
 #include <qhbox.h>
 #include <qiconview.h>
+#include <qwidgetstack.h>
 #include <qpainter.h>
 #include <qregexp.h>
 #include <qtoolbutton.h>
 #include <qimage.h>
+#include <qlabel.h>
+#include <qobjectlist.h>
+
+
+// These define how the busy icon is animated and highlighted
+#define BRIGHTEN_BUSY_ICON
+//#define ALPHA_FADE_BUSY_ICON
+//#define USE_ANIMATED_BUSY_ICON_OVERLAY
+#define BOUNCE_BUSY_ICON
 
-#include <cstdlib>
 
 class BgPixmap
 {
@@ -60,6 +69,43 @@ enum BusyIndicatorType {
 
 static QMap<QString,BgPixmap*> *bgCache = 0;
 
+static void cleanup_cache()
+{
+    QMap<QString,BgPixmap*>::Iterator it = bgCache->begin();
+    while ( it != bgCache->end() ) {
+	QMap<QString,BgPixmap*>::Iterator curr = it;
+	++it;
+	delete (*curr);
+	bgCache->remove( curr );
+    }
+    delete bgCache;
+    bgCache = 0;
+}
+
+
+class LauncherItem : public QIconViewItem
+{
+public:
+    LauncherItem( QIconView *parent, AppLnk* applnk, bool bigIcon=TRUE );
+    ~LauncherItem();
+
+    AppLnk *appLnk() const { return app; }
+    AppLnk *takeAppLnk() { AppLnk* r=app; app=0; return r; }
+
+    void animateIcon();
+    void resetIcon();
+
+    virtual int compare ( QIconViewItem * i ) const;
+    void paintItem( QPainter *p, const QColorGroup &cg );
+protected:
+    bool isBigIcon;
+    int iteration;
+    AppLnk* app;
+private:
+    void paintAnimatedIcon( QPainter *p );
+};
+
+
 class LauncherIconView : public QIconView {
 public:
     LauncherIconView( QWidget* parent, const char* name=0 ) :
@@ -67,13 +113,13 @@ public:
 	tf(""),
 	cf(0),
 	bsy(0),
+	busyTimer(0),
 	bigIcns(TRUE),
 	bgColor(white)
     {
 	sortmeth = Name;
 	hidden.setAutoDelete(TRUE);
 	ike = FALSE;
-	busytimer = 0;
 	calculateGrid( Bottom );
     }
 
@@ -88,12 +134,17 @@ public:
 	}
 #endif
     }
-    
-    void setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; }
 
-    QPixmap* busyPixmap() const { return (QPixmap*)&bpm[abs(busystate)]; }
     QIconViewItem* busyItem() const { return bsy; }
-    void setBigIcons( bool bi ) { bigIcns = bi; }
+#ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
+    QPixmap busyPixmap() const { return busyPix; }
+#endif
+    void setBigIcons( bool bi ) {
+	bigIcns = bi;
+#ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
+	busyPix.resize(0,0);
+#endif
+    }
 
     void updateCategoriesAndMimeTypes();
 
@@ -104,73 +155,31 @@ public:
 
     void setBusy(bool on)
     {
-	QIconViewItem *c = on ? currentItem() : 0;
-	
-	if ( bsy != c ) {
-	    QIconViewItem *oldbsy = bsy;
-	    bsy = c;
-	
-	    if ( oldbsy )
-		oldbsy-> repaint ( );
-	
-	    if ( busytimer ) {
-		killTimer ( busytimer );
-	        busytimer = 0;
-	    }
-	    
-	    if ( bsy ) {
-		QPixmap *src = bsy-> QIconViewItem::pixmap();
-	    	for ( int i = 0; i <= 5; i++ ) {
-		    QImage img = src->convertToImage();
-		    QRgb* rgb;
-		    int count;
-		    if ( img.depth() == 32 ) {
-			rgb = (QRgb*)img.bits();
-			count = img.bytesPerLine()/sizeof(QRgb)*img.height();
-		    } else {
-			rgb = img.colorTable();
-			count = img.numColors();
-		    }
-		    int rc, gc, bc;
-		    int bs = abs ( i * 10 ) + 25;
-		    colorGroup().highlight().rgb( &rc, &gc, &bc );
-		    rc = rc * bs / 100;
-		    gc = gc * bs / 100;
-		    bc = bc * bs / 100;
-		
-		    for ( int r = 0; r < count; r++, rgb++ ) {
-			int ri = rc + qRed   ( *rgb ) * ( 100 - bs ) / 100;
-			int gi = gc + qGreen ( *rgb ) * ( 100 - bs ) / 100;
-			int bi = bc + qBlue  ( *rgb ) * ( 100 - bs ) / 100;
-			int ai = qAlpha ( *rgb );
-			*rgb = qRgba ( ri, gi, bi, ai );
-		    }
+#ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
+	if ( busyPix.isNull() ) {
+	    int size = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize();
+	    busyPix.convertFromImage( Resource::loadImage( "busy" ).smoothScale( size * 16, size ) );
+	}
+#endif
 
-		    bpm [i].convertFromImage( img );
-		}
-		    
-		if ( busyType == BIT_Blinking ) {
-		    busystate = 0;	
-		    busytimer = startTimer ( 200 );
-		}
-		else {		    
-		    busystate = 3;
-		}
-		timerEvent ( 0 );
+	if ( on ) {
+	    busyTimer = startTimer( 100 );
+	} else {
+	    if ( busyTimer ) {
+	        killTimer( busyTimer );
+		busyTimer = 0;
 	    }
 	}
-    }
 
-    virtual void timerEvent ( QTimerEvent *te )
-    {
-	if ( !te || ( te-> timerId ( ) == busytimer )) {
-	    if ( bsy ) {
-		busystate++;
-		if ( busystate > 5 )
-			busystate = -4;
-			
-		QScrollView::updateContents ( bsy-> pixmapRect ( false ));
-	    }
+	LauncherItem *c = on ? (LauncherItem*)currentItem() : 0;
+
+	if ( bsy != c ) {
+	    LauncherItem *oldBusy = bsy;
+	    bsy = c;
+	    if ( oldBusy )
+		oldBusy->resetIcon();
+	    if ( bsy )
+		bsy->animateIcon();
 	}
     }
 
@@ -178,8 +187,13 @@ public:
     void keyPressEvent(QKeyEvent* e)
     {
 	ike = TRUE;
-	if ( e->key() == Key_F33 /* OK button */ || e->key() == Key_Space )
-	    returnPressed(currentItem());
+	if ( e->key() == Key_F33 /* OK button */ || e->key() == Key_Space ) {
+	    if ( (e->state() & ShiftButton) )
+		emit mouseButtonPressed(ShiftButton, currentItem(), QPoint() );
+	    else
+		returnPressed(currentItem());
+	}
+
 	QIconView::keyPressEvent(e);
 	ike = FALSE;
     }
@@ -213,22 +227,11 @@ public:
 	}
     }
 
+    void setBackgroundOrigin( QWidget::BackgroundOrigin ) {
+    }
+
     void setBackgroundPixmap( const QPixmap &pm ) {
-	if ( pm. isNull ( )) {
-	    bgPixmap = pm;
-	}
-	else {    
-	    // This is need for bg images with alpha channel	
-	
-	    QPixmap tmp ( pm. size ( ), pm. depth ( ));
-    	
-	    QPainter p ( &tmp );
-	    p. fillRect ( 0, 0, pm. width ( ), pm. height ( ), bgColor. isValid ( ) ? bgColor : white );
-	    p. drawPixmap ( 0, 0, pm );    	
-	    p. end ( );
-    
-	   bgPixmap = tmp;
-	}
+	bgPixmap = pm;
     }
 
     void setBackgroundColor( const QColor &c ) {
@@ -238,8 +241,7 @@ public:
     void drawBackground( QPainter *p, const QRect &r )
     {
 	if ( !bgPixmap.isNull() ) {
-	    //p-> fillRect ( r, bgColor );
-	    p->drawTiledPixmap( r, bgPixmap,
+           p->drawTiledPixmap( r, bgPixmap,
                    QPoint( (r.x() + contentsX()) % bgPixmap.width(),
                            (r.y() + contentsY()) % bgPixmap.height() ) );
 	} else {
@@ -287,7 +289,7 @@ public:
     {
 	switch (sortmeth) {
 	case Name:
-	    return a->name().compare(b->name());
+	    return a->name().lower().compare(b->name().lower());
 	case Date: {
 	    QFileInfo fa(a->linkFileKnown() ? a->linkFile() : a->file());
 	    QFileInfo fb(b->linkFileKnown() ? b->linkFile() : b->file());
@@ -299,10 +301,18 @@ public:
 	return 0;
     }
 
-    QString getAllDocLinkInfo() const;
-
 protected:
 
+    void timerEvent( QTimerEvent *te )
+    {
+	if ( te->timerId() == busyTimer ) {
+	    if ( bsy )
+		bsy->animateIcon();
+	} else {
+	    QIconView::timerEvent( te );
+	}
+    }
+
     void styleChange( QStyle &old )
     {
 	QIconView::styleChange( old );
@@ -334,47 +344,9 @@ protected:
 	}
     }
 
+    void focusInEvent( QFocusEvent * ) {}
+    void focusOutEvent( QFocusEvent * ) {}
 
-    // flicker free redrawing of busy indicator
-    // code was taken from QScrollView::viewportPaintEvent
-	void viewportPaintEvent( QPaintEvent* pe )
-	{
-		static QPixmap *pix = new QPixmap ( );
-
-		QWidget* vp = viewport();
-
-		if ( vp-> size ( ) != pix-> size ( ))
-			pix-> resize ( vp-> size ( ));
-
-		QPainter p(pix, vp);
-		QRect r = pe->rect();
-		if ( clipper ( ) != vp ) {
-			QRect rr(
-				-vp->x(), -vp->y(),
-				clipper()->width(), clipper()->height()
-			);
-			r &= rr;
-			if ( r.isValid() ) {
-				int ex = r.x() + vp->x() + contentsX();
-				int ey = r.y() + vp->y() + contentsY();
-				int ew = r.width();
-				int eh = r.height();
-				drawContentsOffset(&p,
-					contentsX()+vp->x(),
-					contentsY()+vp->y(),
-					ex, ey, ew, eh);
-			}
-		} else {
-			r &= clipper()->rect();
-			int ex = r.x() + contentsX();
-			int ey = r.y() + contentsY();
-			int ew = r.width();
-			int eh = r.height();
-			drawContentsOffset(&p, contentsX(), contentsY(), ex, ey, ew, eh);
-		}
-		bitBlt ( vp, r.topLeft(), pix, r );
-	}
-                                                                                                                                                                                     
 private:
     QList<AppLnk> hidden;
     QDict<void> mimes;
@@ -382,15 +354,15 @@ private:
     SortMethod sortmeth;
     QRegExp tf;
     int cf;
-    QIconViewItem* bsy;
+    LauncherItem* bsy;
+    int busyTimer;
     bool ike;
     bool bigIcns;
     QPixmap bgPixmap;
-    QPixmap bpm [6];
     QColor bgColor;
-    int busytimer;
-    int busystate;
-    BusyIndicatorType busyType;
+#ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
+    QPixmap busyPix;
+#endif
 };
 
 
@@ -401,63 +373,133 @@ void LauncherView::setBusy(bool on)
     icons->setBusy(on);
 }
 
-class LauncherItem : public QIconViewItem
+void LauncherView::setBusyIndicatorType( const QString& type ) {
+    /* ### FIXME */
+}
+
+LauncherItem::LauncherItem( QIconView *parent, AppLnk *applnk, bool bigIcon )
+    : QIconViewItem( parent, applnk->name(),
+           bigIcon ? applnk->bigPixmap() :applnk->pixmap() ),
+	isBigIcon( bigIcon ),
+	iteration(0),
+	app(applnk) // Takes ownership
 {
-public:
-    LauncherItem( QIconView *parent, AppLnk* applnk, bool bigIcon=TRUE );
-    ~LauncherItem()
-    {
-	LauncherIconView* liv = (LauncherIconView*)iconView();
-	if ( liv->busyItem() == this )
-	    liv->setBusy(FALSE);
-	delete app;
-    }
+}
 
-    AppLnk* appLnk() const { return app; }
-    AppLnk* takeAppLnk() { AppLnk* r=app; app=0; return r; }
+LauncherItem::~LauncherItem()
+{
+    LauncherIconView* liv = (LauncherIconView*)iconView();
+    if ( liv->busyItem() == this )
+	liv->setBusy(FALSE);
+    delete app;
+}
 
-    virtual int compare ( QIconViewItem * i ) const;
+int LauncherItem::compare ( QIconViewItem * i ) const
+{
+    LauncherIconView* view = (LauncherIconView*)iconView();
+    return view->compare(app,((LauncherItem *)i)->appLnk());
+}
 
-    void paintItem( QPainter *p, const QColorGroup &cg )
-    {
-	LauncherIconView* liv = (LauncherIconView*)iconView();
-	QBrush oldBrush( liv->itemTextBackground() );
-	QColorGroup mycg( cg );
-	if ( liv->currentItem() == this ) {
-	    liv->setItemTextBackground( cg.brush( QColorGroup::Highlight ) );
-	    mycg.setColor( QColorGroup::Text, cg.color( QColorGroup::HighlightedText ) );
-	}
-	QIconViewItem::paintItem(p,mycg);
-	if ( liv->currentItem() == this )
-	    liv->setItemTextBackground( oldBrush );
+void LauncherItem::paintItem( QPainter *p, const QColorGroup &cg )
+{
+    LauncherIconView* liv = (LauncherIconView*)iconView();
+    QBrush oldBrush( liv->itemTextBackground() );
+    QColorGroup mycg( cg );
+    if ( liv->currentItem() == this ) {
+	liv->setItemTextBackground( cg.brush( QColorGroup::Highlight ) );
+	mycg.setColor( QColorGroup::Text, cg.color( QColorGroup::HighlightedText ) );
     }
 
-    virtual QPixmap* pixmap () const
-    {
-	const LauncherIconView* liv = (LauncherIconView*)iconView();
-	if ( (const LauncherItem *)liv->busyItem() == this )
-	    return liv->busyPixmap();
-	return QIconViewItem::pixmap();
-    }
+    QIconViewItem::paintItem(p,mycg);
 
-protected:
-    AppLnk* app;
-};
+    // Paint animation overlay
+    if ( liv->busyItem() == this )
+	paintAnimatedIcon(p);
 
+    if ( liv->currentItem() == this )
+	liv->setItemTextBackground( oldBrush );
+}
 
-LauncherItem::LauncherItem( QIconView *parent, AppLnk *applnk, bool bigIcon )
-    : QIconViewItem( parent, applnk->name(),
-           bigIcon ? applnk->bigPixmap() :applnk->pixmap() ),
-	app(applnk) // Takes ownership
+void LauncherItem::paintAnimatedIcon( QPainter *p )
 {
+    LauncherIconView* liv = (LauncherIconView*)iconView();
+    int pic = iteration % 16;
+    int w = pixmap()->width(), h = pixmap()->height();
+    QPixmap dblBuf( w, h + 4 );
+    QPainter p2( &dblBuf );
+    int x1, y1;
+    if ( liv->itemTextPos() == QIconView::Bottom ) {
+	x1 = x() + (width() - w) / 2 - liv->contentsX();
+	y1 = y() - liv->contentsY();
+    } else {
+	x1 = x() - liv->contentsX();
+	y1 = y() + (height() - h) / 2 - liv->contentsY();
+    }
+    y1 -= 2;
+    p2.translate(-x1,-y1);
+    liv->drawBackground( &p2, QRect(x1,y1,w,h+4) );
+    int bounceY = 2;
+#ifdef BOUNCE_BUSY_ICON
+    bounceY = 4 - ((iteration+2)%8);
+    bounceY = bounceY < 0 ? -bounceY : bounceY;
+#endif
+    p2.drawPixmap( x1, y1 + bounceY, *pixmap() );
+#ifdef USE_ANIMATED_BUSY_ICON_OVERLAY
+    p2.drawPixmap( x1, y1 + bounceY, liv->busyPixmap(), w * pic, 0, w, h );
+#endif
+    p->drawPixmap( x1, y1, dblBuf );
 }
 
-int LauncherItem::compare ( QIconViewItem * i ) const
+void LauncherItem::animateIcon()
 {
-    LauncherIconView* view = (LauncherIconView*)iconView();
-    return view->compare(app,((LauncherItem *)i)->appLnk());
+    LauncherIconView* liv = (LauncherIconView*)iconView();
+
+    if ( liv->busyItem() != this || !app )
+	return;
+
+    // Highlight the icon
+    if ( iteration == 0 ) {
+	QPixmap src = isBigIcon ? app->bigPixmap() : app->pixmap();
+	QImage img = src.convertToImage();
+	QRgb *rgb;
+	int count;
+	if ( img.depth() == 32 ) {
+	    rgb = (QRgb*)img.bits();
+	    count = img.bytesPerLine()/sizeof(QRgb)*img.height();
+	} else {
+	    rgb = img.colorTable();
+	    count = img.numColors();
+	}
+	for ( int r = 0; r < count; r++, rgb++ ) {
+#if defined(BRIGHTEN_BUSY_ICON)
+	    QColor c(*rgb);
+	    int h, s, v;
+	    c.hsv(&h,&s,&v);
+	    c.setHsv(h,QMAX(s-24,0),QMIN(v+48,255));
+	    *rgb = qRgba(c.red(),c.green(),c.blue(),qAlpha(*rgb));
+#elif defined(ALPHA_FADE_BUSY_ICON)
+	    *rgb = qRgba(qRed(*rgb),qGreen(*rgb),qBlue(*rgb),qAlpha(*rgb)/2);
+#endif
+	}
+	src.convertFromImage( img );
+	setPixmap( src );
+    }
+
+    iteration++;
+
+    // Paint animation overlay
+    QPainter p( liv->viewport() );
+    paintAnimatedIcon( &p );
+}
+
+void LauncherItem::resetIcon()
+{
+    iteration = 0;
+    setPixmap( isBigIcon ? app->bigPixmap() : app->pixmap() );
 }
 
+//===========================================================================
+
 QStringList LauncherIconView::mimeTypes() const
 {
     QStringList r;
@@ -503,6 +545,7 @@ void LauncherIconView::updateCategoriesAndMimeTypes()
 
 void LauncherIconView::hideOrShowItems(bool resort)
 {
+    viewport()->setUpdatesEnabled( FALSE );
     hidden.setAutoDelete(FALSE);
     QList<AppLnk> links=hidden;
     hidden.clear();
@@ -512,7 +555,6 @@ void LauncherIconView::hideOrShowItems(bool resort)
 	links.append(item->takeAppLnk());
 	item = (LauncherItem*)item->nextItem();
     }
-    viewport()->setUpdatesEnabled( FALSE );
     clear();
     QListIterator<AppLnk> it(links);
     AppLnk* l;
@@ -520,9 +562,9 @@ void LauncherIconView::hideOrShowItems(bool resort)
 	addItem(l,FALSE);
 	++it;
     }
-    viewport()->setUpdatesEnabled( TRUE );
     if ( resort && !autoArrange() )
 	sort();
+    viewport()->setUpdatesEnabled( TRUE );
 }
 
 bool LauncherIconView::removeLink(const QString& linkfile)
@@ -533,20 +575,22 @@ bool LauncherIconView::removeLink(const QString& linkfile)
     DocLnk dl(linkfile);
     while (item) {
 	l = item->appLnk();
-	if ( ( l->linkFileKnown() && ( l->linkFile() == linkfile ))
-	  || ( l->fileKnown() && ( l->file() == linkfile ))
-	  || ( dl.fileKnown() && l->fileKnown() && ( dl.file() == l->file() )) ) {
+	LauncherItem *nextItem = (LauncherItem *)item->nextItem();
+	if (  l->linkFileKnown() && l->linkFile() == linkfile
+		|| l->fileKnown() && (
+		    l->file() == linkfile
+		    || dl.isValid() && dl.file() == l->file() ) ) {
 	    delete item;
 	    did = TRUE;
 	}
-	item = (LauncherItem*)item->nextItem();
+	item = nextItem;
     }
     QListIterator<AppLnk> it(hidden);
     while ((l=it.current())) {
 	++it;
-	if ( ( l->linkFileKnown() && ( l->linkFile() == linkfile ))
-	  || ( l->file() == linkfile )
-	  || ( dl.fileKnown() && ( dl.file() == l->file() )) ) {
+	if ( l->linkFileKnown() && l->linkFile() == linkfile
+		|| l->file() == linkfile
+		|| dl.isValid() && dl.file() == l->file() ) {
 	    hidden.removeRef(l);
 	   did = TRUE;
 	}
@@ -554,62 +598,12 @@ bool LauncherIconView::removeLink(const QString& linkfile)
     return did;
 }
 
-static QString docLinkInfo(const Categories& cats, DocLnk* doc)
-{
-    QString contents;
-
-    QFileInfo fi( doc->file() );
-    if ( !fi.exists() )
-	return contents;
-
-    if ( doc->linkFileKnown() ) {
-	QString lfn = doc->linkFile();
-	QFile f( lfn );
-	if ( f.open( IO_ReadOnly ) ) {
-	    QTextStream ts( &f );
-	    ts.setEncoding( QTextStream::UnicodeUTF8 );
-	    contents += ts.read();
-	    f.close();
-	    goto calcsize;
-	}
-    }
-
-    contents += "[Desktop Entry]\n";
-    contents += "Categories = " // No tr
-	+ cats.labels("Document View", doc->categories()).join(";") + "\n"; // No tr
-    contents += "File = "+doc->file()+"\n"; // No tr
-    contents += "Name = "+doc->name()+"\n"; // No tr
-    contents += "Type = "+doc->type()+"\n"; // No tr
-
-calcsize:
-    contents += QString("Size = %1\n").arg( fi.size() ); // No tr
-    return contents;
-}
-
-QString LauncherIconView::getAllDocLinkInfo() const
-{
-    QString contents;
-    LauncherItem* item = (LauncherItem*)firstItem();
-    Categories cats;
-    while (item) {
-	DocLnk* doc = (DocLnk*)item->appLnk();
-	contents += docLinkInfo(cats,doc);
-	item = (LauncherItem*)item->nextItem();
-    }
-    QListIterator<AppLnk> it(hidden);
-    DocLnk* doc;
-    while ((doc=(DocLnk*)it.current())) {
-	contents += docLinkInfo(cats,doc);
-	++it;
-    }
-    return contents;
-}
-
 //===========================================================================
 
 LauncherView::LauncherView( QWidget* parent, const char* name, WFlags fl )
     : QVBox( parent, name, fl )
 {
+    catmb = 0;
     icons = new LauncherIconView( this );
     setFocusProxy(icons);
     QPEApplication::setStylusOperation( icons->viewport(), QPEApplication::RightOnHold );
@@ -640,6 +634,13 @@ LauncherView::LauncherView( QWidget* parent, const char* name, WFlags fl )
 
 LauncherView::~LauncherView()
 {
+    if ( bgCache && bgCache->contains( bgName ) )
+	(*bgCache)[bgName]->ref--;
+}
+
+void LauncherView::hideIcons()
+{
+    icons->hide();
 }
 
 void LauncherView::setToolsEnabled(bool y)
@@ -650,12 +651,16 @@ void LauncherView::setToolsEnabled(bool y)
 
 	    // Type filter
 	    typemb = new QComboBox(tools);
+	    QSizePolicy p = typemb->sizePolicy();
+	    p.setHorData(QSizePolicy::Expanding);
+	    typemb->setSizePolicy(p);
 
 	    // Category filter
-	    catmb = new CategorySelect(tools);
-
 	    updateTools();
 	    tools->show();
+
+	    // Always show vscrollbar
+	    icons->setVScrollBarMode( QScrollView::AlwaysOn );
 	} else {
 	    delete tools;
 	    tools = 0;
@@ -667,9 +672,10 @@ void LauncherView::updateTools()
 {
     disconnect( typemb, SIGNAL(activated(int)),
 	        this, SLOT(showType(int)) );
-    disconnect( catmb, SIGNAL(signalSelected(int)),
+    if ( catmb ) disconnect( catmb, SIGNAL(signalSelected(int)),
 	        this, SLOT(showCategory(int)) );
 
+    // ### I want to remove this
     icons->updateCategoriesAndMimeTypes();
 
     QString prev;
@@ -689,9 +695,9 @@ void LauncherView::updateTools()
 	} else {
 	    t[0] = t[0].upper();
 	}
-	types += tr("%1 files").arg(t);
+	types += t;
     }
-    types << tr("All types of file");
+    types << tr("All types");
     prev = typemb->currentText();
     typemb->clear();
     typemb->insertStringList(types);
@@ -704,6 +710,9 @@ void LauncherView::updateTools()
     if ( prev.isNull() )
 	typemb->setCurrentItem(typemb->count()-1);
 
+    int pcat = catmb ? catmb->currentCategory() : -2;
+    if ( !catmb )
+	catmb = new CategorySelect(tools);
     Categories cats( 0 );
     cats.load( categoryFileName() );
     QArray<int> vl( 0 );
@@ -711,6 +720,11 @@ void LauncherView::updateTools()
 	tr("Document View") );
     catmb->setRemoveCategoryEdit( TRUE );
     catmb->setAllCategories( TRUE );
+    catmb->setCurrentCategory(pcat);
+
+    // if type has changed we need to redisplay
+    if ( typemb->currentText() != prev )
+	showType( typemb->currentItem() );
 
     connect(typemb, SIGNAL(activated(int)), this, SLOT(showType(int)));
     connect(catmb, SIGNAL(signalSelected(int)), this, SLOT(showCategory(int)));
@@ -758,17 +772,75 @@ void LauncherView::setViewMode( ViewMode m )
     }
 }
 
+//
+// User images may require scaling.
+//
+QImage LauncherView::loadBackgroundImage(QString &bgName)
+{
+    QImageIO imgio;
+    QSize   ds = qApp->desktop()->size();   // should be launcher, not desktop
+    bool    further_scaling = TRUE;
+
+    imgio.setFileName( bgName );
+    imgio.setParameters("GetHeaderInformation");
+
+    if (imgio.read() == FALSE) {
+	return imgio.image();
+    }
+
+    if (imgio.image().width() < ds.width() &&
+	    imgio.image().height() < ds.height()) {
+	further_scaling = FALSE;
+    }
+
+    if (!imgio.image().bits()) {
+	//
+	// Scale and load.  Note we don't scale up.
+	//
+	QString param( "Scale( %1, %2, ScaleMin )" ); // No tr
+	imgio.setParameters(further_scaling ?
+	    param.arg(ds.width()).arg(ds.height()).latin1() :
+	    "");
+	imgio.read();
+    } else {
+	if (further_scaling) {
+	    int	t1 = imgio.image().width() * ds.height();
+	    int t2 = imgio.image().height() * ds.width();
+	    int dsth = ds.height();
+	    int dstw = ds.width();
+
+	    if (t1 > t2) {
+		dsth = t2 / imgio.image().width();
+	    } else {
+		dstw = t1 / imgio.image().height();
+	    }
+
+	    //
+	    // Loader didn't scale for us.  Do it manually.
+	    //
+	    return imgio.image().smoothScale(dstw, dsth);
+	}
+    }
+
+    return imgio.image();
+}
+
 void LauncherView::setBackgroundType( BackgroundType t, const QString &val )
 {
-    if ( !bgCache )
+    if ( !bgCache ) {
 	bgCache = new QMap<QString,BgPixmap*>;
+	qAddPostRoutine( cleanup_cache );
+    }
+
     if ( bgCache->contains( bgName ) )
 	(*bgCache)[bgName]->ref--;
+    bgName = "";
+
+    QPixmap bg;
 
     switch ( t ) {
 	case Ruled: {
 	    bgName = QString("Ruled_%1").arg(colorGroup().background().name()); // No tr
-	    QPixmap bg;
 	    if ( bgCache->contains( bgName ) ) {
 		(*bgCache)[bgName]->ref++;
 		bg = (*bgCache)[bgName]->pm;
@@ -785,55 +857,63 @@ void LauncherView::setBackgroundType( BackgroundType t, const QString &val )
 		painter.end();
 		bgCache->insert( bgName, new BgPixmap(bg) );
 	    }
-	    icons->setBackgroundPixmap( bg );
 	    break;
 	}
 
-	case SolidColor:
-	    icons->setBackgroundPixmap( QPixmap() );
-	    if ( val.isEmpty() ) {
-		icons->setBackgroundColor( colorGroup().base() );
-	    } else {
-		icons->setBackgroundColor( val );
-	    }
-	    bgName = "";
-	    break;
-
 	case Image:
-	    bgName = val;
-	    if ( bgCache->contains( bgName ) ) {
-		(*bgCache)[bgName]->ref++;
-		icons->setBackgroundPixmap( (*bgCache)[bgName]->pm );
-	    } else {
-		QPixmap bg( Resource::loadPixmap( val ) );
-		if ( bg.isNull() ) {
-		    QImageIO imgio;
-		    imgio.setFileName( bgName );
-		    QSize ds = qApp->desktop()->size();
-		    QString param( "Scale( %1, %2, ScaleMin )" ); // No tr
-		    imgio.setParameters( param.arg(ds.width()).arg(ds.height()).latin1() );
-		    imgio.read();
-		    bg = imgio.image();
+	    if (!val.isEmpty()) {
+		bgName = val;
+		if ( bgCache->contains( bgName ) ) {
+		    (*bgCache)[bgName]->ref++;
+		    bg = (*bgCache)[bgName]->pm;
+		} else {
+		    QString imgFile = bgName;
+		    bool tile = FALSE;
+		    if ( imgFile[0]!='/' || !QFile::exists(imgFile) ) {
+			imgFile = Resource::findPixmap( imgFile );
+			tile = TRUE;
+		    }
+		    QImage img = loadBackgroundImage(imgFile);
+
+
+		    if ( img.depth() == 1 )
+			img = img.convertDepth(8);
+		    img.setAlphaBuffer(FALSE);
+		    bg.convertFromImage(img);
+		    bgCache->insert( bgName, new BgPixmap(bg) );
 		}
-		bgCache->insert( bgName, new BgPixmap(bg) );
-		icons->setBackgroundPixmap( bg );
 	    }
 	    break;
+
+	case SolidColor:
+	default:
+	    break;
     }
 
-    // remove unreferenced backgrounds.
-    QMap<QString,BgPixmap*>::Iterator it = bgCache->begin();
-    while ( it != bgCache->end() ) {
-	QMap<QString,BgPixmap*>::Iterator curr = it;
-	++it;
-	if ( (*curr)->ref == 0 ) {
-	    delete (*curr);
-	    bgCache->remove( curr );
+    const QObjectList *list = queryList( "QWidget", 0, FALSE );
+    QObject *obj;
+    for ( QObjectListIt it( *list ); (obj=it.current()); ++it ) {
+	if ( obj->isWidgetType() ) {
+	    QWidget *w = (QWidget*)obj;
+	    w->setBackgroundPixmap( bg );
+	    if ( bgName.isEmpty() ) {
+		// Solid Color
+		if ( val.isEmpty() )
+		    w->setBackgroundColor( colorGroup().base() );
+		else
+		    w->setBackgroundColor( val );
+	    } else {
+		// Ruled or Image pixmap
+		w->setBackgroundOrigin( ParentOrigin );
+	    }
 	}
     }
+    delete list;
 
     bgType = t;
     icons->viewport()->update();
+
+    QTimer::singleShot( 1000, this, SLOT(flushBgCache()) );
 }
 
 void LauncherView::setTextColor( const QColor &tc )
@@ -848,11 +928,13 @@ void LauncherView::setTextColor( const QColor &tc )
 void LauncherView::setViewFont( const QFont &f )
 {
     icons->setFont( f );
+    icons->hideOrShowItems( FALSE );
 }
 
-void LauncherView::unsetViewFont( )
+void LauncherView::clearViewFont()
 {
-    icons->unsetFont( );
+    icons->unsetFont();
+    icons->hideOrShowItems( FALSE );
 }
 
 void LauncherView::resizeEvent(QResizeEvent *e)
@@ -862,17 +944,6 @@ void LauncherView::resizeEvent(QResizeEvent *e)
 	sort();
 }
 
-void LauncherView::populate( AppLnkSet *folder, const QString& typefilter )
-{
-    icons->clear();
-    internalPopulate( folder, typefilter );
-}
-
-QString LauncherView::getAllDocLinkInfo() const
-{
-    return icons->getAllDocLinkInfo();
-}
-
 void LauncherView::selectionChanged()
 {
     QIconViewItem* item = icons->currentItem();
@@ -911,32 +982,15 @@ void LauncherView::itemPressed( int btn, QIconViewItem *item )
 	AppLnk *appLnk = ((LauncherItem *)item)->appLnk();
 	if ( btn == RightButton )
 	    emit rightPressed( appLnk );
-/*
-	else if ( btn == LeftButton )
-	    emit clicked( appLnk );
-*/
+	else if ( btn == ShiftButton )
+	    emit rightPressed( appLnk );
 	item->setSelected(FALSE);
     }
 }
 
-void LauncherView::internalPopulate( AppLnkSet *folder, const QString& typefilter )
+void LauncherView::removeAllItems()
 {
-    QListIterator<AppLnk> it( folder->children() );
-    icons->setTypeFilter(typefilter,FALSE);
-
-    while ( it.current() ) {
-	// show only the icons for existing files
-	if (QFile(it.current()->file()).exists() || ( it.current()->file().left(4) == "http" )) {
-	    icons->addItem(*it,FALSE);
-	}
-	else {
-	    //maybe insert some .desktop file deletion code later
-	    //maybe dir specific
-	}
-	++it;
-    }
-
-    icons->sort();
+    icons->clear();
 }
 
 bool LauncherView::removeLink(const QString& linkfile)
@@ -944,6 +998,18 @@ bool LauncherView::removeLink(const QString& linkfile)
     return icons->removeLink(linkfile);
 }
 
+void LauncherView::setSortEnabled( bool v )
+{
+    icons->setSorting( v );
+    if ( v )
+	sort();
+}
+
+void LauncherView::setUpdatesEnabled( bool u )
+{
+    icons->setUpdatesEnabled( u );
+}
+
 void LauncherView::sort()
 {
     icons->sort();
@@ -954,11 +1020,6 @@ void LauncherView::addItem(AppLnk* app, bool resort)
     icons->addItem(app,resort);
 }
 
-void LauncherView::setFileSystems(const QList<FileSystem> &)
-{
-    // ### does nothing now...
-}
-
 void LauncherView::paletteChange( const QPalette &p )
 {
     icons->unsetPalette();
@@ -970,12 +1031,30 @@ void LauncherView::paletteChange( const QPalette &p )
     icons->setPalette( QPalette(cg,cg,cg) );
 }
 
+void LauncherView::fontChanged(const QFont&)
+{
+    qDebug("LauncherView::fontChanged()");
+    icons->hideOrShowItems( FALSE );
+}
 
-void LauncherView::setBusyIndicatorType ( const QString &type )
+void LauncherView::relayout(void)
 {
-    if ( type. lower ( ) == "blink" )
-	icons-> setBusyIndicatorType ( BIT_Blinking );
-    else
-	icons-> setBusyIndicatorType ( BIT_Normal );
+    icons->hideOrShowItems(FALSE);
+}
+
+void LauncherView::flushBgCache()
+{
+    if ( !bgCache )
+	return;
+    // remove unreferenced backgrounds.
+    QMap<QString,BgPixmap*>::Iterator it = bgCache->begin();
+    while ( it != bgCache->end() ) {
+	QMap<QString,BgPixmap*>::Iterator curr = it;
+	++it;
+	if ( (*curr)->ref == 0 ) {
+	    delete (*curr);
+	    bgCache->remove( curr );
+	}
+    }
 }
 
--
cgit v0.9.0.2