//============================================================================= // // File : classeditor.cpp // Creation date : Mon Feb 15 2010 14:35:55 CEST by Carbone Alessandro // // This file is part of the KVirc irc client distribution // Copyright (C) 2010 Alessandro Carbone (elfonol at gmail dot com) // // This program is FREE software. You can redistribute it and/or // modify it under the linkss 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. // //============================================================================= #include "classeditor.h" #include "kvi_iconmanager.h" #include "kvi_options.h" #include "KviLocale.h" #include "kvi_imagedialog.h" #include "KviConfigurationFile.h" #include "kvi_filedialog.h" #include "KviFileUtils.h" #include "kvi_scripteditor.h" #include "kvi_debug.h" #include "kvi_app.h" #include "kvi_frame.h" #include "KviQString.h" #include "kvi_kvs_kernel.h" #include "kvi_kvs_object_class.h" #include "kvi_kvs_object_controller.h" #include "kvi_filedialog.h" #include "KviCommandFormatter.h" #include "kvi_module.h" #include "kvi_tal_vbox.h" #include "kvi_fileextensions.h" #include "kvi_modulemanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern KviClassEditorWindow * g_pClassEditorWindow; extern KviModule * g_pClassEditorModule; KviClassEditorTreeWidget::KviClassEditorTreeWidget(QWidget * pParent) : QTreeWidget(pParent) { setColumnCount (1); setHeaderLabel(__tr2qs_ctx("Class","editor")); setSelectionMode(QAbstractItemView::ExtendedSelection); setSortingEnabled(true); setRootIsDecorated(true); setAnimated(true); } KviClassEditorTreeWidget::~KviClassEditorTreeWidget() { //remove and delete all items clear(); } void KviClassEditorTreeWidget::mousePressEvent(QMouseEvent * e) { if(e->button() == Qt::RightButton) { QTreeWidgetItem * pItem = itemAt(e->pos()); if(pItem) emit rightButtonPressed(pItem,QCursor::pos()); } QTreeWidget::mousePressEvent(e); } KviClassEditorTreeWidgetItem::KviClassEditorTreeWidgetItem(QTreeWidget * pTreeWidget, Type eType, const QString & szName) : QTreeWidgetItem(pTreeWidget), KviHeapObject(), m_eType(eType) { setName(szName); m_szInheritsClassName = ""; m_iPos = 0; m_bInternal = false; m_bClassModified = false; QPixmap * pIcon = 0; if(eType == KviClassEditorTreeWidgetItem::Namespace) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE); else pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASS); setIcon(0,QIcon(*pIcon)); } KviClassEditorTreeWidgetItem::KviClassEditorTreeWidgetItem(KviClassEditorTreeWidgetItem * pParentItem, Type eType, const QString & szName) : QTreeWidgetItem(pParentItem), m_eType(eType) { setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); setName(szName); m_szInheritsClassName = ""; m_bInternal = false; m_iPos = 0; m_bClassModified = false; QPixmap * pIcon = 0; if(eType == KviClassEditorTreeWidgetItem::Namespace) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE); else if(eType == KviClassEditorTreeWidgetItem::Class) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASS); else pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_FUNCTION); setIcon(0,QIcon(*pIcon)); } void KviClassEditorTreeWidgetItem::setClassNotBuilt(bool bModified) { m_bClassModified = bModified; QPixmap * pIcon = 0; if(bModified) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASSNOTBUILT); else pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASS); setIcon(0,QIcon(*pIcon)); } void KviClassEditorTreeWidgetItem::setName(const QString & szName) { m_szName = szName; setText(0,m_szName); } void KviClassEditorTreeWidgetItem::setType(Type eType) { m_eType = eType; QPixmap * pIcon = 0; if(eType == KviClassEditorTreeWidgetItem::Namespace) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE); else if(eType == KviClassEditorTreeWidgetItem::Class) pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASS); else pIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_FUNCTION); setIcon(0,QIcon(*pIcon)); } KviClassEditor::KviClassEditor(QWidget * pParent) : QWidget(pParent) { m_pClasses = new KviPointerHashTable(100,false); m_pClasses->setAutoDelete(false); m_pLastEditedItem = 0; m_pLastClickedItem = 0; m_szDir = QDir::homePath(); QGridLayout * pLayout = new QGridLayout(this); m_pSplitter = new QSplitter(Qt::Horizontal,this); m_pSplitter->setChildrenCollapsible(false); pLayout->addWidget(m_pSplitter,0,0); KviTalVBox * pVBox = new KviTalVBox(m_pSplitter); pVBox->setSpacing(0); pVBox->setMargin(0); m_pTreeWidget = new KviClassEditorTreeWidget(pVBox); pVBox = new KviTalVBox(m_pSplitter); KviTalHBox * pHBox = new KviTalHBox(pVBox); pHBox->setSpacing(0); pHBox->setMargin(0); m_pClassNameLabel = new QLabel(__tr2qs_ctx("No item selected","editor"),pHBox); pHBox->setStretchFactor(m_pClassNameLabel,2); m_pClassNameLabel->setWordWrap(true); m_pClassNameRenameButton = new QPushButton(__tr2qs_ctx("Rename","editor"),pHBox); m_pClassNameRenameButton->setToolTip(__tr2qs_ctx("Edit the class or namespace name","editor")); m_pClassNameRenameButton->setEnabled(false); connect(m_pClassNameRenameButton,SIGNAL(clicked()),this,SLOT(renameItem())); pHBox = new KviTalHBox(pVBox); pHBox->setSpacing(0); pHBox->setMargin(0); pHBox = new KviTalHBox(pVBox); pHBox->setSpacing(0); pHBox->setMargin(0); m_pFunctionNameLabel = new QLabel(__tr2qs_ctx("No item selected","editor"),pHBox); pHBox->setStretchFactor(m_pFunctionNameLabel,2); m_pFunctionNameRenameButton = new QPushButton(__tr2qs_ctx("Rename","editor"),pHBox); m_pFunctionNameRenameButton->setToolTip(__tr2qs_ctx("Edit the function member name","editor")); m_pFunctionNameRenameButton->setEnabled(false); connect(m_pFunctionNameRenameButton,SIGNAL(clicked()),this,SLOT(renameFunction())); m_pReminderLabel = new QLabel(__tr2qs_ctx("No item selected","editor"),pVBox); m_pReminderLabel->hide(); m_pReminderLabel->setWordWrap(true); m_pEditor = KviScriptEditor::createInstance(pVBox); m_pEditor->setFocus(); connect(m_pEditor,SIGNAL(find(const QString &)),this,SLOT(slotFindWord(const QString &))); connect(m_pEditor,SIGNAL(replaceAll(const QString &,const QString &)),this,SLOT(slotReplaceAll(const QString &,const QString &))); m_pContextPopup = new KviTalPopupMenu(this); oneTimeSetup(); currentItemChanged(0,0); } KviClassEditor::~KviClassEditor() { m_pClasses->clear(); delete m_pClasses; } void KviClassEditor::buildFullItemPath(KviClassEditorTreeWidgetItem * pItem, QString & szBuffer) { if(!pItem) return; szBuffer.prepend(pItem->name() + "::"); pItem = (KviClassEditorTreeWidgetItem *)pItem->parent(); while(pItem) { QString szTmp = pItem->name(); if(!szTmp.isEmpty()) { szBuffer.prepend("::"); szBuffer.prepend(szTmp); } pItem = (KviClassEditorTreeWidgetItem *)pItem->parent(); } } QString KviClassEditor::buildFullClassName(KviClassEditorTreeWidgetItem * pItem) { if(!pItem) return QString(); QString szName = pItem->name(); KviClassEditorTreeWidgetItem * pNItem = (KviClassEditorTreeWidgetItem *)pItem->parent(); while(pNItem) { QString szTmp = pNItem->name(); if(!szTmp.isEmpty()) { szName.prepend("::"); szName.prepend(szTmp); } pNItem = (KviClassEditorTreeWidgetItem *)pNItem->parent(); } return szName; } KviClassEditorTreeWidgetItem * KviClassEditor::findTopLevelItem(const QString & szName) { for(int i=0; i < m_pTreeWidget->topLevelItemCount(); i++) { if(KviQString::equalCI(m_pTreeWidget->topLevelItem(i)->text(0),szName)) return (KviClassEditorTreeWidgetItem *)m_pTreeWidget->topLevelItem(i); } return 0; } KviClassEditorTreeWidgetItem * KviClassEditor::findItem(const QString & szFullName) { bool bFound; QStringList lNamespaces = szFullName.split("::"); if(lNamespaces.count() == 0) return 0; KviClassEditorTreeWidgetItem * pItem = findTopLevelItem(lNamespaces.at(0)); if(!pItem) return 0; for(int i=1; i < lNamespaces.count(); i++) { bFound = false; for(int j=0; j < pItem->childCount(); j++) { if (KviQString::equalCI(pItem->child(j)->text(0),lNamespaces.at(i))) { pItem=( KviClassEditorTreeWidgetItem *)pItem->child(j); bFound = true; break; } } if(!bFound) return 0; } return (KviClassEditorTreeWidgetItem *)pItem; } KviClassEditorTreeWidgetItem * KviClassEditor::createFullItem(const QString & szFullName) { bool bFound; int i; QStringList lNamespaces = szFullName.split("::"); if(lNamespaces.count() == 0) return 0; if(lNamespaces.count() == 1) { KviClassEditorTreeWidgetItem * pItem = findTopLevelItem(lNamespaces.at(0)); if(pItem) return pItem; return new KviClassEditorTreeWidgetItem(m_pTreeWidget,KviClassEditorTreeWidgetItem::Class,lNamespaces.at(0)); } KviClassEditorTreeWidgetItem * pItem = findTopLevelItem(lNamespaces.at(0)); if(!pItem) pItem = new KviClassEditorTreeWidgetItem(m_pTreeWidget,KviClassEditorTreeWidgetItem::Namespace,lNamespaces.at(0)); for(i=1; i < lNamespaces.count()-1; i++) { bFound = false; for(int j=0; j < pItem->childCount();j++) { if(KviQString::equalCI(pItem->child(j)->text(0),lNamespaces.at(i))) { pItem = (KviClassEditorTreeWidgetItem *)pItem->child(j); bFound = true; break; } } if(!bFound) pItem = new KviClassEditorTreeWidgetItem(pItem,KviClassEditorTreeWidgetItem::Namespace,lNamespaces.at(i)); } return new KviClassEditorTreeWidgetItem(pItem,KviClassEditorTreeWidgetItem::Class,lNamespaces.at(i)); } KviClassEditorTreeWidgetItem * KviClassEditor::createFullNamespace(const QString & szFullName) { bool bFound; int i; QStringList lNamespaces = szFullName.split("::"); if(lNamespaces.count() == 0) return 0; KviClassEditorTreeWidgetItem * pItem = findTopLevelItem(lNamespaces.at(0)); if(!pItem) pItem = new KviClassEditorTreeWidgetItem(m_pTreeWidget,KviClassEditorTreeWidgetItem::Namespace,lNamespaces.at(0)); if(lNamespaces.count() == 1) return pItem; for(i=1; i < lNamespaces.count(); i++) { bFound = false; for(int j=0;jchildCount();j++) { if(KviQString::equalCI(pItem->child(j)->text(0),lNamespaces.at(i)) && (( KviClassEditorTreeWidgetItem *)pItem->child(j))->isNamespace()) { pItem = (KviClassEditorTreeWidgetItem *)pItem->child(j); bFound = true; break; } } if(!bFound) pItem = new KviClassEditorTreeWidgetItem(pItem,KviClassEditorTreeWidgetItem::Namespace,lNamespaces.at(i)); } return pItem; } void KviClassEditor::oneTimeSetup() { QStringList sl; QString szClassName; QString szPath; g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes); QDir d(szPath); QString szExtension = QString("*%1").arg(KVI_FILEEXTENSION_SCRIPT); // *.kvs sl = d.entryList(QStringList(szExtension), QDir::Files | QDir::NoDotAndDotDot); g_pModuleManager->getModule("objects"); KviPointerHashTableIterator it(*KviKvsKernel::instance()->objectController()->classDict()); KviKvsObjectClass * pClass = 0; KviClassEditorTreeWidgetItem * pClassItem = 0; while(KviKvsObjectClass * pClass = it.current()) { if(pClass->isBuiltin()) m_pClasses->insert(it.currentKey(),0); else { QString szTmp; szTmp = it.currentKey(); szTmp.replace("::","--"); szTmp.append(".kvs"); if(sl.indexOf(szTmp) == -1) { szClassName = it.currentKey(); pClassItem = createFullItem(szClassName); createFullClass(it.current(),pClassItem,szClassName); } } ++it; } for(int i=0; i < sl.count(); i++) { szClassName = sl.at(i); szClassName.replace("--","::"); szClassName.chop(4); pClassItem = createFullItem(szClassName); pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName); if(pClass) createFullClass(pClass, pClassItem, szClassName); } loadNotBuiltClasses(); connect(m_pTreeWidget,SIGNAL(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)),this,SLOT(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *))); m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_pTreeWidget,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(customContextMenuRequested(const QPoint &))); } void KviClassEditor::createFullClass(KviKvsObjectClass * pClass, KviClassEditorTreeWidgetItem * pClassItem, const QString & szClassName) { KviPointerHashTableIterator it(* pClass->getHandlers()); QStringList szFunctionsList; while(it.current()) { szFunctionsList.append(it.currentKey()); ++it; } szFunctionsList.sort(); KviClassEditorTreeWidgetItem *pFunctionItem; m_pClasses->insert(szClassName,pClassItem); KviKvsObjectClass * pParentClass = pClass->parentClass(); pClassItem->setInheritsClass(pParentClass->name()); for(int i=0;ilookupFunctionHandler(szFunctionsList.at(i)); if (pClass->isScriptHandler(szFunctionsList.at(i)) && !pHandler->isClone()) { pFunctionItem=findFunction(szFunctionsList.at(i), pClassItem); if(!pFunctionItem) pFunctionItem = new KviClassEditorTreeWidgetItem(pClassItem,KviClassEditorTreeWidgetItem::Method,szFunctionsList.at(i)); pClass->getFunctionCode(szCode,*pHandler); pFunctionItem->setBuffer(szCode); pFunctionItem->setReminder(pClass->reminder(pHandler)); if(pHandler->flags() & KviKvsObjectFunctionHandler::Internal) pFunctionItem->setInternalFunction(true); } //++it; } } /* void KviClassEditor::classRefresh(const QString & szName) { if(m_bSaving) return; KviClassEditorTreeWidgetItem * item; KviKvsScript * class = KviKvsClassManager::instance()->classDict()->find(szName); item = createFullItem(szName); if(item!=m_pLastEditedItem) { item->setBuffer(class->code()); return; } if( QMessageBox::warning(0,__tr2qs_ctx("OverWrite Current Class","editor"), __tr2qs_ctx("An external script has changed the class you are currently editing. Do you want to accept the external changes?","editor"), QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes ) return; item->setBuffer(class->code()); m_pEditor->setText(class->code()); } */ bool KviClassEditor::hasSelectedItems() { return m_pTreeWidget->selectedItems().count() ? 1 : 0; } bool KviClassEditor::classExists(QString & szFullItemName) { if(m_pClasses->find(szFullItemName)) return true; else return false; } void KviClassEditor::renameFunction() { if(!m_pLastEditedItem) return; KviClassEditorTreeWidgetItem * pFunction = m_pLastEditedItem; QString szClassName = buildFullClassName((KviClassEditorTreeWidgetItem *)pFunction->parent()); QString szFunctionName = pFunction->name(); QString szReminder = pFunction->reminder(); QString szNewReminder = szReminder; KviClassEditorTreeWidgetItem * pParentClass = (KviClassEditorTreeWidgetItem *) pFunction->parent(); QString szNewFunctionName = szFunctionName; bool bInternal = pFunction->isInternalFunction(); if(!askForFunction(szNewFunctionName,szNewReminder,&bInternal,szClassName,true)) return; if(KviQString::equalCS(szFunctionName,szNewFunctionName) && bInternal == pFunction->isInternalFunction()) { if(!KviQString::equalCS(szNewReminder,szReminder)) { pFunction->setReminder(szNewReminder); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName); if(pClass) { KviKvsObjectFunctionHandler * pHandler = pClass->lookupFunctionHandler(szFunctionName); if(pHandler) { pClass->setReminder(szNewReminder,pHandler); QString szPath; QString szFileName = szClassName.toLower(); szFileName += ".kvs"; szFileName.replace("::","--"); g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes,szFileName); pClass->save(szPath); } } currentItemChanged(pFunction,pFunction); } else { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Function already exists","editor"), __tr2qs_ctx("This name is already in use. Please choose another one.","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); return; } } pFunction->setName(szNewFunctionName); pFunction->setReminder(szNewReminder); currentItemChanged(pFunction,pFunction); pFunction->setInternalFunction(bInternal); pParentClass->setClassNotBuilt(true); KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); searchInheritedClasses(szClassName,lInheritedClasses); for(unsigned int i=0; i < lInheritedClasses.count(); i++) lInheritedClasses.at(i)->setClassNotBuilt(true); activateItem(pFunction); } KviClassEditorTreeWidgetItem * KviClassEditor::findFunction(const QString & szFunctionName, KviClassEditorTreeWidgetItem * pClass) { for(int i=0; i < pClass->childCount(); i++) { if(KviQString::equalCI(szFunctionName,((KviClassEditorTreeWidgetItem *)pClass->child(i))->name())) return (KviClassEditorTreeWidgetItem *) pClass->child(i); } return 0; } void KviClassEditor::renameItem() { if(!m_pLastEditedItem) return; if(m_pLastEditedItem->isClass()) renameClass(m_pLastEditedItem); else if(m_pLastEditedItem->isNamespace()) renameNamespace(m_pLastEditedItem); else { // is function KviClassEditorTreeWidgetItem * pParent = (KviClassEditorTreeWidgetItem *)m_pLastEditedItem->parent(); if(pParent->isClass()) renameClass(pParent); } } void KviClassEditor::renameClass(KviClassEditorTreeWidgetItem * pClassItem) { QString szClassName = buildFullClassName(pClassItem); QString szNewClassName = szClassName; QString szInheritsClassName = pClassItem->inheritsClass(); QString szNewInheritsClassName = szInheritsClassName; bool bOk = askForClassName(szNewClassName,szNewInheritsClassName,true); if(!bOk) return; if(classExists(szNewClassName) && KviQString::equalCS(szClassName,szNewClassName) && KviQString::equalCS(szInheritsClassName,szNewInheritsClassName)) { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Class already exists","editor"), __tr2qs_ctx("This name is already in use. Please choose another one.","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); return; } /*if(szNewClassName.tmp.indexOf("@@",Qt::CaseInsensitive) != -1) { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Bad Namespace Name","editor"), __tr2qs_ctx("Found an empty namespace in namespace name","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); szNewName = ""; continue; }*/ KviClassEditorTreeWidgetItem * pNewItem = 0; m_pClasses->removeRef(pClassItem); cutItem(pClassItem); if(szNewClassName.contains("::")) { pNewItem = createFullNamespace(szNewClassName.left(szNewClassName.lastIndexOf("::"))); pClassItem->setName(szNewClassName.section("::",-1,-1)); pNewItem->addChild(pClassItem); } else { pClassItem->setName(szNewClassName); m_pTreeWidget->addTopLevelItem(pClassItem); } m_pClasses->insert(szNewClassName,pClassItem); pClassItem->setInheritsClass(szNewInheritsClassName); pClassItem->setClassNotBuilt(true); KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); searchInheritedClasses(szClassName,lInheritedClasses); for(unsigned int i=0; i < lInheritedClasses.count(); i++) { lInheritedClasses.at(i)->setClassNotBuilt(true); lInheritedClasses.at(i)->setExpanded(true); lInheritedClasses.at(i)->setInheritsClass(szNewClassName); } if(pNewItem) { activateItem(pNewItem); pNewItem->setExpanded(true); } else { activateItem(pClassItem); pClassItem->setExpanded(true); } qDebug("delete class %s caused by rename",szClassName.toUtf8().data()); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); } void KviClassEditor::cutItem(KviClassEditorTreeWidgetItem * pItem) { int iIdx = m_pTreeWidget->indexOfTopLevelItem(pItem); if(iIdx!=-1) m_pTreeWidget->takeTopLevelItem(iIdx); else { KviClassEditorTreeWidgetItem * pParent = (KviClassEditorTreeWidgetItem *)pItem->parent(); pParent->removeChild(pItem); } } void KviClassEditor::renameNamespace(KviClassEditorTreeWidgetItem * pOldNamespaceItem) { QString szOldNameSpaceName = buildFullClassName(m_pLastEditedItem); QString szNewNameSpaceName; if(!askForNamespaceName(__tr2qs_ctx("Rename Namespace","editor"),__tr2qs_ctx("Please enter the new name for the namespace","editor"),szOldNameSpaceName,szNewNameSpaceName)) return; if(KviQString::equalCI(szOldNameSpaceName,szNewNameSpaceName)) return; KviClassEditorTreeWidgetItem * pNewItem = findItem(szNewNameSpaceName); if(pNewItem) { g_pClassEditorModule->lock(); if(pNewItem->isClass()) { QMessageBox::information(this, __tr2qs_ctx("Name already exists as Class name","editor"), __tr2qs_ctx("This name is already in use as Class name. Please choose another one.","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); } else { QMessageBox::information(this, __tr2qs_ctx("Namespace already exists","editor"), __tr2qs_ctx("This name is already in use. Please choose another one.","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); } g_pClassEditorModule->unlock(); return; } KviPointerList pList; pList.setAutoDelete(false); appendAllClassItemsRecursive(&pList,pOldNamespaceItem); cutItem(pOldNamespaceItem); if(szNewNameSpaceName.contains("::")) { pNewItem=createFullNamespace(szNewNameSpaceName.left(szNewNameSpaceName.lastIndexOf("::"))); pOldNamespaceItem->setName(szNewNameSpaceName.section("::",-1,-1)); pNewItem->addChild(pOldNamespaceItem); } else { m_pTreeWidget->addTopLevelItem(pOldNamespaceItem); pOldNamespaceItem->setName(szNewNameSpaceName); } for(unsigned int u=0; u < pList.count(); u++) { KviPointerHashTableEntry * pEntry = m_pClasses->findRef(pList.at(u)); if(pEntry) { KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); QString szOldName = pEntry->key(); QString szNewName = buildFullClassName(pList.at(u)); searchInheritedClasses(szOldName,lInheritedClasses); for(unsigned int v=0; v < lInheritedClasses.count(); v++) { lInheritedClasses.at(v)->setClassNotBuilt(true); lInheritedClasses.at(v)->setExpanded(true); lInheritedClasses.at(v)->setInheritsClass(szNewName); } m_pClasses->removeRef(pList.at(u)); m_pClasses->insert(szNewName,pList.at(u)); pList.at(u)->setClassNotBuilt(true); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szOldName); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); } } if(pNewItem) { activateItem(pNewItem); pNewItem->setExpanded(true); } else { activateItem(pOldNamespaceItem); pOldNamespaceItem->setExpanded(true); } //searchReplace(szOldNameSpaceName+"::",true,szNewNameSpaceName+"::"); } void KviClassEditor::saveLastEditedItem() { if(!m_pLastEditedItem) return; if(!m_pEditor->isModified() || m_pLastEditedItem->isNamespace() || m_pLastEditedItem->isClass()) return; ((KviClassEditorTreeWidgetItem *)m_pLastEditedItem)->setCursorPosition(m_pEditor->getCursor()); QString newCode; m_pEditor->getText(newCode); ((KviClassEditorTreeWidgetItem *)m_pLastEditedItem)->setBuffer(newCode); ((KviClassEditorTreeWidgetItem *)m_pLastEditedItem->parent())->setClassNotBuilt(true); } void KviClassEditor::currentItemChanged(QTreeWidgetItem * pTree, QTreeWidgetItem *) { saveLastEditedItem(); m_pLastEditedItem = (KviClassEditorTreeWidgetItem *)pTree; if(!m_pLastEditedItem) { m_pClassNameLabel->setText(__tr2qs_ctx("No item selected","editor")); m_pClassNameRenameButton->setEnabled(false); m_pEditor->setText(""); m_pEditor->setEnabled(false); return; } KviClassEditorTreeWidgetItem * pClassItem = 0; if(m_pLastEditedItem->isMethod()) pClassItem = (KviClassEditorTreeWidgetItem *)m_pLastEditedItem->parent(); else pClassItem = m_pLastEditedItem; QString szClassName = buildFullClassName(pClassItem); if(m_pLastEditedItem->isNamespace()) { QString szLabelText = __tr2qs_ctx("Namespace","editor"); szLabelText += ": "; szLabelText += szClassName; szLabelText += ""; m_pClassNameLabel->setText(szLabelText); m_pClassNameRenameButton->setEnabled(true); m_pFunctionNameRenameButton->setEnabled(false); //m_pinheritsClassNameLabel->setText(""); m_pFunctionNameLabel->setText(""); m_pEditor->setText(""); m_pEditor->setEnabled(false); m_pTreeWidget->setFocus(); return; } QString szLabelText = __tr2qs_ctx("Class","editor"); szLabelText += ": "; szLabelText += szClassName; szLabelText += ", "; szLabelText += __tr2qs_ctx("inherits from class ","editor"); szLabelText += ": "; szLabelText += pClassItem->inheritsClass(); szLabelText += ""; m_pClassNameLabel->setText(szLabelText); szLabelText = __tr2qs_ctx("Member Function","editor"); if(m_pLastEditedItem->isMethod()) { szLabelText += ": "; szLabelText += m_pLastEditedItem->text(0); szLabelText += ""; m_pFunctionNameRenameButton->setEnabled(true); if(m_pLastEditedItem->reminder().isEmpty()) m_pReminderLabel->hide(); else { QString szReminderText =__tr2qs_ctx("Reminder text.","editor"); szReminderText += ": "; szReminderText += m_pLastEditedItem->reminder(); szReminderText += ""; m_pReminderLabel->setText(szReminderText); m_pReminderLabel->show(); } m_pFunctionNameLabel->setText(szLabelText); m_pFunctionNameLabel->show(); m_pFunctionNameRenameButton->show(); } else { m_pReminderLabel->hide(); m_pFunctionNameLabel->hide(); m_pClassNameRenameButton->setEnabled(true); m_pFunctionNameRenameButton->hide(); } if(m_pLastEditedItem->isClass()) { m_pFunctionNameRenameButton->setEnabled(false); m_pEditor->setText(""); m_pEditor->setEnabled(true); m_pTreeWidget->setFocus(); QString szBuffer; QStringList szFunctionsList; KviPointerHashTable lFunctions; lFunctions.setAutoDelete(false); KviClassEditorTreeWidgetItem * pItem = 0; for(int i=0; i < pTree->childCount(); i++) { pItem = ((KviClassEditorTreeWidgetItem *)pTree->child(i)); szFunctionsList.append(pItem->name()); lFunctions.insert(pItem->name(),pItem); } szFunctionsList.sort(); for(int i=0; i < szFunctionsList.count(); i++) { szBuffer += "Member Function: $" + szFunctionsList.at(i) + "
"; if(!lFunctions.find(szFunctionsList.at(i))->reminder().isEmpty()) szBuffer+="Parameters reminder: "+lFunctions.find(szFunctionsList.at(i))->reminder()+"
"; szBuffer+="
"; } m_pEditor->setUnHighlightedText(szBuffer); m_pEditor->setReadOnly(true); return; } m_pEditor->setReadOnly(false); m_pEditor->setText(((KviClassEditorTreeWidgetItem *)pTree)->buffer()); m_pEditor->setFocus(); m_pEditor->setCursorPosition(((KviClassEditorTreeWidgetItem *)pTree)->cursorPosition()); m_pEditor->setEnabled(true); } void KviClassEditor::customContextMenuRequested(QPoint pnt) { m_pContextPopup->clear(); m_pLastClickedItem = (KviClassEditorTreeWidgetItem *)m_pTreeWidget->itemAt(pnt); int iId; iId = m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE)), __tr2qs_ctx("Add Namespace","editor"), this,SLOT(newNamespace())); if(!m_pLastClickedItem) m_pContextPopup->setItemEnabled(iId,true); else m_pContextPopup->setItemEnabled(iId,m_pLastClickedItem->isNamespace()); iId = m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASS)), __tr2qs_ctx("Add Class","editor"), this,SLOT(newClass())); if(!m_pLastClickedItem) m_pContextPopup->setItemEnabled(iId,true); else m_pContextPopup->setItemEnabled(iId,m_pLastClickedItem->isNamespace()); iId = m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FUNCTION)), __tr2qs_ctx("Add Member Function","editor"), this,SLOT(newMemberFunction())); if(!m_pLastClickedItem) m_pContextPopup->setItemEnabled(iId,false); else m_pContextPopup->setItemEnabled(iId,m_pLastClickedItem->isClass()| m_pLastClickedItem->isMethod()); bool bHasItems = m_pTreeWidget->topLevelItemCount(); bool bHasSelected = hasSelectedItems(); m_pContextPopup->insertSeparator(); iId = m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)), __tr2qs_ctx("Remove Selected","editor"), this,SLOT(removeSelectedItems())); m_pContextPopup->setItemEnabled(iId,bHasSelected); m_pContextPopup->insertSeparator(); m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)), __tr2qs_ctx("Export Selected...","editor"), this,SLOT(exportSelected())); m_pContextPopup->setItemEnabled(iId,bHasSelected); m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)), __tr2qs_ctx("Export Selected in singles files...","editor"), this,SLOT(exportSelectedSepFiles())); m_pContextPopup->setItemEnabled(iId,bHasSelected); m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)), __tr2qs_ctx("Export All...","editor"), this,SLOT(exportAll())); m_pContextPopup->setItemEnabled(iId,bHasItems); m_pContextPopup->insertSeparator(); m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)), __tr2qs_ctx("Find In Classes...","editor"), this,SLOT(slotFind())); m_pContextPopup->setItemEnabled(iId,bHasItems); m_pContextPopup->insertItem( *(g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE)), __tr2qs_ctx("Collapse All Items","editor"), this,SLOT(slotCollapseItems())); m_pContextPopup->setItemEnabled(iId,bHasItems); m_pContextPopup->popup(m_pTreeWidget->mapToGlobal(pnt)); } void KviClassEditor::searchReplace(const QString & szSearch, bool bReplace, const QString & szReplace) { KviPointerHashTableIterator it (*m_pClasses); while(it.current()) { KviClassEditorTreeWidgetItem * pItem = it.current(); for(int j=0; j < pItem->childCount(); j++) { bool bOpened = false; if(((KviClassEditorTreeWidgetItem *)pItem->child(j))->buffer().indexOf(szSearch,0,Qt::CaseInsensitive) != -1) { pItem->child(j)->setBackground(0, QColor(255,0,0,128)); if(bReplace) { QString &buffer=(QString &)((KviClassEditorTreeWidgetItem *)pItem->child(j))->buffer(); pItem->setClassNotBuilt(true); buffer.replace(szSearch,szReplace,Qt::CaseInsensitive); } if(!bOpened) { openParentItems(pItem->child(j)); bOpened = true; } } else { pItem->child(j)->setBackground(0, QColor(255,255,255)); } } ++it; } } void KviClassEditor::slotFind() { g_pClassEditorModule->lock(); bool bOk; QString szSearch = QInputDialog::getText(this, __tr2qs_ctx("Find In Classes","editor"), __tr2qs_ctx("Please enter the text to be searched for. The matching function will be highlighted.","editor"), QLineEdit::Normal, "", &bOk); g_pClassEditorModule->unlock(); if(!bOk) return; if(szSearch.isEmpty()) return; m_pEditor->setFindText(szSearch); searchReplace(szSearch); } void KviClassEditor::slotFindWord(const QString & szSearch) { m_pEditor->setFindText(szSearch); } void KviClassEditor::recursiveCollapseItems(KviClassEditorTreeWidgetItem * pItem) { if(!pItem) return; for(int i=0; i < pItem->childCount(); i++) { if(pItem->child(i)->childCount()) { pItem->child(i)->setExpanded(false); recursiveCollapseItems((KviClassEditorTreeWidgetItem *)pItem->child(i)); } } } void KviClassEditor::slotCollapseItems() { for(int i=0; i < m_pTreeWidget->topLevelItemCount(); i++) { if(m_pTreeWidget->topLevelItem(i)->childCount()) { m_pTreeWidget->topLevelItem(i)->setExpanded(false); recursiveCollapseItems((KviClassEditorTreeWidgetItem *)m_pTreeWidget->topLevelItem(i)); } } } void KviClassEditor::slotReplaceAll(const QString & szFind, const QString & szReplace) { m_pEditor->setFindText(szReplace); searchReplace(szFind,true,szReplace); /* for (int i=0;itopLevelItemCount();i++) { recursiveSearchReplace(szFind,(KviClassEditorTreeWidgetItem *)m_pTreeWidget->topLevelItem(i),true,szReplace); } */ } void KviClassEditor::exportClassBuffer(QString & szBuffer, KviClassEditorTreeWidgetItem * pItem) { QString szTmp = pItem->buffer(); KviCommandFormatter::blockFromBuffer(szTmp); QString szName = buildFullClassName(pItem); szBuffer = "class(\""; szBuffer += szName; if(!pItem->inheritsClass().isEmpty()) { szBuffer += "\",\""; szBuffer += pItem->inheritsClass(); } szBuffer += "\")\n{\n"; for(int i=0; i < pItem->childCount(); i++) { KviClassEditorTreeWidgetItem * pFunction = (KviClassEditorTreeWidgetItem *)pItem->child(i); if(pFunction->isMethod()) { szBuffer += "\t"; if(pFunction->isInternalFunction()) szBuffer += "internal "; szBuffer += "function "; szBuffer += pFunction->name(); szBuffer += "(" + pFunction->reminder() + ")"; szBuffer += "\n\t{\n"; szBuffer += pFunction->buffer(); szBuffer += "\n\t}\n"; } } szBuffer += "}\n"; } void KviClassEditor::exportAll() { exportClasses(false); } void KviClassEditor::exportSelectedSepFiles() { exportClasses(true,true); } void KviClassEditor::exportSelected() { exportClasses(true); } void KviClassEditor::exportSelectionInSinglesFiles(KviPointerList * pList) { bool bReplaceAll = false; if(!m_szDir.endsWith(QString(KVI_PATH_SEPARATOR))) m_szDir += KVI_PATH_SEPARATOR; if(!pList->first()) { g_pClassEditorModule->lock(); QMessageBox::warning(this,__tr2qs_ctx("Class Export","editor"),__tr2qs_ctx("There is no selection!","editor"),__tr2qs_ctx("OK","editor")); g_pClassEditorModule->unlock(); return; } g_pClassEditorModule->lock(); if(!KviFileDialog::askForDirectoryName(m_szDir,__tr2qs_ctx("Choose a Directory - KVIrc","editor"),m_szDir)) { g_pClassEditorModule->unlock(); return; } if(!m_szDir.endsWith(QString(KVI_PATH_SEPARATOR))) m_szDir += KVI_PATH_SEPARATOR; for(KviClassEditorTreeWidgetItem * pItem = pList->first(); pItem; pItem = pList->next()) { QString szTmp; exportClassBuffer(szTmp,pItem); QString szFileName = buildFullClassName(pItem); szFileName += ".kvs"; szFileName.replace("::","_"); QString szCompletePath = m_szDir+szFileName; if(KviFileUtils::fileExists(szCompletePath) && !bReplaceAll) { QString szMsg = __tr2qs_ctx("The file \"%1\" exists. Do you want to replace it?","editor").arg(szFileName); int iRet = QMessageBox::question(this,__tr2qs_ctx("Replace file","editor"),szMsg,__tr2qs_ctx("Yes","editor"),__tr2qs_ctx("Yes to All","editor"),__tr2qs_ctx("No","editor")); if(iRet != 2) { KviFileUtils::writeFile(szCompletePath,szTmp); if(iRet == 1) bReplaceAll = true; } } else KviFileUtils::writeFile(szCompletePath,szTmp); } g_pClassEditorModule->unlock(); } void KviClassEditor::exportClasses(bool bSelectedOnly, bool bSingleFiles) { QString szOut; QString szNameFile; QString szFile; int iCount = 0; saveLastEditedItem(); KviPointerList list; list.setAutoDelete(false); if(bSelectedOnly) appendSelectedClassItems(&list); else appendAllClassItems(&list); if(bSingleFiles) { exportSelectionInSinglesFiles(&list); return; } KviClassEditorTreeWidgetItem * pTempItem = 0; for(KviClassEditorTreeWidgetItem * pItem = list.first(); pItem; pItem = list.next()) { pTempItem = pItem; iCount++; QString szTmp; exportClassBuffer(szTmp,pItem); szOut += szTmp; szOut += "\n"; } if(szOut.isEmpty()) { g_pClassEditorModule->lock(); QMessageBox::warning(this,__tr2qs_ctx("Class Export","editor"),__tr2qs_ctx("The exported file would be empty: cowardly refusing to write it","editor"),__tr2qs_ctx("OK","editor")); g_pClassEditorModule->unlock(); return; } QString szName = m_szDir; if(!szName.endsWith(QString(KVI_PATH_SEPARATOR))) szName += KVI_PATH_SEPARATOR; g_pClassEditorModule->lock(); if(iCount != 1) szNameFile = "classes"; else { QString szTmp = buildFullClassName(pTempItem); szNameFile = szTmp.replace("::","_"); } szName += szNameFile; szName += ".kvs"; if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs_ctx("Choose a Filename - KVIrc","editor"),szName,KVI_FILTER_SCRIPT,false,true,true)) { g_pClassEditorModule->unlock(); return; } m_szDir=QFileInfo(szFile).absolutePath(); g_pClassEditorModule->unlock(); if(!KviFileUtils::writeFile(szFile,szOut)) { g_pClassEditorModule->lock(); QMessageBox::warning(this,__tr2qs_ctx("Write Failed - KVIrc","editor"),__tr2qs_ctx("Unable to write to the class file.","editor"),__tr2qs_ctx("OK","editor")); g_pClassEditorModule->unlock(); } } void KviClassEditor::saveProperties(KviConfigurationFile * pCfg) { pCfg->writeEntry("Sizes",m_pSplitter->sizes()); QString szName; if(m_pLastEditedItem) szName = buildFullClassName(m_pLastEditedItem); pCfg->writeEntry("LastClass",szName); } void KviClassEditor::loadProperties(KviConfigurationFile * pCfg) { QList def; def.append(20); def.append(80); m_pSplitter->setSizes(pCfg->readIntListEntry("Sizes",def)); QString szTmp = pCfg->readEntry("LastClass",QString()); KviClassEditorTreeWidgetItem * pItem = findItem(szTmp); activateItem(pItem); } void KviClassEditor::appendSelectedClassItems(KviPointerList * pList) { QList list = m_pTreeWidget->selectedItems(); for(int i=0; i < list.count(); i++) { if(((KviClassEditorTreeWidgetItem *)list.at(i))->isClass()) pList->append((KviClassEditorTreeWidgetItem *)list.at(i)); else appendSelectedClassItemsRecursive(pList,list.at(i)); } } void KviClassEditor::appendSelectedClassItemsRecursive(KviPointerList * pList, QTreeWidgetItem * pStartFrom) { for(int i=0; i < pStartFrom->childCount(); i++) { if(((KviClassEditorTreeWidgetItem *)pStartFrom->child(i))->isClass()) pList->append(((KviClassEditorTreeWidgetItem *)pStartFrom->child(i))); else appendSelectedClassItemsRecursive(pList,pStartFrom->child(i)); } } void KviClassEditor::appendAllClassItems(KviPointerList * pList) { KviPointerHashTableIterator it (*m_pClasses); while(it.current()) { pList->append(it.current()); ++it; } } void KviClassEditor::appendAllClassItemsRecursive(KviPointerList * pList, QTreeWidgetItem * pStartFrom) { for(int i=0; i < pStartFrom->childCount(); i++) { if(((KviClassEditorTreeWidgetItem *)pStartFrom->child(i))->isClass()) { pList->append((KviClassEditorTreeWidgetItem *)pStartFrom->child(i)); } else { appendAllClassItemsRecursive(pList,pStartFrom->child(i)); } } } void KviClassEditor::removeItemChildren(KviClassEditorTreeWidgetItem * pItem, KviPointerList & lRemovedItems) { if(pItem->isClass()) { KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); searchInheritedClasses(buildFullClassName(pItem),lInheritedClasses); for(unsigned int u=0; u < lInheritedClasses.count(); u++) { lInheritedClasses.at(u)->setClassNotBuilt(true); lInheritedClasses.at(u)->setExpanded(true); lInheritedClasses.at(u)->setInheritsClass("object"); } } while(pItem->childCount() > 0) { KviClassEditorTreeWidgetItem * pChild = (KviClassEditorTreeWidgetItem *)(pItem->child(0)); if(pChild->childCount()) removeItemChildren(pChild,lRemovedItems); if(pChild->isClass()) { m_pClasses->removeRef(pChild); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(buildFullClassName(pChild)); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); qDebug("removing class %s %p",buildFullClassName(pChild).toUtf8().data(), pClass); } pItem->removeChild(pChild); lRemovedItems.append(pItem); delete pChild; } } bool KviClassEditor::removeItem(KviClassEditorTreeWidgetItem * pItem, KviPointerList & lRemovedItems, bool * pbYesToAll) { if(!pItem) return true; QString szMsg; QString szName = pItem->name(); if(!*pbYesToAll) { saveLastEditedItem(); if(pItem->isClass()) { KviQString::sprintf(szMsg,__tr2qs_ctx("Do you really want to remove the class \"%Q\" ?","editor"),&szName); } else if(pItem->isNamespace()) { KviQString::sprintf(szMsg,__tr2qs_ctx("Do you really want to remove the namespace \"%Q\" ?","editor"),&szName); szMsg += "
"; szMsg += __tr2qs_ctx("Please note that all the children classes/functions will be deleted too.","editor"); } else if(pItem->isMethod()) { KviQString::sprintf(szMsg,__tr2qs_ctx("Do you really want to remove the function \"%Q\" ?","editor"),&szName); } g_pClassEditorModule->lock(); int iRet = QMessageBox::question(this,__tr2qs_ctx("Remove item","editor"),szMsg,__tr2qs_ctx("Yes","editor"),__tr2qs_ctx("Yes to All","editor"),__tr2qs_ctx("No","editor")); g_pClassEditorModule->unlock(); switch(iRet) { case 0: // nothing break; case 1: *pbYesToAll = true; break; default: return false; break; } } if(pItem == m_pLastEditedItem) m_pLastEditedItem = 0; if(pItem == m_pLastClickedItem) m_pLastClickedItem = 0; if(pItem->childCount()) removeItemChildren(pItem,lRemovedItems); if(pItem->isClass()) { m_pClasses->removeRef(pItem); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(buildFullClassName(pItem)); qDebug("rimuovo class %s %p",buildFullClassName(pItem).toUtf8().data(), pClass); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); else { QString szFileName = buildFullClassName(pItem); szFileName.replace("::","--"); szFileName.append(KVI_FILEEXTENSION_SCRIPT); QString szPath; g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes); QDir d(szPath); if(d.exists(szFileName)) { qDebug("rimuovo dal disco il file %s",szFileName.toUtf8().data()); d.remove(szFileName); } } } if(pItem->isMethod()) { updateClassHierarchy((KviClassEditorTreeWidgetItem *)pItem->parent()); } lRemovedItems.append(pItem); delete pItem; return true; } void KviClassEditor::updateClassHierarchy(KviClassEditorTreeWidgetItem * pClass) { pClass->setClassNotBuilt(true); KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); searchInheritedClasses(pClass->name(),lInheritedClasses); for(unsigned int u=0; u < lInheritedClasses.count(); u++) { lInheritedClasses.at(u)->setClassNotBuilt(true); lInheritedClasses.at(u)->setInheritsClass(pClass->name()); lInheritedClasses.at(u)->setExpanded(true); } } void KviClassEditor::removeSelectedItems() { KviPointerList lRemovedItems; lRemovedItems.setAutoDelete(false); QList list = m_pTreeWidget->selectedItems(); bool bYesToAll = false; for(int i=0; i < list.count(); i++) { if(lRemovedItems.findRef((KviClassEditorTreeWidgetItem *) list.at(i)) != -1) continue; if(!removeItem((KviClassEditorTreeWidgetItem *) list.at(i),lRemovedItems,&bYesToAll)) return; } } bool KviClassEditor::askForClassName(QString & szClassName, QString & szInheritsClassName, bool bEdit) { KviClassEditorDialog * pDialog = new KviClassEditorDialog(this,"classdialog",m_pClasses,szClassName,szInheritsClassName,bEdit); szClassName = ""; g_pClassEditorModule->lock(); bool bOk = pDialog->exec(); g_pClassEditorModule->unlock(); if(bOk) { szClassName = pDialog->className(); szInheritsClassName = pDialog->inheritsClassName(); delete pDialog; return true; } delete pDialog; return false; } bool KviClassEditor::askForFunction(QString & szFunctionName, QString & szReminder, bool * bInternal, const QString & szClassName, bool bRenameMode) { KviClassEditorFunctionDialog * pDialog = new KviClassEditorFunctionDialog(this,"function",szClassName,szFunctionName,szReminder,*bInternal, bRenameMode); szFunctionName = ""; g_pClassEditorModule->lock(); bool bOk = pDialog->exec(); g_pClassEditorModule->unlock(); if(bOk) { szFunctionName = pDialog->functionName(); szReminder = pDialog->reminder(); *bInternal = pDialog->isInternalFunction(); delete pDialog; return true; } delete pDialog; return false; } bool KviClassEditor::askForNamespaceName(const QString & szAction, const QString & szText, const QString & szInitialText, QString & szNewName) { bool bOk = false; while(szNewName.isEmpty()) { g_pClassEditorModule->lock(); szNewName = QInputDialog::getText(this, szAction, szText, QLineEdit::Normal, szInitialText, &bOk); g_pClassEditorModule->unlock(); if(!bOk) return false; if(szNewName.isEmpty()) { g_pClassEditorModule->lock(); QMessageBox::warning(this, __tr2qs_ctx("Missing Namespace Name","editor"), __tr2qs_ctx("You must specify a valid name for the namespace","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); continue; } // we allow only [\w:]+ QRegExp re("[\\w:]+"); if(!re.exactMatch(szNewName)) { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Bad Namespace Name","editor"), __tr2qs_ctx("Namespace names can contain only letters, digits, underscores and '::' namespace separators","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); szNewName = ""; continue; } // make sure that we have only doubled "::" and not ":" or ":::..." QString szTmp = szNewName; szTmp.replace("::","@"); // @ is not allowed by the rule above if(szTmp.indexOf(":",Qt::CaseInsensitive) != -1) { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Bad Namespace Name","editor"), __tr2qs_ctx("Stray ':' character in namespace name: did you mean ...:: ?","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); szNewName = ""; continue; } if(szTmp.indexOf("@@",Qt::CaseInsensitive) != -1) { g_pClassEditorModule->lock(); QMessageBox::information(this, __tr2qs_ctx("Bad Namespace Name","editor"), __tr2qs_ctx("Found an empty namespace in namespace name","editor"), __tr2qs_ctx("Ok, Let me try again...","editor")); g_pClassEditorModule->unlock(); szNewName = ""; continue; } } return true; } void KviClassEditor::openParentItems(QTreeWidgetItem * pItem) { if(pItem->parent()) { pItem->parent()->setExpanded(true); openParentItems(pItem->parent()); } } void KviClassEditor::activateItem(QTreeWidgetItem * pItem) { if(!pItem) return; openParentItems(pItem); m_pTreeWidget->setCurrentItem(pItem); } void KviClassEditor::newClass() { QString szClassName; QString szinheritsClassName; askForClassName(szClassName,szinheritsClassName,false); if(szClassName.isEmpty()) return; KviClassEditorTreeWidgetItem * pItem = newItem(szClassName,KviClassEditorTreeWidgetItem::Class); KviQString::escapeKvs(&szClassName, KviQString::EscapeSpace); KviQString::escapeKvs(&szinheritsClassName, KviQString::EscapeSpace); QString szClass = "class("; szClass += szClassName + "," + szinheritsClassName; szClass += "){}\n"; pItem->setInheritsClass(szinheritsClassName); activateItem(pItem); m_pClasses->insert(szClassName,pItem); KviKvsScript::run(szClass,g_pActiveWindow); } void KviClassEditor::newNamespace() { QString szName; if(!askForNamespaceName(__tr2qs_ctx("Add Namespace","editor"),__tr2qs_ctx("Please enter the name for the new namespace","editor"),"mynamespace",szName)) return; if(szName.isEmpty()) return; KviClassEditorTreeWidgetItem * pItem = newItem(szName,KviClassEditorTreeWidgetItem::Namespace); activateItem(pItem); } void KviClassEditor::newMemberFunction() { QString szFunctionName; QString szClassName; QString szReminder; if(m_pLastClickedItem->isMethod()) m_pLastClickedItem = (KviClassEditorTreeWidgetItem*)m_pLastClickedItem->parent(); szClassName = buildFullClassName(m_pLastClickedItem); bool bInternal = false; if(!askForFunction(szFunctionName, szReminder,&bInternal,szClassName,false)) return; if(szFunctionName.isEmpty()) return; KviClassEditorTreeWidgetItem * pItem = newItem(szFunctionName,KviClassEditorTreeWidgetItem::Method); pItem->setInternalFunction(bInternal); if(!szReminder.isEmpty()) pItem->setReminder(szReminder); activateItem(pItem); ((KviClassEditorTreeWidgetItem*)pItem->parent())->setClassNotBuilt(true); } KviClassEditorTreeWidgetItem * KviClassEditor::newItem(QString & szName, KviClassEditorTreeWidgetItem::Type eType) { if(m_pLastClickedItem) buildFullItemPath(m_pLastClickedItem,szName); QString szTmp; if(findItem(szName)) szName.append("1"); int iIdx = 2; while(findItem(szName)) { szTmp.setNum(iIdx); szName.chop(szTmp.length()); szName.append(szTmp); iIdx++; } KviClassEditorTreeWidgetItem * pItem; pItem = createFullItem(szName); pItem->setType(eType); return pItem; } void KviClassEditor::build() { saveLastEditedItem(); KviPointerHashTableIterator it (*m_pClasses); KviPointerList linkedClasses; linkedClasses.setAutoDelete(false); KviPointerList skipClasses; skipClasses.setAutoDelete(false); bool bErrorWhilecompiling = false; while(it.current()) { KviClassEditorTreeWidgetItem * pClass = it.current(); if(skipClasses.findRef(it.current()) != -1) { ++it; continue; } if(pClass->classNotBuilt()) { //qDebug("compiling %s",pClass->name().toUtf8().data()); KviClassEditorTreeWidgetItem * pParentClass = m_pClasses->find(pClass->inheritsClass()); linkedClasses.append(pClass); //if (!pParentClass) qDebug("no parent class"); while(pParentClass) { if(pParentClass->classNotBuilt()) linkedClasses.append(pParentClass); pParentClass = m_pClasses->find(pParentClass->inheritsClass()); } for(int i = linkedClasses.count()-1; i >= 0; i--) { QString szFullClassName = buildFullClassName(linkedClasses.at(i)); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szFullClassName); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); QString szClass; exportClassBuffer(szClass, linkedClasses.at(i)); KviKvsScript::run(szClass,g_pActiveWindow); pClass = KviKvsKernel::instance()->objectController()->lookupClass(szFullClassName); if(!pClass) { bErrorWhilecompiling = true; QString szError = __tr2qs_ctx("Unable to compile class: ","editor"); szError += szFullClassName + "\n"; KviPointerList lInheritedClasses; lInheritedClasses.setAutoDelete(false); searchInheritedClasses(szFullClassName,lInheritedClasses); if(lInheritedClasses.count()) { szError += __tr2qs_ctx("These inherited classes will be not compiled too:","editor"); szError += "\n"; for(unsigned int u=0; u < lInheritedClasses.count(); u++) { szError += buildFullClassName(lInheritedClasses.at(u)) + "\n"; lInheritedClasses.at(u)->setClassNotBuilt(true); skipClasses.append(lInheritedClasses.at(u)); } } QMessageBox::critical(this,__tr2qs_ctx("Compilation error - KVIrc","editor"),szError, QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton); break; } //else qDebug("class compiled %s :\n",szClass.toUtf8().data()); linkedClasses.at(i)->setClassNotBuilt(false); m_pEditor->setModified(false); } } ++it; } if(bErrorWhilecompiling) saveNotBuiltClasses(); else { QString szFileName = "libkviclasseditortmp.kvc"; QString szBuffer; g_pApp->getLocalKvircDirectory(szBuffer,KviApp::ConfigPlugins,szFileName); KviConfigurationFile cfg(szBuffer,KviConfigurationFile::Write); cfg.clear(); cfg.sync(); } KviKvsKernel::instance()->objectController()->flushUserClasses(); } void KviClassEditor::loadNotBuiltClasses() { QString szFileName = "libkviclasseditortmp.kvc"; QString szBuffer; g_pApp->getLocalKvircDirectory(szBuffer,KviApp::ConfigPlugins,szFileName); KviConfigurationFile cfg(szBuffer,KviConfigurationFile::Read); KviConfigurationFileIterator it(*(cfg.dict())); KviPointerList l; l.setAutoDelete(true); while(it.current()) { l.append(new QString(it.currentKey())); ++it; } for(QString * pszTmp = l.first(); pszTmp; pszTmp = l.next()) { cfg.setGroup(*pszTmp); KviClassEditorTreeWidgetItem * pClassItem = createFullItem(*pszTmp); m_pClasses->insert(*pszTmp,pClassItem); pClassItem->setClassNotBuilt(true); KviConfigurationFileGroup * pDict = cfg.dict()->find(*pszTmp); if(pDict) { KviConfigurationFileGroupIterator it(*pDict); KviPointerList names; names.setAutoDelete(true); while(it.current()) { names.append(new QString(it.currentKey())); ++it; } for(QString * pszTmp = names.first(); pszTmp; pszTmp = names.next()) { if(KviQString::equalCI(*pszTmp,"@Inherits")) { pClassItem->setInheritsClass(cfg.readEntry(*pszTmp,"")); continue; } if((*pszTmp).left(9) == "@Reminder") continue; QString szCode = cfg.readEntry(*pszTmp,""); KviClassEditorTreeWidgetItem * pFunctionItem = findFunction(*pszTmp, pClassItem); if(!pFunctionItem) pFunctionItem = new KviClassEditorTreeWidgetItem(pClassItem,KviClassEditorTreeWidgetItem::Method,*pszTmp); pFunctionItem->setBuffer(szCode); QString szEntry = "@Reminder|" + (*pszTmp); QString szReminder = cfg.readEntry(szEntry,""); pFunctionItem->setReminder(szReminder); } } } } void KviClassEditor::saveNotBuiltClasses() { saveLastEditedItem(); KviPointerHashTableIterator it (*m_pClasses); QString szFileName = "libkviclasseditortmp.kvc"; QString szBuffer; g_pApp->getLocalKvircDirectory(szBuffer,KviApp::ConfigPlugins,szFileName); KviConfigurationFile cfg(szBuffer,KviConfigurationFile::Write); cfg.clear(); while(it.current()) { if(it.current()->classNotBuilt()) { KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(it.currentKey()); if(pClass) KviKvsKernel::instance()->objectController()->deleteClass(pClass); cfg.setGroup(it.currentKey()); cfg.writeEntry("@Inherits",it.current()->inheritsClass()); QString szReminderEntry; for(int i=0; i < it.current()->childCount(); i++) { if(!((KviClassEditorTreeWidgetItem *)it.current()->child(i))->reminder().isEmpty()) { szReminderEntry="@Reminder|"+((KviClassEditorTreeWidgetItem *)it.current()->child(i))->name(); cfg.writeEntry(szReminderEntry,((KviClassEditorTreeWidgetItem *)it.current()->child(i))->reminder()); } cfg.writeEntry(((KviClassEditorTreeWidgetItem *)it.current()->child(i))->name(),((KviClassEditorTreeWidgetItem *)it.current()->child(i))->buffer()); } } ++it; } cfg.sync(); } void KviClassEditor::searchInheritedClasses(const QString szClass, KviPointerList & lInheritedClasses) { KviPointerHashTableIterator it (*m_pClasses); while(it.current()) { if(KviQString::equalCI(szClass,it.current()->inheritsClass())) lInheritedClasses.append(it.current()); ++it; } } KviClassEditorWindow::KviClassEditorWindow(KviFrame * pFrm) : KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,pFrm,"classeditor",0) { g_pClassEditorWindow = this; setFixedCaption(__tr2qs_ctx("Class Editor","editor")); QGridLayout * pLayout = new QGridLayout(); m_pEditor = new KviClassEditor(this); pLayout->addWidget(m_pEditor,0,0,1,4); QPushButton * pBtn = new QPushButton(__tr2qs_ctx("&Build","editor"),this); pBtn->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT))); pLayout->addWidget(pBtn,1,1); connect(pBtn,SIGNAL(clicked()),this,SLOT(buildClicked())); pBtn = new QPushButton(__tr2qs_ctx("&Save","editor"),this); pBtn->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT))); pLayout->addWidget(pBtn,1,2); connect(pBtn,SIGNAL(clicked()),this,SLOT(saveClicked())); pBtn = new QPushButton(__tr2qs_ctx("Close","editor"),this); pBtn->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD))); pLayout->addWidget(pBtn,1,3); connect(pBtn,SIGNAL(clicked()),this,SLOT(cancelClicked())); pLayout->setRowStretch(0,1); pLayout->setColumnStretch(0,1); setLayout(pLayout); } KviClassEditorWindow::~KviClassEditorWindow() { g_pClassEditorWindow = 0; } void KviClassEditorWindow::buildClicked() { m_pEditor->build(); } void KviClassEditorWindow::saveClicked() { m_pEditor->saveNotBuiltClasses(); } void KviClassEditorWindow::cancelClicked() { close(); } QPixmap * KviClassEditorWindow::myIconPtr() { return g_pIconManager->getSmallIcon(KVI_SMALLICON_CLASSEDITOR); } void KviClassEditorWindow::configGroupName(QString &szName) { szName = "classeditor"; } void KviClassEditorWindow::saveProperties(KviConfigurationFile * pCfg) { m_pEditor->saveProperties(pCfg); } void KviClassEditorWindow::loadProperties(KviConfigurationFile * pCfg) { m_pEditor->loadProperties(pCfg); } KviClassEditorDialog::KviClassEditorDialog(QWidget * pParent, const QString & szName, KviPointerHashTable * pClasses, const QString & szClassName, const QString & szInheritsClassName, bool bRenameMode) : QDialog(pParent) { setObjectName(szName); QGridLayout * pLayout = new QGridLayout(this); KviTalHBox * pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,0,0); QLabel * pLabel = new QLabel(pHBox); pLabel->setObjectName("classnamelabel"); pLabel->setText(__tr2qs_ctx("Please enter the name for the class:","editor")); m_pClassNameLineEdit = new QLineEdit(pHBox); m_pClassNameLineEdit->setObjectName("classnameineedit"); m_pClassNameLineEdit->setText(szClassName); pLabel->setBuddy(m_pClassNameLineEdit); QRegExp re; if(!bRenameMode) { // we allow only [\w:]+ class name re.setPattern("[\\w]+"); m_pClassNameLineEdit->setToolTip(__tr2qs_ctx("Class names can contain only letters, digits and underscores","editor")); } else { // in editor mode we allow [\w:]+ and namespace separator re.setPattern("[\\w]+(::[\\w]+)+"); m_pClassNameLineEdit->setToolTip(__tr2qs_ctx("In rename mode class names can contain only letters, digits and underscores and namespaces :: separator","editor")); } QRegExpValidator * pValidator = new QRegExpValidator(re,this); m_pClassNameLineEdit->setValidator(pValidator); m_pClassNameLineEdit->setObjectName("functionameineedit"); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,1,0); pLabel = new QLabel(pHBox); pLabel->setObjectName("Inheritsclasslabel"); pLabel->setText(__tr2qs_ctx("Inherits Class:","editor")); m_pInheritsClassComboBox = new QComboBox(pHBox); pLabel->setBuddy(m_pInheritsClassComboBox); KviPointerHashTableIterator pClassesIt(*pClasses); QStringList szClasses; while(pClassesIt.current()) { if(!KviQString::equalCI(pClassesIt.currentKey(),szClassName)) szClasses.append(pClassesIt.currentKey()); ++pClassesIt; } KviPointerHashTableIterator pBuiltinClasses(*KviKvsKernel::instance()->objectController()->classDict()); while(pBuiltinClasses.current()) { if(pBuiltinClasses.current()->isBuiltin()) szClasses.append(pBuiltinClasses.currentKey()); ++pBuiltinClasses; } int iCurrentIdx; szClasses.sort(); for(int i=0; i < szClasses.count(); i++) m_pInheritsClassComboBox->addItem(szClasses.at(i)); if(szInheritsClassName.isEmpty()) iCurrentIdx = m_pInheritsClassComboBox->findText("object"); else { iCurrentIdx = m_pInheritsClassComboBox->findText(szInheritsClassName); if(iCurrentIdx == -1) iCurrentIdx = m_pInheritsClassComboBox->findText("object"); } m_pInheritsClassComboBox->setCurrentIndex(iCurrentIdx); m_pClassNameLineEdit->setFocus(); connect(m_pClassNameLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &))); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,2,0); m_pNewClassButton = new QPushButton(pHBox); m_pNewClassButton->setObjectName("newclassbutton"); if(bRenameMode) m_pNewClassButton->setText(__tr2qs_ctx("&Rename Class","editor")); else { m_pNewClassButton->setText(__tr2qs_ctx("&Create Class","editor")); m_pNewClassButton->setEnabled(false); } connect(m_pNewClassButton, SIGNAL(clicked()), this, SLOT(accept())); QPushButton * pCancelButton = new QPushButton(pHBox); pCancelButton->setObjectName("cancelButton"); pCancelButton->setText(__tr2qs_ctx("&Cancel","editor")); connect(pCancelButton, SIGNAL(clicked()), this, SLOT(reject())); setLayout(pLayout); } KviClassEditorDialog::~KviClassEditorDialog() { } void KviClassEditorDialog::textChanged(const QString & szText) { m_pNewClassButton->setEnabled(!szText.isEmpty()); } KviClassEditorFunctionDialog::KviClassEditorFunctionDialog(QWidget * pParent, const QString & szName, const QString & szClassName, const QString & szFunctionName, const QString & szReminder, bool bIsInternal, bool bRenameMode) : QDialog(pParent) { setObjectName(szName); QGridLayout * pLayout = new QGridLayout(this); KviTalHBox * pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,0,0); QLabel * pLabel = new QLabel(pHBox); pLabel->setObjectName("classnamelabel"); pLabel->setText("Class: "+szClassName+""); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,1,0); pLabel = new QLabel(pHBox); pLabel->setObjectName("functionnamelabel"); pLabel->setText(__tr2qs_ctx("Please enter the name for the member function:","editor")); m_pFunctionNameLineEdit = new QLineEdit(pHBox); // we allow only [\w:]+ function name QRegExp re("[\\w]+"); QRegExpValidator * pValidator = new QRegExpValidator(re,this); m_pFunctionNameLineEdit->setValidator(pValidator); m_pFunctionNameLineEdit->setObjectName("functionameineedit"); m_pFunctionNameLineEdit->setToolTip(__tr2qs_ctx("Function names can contain only letters, digits and underscores","editor")); m_pFunctionNameLineEdit->setText(szFunctionName); pLabel->setBuddy(m_pFunctionNameLineEdit); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,2,0); pLabel = new QLabel(pHBox); pLabel->setObjectName("reminderlabel"); pLabel->setWordWrap(1); pLabel->setText(__tr2qs_ctx("Please enter the optional reminder string for the member function:","editor")); m_pReminderLineEdit = new QLineEdit(pHBox); m_pReminderLineEdit->setText(szReminder); pLabel->setBuddy(m_pReminderLineEdit); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,3,0); pLabel = new QLabel(pHBox); pLabel->setObjectName("functionnamelabel"); pLabel->setText(__tr2qs_ctx("Set as Internal Function: ","editor")); m_pInternalCheckBox = new QCheckBox(pHBox); m_pInternalCheckBox->setChecked(bIsInternal); m_pFunctionNameLineEdit->setFocus(); pLabel->setBuddy(m_pInternalCheckBox); connect(m_pFunctionNameLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &))); pHBox->setAlignment(m_pInternalCheckBox,Qt::AlignLeft); pHBox->setStretchFactor(m_pInternalCheckBox,70); pHBox->setStretchFactor(pLabel,30); pHBox = new KviTalHBox(this); pHBox->setSpacing(0); pHBox->setMargin(0); pLayout->addWidget(pHBox,4,0); m_pNewFunctionButton = new QPushButton(pHBox); m_pNewFunctionButton->setObjectName("newfunctionbutton"); if(!bRenameMode) m_pNewFunctionButton->setText(__tr2qs_ctx("&Add","editor")); else m_pNewFunctionButton->setText(__tr2qs_ctx("&Rename","editor")); if(szFunctionName.isEmpty()) m_pNewFunctionButton->setEnabled(false); connect(m_pNewFunctionButton, SIGNAL(clicked()), this, SLOT(accept())); QPushButton * pCancelButton = new QPushButton(pHBox); pCancelButton->setObjectName("cancelButton"); pCancelButton->setText(__tr2qs_ctx("&Cancel","editor")); connect(pCancelButton, SIGNAL(clicked()), this, SLOT(reject())); setLayout(pLayout); } KviClassEditorFunctionDialog::~KviClassEditorFunctionDialog() { } void KviClassEditorFunctionDialog::textChanged(const QString & szText) { m_pNewFunctionButton->setEnabled(!szText.isEmpty()); }