-rw-r--r-- | core/launcher/startmenu.cpp | 253 | ||||
-rw-r--r-- | core/launcher/startmenu.h | 21 |
2 files changed, 170 insertions, 104 deletions
diff --git a/core/launcher/startmenu.cpp b/core/launcher/startmenu.cpp index 08ae885..f17c7f8 100644 --- a/core/launcher/startmenu.cpp +++ b/core/launcher/startmenu.cpp @@ -9,41 +9,50 @@ ** 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. ** **********************************************************************/ +// TODO. During startup
+// Launcher::typeAdded
+// is called for each new tab and calls then each time the refresh of startmenu
+// suboptimal
+
#define INCLUDE_MENUITEM_DEF #include "startmenu.h" #include <qtopia/qpeapplication.h> #include <qtopia/config.h> #include <qtopia/applnk.h> #include <qtopia/global.h> #include <qtopia/resource.h> #include <qtopia/mimetype.h> #include <qtopia/qlibrary.h> #include <qdict.h> #include <qdir.h> -#include <qpainter.h> +//#include <qpainter.h>
+
+//#include <stdlib.h>
+
-#include <stdlib.h> +#define APPLNK_ID_OFFSET 250
+#define NO_ID -1
void StartPopupMenu::keyPressEvent( QKeyEvent *e ) { if ( e->key() == Key_F33 || e->key() == Key_Space ) { // "OK" button, little hacky QKeyEvent ke(QEvent::KeyPress, Key_Enter, 13, 0); QPopupMenu::keyPressEvent( &ke ); } else { QPopupMenu::keyPressEvent( e ); } } @@ -51,24 +60,25 @@ void StartPopupMenu::keyPressEvent( QKeyEvent *e ) //--------------------------------------------------------------------------- StartMenu::StartMenu(QWidget *parent) : QLabel( parent ) { startButtonPixmap = "go"; // No tr int sz = AppLnk::smallIconSize()+3; QPixmap pm; pm.convertFromImage(Resource::loadImage(startButtonPixmap).smoothScale(sz,sz)); setPixmap(pm); setFocusPolicy( NoFocus ); + useWidePopupMenu = true;
launchMenu = 0; refreshMenu(); } void StartMenu::mousePressEvent( QMouseEvent * ) { launch(); } StartMenu::~StartMenu() @@ -76,200 +86,248 @@ StartMenu::~StartMenu() clearApplets(); } void StartMenu::createMenu() { clearApplets(); delete launchMenu; launchMenu = new StartPopupMenu( this ); loadMenu( launchMenu ); loadApplets(); - bool result = nother || ntabs || m_applets.count(); + bool result = currentItem || menuApplets.count();
if ( result ) connect( launchMenu, SIGNAL(activated(int)), SLOT(itemSelected(int)) ); - } void StartMenu::refreshMenu() { - Config cfg("Taskbar"); + Config cfg( "StartMenu" );
cfg.setGroup("Menu"); bool ltabs = cfg.readBoolEntry("LauncherTabs",TRUE); bool lot = cfg.readBoolEntry("LauncherOther",TRUE); - bool lt = ltabs || lot; - if ( launchMenu && !lt ) - return; // nothing to do + useWidePopupMenu = cfg.readBoolEntry( "LauncherSubPopup", TRUE );
+
+ if ( launchMenu && !(ltabs || lot) ) return; // nothing to do
- if ( launchMenu ) { - int i; - /* find the first entry we want to remove */ - for (i=0; i<(int)launchMenu->count(); i++) { - QMenuItem* item = launchMenu->findItem(launchMenu->idAt(i)); - if ( item && item->id() >= 0 && item->id() < ntabs ) { - break; - } - if ( item && item->isSeparator() ) { - i++; - break; - } - } - /* remove them */ - while (i<(int)launchMenu->count()) - launchMenu->removeItemAt(i); - loadMenu(launchMenu); - addApplets(launchMenu); - } else { createMenu(); } -} void StartMenu::itemSelected( int id ) { - if ( id >= 0 && id < ntabs ) { - emit tabSelected(tabs[id]); - } else if ( id >= 20 && id < 20+nother ) { - other.at(id-20)->execute(); - }else { - MenuApplet *applet = m_applets.find ( id ); + if ( id == NO_ID ) return;
+
+ if ( id < 0 ) {
+ MenuApplet *applet = menuApplets.find( id );
if ( applet ) { - qWarning("activated"); applet-> iface-> activated(); } + } else if ( id >= APPLNK_ID_OFFSET ) {
+ AppLnk * appLnk = appLnks.find( id );
+ if ( appLnk ) {
+ appLnk->execute();
+ }
+ } else {
+ QString *tabName = tabNames.find( id );
+ if ( tabName ) {
+ emit tabSelected( *tabName );
+ }
} } -bool StartMenu::loadMenu( QPopupMenu *menu ) +void StartMenu::createAppEntry( QPopupMenu *menu, QDir dir, QString file )
{ - Config cfg("Taskbar"); - cfg.setGroup("Menu"); - - bool ltabs = cfg.readBoolEntry("LauncherTabs",TRUE); - bool lot = cfg.readBoolEntry("LauncherOther",TRUE); - bool sepfirst = !ltabs && !lot; - - tabs.clear(); - other.setAutoDelete(TRUE); - other.clear(); - ntabs = 0; - nother = 0; + if ( file.right(8) == ".desktop" ) {
+ AppLnk* applnk = new AppLnk( dir.path() + "/" + file );
+ if ( !applnk->isValid() ) {
+ delete applnk;
+ return;
+ }
- bool f=TRUE; - if ( ltabs || lot ) { - QDir dir( MimeType::appsFolderName(), QString::null, QDir::Name ); - for (int i=0; i<(int)dir.count(); i++) { - QString d = dir[i]; - Config cfg(dir.path()+"/"+d+"/.directory",Config::File); - if ( cfg.isValid() ) { - QString nm = cfg.readEntry("Name"); - QString ic = cfg.readEntry("Icon"); - if ( !!nm && !!ic ) { - tabs.append(d); - menu->insertItem( Resource::loadIconSet(ic), nm, ntabs++ ); - } - } else if ( lot && d.right(8)==".desktop") { - AppLnk* applnk = new AppLnk(dir.path()+"/"+d); - if ( applnk->isValid() ) { if ( applnk->type() == "Separator" ) { // No tr - if ( lot ) { menu->insertSeparator(); - sepfirst = f && !ltabs; - } delete applnk; } else { - f = FALSE; - other.append(applnk); - menu->insertItem( Resource::loadIconSet(applnk->icon()), - applnk->name(), 20+nother++ ); + QPixmap test;
+ test.convertFromImage(
+ Resource::loadImage( applnk->icon() ).smoothScale(
+ AppLnk::smallIconSize(), AppLnk::smallIconSize() ), 0 );
+
+ menu->insertItem( test, applnk->name(),
+ currentItem + APPLNK_ID_OFFSET );
+ appLnks.insert( currentItem + APPLNK_ID_OFFSET, applnk );
+ currentItem++;
+ }
} +
+}
+
+void StartMenu::createDirEntry( QPopupMenu *menu, QDir dir, QString file, bool lot )
+{
+ // do some sanity checks and collect information
+
+ if ( file == "." || file == ".." ) return;
+
+ Config cfg( dir.path() + "/" + file + "/.directory", Config::File );
+ if ( !cfg.isValid() ) return;
+
+ QString name = cfg.readEntry( "Name" );
+ QString icon = cfg.readEntry( "Icon" );
+ if ( !name || !icon ) return;
+
+ QDir subdir = QDir( dir );
+ subdir.cd( file );
+ subdir.setFilter( QDir::Files );
+ subdir.setNameFilter( "*.desktop" );
+ // we don' t show the menu if there are no entries
+ // perhaps one should check if there exist subsubdirs with entries...
+ if ( subdir.entryList().isEmpty() ) return;
+
+ // checks were ok
+
+ QPixmap test;
+ test.convertFromImage( Resource::loadImage( icon ).smoothScale(
+ AppLnk::smallIconSize(), AppLnk::smallIconSize() ), 0 );
+
+ if ( useWidePopupMenu ) {
+ // generate submenu
+ QPopupMenu *submenu = new QPopupMenu( menu );
+ connect( submenu, SIGNAL(activated(int)), SLOT(itemSelected(int)) );
+ menu->insertItem( test, name, submenu, NO_ID );
+
+ // ltabs is true cause else we wouldn't stuck around..
+ createMenuEntries( submenu, subdir, true, lot );
} else { - delete applnk; + // no submenus - just bring corresponding tab to front
+ menu->insertItem( test, name, currentItem );
+ tabNames.insert( currentItem, new QString( file ) );
+ currentItem++;
} } +
+void StartMenu::createMenuEntries( QPopupMenu *menu, QDir dir, bool ltabs, bool lot )
+{
+ if ( lot ) {
+ dir.setFilter( QDir::Files );
+ dir.setNameFilter( "*.desktop" );
+ QStringList files = dir.entryList();
+ files.sort();
+
+ for ( QStringList::Iterator it = files.begin(); it != files.end(); it++ ) {
+ createAppEntry( menu, dir, *it );
+ }
} + if ( ltabs ) {
+ dir.setNameFilter( "*" );
+ dir.setFilter( QDir::Dirs );
+ QStringList dirs = dir.entryList();
+ dirs.sort();
- if ( !menu->count() ) - sepfirst = TRUE; + for ( QStringList::Iterator it = dirs.begin(); it != dirs.end(); it++ ) {
+ createDirEntry( menu, dir, *it, lot );
} + }
+}
+
+bool StartMenu::loadMenu( QPopupMenu *menu )
+{
+ Config cfg("StartMenu");
+ cfg.setGroup("Menu");
+
+ bool ltabs = cfg.readBoolEntry("LauncherTabs", TRUE);
+ bool lot = cfg.readBoolEntry("LauncherOther", TRUE);
+ useWidePopupMenu = cfg.readBoolEntry( "LauncherSubPopup", TRUE );
+ bool sepfirst = !ltabs && !lot;
+
+ currentItem = 0;
+ launchMenu->clear();
+
+ appLnks.setAutoDelete( true );
+ tabNames.setAutoDelete( true );
+ appLnks.clear();
+ tabNames.clear();
+ appLnks.setAutoDelete( false );
+ tabNames.setAutoDelete( false );
+
+ QDir dir( MimeType::appsFolderName(), QString::null, QDir::Name );
+ createMenuEntries( menu, dir, ltabs, lot );
+
+ if ( !menu->count() ) sepfirst = TRUE;
launchMenu->setName(sepfirst ? "accessories" : "accessories_need_sep"); // No tr - return (nother || ntabs ); + return currentItem;
} void StartMenu::launch() { int y = mapToGlobal( QPoint() ).y() - launchMenu->sizeHint().height(); if ( launchMenu->isVisible() ) launchMenu->hide(); else launchMenu->popup( QPoint( 1, y ) ); } -static int compareAppletPositions(const void *a, const void *b) +static int compareAppletPositions(const void *b, const void *a)
{ const MenuApplet* aa = *(const MenuApplet**)a; const MenuApplet* ab = *(const MenuApplet**)b; int d = aa->iface->position() - ab->iface->position(); if ( d ) return d; return QString::compare(aa->library->library(),ab->library->library()); } void StartMenu::clearApplets() { if (launchMenu ) launchMenu-> hide(); - for ( QIntDictIterator<MenuApplet> it ( m_applets ); it. current ( ); ++it ) { + for ( QIntDictIterator<MenuApplet> it( menuApplets ); it.current(); ++it ) {
MenuApplet *applet = it. current ( ); if ( launchMenu ) { launchMenu-> removeItem ( applet-> id ); delete applet-> popup; } applet-> iface-> release(); applet-> library-> unload(); delete applet-> library; } - m_applets.clear(); + menuApplets.clear();
} void StartMenu::loadApplets() { Config cfg( "StartMenu" ); cfg.setGroup( "Applets" ); // SafeMode causes too much problems, so we disable it for now -- // maybe we should reenable it for OPIE 1.0 - sandman 26.09.02 // removed in the remerge PluginManager could handle it // we don't currently use it -zecke QStringList exclude = cfg.readListEntry( "ExcludeApplets", ',' ); QString lang = getenv( "LANG" ); QString path = QPEApplication::qpeDir() + "/plugins/applets"; -#ifdef Q_OS_MACX - QDir dir( path, "lib*.dylib" ); -#else QDir dir( path, "lib*.so" ); -#endif /* Q_OS_MACX */ QStringList list = dir.entryList(); QStringList::Iterator it; int napplets=0; MenuApplet* *xapplets = new MenuApplet*[list.count()]; for ( it = list.begin(); it != list.end(); ++it ) { if ( exclude.find( *it ) != exclude.end() ) continue; MenuAppletInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if (( lib->queryInterface( IID_MenuApplet, (QUnknownInterface**)&iface ) == QS_OK ) && iface ) { MenuApplet *applet = new MenuApplet; xapplets[napplets++] = applet; @@ -280,58 +338,55 @@ void StartMenu::loadApplets() QString type = (*it).left( (*it).find(".") ); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } else { exclude += *it; delete lib; } } cfg.writeEntry( "ExcludeApplets", exclude, ',' ); - qsort(xapplets,napplets,sizeof(m_applets[0]),compareAppletPositions); + qsort(xapplets, napplets, sizeof(menuApplets[0]), compareAppletPositions);
- int foo = ( launchMenu-> count ( )) ? launchMenu-> insertSeparator ( ) : 0; - while (napplets--) { MenuApplet *applet = xapplets[napplets]; applet-> popup = applet-> iface-> popup ( this ); - if ( applet-> popup ) - applet-> id = launchMenu-> insertItem ( applet-> iface-> icon ( ), applet-> iface-> text ( ), applet-> popup ); - else - applet-> id = launchMenu-> insertItem ( applet-> iface-> icon ( ), applet-> iface-> text ( ) ); - - - m_applets.insert ( applet-> id, new MenuApplet(*applet)); + // menuApplets got an id < -1
+ menuApplets.insert( -( currentItem + 2 ), new MenuApplet( *applet ) );
+ currentItem++;
} delete [] xapplets; + addApplets( launchMenu );
} /* * Launcher calls loadMenu too often fix that */ void StartMenu::addApplets(QPopupMenu* pop) { QIntDict<MenuApplet> dict; if( pop-> count ( )) pop-> insertSeparator ( ); - for ( QIntDictIterator<MenuApplet> it ( m_applets ); it. current ( ); ++it ) { + for ( QIntDictIterator<MenuApplet> it( menuApplets ); it.current(); ++it ) {
MenuApplet *applet = it. current ( ); if ( applet-> popup ) - applet-> id = pop-> insertItem ( applet-> iface-> icon ( ), applet-> iface-> text ( ), applet-> popup ); + applet->id = pop->insertItem( applet->iface->icon(),
+ applet->iface->text(), applet->popup );
else - applet-> id = pop-> insertItem ( applet-> iface-> icon ( ), applet-> iface-> text ( ) ); + applet->id = pop->insertItem( applet->iface->icon(),
+ applet->iface->text() );
dict.insert( applet->id, new MenuApplet(*applet) ); } /* need to update the key */ - m_applets.setAutoDelete( true ); - m_applets.clear(); - m_applets.setAutoDelete( false ); - m_applets = dict; + menuApplets.setAutoDelete( true );
+ menuApplets.clear();
+ menuApplets.setAutoDelete( false );
+ menuApplets = dict;
} diff --git a/core/launcher/startmenu.h b/core/launcher/startmenu.h index 99df0f0..7218035 100644 --- a/core/launcher/startmenu.h +++ b/core/launcher/startmenu.h @@ -16,49 +16,56 @@ ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __START_MENU_H__ #define __START_MENU_H__ #include <qtopia/applnk.h> #include <qintdict.h> #include <qstring.h> #include <qlist.h> +#include <qmap.h>
+#include <qdir.h>
#include <qlabel.h> #include <qpopupmenu.h> #include <qtopia/menuappletinterface.h> class StartPopupMenu : public QPopupMenu { +
public: StartPopupMenu( QWidget *parent ) : QPopupMenu( parent ) {} +
protected: void keyPressEvent( QKeyEvent *e ); +
}; class QLibrary; struct MenuApplet { QLibrary *library; MenuAppletInterface *iface; int id; QPopupMenu *popup; }; class StartMenu : public QLabel { +
Q_OBJECT +
public: StartMenu( QWidget * ); ~StartMenu(); void refreshMenu(); public: StartPopupMenu *launchMenu; signals: void tabSelected(const QString&); @@ -68,28 +75,32 @@ public slots: protected slots: void itemSelected( int id ); protected: virtual void mousePressEvent( QMouseEvent * ); private: void loadApplets(); void clearApplets(); void addApplets( QPopupMenu* menu ); bool loadMenu( QPopupMenu *menu ); + void createMenuEntries( QPopupMenu *menu, QDir dir, bool ltabs, bool lot );
+ void createDirEntry( QPopupMenu *menu, QDir dir, QString file, bool lot );
+ void createAppEntry( QPopupMenu *menu, QDir dir, QString file );
private: bool useWidePopupMenu; QString popupMenuSidePixmap; bool startButtonIsFlat; QString startButtonPixmap; - QStringList tabs; - QList<AppLnk> other; - QIntDict<MenuApplet> m_applets; - int ntabs; - int nother; + int currentItem;
+
+ QIntDict<AppLnk> appLnks;
+ QIntDict<QString> tabNames;
+ QIntDict<MenuApplet> menuApplets;
+
}; #endif // __START_MENU_H__ |