/*****************************************************************

Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

******************************************************************/

#include <stdlib.h>
#include <unistd.h>

#include <qdir.h>
#include <qdragobject.h>

#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <ksimpleconfig.h>
#include <kapp.h>
#include <khelpmenu.h>
#include <kdesktopfile.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kglobalsettings.h>
#include <kstddirs.h>
#include <kmimetype.h>
#include <kurl.h>
#include <kfiledialog.h>
#include <kaboutkde.h>
#include <krun.h>
#include <kwm.h>
#include <kwin.h>
#include <kprocess.h>
#include <kpanelapplet.h>
#include <dcopclient.h>
#include <kwinmodule.h>
#include <kstringhandler.h>

#include "menus.h"
#include "menus.moc"
#include "servicemenu.h"
#include "dialogs.h"
#include "panel.h"
#include "global.h"
#include "appletarea.h"
#include "appletcontainer.h"

template class QList<PanelBrowserMenu>;

PanelMenu::PanelMenu(const QString &startDir, QWidget *parent, 
		     const char *name)
  : QPopupMenu(parent, name)
{
  init = false;
  startPath = startDir;
  connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
  connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
  KConfig *config = KGlobal::config();
  config->setGroup("menus");
  clearDelay = config->readNumEntry("MenuCacheTime", 60000); // 1 minute
  if(clearDelay)
    connect(&t, SIGNAL(timeout()), this, SLOT(slotClear()));
}

void PanelMenu::slotAboutToShow()
{
  if(clearDelay)
    t.stop();
  initialize();
}

void PanelMenu::slotClear()
{
  clear();
  init = false;
}

void PanelMenu::hideEvent(QHideEvent *ev)
{
  if(clearDelay)
    t.start(clearDelay, true);
  QPopupMenu::hideEvent(ev);
}

PanelBrowserMenu::PanelBrowserMenu(QString startDir,
				   bool expandFSTypes,
                                   bool ignoreEmptyDirs, QWidget *parent,
                                   const char *name, int filter,
                                   int sorting)
  : PanelMenu(startDir, parent, name)
{
  expandFS = expandFSTypes;
  ignoreEmpty = ignoreEmptyDirs;
  KConfig *config = KGlobal::config();
  config->setGroup("menus");
  max = config->readNumEntry("MaxEntries", 100);
  maxedOut=false;
  // gcc didn't like me using QDir:: for the type in the declaration
  filterSpec = (QDir::FilterSpec)filter;
  sortSpec = (QDir::SortSpec)sorting;
}

PanelBrowserMenu* PanelBrowserMenu::createSubMenu(QString startDir,
						  bool expandFSTypes,
                                                  bool ignoreEmptyDirs, QWidget *parent,
                                                  const char *name, int filter, int sorting)
{
  return new PanelBrowserMenu(startDir, expandFSTypes, ignoreEmptyDirs,
                              parent, name, filter, sorting);
}

