Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

launcherview.cpp

Go to the documentation of this file.
00001 /*
00002                              This file is part of the Opie Project
00003               =.             (C) 2000-2002 Trolltech AS
00004             .=l.             (C) 2002-2005 The Opie Team <opie-devel@handhelds.org>
00005            .>+-=
00006  _;:,     .>    :=|.         This program is free software; you can
00007 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00008     :`=1 )Y*s>-.--   :       the terms of the GNU Library General Public
00009 .="- .-=="i,     .._         License as published by the Free Software
00010  - .   .-<_>     .<>         Foundation; version 2 of the License.
00011      ._= =}       :
00012     .%`+i>       _;_.
00013     .i_,=:_.      -<s.       This program is distributed in the hope that
00014      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00015     : ..    .:,     . . .    without even the implied warranty of
00016     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00017   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00018 ..}^=.=       =       ;      Library General Public License for more
00019 ++=   -.     .`     .:       details.
00020     :     =  ...= . :.=-
00021  -.   .:....=;==+<;          You should have received a copy of the GNU
00022   -_. . .   )=.  =           Library General Public License along with
00023     --        :-=`           this library; see the file COPYING.LIB.
00024                              If not, write to the Free Software Foundation,
00025                              Inc., 59 Temple Place - Suite 330,
00026                              Boston, MA 02111-1307, USA.
00027 */
00028 #include "launcherview.h"
00029 
00030 /* OPIE */
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 /* QT */
00043 #include <qtimer.h>
00044 #include <qfileinfo.h>
00045 #include <qiconview.h>
00046 #include <qobjectlist.h>
00047 
00048 
00049 // These define how the busy icon is animated and highlighted
00050 #define BRIGHTEN_BUSY_ICON
00051 //#define ALPHA_FADE_BUSY_ICON
00052 //#define USE_ANIMATED_BUSY_ICON_OVERLAY
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), // Takes ownership
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     // Paint animation overlay
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     // Highlight the icon
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     // Paint animation overlay
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 // Implemantation of LauncherIconview start
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         //odebug << "" << l << ": hidden (should remove)" << oendl;
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     //  QStringList c = app->categories();
00419     //  for (QStringList::ConstIterator cit=c.begin(); cit!=c.end(); ++cit) {
00420     //      cats.replace(*cit,(void*)1);
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 /* OK button */ || 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 // Implemantation of LauncherIconview end
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             // Type filter
00789             typemb = new QComboBox(tools);
00790             QSizePolicy p = typemb->sizePolicy();
00791             p.setHorData(QSizePolicy::Expanding);
00792             typemb->setSizePolicy(p);
00793             // Category filter
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     // ### I want to remove this
00812     icons->updateCategoriesAndMimeTypes();
00813 
00814     QString prev;
00815 
00816     // Type filter
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", // No tr
00857         tr("Document View") );
00858     catmb->setRemoveCategoryEdit( TRUE );
00859     catmb->setAllCategories( TRUE );
00860     catmb->setCurrentCategory(pcat);
00861 
00862     // if type has changed we need to redisplay
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 // User images may require scaling.
00915 //
00916 QImage LauncherView::loadBackgroundImage(QString &bgName)
00917 {
00918     QImageIO imgio;
00919     QSize   ds = qApp->desktop()->size();   // should be launcher, not desktop
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     // Scale and load.  Note we don't scale up.
00937     //
00938     QString param( "Scale( %1, %2, ScaleMin )" ); // No tr
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         // Loader didn't scale for us.  Do it manually.
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()); // No tr
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         // Solid Color
01039         if ( val.isEmpty() )
01040             w->setBackgroundColor( colorGroup().base() );
01041         else
01042             w->setBackgroundColor( val );
01043         } else {
01044         // Ruled or Image pixmap
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 //  qDebug("LauncherView resize event");
01092     QVBox::resizeEvent( e );
01093 // commented out for launcherview and qt/e 2.3.8 problems, probably needs real fixing somewhere...
01094 //    if ( e->size().width() != e->oldSize().width() )
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() ) // not for mouse press
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         // Make sure it's the item we execute that gets highlighted
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     // remove unreferenced backgrounds.
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  * Launcherthumbnail handling for image files
01221  */
01222 
01223 /* special image handling - based on opie eye */
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     /* we are just interested in thumbmails */
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 }

Generated on Sat Nov 5 16:15:31 2005 for OPIE by  doxygen 1.4.2