-rw-r--r-- | core/launcher/launcher.cpp | 43 | ||||
-rw-r--r-- | core/launcher/launcher.h | 4 | ||||
-rw-r--r-- | core/launcher/launcherview.cpp | 109 | ||||
-rw-r--r-- | core/launcher/launcherview.h | 7 |
4 files changed, 113 insertions, 50 deletions
diff --git a/core/launcher/launcher.cpp b/core/launcher/launcher.cpp index 5ec1cf8..ccc2114 100644 --- a/core/launcher/launcher.cpp +++ b/core/launcher/launcher.cpp @@ -1,352 +1,355 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "startmenu.h" #include "taskbar.h" #include "serverinterface.h" #include "launcherview.h" #include "launcher.h" #include "server.h" /* OPIE */ #include <opie2/odebug.h> #include <qtopia/global.h> #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif #include <qtopia/resource.h> #include <qtopia/applnk.h> #include <qtopia/config.h> #include <qtopia/qpeapplication.h> #include <qtopia/mimetype.h> #include <qtopia/private/categories.h> #define QTOPIA_INTERNAL_FSLP #include <qtopia/lnkproperties.h> /* QT */ #include <qdir.h> #ifdef Q_WS_QWS #include <qkeyboard_qws.h> #include <qwindowsystem_qws.h> #endif #include <qtimer.h> #include <qcombobox.h> #include <qvbox.h> #include <qlayout.h> #include <qstyle.h> #include <qpushbutton.h> #include <qtabbar.h> #include <qwidgetstack.h> #include <qregexp.h> #include <qmessagebox.h> #include <qframe.h> #include <qpainter.h> #include <qlabel.h> #include <qtextstream.h> #include <qpopupmenu.h> /* STD */ #include <stdlib.h> #include <assert.h> #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <unistd.h> #include <stdio.h> #include <sys/vfs.h> #include <mntent.h> #endif static bool isVisibleWindow( int ); //=========================================================================== LauncherTabWidget::LauncherTabWidget( Launcher* parent ) : - QVBox( parent ), docview( 0 ) + QVBox( parent ), docview( 0 ),docTabEnabled(true),m_DocumentTabId(0) { docLoadingWidgetEnabled = false; docLoadingWidget = 0; docLoadingWidgetProgress = 0; launcher = parent; categoryBar = new LauncherTabBar( this ); QPalette pal = categoryBar->palette(); pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); categoryBar->setPalette( pal ); stack = new QWidgetStack(this); connect( categoryBar, SIGNAL(selected(int)), this, SLOT(raiseTabWidget()) ); categoryBar->show(); stack->show(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QCopChannel *channel = new QCopChannel( "QPE/Launcher", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(launcherMessage(const QCString&,const QByteArray&)) ); connect( qApp, SIGNAL(appMessage(const QCString&,const QByteArray&)), this, SLOT(appMessage(const QCString&,const QByteArray&))); #endif createDocLoadingWidget(); } void LauncherTabWidget::createDocLoadingWidget() { // Construct the 'doc loading widget' shown when finding documents // ### LauncherView class needs changing to be more generic so // this widget can change its background similar to the iconviews // so the background for this matches docLoadingWidget = new LauncherView( stack ); docLoadingWidget->hideIcons(); QVBox *docLoadingVBox = new QVBox( docLoadingWidget ); docLoadingVBox->setSpacing( 20 ); docLoadingVBox->setMargin( 10 ); QWidget *space1 = new QWidget( docLoadingVBox ); docLoadingVBox->setStretchFactor( space1, 1 ); QLabel *waitPixmap = new QLabel( docLoadingVBox ); waitPixmap->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, waitPixmap->sizePolicy().hasHeightForWidth() ) ); waitPixmap->setPixmap( Resource::loadPixmap( "bigwait" ) ); waitPixmap->setAlignment( int( QLabel::AlignCenter ) ); Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); - bool docTabEnabled = cfg.readBoolEntry( "Enable", true ); + docTabEnabled = cfg.readBoolEntry( "Enable", true ); QLabel *textLabel = new QLabel( docLoadingVBox ); textLabel->setAlignment( int( QLabel::AlignCenter ) ); docLoadingWidgetProgress = new QProgressBar( docLoadingVBox ); docLoadingWidgetProgress->setProgress( 0 ); docLoadingWidgetProgress->setCenterIndicator( TRUE ); docLoadingWidgetProgress->setBackgroundMode( NoBackground ); // No flicker setProgressStyle(); if ( docTabEnabled ) { textLabel->setText( tr( "<b>Finding Documents...</b>" ) ); } else { textLabel->setText( tr( "<b>The Documents Tab<p>has been disabled.<p>" "Use Settings->Launcher->DocTab<p>to reenable it.</b></center>" ) ); docLoadingWidgetProgress->hide(); docLoadingWidgetEnabled = true; } QWidget *space2 = new QWidget( docLoadingVBox ); docLoadingVBox->setStretchFactor( space2, 1 ); cfg.setGroup( "Tab Documents" ); // No tr setTabViewAppearance( docLoadingWidget, cfg ); stack->addWidget( docLoadingWidget, 0 ); } void LauncherTabWidget::initLayout() { layout()->activate(); docView()->setFocus(); categoryBar->showTab("Documents"); } void LauncherTabWidget::appMessage(const QCString& message, const QByteArray&) { if ( message == "nextView()" ) - categoryBar->nextTab(); + categoryBar->nextTab(); } void LauncherTabWidget::raiseTabWidget() { if ( categoryBar->currentView() == docView() - && docLoadingWidgetEnabled ) { - stack->raiseWidget( docLoadingWidget ); - docLoadingWidget->updateGeometry(); + && docLoadingWidgetEnabled ) { + stack->raiseWidget( docLoadingWidget ); + docLoadingWidget->updateGeometry(); } else { - stack->raiseWidget( categoryBar->currentView() ); + stack->raiseWidget( categoryBar->currentView() ); } } void LauncherTabWidget::tabProperties() { LauncherView *view = categoryBar->currentView(); QPopupMenu *m = new QPopupMenu( this ); m->insertItem( tr("Icon View"), LauncherView::Icon ); m->insertItem( tr("List View"), LauncherView::List ); m->setItemChecked( (int)view->viewMode(), TRUE ); int rv = m->exec( QCursor::pos() ); if ( rv >= 0 && rv != view->viewMode() ) { - view->setViewMode( (LauncherView::ViewMode)rv ); + view->setViewMode( (LauncherView::ViewMode)rv ); } delete m; } void LauncherTabWidget::deleteView( const QString& id ) { LauncherTab *t = categoryBar->launcherTab(id); if ( t ) { - stack->removeWidget( t->view ); - delete t->view; - categoryBar->removeTab( t ); + stack->removeWidget( t->view ); + delete t->view; + categoryBar->removeTab( t ); } } LauncherView* LauncherTabWidget::newView( const QString& id, const QPixmap& pm, const QString& label ) { LauncherView* view = new LauncherView( stack ); connect( view, SIGNAL(clicked(const AppLnk*)), this, SIGNAL(clicked(const AppLnk*))); connect( view, SIGNAL(rightPressed(AppLnk*)), this, SIGNAL(rightPressed(AppLnk*))); + int n = categoryBar->count(); + stack->addWidget( view, n ); LauncherTab *tab = new LauncherTab( id, view, pm, label ); categoryBar->insertTab( tab, n-1 ); - - if ( id == "Documents" ) - docview = view; + if ( id == "Documents" ) { + docview = view; + m_DocumentTabId = n; + } odebug << "inserting " << id << " at " << n-1 << "" << oendl; Config cfg("Launcher"); setTabAppearance( tab, cfg ); cfg.setGroup( "GUI" ); view->setBusyIndicatorType( cfg.readEntry( "BusyType", QString::null ) ); return view; } LauncherView *LauncherTabWidget::view( const QString &id ) { LauncherTab *t = categoryBar->launcherTab(id); if ( !t ) - return 0; + return 0; return t->view; } LauncherView *LauncherTabWidget::docView() { return docview; } void LauncherTabWidget::setLoadingWidgetEnabled( bool v ) { if ( v != docLoadingWidgetEnabled && docLoadingWidget ) { - docLoadingWidgetEnabled = v; - raiseTabWidget(); + docLoadingWidgetEnabled = v; + raiseTabWidget(); } } void LauncherTabWidget::setLoadingProgress( int percent ) { docLoadingWidgetProgress->setProgress( (percent / 4) * 4 ); } // ### this function could more to LauncherView void LauncherTabWidget::setTabViewAppearance( LauncherView *v, Config &cfg ) { // View QString view = cfg.readEntry( "View", "Icon" ); if ( view == "List" ) // No tr v->setViewMode( LauncherView::List ); QString bgType = cfg.readEntry( "BackgroundType", "Image" ); if ( bgType == "Image" ) { // No tr QString pm = cfg.readEntry( "BackgroundImage", "launcher/opie-background" ); v->setBackgroundType( LauncherView::Image, pm ); } else if ( bgType == "SolidColor" ) { QString c = cfg.readEntry( "BackgroundColor" ); v->setBackgroundType( LauncherView::SolidColor, c ); } else { v->setBackgroundType( LauncherView::Ruled, QString::null ); } QString textCol = cfg.readEntry( "TextColor" ); if ( textCol.isEmpty() ) v->setTextColor( QColor() ); else v->setTextColor( QColor(textCol) ); // bool customFont = cfg.readBoolEntry( "CustomFont", FALSE ); QStringList font = cfg.readListEntry( "Font", ',' ); if ( font.count() == 4 ) v->setViewFont( QFont(font[0], font[1].toInt(), font[2].toInt(), font[3].toInt()!=0) ); // ### FIXME TabColor TabTextColor } // ### Could move to LauncherTab void LauncherTabWidget::setTabAppearance( LauncherTab *tab, Config &cfg ) { cfg.setGroup( QString( "Tab %1" ).arg(tab->type) ); // No tr setTabViewAppearance( tab->view, cfg ); // Tabs QString tabCol = cfg.readEntry( "TabColor" ); if ( tabCol.isEmpty() ) tab->bgColor = QColor(); else tab->bgColor = QColor(tabCol); QString tabTextCol = cfg.readEntry( "TabTextColor" ); if ( tabTextCol.isEmpty() ) tab->fgColor = QColor(); else tab->fgColor = QColor(tabTextCol); } void LauncherTabWidget::paletteChange( const QPalette &p ) { QVBox::paletteChange( p ); QPalette pal = palette(); pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); categoryBar->setPalette( pal ); categoryBar->update(); } void LauncherTabWidget::styleChange( QStyle & ) { QTimer::singleShot( 0, this, SLOT(setProgressStyle()) ); } void LauncherTabWidget::setProgressStyle() { if (docLoadingWidgetProgress) { docLoadingWidgetProgress->setFrameShape( QProgressBar::Box ); docLoadingWidgetProgress->setFrameShadow( QProgressBar::Plain ); docLoadingWidgetProgress->setMargin( 1 ); docLoadingWidgetProgress->setLineWidth( 1 ); } } /* * FIXME * The following NULL check is triggered by inserting, then removing a tab on the fly * as you would if you had removable media (which I do). Without this check * the first app launched after a tab removal causes qpe to Segfault. * This obviously has a more sinister cause, but this works around it with no * obvious adverse effects. Please FIXME * bkc - 17/6/2004 * */ @@ -511,273 +514,277 @@ Launcher::~Launcher() { Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); return cfg.readBoolEntry( "Enable", true ); } void Launcher::makeVisible() { showMaximized(); } void Launcher::destroyGUI() { delete tb; tb = 0; delete tabs; tabs =0; } bool Launcher::eventFilter( QObject*, QEvent *ev ) { #ifdef QT_QWS_CUSTOM if ( ev->type() == QEvent::KeyPress ) { QKeyEvent *ke = (QKeyEvent *)ev; if ( ke->key() == Qt::Key_F11 ) { // menu key QWidget *active = qApp->activeWindow(); if ( active && active->isPopup() ) active->close(); else { Global::terminateBuiltin("calibrate"); // No tr tb->launchStartMenu(); } return TRUE; } } #else Q_UNUSED(ev); #endif return FALSE; } static bool isVisibleWindow(int wid) { #ifdef Q_WS_QWS const QList<QWSWindow> &list = qwsServer->clientWindows(); QWSWindow* w; for (QListIterator<QWSWindow> it(list); (w=it.current()); ++it) { if ( w->winId() == wid ) return !w->isFullyObscured(); } #endif return FALSE; } void Launcher::viewSelected(const QString& s) { setCaption( s + tr(" - Launcher") ); } void Launcher::showTab(const QString& id) { tabs->categoryBar->showTab(id); raise(); } void Launcher::select( const AppLnk *appLnk ) { if ( appLnk->type() == "Folder" ) { // No tr // Not supported: flat is simpler for the user } else { if ( appLnk->exec().isNull() ) { int i = QMessageBox::information(this,tr("No application"), tr("<p>No application is defined for this document." "<p>Type is %1.").arg(appLnk->type()), tr("OK"), tr("View as text"), 0, 0, 1); /* ### Fixme */ if ( i == 1 ) Global::execute("textedit",appLnk->file()); return; } tabs->setBusy(TRUE); emit executing( appLnk ); appLnk->execute(); } } void Launcher::properties( AppLnk *appLnk ) { if ( appLnk->type() == "Folder" ) { // No tr // Not supported: flat is simpler for the user } else { /* ### libqtopia FIXME also moving docLnks... */ LnkProperties prop(appLnk,0 ); if (QPEApplication::execDialog( &prop )==QDialog::Accepted && tabs->currentView()==tabs->docView()) { - tabs->docView()->updateTools(); } } } void Launcher::storageChanged( const QList<FileSystem> & ) { // ### update combo boxes if we had a combo box for the storage type } void Launcher::systemMessage( const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "busy()" ) { tb->startWait(); } else if ( msg == "notBusy(QString)" ) { QString app; stream >> app; tabs->setBusy(FALSE); tb->stopWait(app); } else if (msg == "applyStyle()") { tabs->currentView()->relayout(); } } // These are the update functions from the server void Launcher::typeAdded( const QString& type, const QString& name, const QPixmap& pixmap, const QPixmap& ) { tabs->newView( type, pixmap, name ); ids.append( type ); /* this will be called in applicationScanningProgress with value 100! */ // tb->refreshStartMenu(); static bool first = TRUE; if ( first ) { first = FALSE; tabs->categoryBar->showTab(type); } tabs->view( type )->setUpdatesEnabled( FALSE ); tabs->view( type )->setSortEnabled( FALSE ); } void Launcher::typeRemoved( const QString& type ) { tabs->view( type )->removeAllItems(); tabs->deleteView( type ); ids.remove( type ); /* this will be called in applicationScanningProgress with value 100! */ // tb->refreshStartMenu(); } void Launcher::applicationAdded( const QString& type, const AppLnk& app ) { if ( app.type() == "Separator" ) // No tr return; LauncherView *view = tabs->view( type ); if ( view ) view->addItem( new AppLnk( app ), FALSE ); else owarn << "addAppLnk: No view for type " << type.latin1() << ". Can't add app " << app.name().latin1() << "!", MimeType::registerApp( app ); } void Launcher::applicationRemoved( const QString& type, const AppLnk& app ) { LauncherView *view = tabs->view( type ); if ( view ) view->removeLink( app.linkFile() ); else owarn << "removeAppLnk: No view for " << type << "!" << oendl; } void Launcher::allApplicationsRemoved() { MimeType::clear(); for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) tabs->view( (*it) )->removeAllItems(); } void Launcher::documentAdded( const DocLnk& doc ) { tabs->docView()->addItem( new DocLnk( doc ), FALSE ); } void Launcher::aboutToAddBegin() { tabs->docView()->setUpdatesEnabled( false ); } void Launcher::aboutToAddEnd() { tabs->docView()->setUpdatesEnabled( true ); } void Launcher::showLoadingDocs() { tabs->docView()->hide(); } void Launcher::showDocTab() { if ( tabs->categoryBar->currentView() == tabs->docView() ) tabs->docView()->show(); } void Launcher::documentRemoved( const DocLnk& doc ) { tabs->docView()->removeLink( doc.linkFile() ); } void Launcher::documentChanged( const DocLnk& oldDoc, const DocLnk& newDoc ) { +#if 0 documentRemoved( oldDoc ); documentAdded( newDoc ); +// tabs->docView()->updateTools(); +#else + tabs->docView()->changeItem(oldDoc,new DocLnk(newDoc)); +#endif } void Launcher::allDocumentsRemoved() { tabs->docView()->removeAllItems(); } void Launcher::applicationStateChanged( const QString& name, ApplicationState state ) { tb->setApplicationState( name, state ); } void Launcher::applicationScanningProgress( int percent ) { switch ( percent ) { case 0: { for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) { tabs->view( (*it) )->setUpdatesEnabled( FALSE ); tabs->view( (*it) )->setSortEnabled( FALSE ); } break; } case 100: { for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) { tabs->view( (*it) )->setUpdatesEnabled( TRUE ); tabs->view( (*it) )->setSortEnabled( TRUE ); } tb->refreshStartMenu(); break; } default: break; } } void Launcher::documentScanningProgress( int percent ) { switch ( percent ) { case 0: { tabs->setLoadingProgress( 0 ); tabs->setLoadingWidgetEnabled( TRUE ); tabs->docView()->setUpdatesEnabled( FALSE ); tabs->docView()->setSortEnabled( FALSE ); break; } case 100: { tabs->docView()->updateTools(); tabs->docView()->setSortEnabled( TRUE ); tabs->docView()->setUpdatesEnabled( TRUE ); tabs->setLoadingWidgetEnabled( FALSE ); break; } default: tabs->setLoadingProgress( percent ); break; } } diff --git a/core/launcher/launcher.h b/core/launcher/launcher.h index 2eaf77c..db6ac54 100644 --- a/core/launcher/launcher.h +++ b/core/launcher/launcher.h @@ -1,156 +1,158 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef LAUNCHER_H #define LAUNCHER_H #include <qtopia/config.h> #include <qtopia/storage.h> #include <qtopia/applnk.h> #include <qmainwindow.h> #include <qstringlist.h> #include <qprogressbar.h> #include <qvbox.h> #include <qlist.h> #include <qdict.h> #include "launcherview.h" #include "launchertab.h" #include "serverinterface.h" class QWidgetStack; class TaskBar; class Launcher; class LauncherTabWidget : public QVBox { // can't use a QTabWidget, since it won't let us set the frame style. Q_OBJECT public: LauncherTabWidget( Launcher* parent ); void updateDocs(AppLnkSet* docFolder); void setBusy(bool on); LauncherView *currentView(void); LauncherView* newView( const QString&, const QPixmap& pm, const QString& label ); void deleteView( const QString& ); void setTabViewAppearance( LauncherView *v, Config &cfg ); void setTabAppearance( LauncherTab *, Config &cfg ); LauncherView *view( const QString & ); LauncherView *docView(); void createDocLoadingWidget(); void setLoadingWidgetEnabled( bool v ); void setLoadingProgress( int percent ); LauncherTabBar* categoryBar; void setBusyIndicatorType( const QString& type ); signals: void selected(const QString&); void clicked(const AppLnk*); void rightPressed(AppLnk*); protected slots: void raiseTabWidget(); void tabProperties(); void initLayout(); private slots: void launcherMessage( const QCString &, const QByteArray &); void appMessage( const QCString &, const QByteArray &); void setProgressStyle(); protected: void paletteChange( const QPalette &p ); void styleChange( QStyle & ); private: Launcher *launcher; LauncherView *docview; QWidgetStack *stack; LauncherView *docLoadingWidget; QProgressBar *docLoadingWidgetProgress; bool docLoadingWidgetEnabled; + bool docTabEnabled; + int m_DocumentTabId; }; class Launcher : public QMainWindow, public ServerInterface { Q_OBJECT public: Launcher(); ~Launcher(); // implementing ServerInterface void createGUI(); void destroyGUI(); void typeAdded( const QString& type, const QString& name, const QPixmap& pixmap, const QPixmap& bgPixmap ); void typeRemoved( const QString& type ); void applicationAdded( const QString& type, const AppLnk& doc ); void applicationRemoved( const QString& type, const AppLnk& doc ); void allApplicationsRemoved(); void applicationStateChanged( const QString& name, ApplicationState state ); void documentAdded( const DocLnk& doc ); void documentRemoved( const DocLnk& doc ); void aboutToAddBegin(); void aboutToAddEnd(); void allDocumentsRemoved(); void documentChanged( const DocLnk& oldDoc, const DocLnk& newDoc ); void storageChanged( const QList<FileSystem> & ); void applicationScanningProgress( int percent ); void documentScanningProgress( int percent ); bool requiresApplications() const { return TRUE; } bool requiresDocuments() const; void showLoadingDocs(); void showDocTab(); QStringList idList() const { return ids; } public slots: void viewSelected(const QString&); void showTab(const QString&); void select( const AppLnk * ); void properties( AppLnk * ); void makeVisible(); signals: void executing( const AppLnk * ); private slots: - void systemMessage( const QCString &, const QByteArray &); + void systemMessage( const QCString &, const QByteArray &); protected: bool eventFilter( QObject *o, QEvent *ev ); private: void updateApps(); void loadDocs(); void updateDocs(); void updateTabs(); LauncherTabWidget *tabs; QStringList ids; TaskBar *tb; bool docTabEnabled; }; #endif // LAUNCHERVIEW_H diff --git a/core/launcher/launcherview.cpp b/core/launcher/launcherview.cpp index ff26133..c9efacb 100644 --- a/core/launcher/launcherview.cpp +++ b/core/launcher/launcherview.cpp @@ -1,856 +1,900 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "launcherview.h" /* OPIE */ #include <opie2/odebug.h> #include <qtopia/qpeapplication.h> #include <qtopia/private/categories.h> #include <qtopia/categoryselect.h> #include <qtopia/mimetype.h> #include <qtopia/resource.h> using namespace Opie::Core; #include <qpe/qcopenvelope_qws.h> /* QT */ #include <qtimer.h> #include <qfileinfo.h> #include <qiconview.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 +typedef QMap<QString,QPixmap>::Iterator pixiter; class BgPixmap { public: BgPixmap( const QPixmap &p ) : pm(p), ref(1) {} QPixmap pm; int ref; }; 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: enum iconstate_t { BASE_ICON, WAITING_ICON, EYE_ICON }; 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(); bool isEyeImage()const{return m_EyeImage;} virtual int compare ( QIconViewItem * i ) const; void paintItem( QPainter *p, const QColorGroup &cg ); void setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; } void setEyePixmap(const QPixmap&aIcon); virtual QPixmap*pixmap()const; protected: bool isBigIcon; int iteration; AppLnk* app; private: void paintAnimatedIcon( QPainter *p ); BusyIndicatorType busyType; int psize; - QPixmap m_iPixmap; bool m_EyeImage; iconstate_t m_EyeImageSet; }; 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 psize( (bigIcon ? applnk->bigPixmap().width() :applnk->pixmap().width() ) ), - m_iPixmap(), m_EyeImage(false), m_EyeImageSet(BASE_ICON) { if (applnk->type().lower().startsWith("image/") && applnk->exec().contains("opie-eye",false)) { m_EyeImage = true; - m_iPixmap = (bigIcon ? applnk->bigPixmap():applnk->pixmap()); + QMap<QString,QPixmap>::Iterator it = LauncherIconView::sm_EyeCache->find(applnk->file()); + if (it != LauncherIconView::sm_EyeCache->end()) { + m_EyeImageSet = EYE_ICON; + setPixmap(*it); + } } } LauncherItem::~LauncherItem() { LauncherIconView* liv = (LauncherIconView*)iconView(); if ( liv->busyItem() == this ) liv->setBusy(FALSE); delete app; } QPixmap*LauncherItem::pixmap()const { if (m_EyeImage && m_EyeImageSet == BASE_ICON) { LauncherIconView* liv = (LauncherIconView*)iconView(); liv->requestEyePix(this); } return QIconViewItem::pixmap(); } int LauncherItem::compare ( QIconViewItem * i ) const { LauncherIconView* view = (LauncherIconView*)iconView(); return view->compare(app,((LauncherItem *)i)->appLnk()); } 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 ) ); } QIconViewItem::paintItem(p,mycg); // Paint animation overlay if ( liv->busyItem() == this ) paintAnimatedIcon(p); if ( liv->currentItem() == this ) liv->setItemTextBackground( oldBrush ); } 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 if ( busyType == BIT_Animated ) { 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 ); #else Q_UNUSED( pic ) #endif p->drawPixmap( x1, y1, dblBuf ); } void LauncherItem::animateIcon() { LauncherIconView* liv = (LauncherIconView*)iconView(); if ( liv->busyItem() != this || !app ) return; // Highlight the icon if ( iteration == 0 ) { - QPixmap src = (isEyeImage()?m_iPixmap:(isBigIcon ? app->bigPixmap() : app->pixmap())); + QPixmap src; + pixiter it; + if (isEyeImage() && (it=LauncherIconView::sm_EyeCache->find(appLnk()->file()))!=LauncherIconView::sm_EyeCache->end()) { + src = (*it); + } else { + 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((isEyeImage()?m_iPixmap:(isBigIcon ? app->bigPixmap() : app->pixmap()))); + if (isEyeImage()) { + QMap<QString,QPixmap>::Iterator it = LauncherIconView::sm_EyeCache->find(appLnk()->file()); + if (it != LauncherIconView::sm_EyeCache->end()) { + setPixmap(*it); + return; + } + } + setPixmap(isBigIcon ? app->bigPixmap() : app->pixmap()); } void LauncherItem::setEyePixmap(const QPixmap&aIcon) { if (!isEyeImage()) return; - m_iPixmap = aIcon; setPixmap(aIcon); m_EyeImageSet = EYE_ICON; } //=========================================================================== // Implemantation of LauncherIconview start //=========================================================================== + +QMap<QString,QPixmap>* LauncherIconView::sm_EyeCache=0; + LauncherIconView::LauncherIconView( QWidget* parent, const char* name ) : QIconView(parent,name),tf(""),cf(0),bsy(0),busyTimer(0),bigIcns(TRUE),bgColor(white) { m_EyeCallBack = 0; + if (!sm_EyeCache) sm_EyeCache = new QMap<QString,QPixmap>(); sortmeth = Name; hidden.setAutoDelete(TRUE); ike = FALSE; calculateGrid( Bottom ); connect(&m_eyeTimer,SIGNAL(timeout()),this,SLOT(stopEyeTimer())); } LauncherIconView::~LauncherIconView() { odebug << "LauncherIconView::~LauncherIconView()" << oendl; #if 0 // debuggery QListIterator<AppLnk> it(hidden); AppLnk* l; while ((l=it.current())) { ++it; //odebug << "" << l << ": hidden (should remove)" << oendl; } #endif } int LauncherIconView::compare(const AppLnk* a, const AppLnk* b) { switch (sortmeth) { case 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()); return fa.lastModified().secsTo(fb.lastModified()); } case Type: return a->type().compare(b->type()); } return 0; } void LauncherIconView::setSortMethod( SortMethod m ) { if ( sortmeth != m ) { sortmeth = m; sort(); } } void LauncherIconView::setCategoryFilter( int catfilter, bool resort ) { Categories cat; cat.load( categoryFileName() ); QString str; if ( catfilter == -2 ) cf = 0; else cf = catfilter; hideOrShowItems(resort); } void LauncherIconView::setTypeFilter(const QString& typefilter, bool resort) { tf = QRegExp(typefilter,FALSE,TRUE); hideOrShowItems(resort); } void LauncherIconView::setItemTextPos( ItemTextPos pos ) { calculateGrid( pos ); QIconView::setItemTextPos( pos ); } void LauncherIconView::drawBackground( QPainter *p, const QRect &r ) { if ( !bgPixmap.isNull() ) { p->drawTiledPixmap( r, bgPixmap, QPoint( (r.x() + contentsX()) % bgPixmap.width(), (r.y() + contentsY()) % bgPixmap.height() ) ); } else { p->fillRect( r, bgColor ); } } void LauncherIconView::addCatsAndMimes(AppLnk* app) { // QStringList c = app->categories(); // for (QStringList::ConstIterator cit=c.begin(); cit!=c.end(); ++cit) { // cats.replace(*cit,(void*)1); // } QString maj=app->type(); int sl=maj.find('/'); if (sl>=0) { QString k; k = maj.left(12) == "application/" ? maj : maj.left(sl); mimes.replace(k,(void*)1); } } void LauncherIconView::setBusy(bool on) { #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 if ( on ) { busyTimer = startTimer( 100 ); } else { if ( busyTimer ) { killTimer( busyTimer ); busyTimer = 0; } } LauncherItem *c = on ? (LauncherItem*)currentItem() : 0; if ( bsy != c ) { LauncherItem *oldBusy = bsy; bsy = c; if ( oldBusy ) { oldBusy->resetIcon(); } if ( bsy ) { bsy->setBusyIndicatorType( busyType ) ; bsy->animateIcon(); } } } void LauncherIconView::clear() { mimes.clear(); cats.clear(); QIconView::clear(); hidden.clear(); } QStringList LauncherIconView::mimeTypes() const { QStringList r; QDictIterator<void> it(mimes); while (it.current()) { r.append(it.currentKey()); ++it; } r.sort(); return r; } LauncherItem*LauncherIconView::findDocItem(const QString&fname) { LauncherItem* item = (LauncherItem*)firstItem(); while (item) { if (item->appLnk()->file()==fname) { break; } item = (LauncherItem*)item->nextItem(); } return item; } void LauncherIconView::setEyePixmap(const QPixmap&aPixmap,const QString&aFile,int width) { int s = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize(); if (s!=width) return; LauncherItem*item = findDocItem(aFile); if (!item||!item->isEyeImage()) return; + (*sm_EyeCache)[aFile]=aPixmap; item->setEyePixmap(aPixmap); } void LauncherIconView::checkCallback() { if (!m_EyeCallBack) { m_EyeCallBack = new LauncherThumbReceiver(); connect(m_EyeCallBack,SIGNAL(sig_Thumbnail(const QPixmap&,const QString&,int)), this,SLOT(setEyePixmap(const QPixmap&,const QString&,int))); - m_eyeTimer.changeInterval(600000); } + m_eyeTimer.changeInterval(600000); } void LauncherIconView::addCheckItem(AppLnk* app) { LauncherItem*item = new LauncherItem( this, app, bigIcns ); if (item->isEyeImage()) { checkCallback(); } } void LauncherIconView::requestEyePix(const LauncherItem*item) { if (!item) return; if (item->isEyeImage()) { checkCallback(); int s = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize(); m_EyeCallBack->requestThumb(item->appLnk()->file(),s,s); } } void LauncherIconView::stopEyeTimer() { if (m_EyeCallBack) { + disconnect(m_EyeCallBack,SIGNAL(sig_Thumbnail(const QPixmap&,const QString&,int)), + this,SLOT(setEyePixmap(const QPixmap&,const QString&,int))); delete m_EyeCallBack; m_EyeCallBack=0; } m_eyeTimer.stop(); } -void LauncherIconView::addItem(AppLnk* app, bool resort) -{ - addCatsAndMimes(app); - if ( (tf.isEmpty() || tf.match(app->type()) >= 0) - && (cf == 0 || app->categories().contains(cf) - || cf == -1 && app->categories().count() == 0 ) ) { - addCheckItem(app); - } else { - hidden.append(app); - } - if ( resort ){ - sort(); - } -} - void LauncherIconView::updateCategoriesAndMimeTypes() { mimes.clear(); cats.clear(); LauncherItem* item = (LauncherItem*)firstItem(); while (item) { addCatsAndMimes(item->appLnk()); item = (LauncherItem*)item->nextItem(); } QListIterator<AppLnk> it(hidden); AppLnk* l; while ((l=it.current())) { addCatsAndMimes(l); ++it; } } void LauncherIconView::hideOrShowItems(bool resort) { viewport()->setUpdatesEnabled( FALSE ); hidden.setAutoDelete(FALSE); QList<AppLnk> links=hidden; hidden.clear(); hidden.setAutoDelete(TRUE); LauncherItem* item = (LauncherItem*)firstItem(); while (item) { links.append(item->takeAppLnk()); item = (LauncherItem*)item->nextItem(); } clear(); QListIterator<AppLnk> it(links); AppLnk* l; while ((l=it.current())) { addItem(l,FALSE); ++it; } if ( resort && !autoArrange() ) sort(); viewport()->setUpdatesEnabled( TRUE ); } -bool LauncherIconView::removeLink(const QString& linkfile) +bool LauncherIconView::removeLink(const QString& linkfile,bool removeCache) { LauncherItem* item = (LauncherItem*)firstItem(); AppLnk* l; bool did = FALSE; DocLnk dl(linkfile); while (item) { l = item->appLnk(); LauncherItem *nextItem = (LauncherItem *)item->nextItem(); if ( l->linkFileKnown() && l->linkFile() == linkfile || l->fileKnown() && ( l->file() == linkfile || dl.isValid() && dl.file() == l->file() ) ) { + if (removeCache) sm_EyeCache->remove(l->file()); delete item; did = TRUE; } item = nextItem; } QListIterator<AppLnk> it(hidden); while ((l=it.current())) { ++it; if ( l->linkFileKnown() && l->linkFile() == linkfile || l->file() == linkfile || dl.isValid() && dl.file() == l->file() ) { hidden.removeRef(l); did = TRUE; } } return did; } +void LauncherIconView::addItem(AppLnk* app, bool resort) +{ + addCatsAndMimes(app); + if ( (tf.isEmpty() || tf.match(app->type()) >= 0) + && (cf == 0 || app->categories().contains(cf) + || cf == -1 && app->categories().count() == 0 ) ) { + addCheckItem(app); + } else { + hidden.append(app); + } + if ( resort ){ + sort(); + } +} + +void LauncherIconView::changeItem(const AppLnk&old,AppLnk*nlink) +{ + QString oldfile = old.file(); + QString newfile = nlink->file(); + + if (newfile != oldfile) { + QMap<QString,QPixmap>::Iterator it = sm_EyeCache->find(oldfile); + if (it != sm_EyeCache->end()) { + (*sm_EyeCache)[newfile]=(*it); + } + removeLink(old.linkFile()); + } else { + removeLink(old.linkFile(),false); + } + addItem(nlink,false); +} + void LauncherIconView::timerEvent( QTimerEvent *te ) { if ( te->timerId() == busyTimer ) { if ( bsy ) bsy->animateIcon(); } else { QIconView::timerEvent( te ); } } void LauncherIconView::setBigIcons( bool bi ) { + sm_EyeCache->clear(); bigIcns = bi; #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY busyPix.resize(0,0); #endif } QIconViewItem* LauncherIconView::busyItem() const { return bsy; } void LauncherIconView::setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; } void LauncherIconView::calculateGrid( ItemTextPos pos ) { int dw = QApplication::desktop()->width(); int viewerWidth = dw-style().scrollBarExtent().width(); if ( pos == Bottom ) { int cols = 3; if ( viewerWidth <= 200 ) cols = 2; else if ( viewerWidth >= 400 ) cols = viewerWidth/96; setSpacing( 4 ); setGridX( (viewerWidth-(cols+1)*spacing())/cols ); setGridY( fontMetrics().height()*2+24 ); } else { int cols = 2; if ( viewerWidth < 150 ) cols = 1; else if ( viewerWidth >= 400 ) cols = viewerWidth/150; setSpacing( 2 ); setGridX( (viewerWidth-(cols+1)*spacing())/cols ); setGridY( fontMetrics().height()+2 ); } } void LauncherIconView::styleChange( QStyle &old ) { QIconView::styleChange( old ); calculateGrid( itemTextPos() ); } void LauncherIconView::keyPressEvent(QKeyEvent* e) { ike = TRUE; 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; } //=========================================================================== // Implemantation of LauncherIconview end //=========================================================================== //=========================================================================== 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 ); icons->setItemsMovable( FALSE ); icons->setAutoArrange( TRUE ); icons->setSorting( TRUE ); icons->setFrameStyle( QFrame::NoFrame ); icons->setMargin( 0 ); icons->setSelectionMode( QIconView::NoSelection ); icons->setBackgroundMode( PaletteBase ); icons->setResizeMode( QIconView::Fixed ); vmode = (ViewMode)-1; setViewMode( Icon ); connect( icons, SIGNAL(mouseButtonClicked(int,QIconViewItem*,const QPoint&)), SLOT(itemClicked(int,QIconViewItem*)) ); connect( icons, SIGNAL(selectionChanged()), SLOT(selectionChanged()) ); connect( icons, SIGNAL(returnPressed(QIconViewItem*)), SLOT(returnPressed(QIconViewItem*)) ); connect( icons, SIGNAL(mouseButtonPressed(int,QIconViewItem*,const QPoint&)), SLOT(itemPressed(int,QIconViewItem*)) ); tools = 0; setBackgroundType( Ruled, QString::null ); } LauncherView::~LauncherView() { if ( bgCache && bgCache->contains( bgName ) ) (*bgCache)[bgName]->ref--; } bool LauncherView::bsy=FALSE; void LauncherView::setBusy(bool on) { icons->setBusy(on); } void LauncherView::setBusyIndicatorType( const QString& type ) { if ( type. lower ( ) == "animated" ) icons->setBusyIndicatorType( BIT_Animated ) ; else icons->setBusyIndicatorType( BIT_Normal ) ; } void LauncherView::hideIcons() { icons->hide(); } void LauncherView::setToolsEnabled(bool y) { if ( !y != !tools ) { if ( y ) { tools = new QHBox(this); // Type filter typemb = new QComboBox(tools); QSizePolicy p = typemb->sizePolicy(); p.setHorData(QSizePolicy::Expanding); typemb->setSizePolicy(p); // Category filter updateTools(); tools->show(); } else { delete tools; tools = 0; } } } void LauncherView::updateTools() { disconnect( typemb, SIGNAL(activated(int)), this, SLOT(showType(int)) ); if ( catmb ) { disconnect( catmb, SIGNAL(signalSelected(int)),this,SLOT(showCategory(int))); } // ### I want to remove this icons->updateCategoriesAndMimeTypes(); QString prev; // Type filter QStringList types; typelist = icons->mimeTypes(); for (QStringList::ConstIterator it = typelist.begin(); it!=typelist.end(); ++it) { QString t = *it; if ( t.left(12) == "application/" ) { MimeType mt(t); const AppLnk* app = mt.application(); if ( app ) t = app->name(); else t = t.mid(12); } else { t[0] = t[0].upper(); } types += t; } types << tr("All types"); prev = typemb->currentText(); typemb->clear(); typemb->insertStringList(types); for (int i=0; i<typemb->count(); i++) { if ( typemb->text(i) == prev ) { typemb->setCurrentItem(i); break; } } if ( prev.isNull() ) { typemb->setCurrentItem(typemb->count()-1); } int pcat = catmb ? catmb->currentCategory() : -2; - if ( !catmb ) + if ( !catmb ) { catmb = new CategorySelect(tools); + } else if (pcat!=-2) { + + } Categories cats( 0 ); cats.load( categoryFileName() ); QArray<int> vl( 0 ); catmb->setCategories( vl, "Document View", // No tr 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))); } void LauncherView::sortBy(int s) { icons->setSortMethod((LauncherIconView::SortMethod)s); } void LauncherView::showType(int t) { if ( t >= (int)typelist.count() ) { icons->setTypeFilter("",TRUE); } else { QString ty = typelist[t]; if ( !ty.contains('/') ) ty += "/*"; icons->setTypeFilter(ty,TRUE); } } void LauncherView::showCategory( int c ) { icons->setCategoryFilter( c, TRUE ); } void LauncherView::setViewMode( ViewMode m ) { odebug << "LauncherView::setViewMode( ViewMode m )" << oendl; if ( vmode != m ) { bool bigIcons = m == Icon; icons->viewport()->setUpdatesEnabled( FALSE ); icons->setBigIcons( bigIcons ); switch ( m ) { case List: icons->setItemTextPos( QIconView::Right ); break; case Icon: icons->setItemTextPos( QIconView::Bottom ); break; } icons->hideOrShowItems( FALSE ); icons->viewport()->setUpdatesEnabled( TRUE ); vmode = 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(); @@ -927,241 +971,246 @@ void LauncherView::setBackgroundType( BackgroundType t, const QString &val ) img.setAlphaBuffer(FALSE); bg.convertFromImage(img); bgCache->insert( bgName, new BgPixmap(bg) ); } } break; case SolidColor: default: break; } 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 ) { textCol = tc; QColorGroup cg = icons->colorGroup(); cg.setColor( QColorGroup::Text, tc ); icons->setPalette( QPalette(cg,cg,cg) ); icons->viewport()->update(); } void LauncherView::setViewFont( const QFont &f ) { icons->setFont( f ); icons->hideOrShowItems( FALSE ); } void LauncherView::clearViewFont() { icons->unsetFont(); icons->hideOrShowItems( FALSE ); } void LauncherView::resizeEvent(QResizeEvent *e) { // qDebug("LauncherView resize event"); QVBox::resizeEvent( e ); // commented out for launcherview and qt/e 2.3.8 problems, probably needs real fixing somewhere... // if ( e->size().width() != e->oldSize().width() ) sort(); } void LauncherView::selectionChanged() { QIconViewItem* item = icons->currentItem(); if ( item && item->isSelected() ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( icons->inKeyEvent() ) // not for mouse press emit clicked( appLnk ); item->setSelected(FALSE); } } void LauncherView::returnPressed( QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); emit clicked( appLnk ); } } void LauncherView::itemClicked( int btn, QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( btn == LeftButton ) { // Make sure it's the item we execute that gets highlighted icons->setCurrentItem( item ); emit clicked( appLnk ); } - item->setSelected(FALSE); + item->setSelected(FALSE); } } void LauncherView::itemPressed( int btn, QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( btn == RightButton ) emit rightPressed( appLnk ); else if ( btn == ShiftButton ) emit rightPressed( appLnk ); item->setSelected(FALSE); } } void LauncherView::removeAllItems() { odebug << "LauncherView::removeAllItems()" << oendl; icons->clear(); } bool LauncherView::removeLink(const QString& linkfile) { return icons->removeLink(linkfile); } +void LauncherView::addItem(AppLnk* app, bool resort) +{ + icons->addItem(app,resort); +} + +void LauncherView::changeItem(const AppLnk&old,AppLnk*nlink) +{ + icons->changeItem(old,nlink); +} + void LauncherView::setSortEnabled( bool v ) { icons->setSorting( v ); if ( v ) sort(); } void LauncherView::setUpdatesEnabled( bool u ) { icons->setUpdatesEnabled( u ); } void LauncherView::sort() { icons->sort(); } -void LauncherView::addItem(AppLnk* app, bool resort) -{ - icons->addItem(app,resort); -} - void LauncherView::paletteChange( const QPalette &p ) { icons->unsetPalette(); QVBox::paletteChange( p ); if ( bgType == Ruled ) setBackgroundType( Ruled, QString::null ); QColorGroup cg = icons->colorGroup(); cg.setColor( QColorGroup::Text, textCol ); icons->setPalette( QPalette(cg,cg,cg) ); } void LauncherView::fontChanged(const QFont&) { odebug << "LauncherView::fontChanged()" << oendl; icons->hideOrShowItems( FALSE ); } void LauncherView::relayout(void) { 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 ); } } } /* * Launcherthumbnail handling for image files */ /* special image handling - based on opie eye */ QDataStream &operator>>( QDataStream& s, PixmapInfo& inf ) { s >> inf.file >> inf.pixmap >> inf.width >> inf.height; return s; } QDataStream &operator<<( QDataStream& s, const PixmapInfo& inf) { return s << inf.file << inf.width << inf.height; } LauncherThumbReceiver::LauncherThumbReceiver() :QObject() { QCopChannel * chan = new QCopChannel( "QPE/opie-eye",this ); connect(chan, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(recieve(const QCString&,const QByteArray&)) ); { QCopEnvelope( "QPE/Application/opie-eye_slave", "refUp()" ); } } LauncherThumbReceiver::~LauncherThumbReceiver() { { QCopEnvelope( "QPE/Application/opie-eye_slave", "refDown()" ); } } void LauncherThumbReceiver::recieve( const QCString&str, const QByteArray&at ) { PixmapInfos pixinfos; QDataStream stream( at, IO_ReadOnly ); /* we are just interested in thumbmails */ if ( str == "pixmapsHandled(PixmapList)" ) stream >> pixinfos; for ( PixmapInfos::Iterator it = pixinfos.begin(); it != pixinfos.end(); ++it ) { emit sig_Thumbnail((*it).pixmap,(*it).file,(*it).width); } } void LauncherThumbReceiver::requestThumb(const QString&file,int width,int height) { PixmapInfo rItem; rItem.file = file; rItem.width = width; rItem.height = height; m_inThumbNail.append(rItem); QTimer::singleShot(2, this, SLOT(sendRequest())); } void LauncherThumbReceiver::sendRequest() diff --git a/core/launcher/launcherview.h b/core/launcher/launcherview.h index 6d94539..05073ab 100644 --- a/core/launcher/launcherview.h +++ b/core/launcher/launcherview.h @@ -1,245 +1,250 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef LAUNCHERVIEW_H #define LAUNCHERVIEW_H #include <qtopia/storage.h> #include <qtopia/applnk.h> #include <qvbox.h> #include <qiconview.h> #include <qtimer.h> #include <qmap.h> class CategorySelect; class LauncherIconView; class LauncherItem; class QIconViewItem; class QLabel; class QWidgetStack; class MenuButton; class QComboBox; enum BusyIndicatorType { BIT_Normal = 0, BIT_Animated }; class LauncherView : public QVBox { Q_OBJECT public: LauncherView( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); ~LauncherView(); void hideIcons(); bool removeLink(const QString& linkfile); void addItem(AppLnk* app, bool resort=TRUE); + void changeItem(const AppLnk&old,AppLnk*nlink); + void removeAllItems(); void setSortEnabled(bool); void setUpdatesEnabled(bool); void sort(); void setToolsEnabled(bool); void updateTools(); void setBusy(bool); void setBusyIndicatorType( const QString& ); enum ViewMode { Icon, List }; void setViewMode( ViewMode m ); ViewMode viewMode() const { return vmode; } enum BackgroundType { Ruled, SolidColor, Image }; void setBackgroundType( BackgroundType t, const QString & ); BackgroundType backgroundType() const { return bgType; } void setTextColor( const QColor & ); QColor textColor() const { return textCol; } void setViewFont( const QFont & ); void clearViewFont(); void relayout(void); signals: void clicked( const AppLnk * ); void rightPressed( AppLnk * ); protected slots: void selectionChanged(); void returnPressed( QIconViewItem *item ); void itemClicked( int, QIconViewItem * ); void itemPressed( int, QIconViewItem * ); void sortBy(int); void showType(int); void showCategory( int ); void resizeEvent(QResizeEvent *); void flushBgCache(); protected: void paletteChange( const QPalette & ); void fontChanged(const QFont &); private: static bool bsy; QWidget* tools; LauncherIconView* icons; QComboBox *typemb; QStringList typelist; CategorySelect *catmb; ViewMode vmode; BackgroundType bgType; QString bgName; QColor textCol; QImage loadBackgroundImage(QString &fname); }; /* from opie-eye */ struct PixmapInfo { PixmapInfo() : width( -1 ), height( -1 ) {} bool operator==( const PixmapInfo& r ) { if ( width != r.width ) return false; if ( height != r.height ) return false; if ( file != r.file ) return false; return true; } int width, height; QString file; QPixmap pixmap; }; class LauncherThumbReceiver:public QObject { Q_OBJECT typedef QValueList<PixmapInfo> PixmapInfos; public: LauncherThumbReceiver(); ~LauncherThumbReceiver(); void requestThumb(const QString&file,int width,int height); public slots: void recieve( const QCString&, const QByteArray& ); protected slots: virtual void sendRequest(); signals: void sig_Thumbnail(const QPixmap&,const QString&,int); protected: PixmapInfos m_inThumbNail; }; class LauncherIconView : public QIconView { Q_OBJECT public: LauncherIconView( QWidget* parent, const char* name=0 ); ~LauncherIconView(); QIconViewItem* busyItem() const; #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY QPixmap busyPixmap() const { return busyPix; } #endif void setBigIcons( bool bi ); void updateCategoriesAndMimeTypes(); void setBusyIndicatorType ( BusyIndicatorType t ); void doAutoScroll() { // We don't want rubberbanding (yet) } void setBusy(bool on); bool inKeyEvent() const { return ike; } void addItem(AppLnk* app, bool resort=TRUE); - bool removeLink(const QString& linkfile); + bool removeLink(const QString& linkfile,bool removeCache = true); + void changeItem(const AppLnk&old,AppLnk*nlink); QStringList mimeTypes() const; QStringList categories() const; void clear(); void addCatsAndMimes(AppLnk* app); void setBackgroundOrigin( QWidget::BackgroundOrigin ) {} void setBackgroundPixmap( const QPixmap &pm ) { bgPixmap = pm; } void setBackgroundColor( const QColor &c ) { bgColor = c; } void drawBackground( QPainter *p, const QRect &r ); void setItemTextPos( ItemTextPos pos ); void hideOrShowItems(bool resort); void setTypeFilter(const QString& typefilter, bool resort); void setCategoryFilter( int catfilter, bool resort ); enum SortMethod { Name, Date, Type }; void setSortMethod( SortMethod m ); int compare(const AppLnk* a, const AppLnk* b); void requestEyePix(const LauncherItem*which); + static QMap<QString,QPixmap>* sm_EyeCache; + protected: virtual void timerEvent( QTimerEvent *te ); void styleChange( QStyle &old ); void calculateGrid( ItemTextPos pos ); void focusInEvent( QFocusEvent * ) {} void focusOutEvent( QFocusEvent * ) {} LauncherItem*findDocItem(const QString&); void addCheckItem(AppLnk* app); void checkCallback(); virtual void keyPressEvent(QKeyEvent* e); protected slots: void setEyePixmap(const QPixmap&,const QString&,int width); void stopEyeTimer(); private: QList<AppLnk> hidden; QDict<void> mimes; QDict<void> cats; SortMethod sortmeth; QRegExp tf; int cf; LauncherItem* bsy; int busyTimer; bool ike; bool bigIcns; QPixmap bgPixmap; QColor bgColor; LauncherThumbReceiver*m_EyeCallBack; #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY QPixmap busyPix; #endif BusyIndicatorType busyType; QTimer m_eyeTimer; }; #endif // LAUNCHERVIEW_H |