void PanelBrowserMenu::initialize()
{
    if (init) return;
    
    QPixmap smallIcon, medIcon;
    
    // precache often used default icons 
    QIconSet defaultIcons(SmallIcon("unknown"));
    defaultIcons.setPixmap(KGlobal::iconLoader()->
			   loadIcon("unknown", KIcon::Desktop, 
				    KIcon::SizeMedium),
			   QIconSet::Large);
  
    QIconSet defaultFolders(SmallIcon("folder"));
    defaultFolders.setPixmap(KGlobal::iconLoader()->
			     loadIcon("folder", KIcon::Desktop, 
				      KIcon::SizeMedium),
			     QIconSet::Large);
    
    // some often used strings
    QString cwd = QString::fromLatin1(".");
    QString up = QString::fromLatin1("..");
    QString slashDotDirectory = QString::fromLatin1("/.directory");
    
    fileList.clear();
	
    QDir dir(startPath);
    if (!dir.exists())
	return;
    
    dir.setSorting(sortSpec);
    dir.setFilter(filterSpec);
    const QFileInfoList *list = dir.entryInfoList();
    
    if(!list) {
	insertItem(SmallIcon("stop"), i18n("Permission Denied!"));
	maxedOut = true;
	return;
    }
    
    if(list->count() > max){
	maxedOut = true;
	insertItem(SmallIcon("exclamation"),
		   i18n("Too many files to load."));
	return;
    }
    
    QFileInfoListIterator filit(*list);
    QFileInfo *fi;
    
    for (; (fi = filit.current()) != NULL; ++filit) {
	// directories
	const QString& fileName = fi->fileName();
	const QString& absFilePath = fi->absFilePath();
	
	if(fi->isDir() && fileName != cwd && fileName != up){
	    if(ignoreEmpty){
		QDir tmpDir(absFilePath);
		if((int)tmpDir.count() == 2) {
		    continue;
		}
	    }
	    
            QString dirFile(absFilePath + slashDotDirectory);
            QString entryName;
            if(QFile::exists(dirFile)){
		KSimpleConfig config(dirFile);
		config.setDesktopGroup();
//		if (config.readBoolEntry("X-KDE-HideFromPanel", false))
//		    continue;
		
		smallIcon = SmallIcon(config.readEntry("Icon",
						       "folder"));
		medIcon = KGlobal::iconLoader()->
		    loadIcon(config.readEntry("Icon", "folder"),
			     KIcon::Desktop, KIcon::SizeMedium);
		entryName = config.readEntry("Name", fileName);
            }
            PanelBrowserMenu *subMenu = createSubMenu(absFilePath, expandFS,
						      ignoreEmpty, this);
            if (entryName.isNull())
		entryName = fileName;
            if(smallIcon.isNull())
		append(defaultFolders, entryName, subMenu);
            else
		append(smallIcon, medIcon, entryName, subMenu);
	} else if(fi->isFile() && fileName != ".directory" &&
		  fileName != ".order") {
	    // kdelnks
	    if(KDesktopFile::isDesktopFile(absFilePath))
	    {
		KDesktopFile dFile(absFilePath);
		if(dFile.tryExec() /*&& !dFile.readBoolEntry("X-KDE-HideFromPanel", false)*/)
		{
		    smallIcon = SmallIcon(dFile.readIcon());
		    medIcon = KGlobal::iconLoader()->
			loadIcon(dFile.readIcon(), KIcon::Desktop,
				 KIcon::SizeMedium);
		    if(smallIcon.isNull())
			smallIcon = KMimeType::
			pixmapForURL(KURL(absFilePath), 0,
				     KIcon::SizeSmall);
		    if(medIcon.isNull())
			medIcon = KMimeType::
			pixmapForURL(KURL(absFilePath), 0,
				     KIcon::SizeMedium);
		    
		    if ((dFile.hasDeviceType() || dFile.hasLinkType()) &&
			expandFS) {
			PanelBrowserMenu *mnu =
			    createSubMenu(KURL(dFile.readURL()).path(), 
					  expandFS, ignoreEmpty, this);
			append(smallIcon, medIcon,
			       fi->baseName(), mnu);
		    } else {
			append(smallIcon, medIcon, fileName, fileName);
		    }
		}
	    }
	    // normal files
	    else {
	    QPixmap cachePix =
		KMimeType::pixmapForURL(KURL(absFilePath), 0,
					KIcon::SizeSmall);
	    if(!cachePix.isNull())
		append(cachePix, fileName, fileName);
	    else
		append(defaultIcons, fileName, fileName);
	    }
	}
    }
	
    smallIcon.resize(0, 0);
    medIcon.resize(0, 0);
    
    adjustSize();
}


void PanelBrowserMenu::append(const QPixmap &pixmap, const QString &title,
                              const QString &fileName)
{
    fileList.append(fileName);
    insertItem(QIconSet(pixmap), title, fileList.count()-1);
}

void PanelBrowserMenu::append(const QPixmap &smallPixmap,
                              const QPixmap &mediumPixmap,
                              const QString &title,
                              const QString &fileName)
{
    fileList.append(fileName);
    QIconSet is(smallPixmap);
    is.setPixmap(mediumPixmap, QIconSet::Large);
    insertItem(is, title, fileList.count()-1);
}

void PanelBrowserMenu::append(const QIconSet &iconSet, const QString &title,
                              const QString &fileName)
{
    fileList.append(fileName);
    insertItem(iconSet, title, fileList.count()-1);
}

