You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/kvs/kvi_kvs_popupmenu.cpp

1235 lines
34 KiB

//=============================================================================
//
// File : kvi_kvs_popupmenu.cpp
// Created on Wed 07 Jan 2004 05:02:57 by Szymon Stefanek
//
// This file is part of the KVIrc IRC client distribution
// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot net>
//
// This program is FREE software. You can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your opinion) any later version.
//
// This program is distributed in the HOPE that it will be USEFUL,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, write to the Free Software Foundation,
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
#define __KVIRC__
#include "kvi_kvs_popupmenu.h"
#include "kvi_locale.h"
#include "kvi_iconmanager.h"
#include "kvi_out.h"
#include "kvi_app.h"
#include "kvi_kvs_popupmanager.h"
#include "kvi_console.h"
#include "kvi_config.h"
#include "kvi_cmdformatter.h"
#include "kvi_options.h"
// popup names
// rootname : the root popup
// rootname.anonymousmenuX : child popups with no name
// rootname.externalrootname : child popups copied from external menus
// rootname.itemX : child items
// rootname.separatorX : child separators
// rootname.labelX : child labels
KviKvsPopupMenuItem::KviKvsPopupMenuItem(Type t,const TQString &szItemName,const TQString &szCondition)
{
m_szItemName = szItemName;
m_eType = t;
if(szCondition.isEmpty())
{
// true by default
m_pKvsCondition = 0;
} else {
TQString szName = "condition callback for ";
szName += szItemName;
m_pKvsCondition = new KviKvsScript(szName,szCondition,KviKvsScript::Expression);
}
}
KviKvsPopupMenuItem::KviKvsPopupMenuItem(Type t,const TQString &szItemName,const KviKvsScript * pCondition)
{
m_szItemName = szItemName;
m_eType = t;
if(!pCondition)
{
// true by default
m_pKvsCondition = 0;
} else {
m_pKvsCondition = new KviKvsScript(*pCondition);
}
}
KviKvsPopupMenuItem::~KviKvsPopupMenuItem()
{
if(m_pKvsCondition)delete m_pKvsCondition;
}
void KviKvsPopupMenuItem::clear()
{
}
KviKvsScript * KviKvsPopupMenuItem::kvsIcon()
{
return 0;
}
KviKvsScript * KviKvsPopupMenuItem::kvsText()
{
return 0;
}
KviKvsScript * KviKvsPopupMenuItem::kvsCode()
{
return 0;
}
bool KviKvsPopupMenuItem::evaluateCondition(KviKvsPopupMenuTopLevelData * pData)
{
if(!m_pKvsCondition)return true;
KviKvsVariant vRet;
if(!m_pKvsCondition->run(pData->window(),
pData->parameters(),
&vRet,
KviKvsScript::PreserveParams,
pData->extendedRunTimeData()))
{
// broken condition
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken condition in menu setup: assuming false"));
return false;
}
return vRet.asBoolean();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemSeparator::KviKvsPopupMenuItemSeparator(const TQString &szItemName,const TQString &szCondition)
: KviKvsPopupMenuItem(KviKvsPopupMenuItem::Separator,szItemName,szCondition)
{
}
KviKvsPopupMenuItemSeparator::KviKvsPopupMenuItemSeparator(const TQString &szItemName,const KviKvsScript * pCondition)
: KviKvsPopupMenuItem(KviKvsPopupMenuItem::Separator,szItemName,pCondition)
{
}
KviKvsPopupMenuItemSeparator::~KviKvsPopupMenuItemSeparator()
{
}
void KviKvsPopupMenuItemSeparator::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
{
if(!evaluateCondition(pData))return;
pMenu->insertSeparator();
}
KviKvsPopupMenuItem * KviKvsPopupMenuItemSeparator::clone() const
{
return new KviKvsPopupMenuItemSeparator(m_szItemName,m_pKvsCondition);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemWithTextAndIcon::KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const TQString &szItemName,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
: KviKvsPopupMenuItem(t,szItemName,szCondition)
{
TQString szName = "text callback for ";
szName += szItemName;
m_pKvsText = new KviKvsScript(szName,szText,KviKvsScript::Parameter);
if(szIcon.isEmpty())
{
m_pKvsIcon = 0;
} else {
szName = "icon callback for ";
szName += szItemName;
m_pKvsIcon = new KviKvsScript(szName,szIcon,KviKvsScript::Parameter);
}
}
KviKvsPopupMenuItemWithTextAndIcon::KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const TQString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
: KviKvsPopupMenuItem(t,szItemName,pCondition)
{
if(pText)
{
m_pKvsText = new KviKvsScript(*pText);
} else {
// hum.. this should never happen anyway
TQString szName = "text callback for ";
szName += szItemName;
m_pKvsText = new KviKvsScript(szName,"",KviKvsScript::Parameter);
}
if(!pIcon)
{
m_pKvsIcon = 0;
} else {
m_pKvsIcon = new KviKvsScript(*pIcon);
}
}
KviKvsPopupMenuItemWithTextAndIcon::~KviKvsPopupMenuItemWithTextAndIcon()
{
delete m_pKvsText;
if(m_pKvsIcon)delete m_pKvsIcon;
}
KviKvsScript * KviKvsPopupMenuItemWithTextAndIcon::kvsIcon()
{
return m_pKvsIcon;
}
KviKvsScript * KviKvsPopupMenuItemWithTextAndIcon::kvsText()
{
return m_pKvsText;
}
TQPixmap * KviKvsPopupMenuItemWithTextAndIcon::evaluateIcon(KviKvsPopupMenuTopLevelData * pData)
{
if(KVI_OPTION_BOOL(KviOption_boolDisablePopupIcons))return 0;
if(!m_pKvsIcon)return 0;
KviKvsVariant vRet;
if(!m_pKvsIcon->run(pData->window(),
pData->parameters(),
&vRet,
KviKvsScript::PreserveParams,
pData->extendedRunTimeData()))
{
// broken text
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken icon parameter: ignoring"));
return 0;
}
TQString szRet;
vRet.asString(szRet);
TQPixmap * p = g_pIconManager->getImage(szRet);
if(!p)pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Can't find the icon \"%Q\": ignoring"),&szRet);
return p;
}
TQString KviKvsPopupMenuItemWithTextAndIcon::evaluateText(KviKvsPopupMenuTopLevelData *pData)
{
TQString szRet;
if(!m_pKvsText)return szRet;
KviKvsVariant vRet;
if(!m_pKvsText->run(pData->window(),
pData->parameters(),
&vRet,
KviKvsScript::PreserveParams,
pData->extendedRunTimeData()))
{
// broken text
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken text parameter: assuming empty string"));
return szRet;
}
vRet.asString(szRet);
return szRet;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemLabelHelper::KviKvsPopupMenuItemLabelHelper(KviKvsPopupMenuItemLabel * pItem)
: TQObject()
{
m_pItem = pItem;
}
KviKvsPopupMenuItemLabelHelper::~KviKvsPopupMenuItemLabelHelper()
{
}
void KviKvsPopupMenuItemLabelHelper::labelDestroyed()
{
m_pItem->labelDestroyed();
}
KviKvsPopupMenuItemLabel::KviKvsPopupMenuItemLabel(const TQString &szItemName,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Label,szItemName,szText,szIcon,szCondition)
{
m_pLabel = 0;
m_pSignalRelay = new KviKvsPopupMenuItemLabelHelper(this);
}
KviKvsPopupMenuItemLabel::KviKvsPopupMenuItemLabel(const TQString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Label,szItemName,pText,pIcon,pCondition)
{
m_pLabel = 0;
m_pSignalRelay = new KviKvsPopupMenuItemLabelHelper(this);
}
KviKvsPopupMenuItemLabel::~KviKvsPopupMenuItemLabel()
{
if(m_pLabel)
{
TQObject::disconnect(m_pLabel,TQT_SIGNAL(destroyed()),m_pSignalRelay,TQT_SLOT(labelDestroyed()));
delete m_pLabel;
}
delete m_pSignalRelay;
}
void KviKvsPopupMenuItemLabel::labelDestroyed()
{
m_pLabel = 0; // someone (maybe qt, maybe us) has destroyed the label
}
KviKvsPopupMenuItem * KviKvsPopupMenuItemLabel::clone() const
{
return new KviKvsPopupMenuItemLabel(m_szItemName,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
}
void KviKvsPopupMenuItemLabel::clear()
{
if(m_pLabel)
{
TQObject::disconnect(m_pLabel,TQT_SIGNAL(destroyed()),m_pSignalRelay,TQT_SLOT(labelDestroyed()));
delete m_pLabel;
m_pLabel = 0;
}
}
void KviKvsPopupMenuItemLabel::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
{
if(!evaluateCondition(pData))return;
TQString szText = evaluateText(pData);
TQPixmap * pPix = evaluateIcon(pData);
if(m_pLabel)
{
TQObject::disconnect(m_pLabel,TQT_SIGNAL(destroyed()),m_pSignalRelay,TQT_SLOT(labelDestroyed()));
delete m_pLabel;
}
m_pLabel = new TQLabel(szText,pMenu);
TQObject::connect(m_pLabel,TQT_SIGNAL(destroyed()),m_pSignalRelay,TQT_SLOT(labelDestroyed()));
#ifndef COMPILE_USE_QT4
// FIXME: QT4 Seems to not allow widgets as TQMenu items
pMenu->insertItem(m_pLabel);
#endif
m_pLabel->setFrameStyle(TQFrame::StyledPanel | TQFrame::Raised);
if(pPix)m_pLabel->setPixmap(*pPix);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemItem::KviKvsPopupMenuItemItem(const TQString &szItemName,const TQString &szCode,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Item,szItemName,szText,szIcon,szCondition)
{
TQString szName = "click callback for ";
szName += szItemName;
m_pKvsCode = new KviKvsScript(szName,szCode);
}
KviKvsPopupMenuItemItem::KviKvsPopupMenuItemItem(const TQString &szItemName,const KviKvsScript * pCode,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Item,szItemName,pText,pIcon,pCondition)
{
m_pKvsCode = new KviKvsScript(*pCode);
}
KviKvsPopupMenuItemItem::~KviKvsPopupMenuItemItem()
{
delete m_pKvsCode;
}
void KviKvsPopupMenuItemItem::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
{
if(!evaluateCondition(pData))return;
TQString szText = evaluateText(pData);
TQPixmap * pPix = evaluateIcon(pData);
int id;
if(pPix)id = pMenu->insertItem(*pPix,szText);
else id = pMenu->insertItem(szText);
pMenu->setItemParameter(id,iIdx);
}
KviKvsPopupMenuItem * KviKvsPopupMenuItemItem::clone() const
{
return new KviKvsPopupMenuItemItem(m_szItemName,m_pKvsCode,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
}
KviKvsScript * KviKvsPopupMenuItemItem::kvsCode()
{
return m_pKvsCode;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemMenu::KviKvsPopupMenuItemMenu(const TQString &szItemName,KviKvsPopupMenu * pMenu,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Menu,szItemName,szText,szIcon,szCondition)
{
m_pMenu = pMenu;
}
KviKvsPopupMenuItemMenu::KviKvsPopupMenuItemMenu(const TQString &szItemName,KviKvsPopupMenu * pMenu,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Menu,szItemName,pText,pIcon,pCondition)
{
m_pMenu = pMenu;
}
KviKvsPopupMenuItemMenu::~KviKvsPopupMenuItemMenu()
{
delete m_pMenu;
}
KviKvsPopupMenuItem * KviKvsPopupMenuItemMenu::clone() const
{
KviKvsPopupMenu * copy = new KviKvsPopupMenu(m_pMenu->name());
copy->copyFrom(m_pMenu);
return new KviKvsPopupMenuItemMenu(m_szItemName,copy,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
}
void KviKvsPopupMenuItemMenu::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
{
if(!evaluateCondition(pData))return;
TQString szText = evaluateText(pData);
TQPixmap * pPix = evaluateIcon(pData);
int id;
m_pMenu->setParentPopup(pMenu);
if(pPix)id = pMenu->insertItem(*pPix,szText,m_pMenu);
else id = pMenu->insertItem(szText,m_pMenu);
pMenu->setItemParameter(id,iIdx);
}
void KviKvsPopupMenuItemMenu::clear()
{
m_pMenu->clearMenuContents();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
KviKvsPopupMenuItemExtMenu::KviKvsPopupMenuItemExtMenu(const TQString &szItemName,const TQString &szMenuName,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::ExtMenu,szItemName,szText,szIcon,szCondition)
{
m_szMenuName = szMenuName;
if(m_szMenuName[0]=='"' && m_szMenuName[(int)(m_szMenuName.length()-1)]=='"')
{
m_szMenuName.remove(0,1);
m_szMenuName.remove(m_szMenuName.length()-1,1);
}
m_pMenu = 0;
}
KviKvsPopupMenuItemExtMenu::KviKvsPopupMenuItemExtMenu(const TQString &szItemName,const TQString &szMenuName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::ExtMenu,szItemName,pText,pIcon,pCondition)
{
m_szMenuName = szMenuName;
if(m_szMenuName[0]=='"' && m_szMenuName[(int)(m_szMenuName.length()-1)]=='"')
{
m_szMenuName.remove(0,1);
m_szMenuName.remove(m_szMenuName.length()-1,1);
}
m_pMenu = 0;
}
KviKvsPopupMenuItemExtMenu::~KviKvsPopupMenuItemExtMenu()
{
if(m_pMenu)delete m_pMenu;
}
void KviKvsPopupMenuItemExtMenu::clear()
{
if(m_pMenu)
{
delete m_pMenu;
m_pMenu = 0;
}
}
KviKvsPopupMenuItem * KviKvsPopupMenuItemExtMenu::clone() const
{
return new KviKvsPopupMenuItemExtMenu(m_szItemName,m_szMenuName,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
}
void KviKvsPopupMenuItemExtMenu::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
{
if(!evaluateCondition(pData))return;
TQString szText = evaluateText(pData);
TQPixmap * pPix = evaluateIcon(pData);
KviKvsPopupMenu * source = KviKvsPopupManager::instance()->lookup(m_szMenuName);
if(source)
{
if(source->isLocked())
{
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Recursive definition detected for popup '%Q': ignoring"),&(pMenu->popupName()));
return;
}
TQString tmp;
KviTQString::sprintf(tmp,"%Q.%Q",&(pMenu->popupName()),&m_szMenuName);
if(m_pMenu)delete m_pMenu;
m_pMenu = new KviKvsPopupMenu(tmp);
m_pMenu->copyFrom(source);
m_pMenu->setParentPopup(pMenu);
int id;
if(pPix)id = pMenu->insertItem(*pPix,szText,m_pMenu);
else id = pMenu->insertItem(szText,m_pMenu);
pMenu->setItemParameter(id,iIdx);
} else {
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Can't find the external popup '%Q'; ignoring"),&m_szMenuName);
}
}
KviKvsPopupMenuTopLevelData::KviKvsPopupMenuTopLevelData(KviKvsVariantList * pParameters,KviWindow * pWindow)
{
m_pExtendedRunTimeData = new KviKvsExtendedRunTimeData(new KviKvsHash(),TRUE);
m_pParameters = pParameters;
m_pWindow = pWindow;
m_bTestMode = false;
m_bLocked = false;
}
KviKvsPopupMenuTopLevelData::~KviKvsPopupMenuTopLevelData()
{
delete m_pExtendedRunTimeData;
delete m_pParameters;
}
KviKvsPopupMenu::KviKvsPopupMenu(const TQString &szName)
:KviTalPopupMenu(0,szName)
{
m_szName = szName;
m_pItemList = new KviPointerList<KviKvsPopupMenuItem>;
m_pItemList->setAutoDelete(true);
m_pPrologues = new KviPointerList<KviKvsScript>;
m_pPrologues->setAutoDelete(true);
m_pEpilogues = new KviPointerList<KviKvsScript>;
m_pEpilogues->setAutoDelete(true);
m_pParentPopup = 0;
m_pTopLevelData = 0;
m_pTempTopLevelData = 0;
m_bSetupDone = false;
connect(this,TQT_SIGNAL(activated(int)),this,TQT_SLOT(itemClicked(int)));
connect(this,TQT_SIGNAL(aboutToShow()),this,TQT_SLOT(setupMenuContents()));
}
KviKvsPopupMenu::~KviKvsPopupMenu()
{
clearMenuContents();
delete m_pItemList;
delete m_pPrologues;
delete m_pEpilogues;
if(m_pTopLevelData)delete m_pTopLevelData;
if(m_pTempTopLevelData)delete m_pTempTopLevelData;
}
void KviKvsPopupMenu::copyFrom(const KviKvsPopupMenu * src)
{
doClear();
for(KviKvsScript * se = src->m_pEpilogues->first();se;se = src->m_pEpilogues->next())
{
m_pEpilogues->append(new KviKvsScript(*se));
}
for(KviKvsScript * sp = src->m_pPrologues->first();sp;sp = src->m_pPrologues->next())
{
m_pPrologues->append(new KviKvsScript(*sp));
}
for(const KviKvsPopupMenuItem * it = src->m_pItemList->first();it;it = src->m_pItemList->next())
{
addItemInternal(it->clone());
}
}
void KviKvsPopupMenu::addPrologue(const TQString &szItemName,const TQString &szCode)
{
// FIXME: translate this or not ?
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"prologue_%u_for_%Q",m_pPrologues->count(),&m_szName);
m_pPrologues->append(new KviKvsScript(szName,szCode));
}
void KviKvsPopupMenu::addEpilogue(const TQString &szItemName,const TQString &szCode)
{
// FIXME: translate this or not ?
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"epilogue_%u_for_%Q",m_pPrologues->count(),&m_szName);
m_pEpilogues->append(new KviKvsScript(szName,szCode));
}
KviKvsPopupMenuTopLevelData * KviKvsPopupMenu::topLevelData()
{
if(parentPopup())return parentPopup()->topLevelData();
return m_pTopLevelData;
}
bool KviKvsPopupMenu::removeItemByName(const TQString &szItemName,bool bRecursive)
{
KviKvsScript * se;
for(se = m_pEpilogues->first();se;se = m_pEpilogues->next())
{
if(KviTQString::equalCI(szItemName,se->name()))
{
m_pEpilogues->removeRef(se);
return true;
}
}
for(se = m_pPrologues->first();se;se = m_pPrologues->next())
{
if(KviTQString::equalCI(szItemName,se->name()))
{
m_pPrologues->removeRef(se);
return true;
}
}
for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
{
if(KviTQString::equalCI(szItemName,it->name()))
{
m_pItemList->removeRef(it); // bye :)
return true;
}
}
if(bRecursive)
{
for(KviKvsPopupMenuItem * ii = m_pItemList->first();ii;ii = m_pItemList->next())
{
if(ii->isMenu())
{
if(((KviKvsPopupMenuItemMenu *)ii)->menu())
{
bool bRet = ((KviKvsPopupMenuItemMenu *)ii)->menu()->removeItemByName(szItemName,true);
if(bRet)return true;
}
}
}
}
return false;
}
bool KviKvsPopupMenu::isLocked()
{
if(topLevelPopup()->isVisible())return true;
KviKvsPopupMenuTopLevelData * d = topLevelData();
return d ? d->isLocked() : false;
}
KviKvsPopupMenu * KviKvsPopupMenu::topLevelPopup()
{
if(parentPopup())return parentPopup();
return this;
}
KviKvsPopupMenu * KviKvsPopupMenu::addPopup(const TQString &szItemName,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
{
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"%Q.subpopup%d",&m_szName,m_pItemList->count());
KviKvsPopupMenu * pNew = new KviKvsPopupMenu(szName);
pNew->setParentPopup(this);
addItemInternal(new KviKvsPopupMenuItemMenu(szName,pNew,szText,szIcon,szCondition));
return pNew;
}
void KviKvsPopupMenu::addSeparator(const TQString &szItemName,const TQString &szCondition)
{
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"%Q.separator%d",&m_szName,m_pItemList->count());
addItemInternal(new KviKvsPopupMenuItemSeparator(szName,szCondition));
}
void KviKvsPopupMenu::addLabel(const TQString &szItemName,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
{
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"%Q.label%d",&m_szName,m_pItemList->count());
addItemInternal(new KviKvsPopupMenuItemLabel(szName,szText,szIcon,szCondition));
}
void KviKvsPopupMenu::addItem(const TQString &szItemName,const TQString &szCode,const TQString &szText,const TQString &szIcon,const TQString &szCondition)
{
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"%Q.item%d",&m_szName,m_pItemList->count());
addItemInternal(new KviKvsPopupMenuItemItem(szName,szCode,szText,szIcon,szCondition));
}
void KviKvsPopupMenu::addExtPopup(const TQString &szItemName,const TQString &szPopupName,const TQString szText,const TQString &szIcon,const TQString &szCondition)
{
TQString szName = szItemName;
if(szName.isEmpty())
KviTQString::sprintf(szName,"%Q.%Q",&m_szName,&szName);
addItemInternal(new KviKvsPopupMenuItemExtMenu(szName,szPopupName,szText,szIcon,szCondition));
}
void KviKvsPopupMenu::addItemInternal(KviKvsPopupMenuItem * it)
{
if(isLocked())tqDebug("Ooops... KviKvsPopupMenu is locked in ::addItem()");
m_pItemList->append(it);
}
void KviKvsPopupMenu::doPopup(const TQPoint & pnt,KviWindow * wnd,KviKvsVariantList * pParams,bool bTestMode)
{
// This might be a compat problem later :(((((
// it is also an ugly trick
clearMenuContents();
m_pTempTopLevelData = new KviKvsPopupMenuTopLevelData(pParams,wnd);
m_pTempTopLevelData->setTestMode(bTestMode);
KviTalPopupMenu::popup(pnt);
}
void KviKvsPopupMenu::clearMenuContents()
{
m_bSetupDone = false;
clear();
for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
{
it->clear();
}
if(m_pTopLevelData)
{
delete m_pTopLevelData;
m_pTopLevelData = 0;
}
if(m_pTempTopLevelData)
{
delete m_pTempTopLevelData;
m_pTempTopLevelData = 0;
}
}
void KviKvsPopupMenu::doClear()
{
clear();
if(m_pTopLevelData)
{
delete m_pTopLevelData;
m_pTopLevelData = 0;
}
if(m_pTempTopLevelData)
{
delete m_pTempTopLevelData;
m_pTempTopLevelData = 0;
}
m_bSetupDone = false;
m_pItemList->clear();
m_pPrologues->clear();
m_pEpilogues->clear();
}
void KviKvsPopupMenu::lock(bool bLock)
{
KviKvsPopupMenuTopLevelData * d = topLevelData();
if(!d)return;
d->setLocked(bLock);
}
void KviKvsPopupMenu::setupMenuContents()
{
// This might be a compat problem later :((((
if(parentPopup() == 0)
{
if(m_pTempTopLevelData == 0)
{
// We have been called by a KviMenuBar!
// m_bSetupDone is not valid here
clearMenuContents();
m_pTopLevelData = new KviKvsPopupMenuTopLevelData(new KviKvsVariantList(),g_pActiveWindow);
} else {
if(m_bSetupDone)return;
// we have been called by doPopup
// the menu contents have been already cleared
if(m_pTopLevelData)tqDebug("Ops.. something got messed in KviKvsPopupMenu activation system");
// Swap the top level data from temporary to the permanent
m_pTopLevelData = m_pTempTopLevelData;
m_pTempTopLevelData = 0;
}
} else {
if(m_bSetupDone)return;
}
m_bSetupDone = true;
// HACK...this is to remove the separator inserted by TQt when popup() is called and the popup is empty
clear();
KviKvsPopupMenuTopLevelData * d = topLevelData();
if(!d)
{
tqDebug("Ops...menu contents changed behind my back!");
return;
}
lock(true);
if(!g_pApp->windowExists(d->window()))d->setWindow(g_pApp->activeConsole());
if(!d->testMode())
executePrologues(d);
// Fill this menu contents
int idx = 0;
for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
{
it->fill(this,d,idx);
++idx;
}
if(!d->testMode())
executeEpilogues(d);
lock(false);
}
void KviKvsPopupMenu::executePrologues(KviKvsPopupMenuTopLevelData * pData)
{
for(KviKvsScript * s = m_pPrologues->first();s;s = m_pPrologues->next())
{
if(!s->run(pData->window(),
pData->parameters(),
0,
KviKvsScript::PreserveParams,
pData->extendedRunTimeData()))
{
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken prologue in popup menu '%Q': ignoring"),&m_szName);
}
}
}
void KviKvsPopupMenu::executeEpilogues(KviKvsPopupMenuTopLevelData * pData)
{
for(KviKvsScript * s = m_pEpilogues->first();s;s = m_pEpilogues->next())
{
if(!s->run(pData->window(),
pData->parameters(),
0,
KviKvsScript::PreserveParams,
pData->extendedRunTimeData()))
{
pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken epilogue in popup menu '%Q': ignoring"),&m_szName);
}
}
}
void KviKvsPopupMenu::itemClicked(int itemId)
{
int param = itemParameter(itemId);
KviKvsPopupMenuItem * it = m_pItemList->at(param);
KviKvsPopupMenuTopLevelData * d = topLevelData();
if(it && d)
{
if(it->isItem())
{
if(d->testMode())
{
emit testModeItemClicked(it);
} else {
// rebind if window is lost
if(!g_pApp->windowExists(d->window()))d->setWindow(g_pApp->activeConsole());
// FIXME: we could avoid locking since scripts can be shared now!
// see KviKvsTimerManager implementation
lock(true);
((KviKvsPopupMenuItemItem *)it)->kvsCode()->run(
d->window(),
d->parameters(),
0,
KviKvsScript::PreserveParams,
d->extendedRunTimeData());
// FIXME: should we print somethng if run() returns false ?
lock(false);
}
} else tqDebug("oops....clicked something that is not an item at position %d",param);
// FIXME: #warning "Maybe tell that the window has changed"
} else tqDebug("oops....no menu item at position %d",param);
// UGLY TQt 3.0.0.... we can't clear menu contents here :(
//#if [[[TQT_VERSION IS DEPRECATED]]] < 300
// topLevelPopup()->clearMenuContents();
//#endif
}
void KviKvsPopupMenu::load(const TQString &prefix,KviConfig * cfg)
{
doClear();
int cnt;
int idx;
TQString tmp = prefix;
tmp.append("_PrologueCount");
cnt = cfg->readIntEntry(tmp,0);
if(cnt > 0)
{
for(idx = 0;idx < cnt;idx++)
{
KviTQString::sprintf(tmp,"%TQ_Prologue%d",&(prefix),idx);
TQString pr = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_PrologueId%d",&(prefix),idx);
TQString itemName = cfg->readTQStringEntry(tmp,"");
if(!pr.isEmpty())addPrologue(itemName,pr);
}
} else {
// Might be old version!
KviTQString::sprintf(tmp,"%TQ_Prologue",&(prefix));
TQString pr = cfg->readTQStringEntry(tmp,"");
if(!pr.isEmpty())addPrologue(TQString(),pr);
}
KviTQString::sprintf(tmp,"%TQ_EpilogueCount",&prefix);
cnt = cfg->readIntEntry(tmp,0);
if(cnt > 0)
{
for(idx = 0;idx < cnt;idx++)
{
KviTQString::sprintf(tmp,"%TQ_Epilogue%d",&prefix,idx);
TQString ep = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_PrologueId%d",&(prefix),idx);
TQString itemName = cfg->readTQStringEntry(tmp,"");
if(!ep.isEmpty())addEpilogue(itemName,ep);
}
} else {
// Might be old version!
KviTQString::sprintf(tmp,"%TQ_Epilogue",&prefix);
TQString ep = cfg->readTQStringEntry(tmp,"");
if(!ep.isEmpty())addEpilogue(TQString(),ep);
}
KviTQString::sprintf(tmp,"%TQ_Count",&prefix);
cnt = cfg->readIntEntry(tmp,0);
for(idx = 0;idx < cnt;idx++)
{
TQString pre;
KviTQString::sprintf(pre,"%TQ_%d",&prefix,idx);
KviTQString::sprintf(tmp,"%TQ_Id",&pre);
TQString itemName = cfg->readTQStringEntry(tmp,TQString());
KviTQString::sprintf(tmp,"%TQ_Type",&pre);
int type = cfg->readIntEntry(tmp,3);
switch(type)
{
case 0: // separator
{
TQString expr;
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
expr = cfg->readTQStringEntry(tmp,"");
addSeparator(itemName,expr);
}
break;
case 1: // item
{
TQString text,icon,code,expr;
KviTQString::sprintf(tmp,"%TQ_Text",&pre);
text = cfg->readTQStringEntry(tmp,"Unnamed");
KviTQString::sprintf(tmp,"%TQ_Icon",&pre);
icon = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_Code",&pre);
code = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
expr = cfg->readTQStringEntry(tmp,"");
addItem(itemName,code,text,icon,expr);
}
break;
case 2: // menu
{
TQString text,icon,expr;
KviTQString::sprintf(tmp,"%TQ_Text",&pre);
text = cfg->readTQStringEntry(tmp,"Unnamed");
KviTQString::sprintf(tmp,"%TQ_Icon",&pre);
icon = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
expr = cfg->readTQStringEntry(tmp,"");
KviKvsPopupMenu * pop = addPopup(itemName,text,icon,expr);
pop->load(pre,cfg);
}
break;
case 3: // label
{
TQString text,icon,expr;
KviTQString::sprintf(tmp,"%TQ_Text",&pre);
text = cfg->readTQStringEntry(tmp,"Unnamed");
KviTQString::sprintf(tmp,"%TQ_Icon",&pre);
icon = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
expr = cfg->readTQStringEntry(tmp,"");
addLabel(itemName,text,icon,expr);
}
break;
case 4: // extmenu
{
TQString text,icon,code,expr;
KviTQString::sprintf(tmp,"%TQ_Text",&pre);
text = cfg->readTQStringEntry(tmp,"Unnamed");
KviTQString::sprintf(tmp,"%TQ_Icon",&pre);
icon = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_ExtName",&pre);
code = cfg->readTQStringEntry(tmp,"");
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
expr = cfg->readTQStringEntry(tmp,"");
addExtPopup(itemName,code,text,icon,expr);
}
break;
default: // ignore
break;
}
}
}
// FIXME: #warning "NOBODY EDITS THE POPUPS IN THE CONFIG!...A binary config would be faster and work better for sure here"
void KviKvsPopupMenu::save(const TQString & prefix,KviConfig * cfg)
{
int idx;
KviKvsScript * s;
TQString tmp;
KviTQString::sprintf(tmp,"%TQ_PrologueCount",&prefix);
cfg->writeEntry(tmp,m_pPrologues->count());
idx = 0;
for(s = m_pPrologues->first();s;s = m_pPrologues->next())
{
KviTQString::sprintf(tmp,"%TQ_Prologue%d",&prefix,idx);
cfg->writeEntry(tmp,s->code());
KviTQString::sprintf(tmp,"%TQ_PrologueId%d",&prefix,idx);
cfg->writeEntry(tmp,s->name());
idx++;
}
KviTQString::sprintf(tmp,"%TQ_EpilogueCount",&prefix);
cfg->writeEntry(tmp,m_pEpilogues->count());
idx = 0;
for(s = m_pEpilogues->first();s;s = m_pEpilogues->next())
{
KviTQString::sprintf(tmp,"%TQ_Epilogue%d",&prefix,idx);
cfg->writeEntry(tmp,s->code());
KviTQString::sprintf(tmp,"%TQ_EpilogueId%d",&prefix,idx);
cfg->writeEntry(tmp,s->name());
idx++;
}
KviTQString::sprintf(tmp,"%TQ_Count",&prefix);
cfg->writeEntry(tmp,m_pItemList->count());
idx = 0;
for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
{
TQString pre;
KviTQString::sprintf(pre,"%TQ_%d",&prefix,idx);
KviTQString::sprintf(tmp,"%TQ_Type",&pre);
int typeCode = 0;
switch(it->type())
{
case KviKvsPopupMenuItem::Label: typeCode = 3; break;
case KviKvsPopupMenuItem::Separator: typeCode = 0; break;
case KviKvsPopupMenuItem::Menu: typeCode = 2; break;
case KviKvsPopupMenuItem::Item: typeCode = 1; break;
case KviKvsPopupMenuItem::ExtMenu: typeCode = 4; break;
}
cfg->writeEntry(tmp,typeCode);
KviTQString::sprintf(tmp,"%TQ_Id",&pre);
cfg->writeEntry(tmp,it->name());
s = it->kvsCondition();
if(s)
{
KviTQString::sprintf(tmp,"%TQ_Expr",&pre);
cfg->writeEntry(tmp,s->code());
}
s = it->kvsIcon();
if(s)
{
KviTQString::sprintf(tmp,"%TQ_Icon",&pre);
cfg->writeEntry(tmp,s->code());
}
s = it->kvsText();
if(s)
{
KviTQString::sprintf(tmp,"%TQ_Text",&pre);
cfg->writeEntry(tmp,s->code());
}
s = it->kvsCode();
if(s)
{
KviTQString::sprintf(tmp,"%TQ_Code",&pre);
cfg->writeEntry(tmp,s->code());
}
if(it->isMenu())
{
((KviKvsPopupMenuItemMenu *)it)->menu()->save(pre,cfg);
} else if(it->isExtMenu())
{
KviTQString::sprintf(tmp,"%TQ_ExtName",&pre);
cfg->writeEntry(tmp,((KviKvsPopupMenuItemExtMenu *)it)->extName());
}
++idx;
}
}
void KviKvsPopupMenu::generateDefPopupCore(TQString &buffer)
{
TQString tmp;
buffer = "";
KviKvsScript * s;
for(s = m_pPrologues->first();s;s = m_pPrologues->next())
{
buffer.append("prologue\n");
tmp = s->code();
tmp.stripWhiteSpace();
KviCommandFormatter::blockFromBuffer(tmp);
buffer.append(tmp);
buffer.append('\n');
}
for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
{
switch(it->type())
{
case KviKvsPopupMenuItem::Item:
if(it->kvsIcon())KviTQString::appendFormatted(buffer,"item(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
else KviTQString::appendFormatted(buffer,"item(%Q)",&(it->kvsText()->code()));
if(it->kvsCondition())KviTQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
buffer.append("\n");
tmp = it->kvsCode()->code();
KviCommandFormatter::blockFromBuffer(tmp);
buffer.append(tmp);
buffer.append("\n");
break;
case KviKvsPopupMenuItem::Menu:
if(it->kvsIcon())KviTQString::appendFormatted(buffer,"popup(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
else KviTQString::appendFormatted(buffer,"popup(%Q)",&(it->kvsText()->code()));
if(it->kvsCondition())KviTQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
buffer.append("\n");
((KviKvsPopupMenuItemMenu *)it)->menu()->generateDefPopupCore(tmp);
KviCommandFormatter::blockFromBuffer(tmp);
buffer.append(tmp);
buffer.append("\n");
break;
case KviKvsPopupMenuItem::Separator:
if(it->kvsCondition())KviTQString::appendFormatted(buffer,"separator(%Q)\n\n",&(it->kvsCondition()->code()));
else buffer.append("separator\n\n");
break;
case KviKvsPopupMenuItem::Label:
if(it->kvsIcon())KviTQString::appendFormatted(buffer,"label(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
else KviTQString::appendFormatted(buffer,"label(%Q)",&(it->kvsText()->code()));
if(it->kvsCondition())KviTQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
buffer.append("\n\n");
break;
case KviKvsPopupMenuItem::ExtMenu:
if(it->kvsIcon())KviTQString::appendFormatted(buffer,"extpopup(%Q,%Q,%Q)",&(it->kvsText()->code()),&(((KviKvsPopupMenuItemExtMenu *)it)->extName()),&(it->kvsIcon()->code()));
else KviTQString::appendFormatted(buffer,"extpopup(%Q)",&(it->kvsText()->code()));
if(it->kvsCondition())KviTQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
buffer.append("\n\n");
break;
}
}
for(s = m_pEpilogues->first();s;s = m_pEpilogues->next())
{
buffer.append("epilogue\n");
tmp = s->code();
tmp.stripWhiteSpace();
KviCommandFormatter::blockFromBuffer(tmp);
buffer.append(tmp);
buffer.append('\n');
}
}
void KviKvsPopupMenu::generateDefPopup(TQString &buffer)
{
KviTQString::sprintf(buffer,"defpopup(%s)\n",name());
TQString core;
generateDefPopupCore(core);
KviCommandFormatter::blockFromBuffer(core);
buffer.append(core);
}