void PanelBrowserMenu::append(const QPixmap &pixmap, const QString &title,
                              PanelBrowserMenu *subMenu)
{
    fileList.append(""); // keep in sync
    insertItem(QIconSet(pixmap), title, subMenu, fileList.count()-1);
}

void PanelBrowserMenu::append(const QPixmap &smallPixmap,
                              const QPixmap &mediumPixmap,
                              const QString &title,
                              PanelBrowserMenu *subMenu)
{
    QIconSet is(smallPixmap);
    is.setPixmap(mediumPixmap, QIconSet::Large);
    insertItem(is, title, subMenu, fileList.count()-1);
}

void PanelBrowserMenu::append(const QIconSet &iconSet, const QString &title,
                              PanelBrowserMenu *subMenu)
{
    insertItem(iconSet, title, subMenu, fileList.count()-1);
}

void PanelBrowserMenu::mousePressEvent(QMouseEvent *me)
{
    QPopupMenu::mousePressEvent(me);

    m_pressedPos = me->pos();
}

void PanelBrowserMenu::mouseMoveEvent(QMouseEvent *me)
{
    QPopupMenu::mouseMoveEvent(me);

    if (!(me->state() & LeftButton))
	return; // only handle left button drags
    
    int x = me->pos().x();
    int y = me->pos().y();
    
    if (abs(x - m_pressedPos.x()) > KGlobalSettings::dndEventDelay() ||
	abs(y - m_pressedPos.y()) > KGlobalSettings::dndEventDelay()) {
	int id = idAt(m_pressedPos);
	// the >=0 thing is a neat hack to avoid checking manual items
	if(id >= 0 && !maxedOut && !fileList[id].isEmpty()) {
	    //      QUriDrag *d = new QUriDrag(findItem(id));
	    QUriDrag *d = new QUriDrag(this);
	    QPoint hotspot;
	    hotspot.setX(iconSet(id)->pixmap(QIconSet::Large,
					     QIconSet::Active).width() / 2);
	    hotspot.setY(iconSet(id)->pixmap(QIconSet::Large,
					     QIconSet::Active).height() / 2);
	    d->setPixmap(iconSet(id)->pixmap(QIconSet::Large,
					     QIconSet::Active), hotspot);
	    
	    QStringList l;
	    l.append(startPath + fileList[id]);
	    d->setFilenames(l);
	    
	    d->drag();
	}
    }
}

void PanelBrowserMenu::slotExec(int id)
{
    kapp->propagateSessionManager();
    
    // the >=0 thing is a neat hack to avoid checking manual items
    if(id >= 0 && !maxedOut && !fileList[id].isEmpty()) {
	new KRun(startPath + "/" + fileList[id], 0, true);
    }
}

PanelQuickBrowser::PanelQuickBrowser(QWidget *parent, const char *name)
  : PanelMenu("", parent, name)
{
  KConfig *config = KGlobal::config();
  config->setGroup("menus");
  max = config->readNumEntry("MaxEntries", 100);
}

void PanelQuickBrowser::initialize()
{
  if(!init) {
    init = true;
    // special handling for the device menu
    QDir dir( KGlobalSettings::desktopPath() );
    dir.setSorting(QDir::DirsFirst| QDir::Name | QDir::IgnoreCase);
    dir.setFilter(QDir::Files);
    const QFileInfoList *list = dir.entryInfoList();
    bool flag = false;
    if(list){
      QFileInfoListIterator it(*list);
      QFileInfo *fi;
      for(; (fi = it.current()) != NULL; ++it) {
        KDesktopFile dFile(fi->absFilePath());
        if(dFile.hasDeviceType()){
          if(!flag){
            fileList.append("");
            flag = true;
          }
          PanelBrowserMenu *mnu =
	      new PanelBrowserMenu(KURL(dFile.readURL()).path(), true, 
				   false, this, 0L, QDir::Dirs|QDir::Files);
          insertItem(SmallIcon(dFile.readIcon()), fi->baseName(), mnu);
          fileList.append("");
        }
      }
    }

    int count = KGlobal::dirs()->findDirs("data", "quickbrowser").count();
    if(count){
      dir.setPath(KGlobal::dirs()->findDirs("data", "quickbrowser")
                  [count > 1 ? 1 : 0]);
      list = dir.entryInfoList();
      if(list){
        QFileInfoListIterator it(*list);
        parseBrowserApplnks(it, i18n("System Entries:"),
                            locate("mini", "shared"));
      }
      if(count > 1){
        dir.setPath(KGlobal::dirs()->findDirs("data", "quickbrowser")[0]);
        if(dir.exists()){
          list = dir.entryInfoList();
          if(list){
            QFileInfoListIterator it(*list);
            parseBrowserApplnks(it, i18n("Personal Entries:"),
                                locate("mini", "personal"));
          }
        }
      }
    }
    adjustSize();
  }
}

void PanelQuickBrowser::parseBrowserApplnks(QFileInfoListIterator &it,
                                            const QString &/*title*/,
                                            const QString &/*pixmap*/)
{
  bool flag = false;
  QFileInfo *fi;
  for(; (fi = it.current()) != NULL; ++it){
    if(KDesktopFile::isDesktopFile(fi->absFilePath())){
      KDesktopFile dFile(fi->absFilePath());
      dFile.setDollarExpansion(true); // need to expand $HOME and the like.
      if(!flag){
        //insertTitle(QPixmap(pixmap), title);
        fileList.append("");
        flag = true;
      }
      if (dFile.hasDeviceType() || dFile.hasLinkType()) {
	  PanelBrowserMenu *mnu =
	      new PanelBrowserMenu(KURL(dFile.readURL()).path(), 
				   true, false, this,
				   0L, QDir::Dirs|QDir::Files);
	  insertItem(SmallIcon(dFile.readIcon()), fi->baseName(), mnu);
	  fileList.append("");
      } else{
	  insertItem(SmallIcon(dFile.readIcon()), fi->baseName());
	  fileList.append(fi->absFilePath());
      }
    }
  }
}

void PanelQuickBrowser::slotExec(int id)
{
  kapp->propagateSessionManager();
  if(!fileList[id].isEmpty() && id)
    new KRun(fileList[id]); // will delete itself
}

PanelKMenu::PanelKMenu(QWidget *parent, const char *name)
  : PanelServiceMenu(QString::null, QString::null, parent, name)
{
  // set the first client id to some arbitrarily large value. I guess more
  // than 10000 menu entries in the toplevel K menu are quite useless, anyway :-)
  client_id = 10000;
  aboutKDE = 0;
}

PanelKMenu::~PanelKMenu()
{
  delete aboutKDE;
}

void PanelKMenu::initialize()
{
  if (!init)
    {
      // Add services
      PanelServiceMenu::initialize();
      insertSeparator();

      // insert recent documents menu
      KConfig *config = KGlobal::config();
      config->setGroup("menus");

      if(config->readBoolEntry("UseRecent", true))
        {
          PanelRecentMenu *recentMnu = new PanelRecentMenu(this);
          insertItem(SmallIcon("document"), i18n("Recent Documents"), recentMnu);
          insertSeparator();
        }

      // insert quickbrowser
      if(config->readBoolEntry("UseBrowser", true))
        {
          PanelQuickBrowser *browserMnu = new PanelQuickBrowser(this);
          insertItem(SmallIcon("kdisknav"), i18n("Quick Browser"), browserMnu);
          insertSeparator();
        }

      // insert client menus, if any
      if (clients.count() > 0)
        {
          QIntDictIterator<KickerClientMenu> it(clients);
          while (it)
            {
              insertItem(it.current()->icon, it.current()->text, it.current(), it.currentKey());
              ++it;
            }
          insertSeparator();
        }

      // insert some default menu items like logout/lock screen
      insertItem(SmallIcon("run"), i18n("Run..."), this, SLOT( slotRunCommand() ) );
      insertSeparator();
      insertItem(SmallIcon("panel"), i18n("Panel Menu..."), new PanelOpMenu(this));
      insertItem(SmallIcon("go"), i18n("About KDE"), this, SLOT( slotAboutKDE() ) );
      insertItem(SmallIcon("key"), i18n("Lock Screen"), this, SLOT(slotLock()));
      insertItem(SmallIcon("exit"), i18n("Logout"), this, SLOT(slotLogout()));
      adjustSize();
  }
  
  init = true;
}

int PanelKMenu::insertClientMenu(KickerClientMenu *p)
{
  int id = client_id;
  clients.insert(id, p);
  slotClear();
  return id;
}


void PanelKMenu::removeClientMenu(int id)
{
  clients.remove(id);
  removeItem(id);
  slotClear();
}


void PanelKMenu::slotLock()
{
  DCOPClient *client = kapp->dcopClient();
  client->send("kdesktop", "KScreensaverIface", "lock()", "");
}

void PanelKMenu::slotLogout()
{
  PGlobal::panel->writeConfig();
  kapp->requestShutDown();
}

void PanelKMenu::slotContextHelp()
{
  KWin::invokeContextHelp();
}

void PanelKMenu::slotAboutKDE()
{
  if (!aboutKDE)
    aboutKDE = new KAboutKDE (0, "aboutkde", false);
  aboutKDE->show();
}

void PanelKMenu::slotRunCommand()
{
  QByteArray data;
  kapp->dcopClient()->send( "kdesktop", "KDesktopIface", "popupExecuteCommand()", data );
}

PanelAddAppsMenu::PanelAddAppsMenu(QWidget *parent, const char *name)
  : PanelAddAppsBaseMenu(KGlobal::dirs()->resourceDirs("apps").last(), false,
                     true, parent, name)
{}

PanelAddAppsBaseMenu::PanelAddAppsBaseMenu(QString startDir, bool expandFSTypes,
                                           bool ignoreEmptyDirs, QWidget *parent,
                                           const char *name, int filter, int sorting)
  : PanelBrowserMenu(startDir, expandFSTypes, ignoreEmptyDirs, parent, name, filter, sorting) {}


PanelBrowserMenu* PanelAddAppsBaseMenu::createSubMenu(QString startDir,
						      bool expandFSTypes,
                                                      bool ignoreEmptyDirs, QWidget *parent,
                                                      const char *name, int filter, int sorting)
{
  return new PanelAddAppsBaseMenu(startDir, expandFSTypes, ignoreEmptyDirs,
                                  parent, name, filter, sorting);
}

void PanelAddAppsBaseMenu::slotExec(int id)
{
  // the >=0 thing is a neat hack to avoid checking manual items
  if(id >= 0 && !maxedOut && !fileList[id].isEmpty())
    {
      kdDebug() << "adding url button: " << startPath + "/" +fileList[id] << endl;
      PGlobal::panel->appletArea()->addURLButton(startPath + "/" + fileList[id]);
    }
}

void PanelAddAppsMenu::initialize()
{
    PanelBrowserMenu::initialize();
}

PanelRecentMenu::PanelRecentMenu(QWidget *parent, const char *name)
  :PanelBrowserMenu(locateLocal("data", "RecentDocuments/"),
		    false, false, parent, name,
                    QDir::Files, QDir::Time || QDir::Reversed)
{
  QString path(locateLocal("data", "RecentDocuments/"));
  if(!QFile::exists(path)){
    QDir d;
    d.mkdir(path);
  }
}

void PanelRecentMenu::initialize()
{
  if(init)
    clear();

  PanelBrowserMenu::initialize();
  if(count()){
    insertSeparator();
    insertItem(SmallIcon("delete"), i18n("Clear History"),
	           this, SLOT(slotClearHistory())) ;
  }
  adjustSize();
}

void PanelRecentMenu::slotClearHistory()
{
    QDir dir(locateLocal("data", "RecentDocuments/"));
    QStringList list = dir.entryList(QDir::Files);
    QStringList::Iterator it = list.begin();
    for(it = list.begin(); it != list.end() ; ++it)
        dir.remove(*it);
}



PanelAppletOpMenu::PanelAppletOpMenu(int actions, QWidget *parent, const char *name)
  : QPopupMenu(parent, name)
{
  insertItem(SmallIcon("panel"), i18n("Panel Menu"), new PanelOpMenu(this));
  insertSeparator();

  insertItem(SmallIcon("move"), i18n("&Move"), Move);
  setAccel(CTRL+Key_M, Move);

  insertItem(SmallIcon("stop"), i18n("&Remove"), Remove);
  setAccel(CTRL+Key_R, Remove);

  if (actions & KPanelApplet::Help
	  || actions & KPanelApplet::About)
	insertSeparator();

  if (actions & KPanelApplet::About)
	{
	  insertItem(i18n("&About"), About);
	  setAccel(CTRL+Key_A, About);
	}
  
  if (actions & KPanelApplet::Help)
	{
	  insertItem(SmallIcon("help"), i18n("&Help"), Help);
	  setAccel(CTRL+Key_H, Help);
	}

  if (actions & KPanelApplet::Preferences)
	{
	  insertSeparator();
	  insertItem(SmallIcon("configure"), i18n("&Preferences"), Preferences);
	  setAccel(CTRL+Key_P, Preferences);
	}

  adjustSize();
}

PanelDirDropMenu::PanelDirDropMenu(QWidget *parent, const char *name)
  :QPopupMenu(parent, name)
{
  insertItem(SmallIcon("folder"), i18n("Add as &file manager URL"), Url);
  setAccel(CTRL+Key_F, Url);
  insertItem(SmallIcon("kdisknav"), i18n("Add as Quick&Browser"), Browser);
  setAccel(CTRL+Key_B, Browser);
  adjustSize();
}

PanelOpMenu::PanelOpMenu(QWidget *parent, const char *name)
  : QPopupMenu(parent, name)
{
  QPopupMenu *sizeMnu = new QPopupMenu(this);
  sizeMnu->insertItem(i18n("Tiny"), this, SLOT(slotSizeSmall()));
  sizeMnu->insertItem(i18n("Normal"), this, SLOT(slotSizeNormal()));
  sizeMnu->insertItem(i18n("Large"), this, SLOT(slotSizeLarge()));

  QPopupMenu *configMnu = new QPopupMenu(this);
  configMnu->insertItem(i18n("Panel Size"), sizeMnu);
  configMnu->insertItem(SmallIcon("panel_settings"), i18n("Panel Settings"), this, SLOT(slotConfigure()));

  QPopupMenu *addMnu = new QPopupMenu(this);
  addMnu->insertItem(i18n("Application"), new PanelAddAppsMenu(this));
  addMnu->insertItem(i18n("Applet"), new PanelAppletMenu(this));
  addMnu->insertSeparator();
  addMnu->insertItem(SmallIcon("go"), i18n("K Menu"), this, SLOT(slotAddKMenu()));
  addMnu->insertItem(SmallIcon("window_list"), i18n("Windowlist"), this, SLOT(slotAddWindowList()));
  addMnu->insertItem(SmallIcon("kdisknav"), i18n("Quick Browser"),
                     this, SLOT(slotAddQuickBrowser()));
  addMnu->insertItem(SmallIcon("exec"), i18n("Legacy Application"),
                     this, SLOT(slotAddNonKDEApp()));

  KHelpMenu *help = new KHelpMenu(0, KGlobal::instance()->aboutData(), false);
  QPopupMenu *helpMnu = help->menu();

  insertItem(i18n("Add..."), addMnu);
  insertItem(SmallIcon("configure"), i18n("Configure..."), configMnu);
  insertItem(SmallIcon("help"), i18n("Help..."), helpMnu);
  insertSeparator();
  insertItem(i18n("Restart"), this, SLOT(slotRestartDontAsk()));
  adjustSize();
}

void PanelOpMenu::slotAddKMenu()
{
  PGlobal::panel->appletArea()->addKMenuButton();
}

void PanelOpMenu::slotAddWindowList()
{
  PGlobal::panel->appletArea()->addWindowListButton();
}

void PanelOpMenu::slotAddQuickBrowser()
{
  QString dir = KFileDialog::getExistingDirectory(QString::null, 0, i18n("Select a directory"));
  QFileInfo fi(dir);
  if(fi.isDir())  // directory
    PGlobal::panel->appletArea()->addBrowserButton(dir);
}

void PanelOpMenu::slotAddNonKDEApp()
{
  QString exec = KFileDialog::getOpenFileName(QString::null, QString::null, 0,i18n("Select a executable"));
  QFileInfo fi(exec);
  if(!fi.isExecutable())  // executable
    return;

  QString pixmapFile;
  KMimeType::pixmapForURL(exec, 0, KIcon::Desktop, 0, KIcon::DefaultState, &pixmapFile);

  PanelExeDialog dlg(exec, pixmapFile, QString::null, false, 0);

  if(dlg.exec() == QDialog::Accepted)
    {
      // KIconloader returns a full path, we only want name
      QFileInfo iconfi(dlg.icon());
      PGlobal::panel->appletArea()->addExeButton(exec, iconfi.fileName(), dlg.commandLine(), dlg.useTerminal());
    }
}

void PanelOpMenu::slotSizeSmall()
{
  PGlobal::panel->setSize(Tiny);
}

void PanelOpMenu::slotSizeNormal()
{
  PGlobal::panel->setSize(Normal);
}

void PanelOpMenu::slotSizeLarge()
{
  PGlobal::panel->setSize(Large);
}

void PanelOpMenu::slotConfigure()
{
  PGlobal::panel->writeConfig();

  KProcess proc;
  proc << locate("exe", "kcmshell");
  proc << "LookNFeel/panel";
  proc.start(KProcess::DontCare);
}

void PanelOpMenu::slotRestart()
{

  int ret = KMessageBox::questionYesNo(0, i18n("Do you really want to restart the panel?"),
                                        i18n("Restart Panel"));

  if (ret != KMessageBox::Yes) return;

  slotRestartDontAsk();
}

void PanelOpMenu::slotRestartDontAsk()
{
    char ** o_argv = new char*[2];
    o_argv[0] = strdup("kicker");
    o_argv[1] = 0L;

    PGlobal::panel->writeConfig();
    QApplication::exit();
    execv(locate("exe", "kicker"), o_argv);
    exit(1);
}

PanelAppletMenu::PanelAppletMenu(QWidget *parent, const char *name)
  : QPopupMenu(parent, name)
{
  connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));

  QStringList list = KGlobal::dirs()->findAllResources("internalapplets", "*.desktop");

  for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
    {
      KDesktopFile df(*it);
      internalApplets.append(*it);
      insertItem(df.readName(), internalApplets.count()-1);
    }
  adjustSize();
}

void PanelAppletMenu::slotExec(int id)
{
  if(id >= 0 && !internalApplets[id].isEmpty())
    {
      QFileInfo fi(internalApplets[id]);
      QString name = fi.baseName();
      PGlobal::panel->appletArea()->addInternalFrame(name, internalApplets[id]);
    }
}

PanelWindowListMenu::PanelWindowListMenu(QWidget *parent, const char *name)
  : QPopupMenu(parent, name)
{  
  connect(
      this, SIGNAL(activated(int)), 
      SLOT(slotExec(int)));
}

void PanelWindowListMenu::slotExec(int id)
{  
  if (id > 1000) {
    KWin::setCurrentDesktop(id - 1000);
  }
  else {
    Window w = PGlobal::kwin_module->windows()[id];
    KWin::setActiveWindow(w);
  }
}

/**
 * Generate the list of windows
 **/
void PanelWindowListMenu::init()
{
  int i, d;
  int nd = KWin::numberOfDesktops();
  int cd = KWin::currentDesktop();
  WId active_window = KWin::activeWindow();
  
  clear();
  
  for (d = 1; d <= nd; d++)
	{
	  if (nd > 1)
		{
		  insertItem(QString("Desktop &") + QString::number(d), 1000 + d);
		  insertSeparator();
		}
	  
	  int items = 0;
	  
	  if (!active_window && d == cd)
        setItemChecked(1000 + d, TRUE);
      
      QValueList<WId>::ConstIterator it;
      for (it = PGlobal::kwin_module->windows().begin(), i = 0;
		   it != PGlobal::kwin_module->windows().end(); ++it, ++i) {
        if (
			(KWM::desktop(*it) == d
			 && !KWM::isSticky(*it)
			 )
			||
			(d == cd && KWM::isSticky(*it))
			) {
          QString title = KWM::titleWithState(*it);
          if (title != "Kicker") { // Don't show Kicker
            QPixmap pm = KWM::miniIcon(*it, 16, 16);
			items++;
            insertItem(/*pm.isNull()?defaultPixmap:*/pm,
					   QString("   ")+ 
					   KStringHandler::csqueeze(
												KWM::titleWithState(*it),25),i);
            if (*it == active_window)
              setItemChecked(i, TRUE);
          }
        }
      }
	  if (items > 0)
		{
		  items = 0;
		  if (d < nd)
			insertSeparator();
		}
    }
  adjustSize();
}

