/*************************************************************************** kxmleditorpart.cpp - description ------------------- begin : Wed Sep 19 2001 copyright : (C) 2001, 2002, 2003 by The KXMLEditor Team email : OleBowle@gmx.de ***************************************************************************/ /*************************************************************************** * * * 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 option) any later version. * * * ***************************************************************************/ #include "kxmleditorpart.h" #include "kxmleditorfactory.h" #include "kxedocument.h" #include "kxeconfiguration.h" #include "kxenewfilesettings.h" #include "kxearchiveextssettings.h" #include "kxeprintsettings.h" #include "kxetextviewsettings.h" #include "commands_edit.h" #include "commands_insert.h" #include "kxe_viewelement.h" #include "kxe_treeviewitem.h" #include "kxesearchdialog.h" #include "kxechoosestringdialog.h" #include "kxeelementdialog.h" #include "kxeattributedialog.h" #include "kxeprocinstrdialog.h" #include "kxespecprocinstrdialog.h" #include "kxefilenewdialog.h" #include "kxechardatadialog.h" #include "kxeattachdialogbase.h" #include "kxetexteditordialog.h" #include "actions.h" #include "qdom_add.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dcopiface_part_ro.h" // DCOP Iface #define CONFIG_MAIN_SPLITTER_SIZES "Main splitter sizes" KXMLEditorPart::KXMLEditorPart( bool fReadWrite, KXEDocument* pDocument, TQWidget * pParent, const char * pszName ) : KParts::ReadWritePart(pParent,pszName), m_pDlgSearch(0), m_pDocument(0) { ////////////////////////////// // INIT PART ////////////////////////////// setInstance(KXMLEditorFactory::instance()); if(fReadWrite) m_pBrowserExt = 0L; // Create Browser extension only for read-only part else m_pBrowserExt = new KXMLEditorBrowserExtension( this, "KXMLEditorPart browser extension" ); m_pPrinter = 0L; m_bAlreadyModified = false; ////////////////////////////// // CREATE ACTIONS ////////////////////////////// // file actions if(fReadWrite) { KStdAction::save(this, TQ_SLOT(save()), actionCollection()); KStdAction::saveAs(this, TQ_SLOT(slotFileSaveAs()), actionCollection()); } // edit actions m_pActEditFind = KStdAction::find( this, TQ_SLOT(slotEditFind()), actionCollection()); m_pActEditFindNext = KStdAction::findNext( this, TQ_SLOT(slotEditFindNext()), actionCollection()); m_pActEditDeselect = new TDEAction( i18n("D&eselect Node"), CTRL+Key_E, this, TQ_SLOT(slotEditDeselect()), actionCollection(), "deselect" ); // view actions m_pActViewNodeUp = new TDEAction( i18n("To &Parent Node"), "up", 0, this, TQ_SLOT(slotViewNodeUp()), actionCollection(), "treeitem_up" ); m_pActViewExpNode = new TDEToolBarPopupAction( i18n("&Expand Node"), "expand_node", CTRL+Key_Plus, this, TQ_SLOT(slotViewExpNode()), actionCollection(), "treeitem_expand" ); TDEPopupMenu * pMenuExpNode = m_pActViewExpNode->popupMenu(); connect( pMenuExpNode, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotViewExpNode(int)) ); for ( uint i = 1; i <= 8; i++ ) pMenuExpNode->insertItem( i18n("Expand To Level %1").arg(i), i-1 ); m_pActViewColNode = new TDEToolBarPopupAction( i18n("&Collapse Node"), "collapse_node", CTRL+Key_Minus, this, TQ_SLOT(slotViewColNode()), actionCollection(), "treeitem_collapse" ); TDEPopupMenu * pMenuColNode = m_pActViewColNode->popupMenu(); connect( pMenuColNode, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotViewColNode(int)) ); for ( uint i = 0; i <= 7; i++ ) pMenuColNode->insertItem( i18n("Collapse To Level %1").arg(i), i ); // bookmark actions m_pActBookmarksToggle = new TDEAction( i18n("&Toggle Bookmark"), "bookmark_add", CTRL+Key_B, this, TQ_SLOT(slotBookmarksToggle()), actionCollection(), "bookmark_toggle" ); m_pActBookmarksPrev = new TDEAction( i18n("&Previous Bookmark"), "bookmark_prev", SHIFT+Key_F5, this, TQ_SLOT(slotBookmarksPrev()), actionCollection(), "bookmark_prev" ); m_pActBookmarksNext = new TDEAction( i18n("&Next Bookmark"), "bookmark_next", Key_F5, this, TQ_SLOT(slotBookmarksNext()), actionCollection(), "bookmark_next" ); // settings actions new TDEAction( i18n("&Configure KXMLEditor..."), "configure", 0, this, TQ_SLOT (slotConfigure()), actionCollection(), "configure" ); // path toolbar m_pActPathCombo = new KXmlEditorComboAction( i18n("Path Bar"), 0, this, TQ_SLOT(slotPathSelected(const TQString &)), actionCollection(), "path_combo" ); new TDEAction( i18n("Clear Path Bar"), BarIcon("locationbar_erase", 16), 0, this, TQ_SLOT(slotPathClear()), actionCollection(), "path_clear" ); TQLabel *m_locationLabel = new ToolbarLabel( i18n("Path: ") ); new KWidgetAction( m_locationLabel, i18n("Path: "), 0, this, 0, actionCollection(), "path_label" ); m_locationLabel->setBuddy( m_pActPathCombo->comboBox()); if ( ! fReadWrite ) { setXMLFile( "kxmleditorpartBrowseUI.rc", true ); KStdAction::cut( m_pBrowserExt, TQ_SLOT(slotEditCut()), actionCollection(), "cut" ); KStdAction::copy( m_pBrowserExt, TQ_SLOT(slotEditCopy()), actionCollection(), "copy" ); KStdAction::paste( m_pBrowserExt, TQ_SLOT(slotEditPaste()), actionCollection(), "paste"); m_pCmdHistory = 0L; m_pActVersionEncoding = 0L; m_pActAttachSchema = 0L; m_pActDetachSchema = 0L; m_pActAttachStylesheet = 0L; m_pActDetachStylesheet = 0L; } else { // document specific actions here m_pActVersionEncoding = new TDEAction( i18n("&Version && Encoding..."), 0, 0, this, TQ_SLOT(slotActVersionEncoding()), actionCollection(), "xml_ins_spec_procins" ); m_pActAttachSchema = new TDEAction(i18n("Attach Schema..."),0,0,this,TQ_SLOT(slotActAttachSchema()), actionCollection(), "xml_attach_schema"); m_pActDetachSchema = new TDEAction(i18n("Detach Schema"),0,0,this,TQ_SLOT(slotActDetachSchema()), actionCollection(), "xml_detach_schema"); m_pActAttachStylesheet = new TDEAction(i18n("Attach Stylesheet..."),0,0,this,TQ_SLOT(slotActAttachStylesheet()), actionCollection(), "xml_attach_stylesheet"); m_pActDetachStylesheet = new TDEAction(i18n("Detach Stylesheet"),0,0,this,TQ_SLOT(slotActDetachStylesheet()), actionCollection(), "xml_detach_stylesheet"); KStdAction::print( this, TQ_SLOT(slotActPrint()), actionCollection(), "print" ); m_pActAttachSchema->setEnabled(false); m_pActDetachSchema->setEnabled(false); m_pActDetachStylesheet->setEnabled(false); // undo & redo KStdAction::undo(this, TQ_SLOT(slotActUndo()), actionCollection()); KStdAction::redo(this, TQ_SLOT(slotActRedo()), actionCollection()); m_pCmdHistory = new KCommandHistory(actionCollection()); m_pActEditCut = KStdAction::cut( this, TQ_SLOT(slotEditCut()), actionCollection()); m_pActEditCopy = KStdAction::copy( this, TQ_SLOT(slotEditCopy()), actionCollection()); m_pActEditPaste = KStdAction::paste( this, TQ_SLOT(slotEditPaste()), actionCollection()); // Move node Up & Down m_pActXmlMoveNodeUp = new TDEAction( i18n("&Move Up"), "xml_move_item_up", CTRL+Key_U, this, TQ_SLOT(slotXmlMoveNodeUp()), actionCollection(), "xml_move_item_up" ); m_pActXmlMoveNodeDown = new TDEAction( i18n("Move &Down"), "xml_move_item_down", CTRL+Key_D, this, TQ_SLOT(slotXmlMoveNodeDown()), actionCollection(), "xml_move_item_down" ); // Insert actions m_pActXmlElementInsert = new TDEAction( i18n("&Element..."), "xml_insert_element", CTRL+SHIFT+Key_E, this, TQ_SLOT(slotXmlElementInsert()), actionCollection(), "xml_ins_element" ); m_pActXmlAttributesAdd = new TDEAction( i18n("&Attribute..."), "xml_insert_attribute", CTRL+SHIFT+Key_A, this, TQ_SLOT(slotXmlAttributesAdd()), actionCollection(), "xml_add_attribute" ); m_pActInsertText = new TDEAction( i18n("&Text..."), "xml_text", CTRL+SHIFT+Key_T, this, TQ_SLOT(slotActInsertText()), actionCollection(), "insert_text" ); m_pActInsertCDATA = new TDEAction( i18n("C&DATA..."), "xml_cdata", CTRL+SHIFT+Key_D, this, TQ_SLOT(slotActInsertCDATA()), actionCollection(), "insert_cdata" ); m_pActInsertComment = new TDEAction( i18n("&Comment..."), "xml_comment", CTRL+SHIFT+Key_C, this, TQ_SLOT(slotActInsertComment()), actionCollection(), "insert_comment" ); m_pActXmlProcInstrInsert = new TDEAction( i18n("&Processing Instruction..."), "xml_insert_procins", CTRL+SHIFT+Key_P, this, TQ_SLOT(slotXmlProcInstrInsert()), actionCollection(), "xml_ins_procins" ); // Edit node properties m_pActProperties = new TDEAction(i18n("&Properties..."),"edit",0,this,TQ_SLOT(slotActProperties()),actionCollection(),"edit_properties"); m_pActEditRawXml = new TDEAction(i18n("Edit &raw XML..."), 0, 0, this, TQ_SLOT(slotActEditRawXml()),actionCollection(),"edit_as_raw_xml"); // delete actions m_pActXmlAttributeDel = new TDEAction( i18n("&Delete"), "editdelete", 0, this, TQ_SLOT(slotXmlAttributeDel()), actionCollection(), "xml_del_attribute" ); m_pActXmlAttributesDel = new TDEAction( i18n("Delete all Attributes..."), 0, 0, this, TQ_SLOT(slotXmlAttributesDel()), actionCollection(), "xml_del_attributes" ); m_pActDelete = new TDEAction(i18n("&Delete"),"editdelete",0,this,TQ_SLOT(slotActDelete()),actionCollection(),"edit_delete"); setXMLFile( "kxmleditorpartEditUI.rc", true ); // we are not modified since we haven't done anything yet setModified(false); } ////////////////////////////// // CREATE WIDGETS ////////////////////////////// pSplitter = new TQSplitter( pParent, "KXMLEditorPart main widget (Splitter)" ); pSplitter->setFocusPolicy( TQWidget::NoFocus ); pSplitter->setOpaqueResize(true); setWidget( pSplitter ); // create the tree view ------------------- m_pViewTree = new KXE_TreeView( this, pSplitter, "KXMLEditorPart treeview" ); connect( m_pViewTree, TQ_SIGNAL(sigSelectionCleared(bool)), this, TQ_SLOT(slotSelectionCleared(bool)) ); connect( m_pViewTree, TQ_SIGNAL(sigSelectionChanged(const TQDomElement &)), this, TQ_SLOT(slotSelectionChanged(const TQDomElement &)) ); connect( m_pViewTree, TQ_SIGNAL(sigSelectionChanged(const TQDomCharacterData &)), this, TQ_SLOT(slotSelectionChanged(const TQDomCharacterData &)) ); connect( m_pViewTree, TQ_SIGNAL(sigSelectionChanged(const TQDomProcessingInstruction &)), this, TQ_SLOT(slotSelectionChanged(const TQDomProcessingInstruction &)) ); connect( m_pViewTree, TQ_SIGNAL(sigContextMenuRequested(const TQString&,const TQPoint&)), this, TQ_SLOT(slotContextMenuRequested(const TQString&,const TQPoint&)) ); connect( m_pViewTree, TQ_SIGNAL(itemRenamed(TQListViewItem *)), this, TQ_SLOT(slotItemRenamedInplace(TQListViewItem *)) ); connect( m_pViewTree, TQ_SIGNAL(sigKeyPressed(TQKeyEvent* )),this,TQ_SLOT(slotTreeViewKeyPressed(TQKeyEvent*))); // create tab widget ---------------------- m_pTabWidget = new TQTabWidget( pSplitter, "KXMLEditorPart tabwidget"); m_pTabWidget->setFocusPolicy( TQWidget::NoFocus ); // create element view m_pViewElement = new KXE_ViewElement( m_pTabWidget, instance()->config(), "KXMLEditorPart element view" ); m_pTabWidget->addTab( m_pViewElement, g_iconElement, i18n("Element") ); connect( m_pViewElement, TQ_SIGNAL(sigContextMenuRequested(const TQString&,const TQPoint&)), this, TQ_SLOT(slotContextMenuRequested(const TQString&,const TQPoint&)) ); connect( m_pViewElement, TQ_SIGNAL(sigAttributeNameChangedInplace(const TQDomAttr&, const TQString)), this, TQ_SLOT(slotAttributeNameChangedInplace(const TQDomAttr&, const TQString)) ); connect( m_pViewElement, TQ_SIGNAL(sigAttributeValueChangedInplace(const TQDomAttr&, const TQString)), this, TQ_SLOT(slotAttributeValueChangedInplace(const TQDomAttr&, const TQString)) ); // create edit widget, that display XML character data contents m_pViewContents = new TQTextEdit( m_pTabWidget, "KXMLEditorPart contents view" ); m_pTabWidget->addTab( m_pViewContents, g_iconText, i18n("Contents") ); m_pViewContents->setReadOnly( true ); m_pViewContents->setWordWrap( TQTextEdit::NoWrap ); m_pViewContents->setTextFormat(TQTextEdit::PlainText); // create proc.instr. view m_pViewProcInstr = new TQTextEdit( m_pTabWidget, "KXMLEditorPart proc.instr. view" ); m_pTabWidget->addTab( m_pViewProcInstr, g_iconProcessingInstruction, i18n("Proc.Instruction") ); m_pViewProcInstr->setReadOnly( true ); m_pViewProcInstr->setWordWrap( TQTextEdit::NoWrap ); connect( this, TQ_SIGNAL(started(TDEIO::Job*)), this, TQ_SLOT(started()) ); connect( this, TQ_SIGNAL(completed()), this, TQ_SLOT(completed()) ); connect( this, TQ_SIGNAL(canceled(const TQString &)), this, TQ_SLOT(canceled()) ); ////////////////////////////// // INIT BEGIN STATE ////////////////////////////// // Disable actions if(m_pBrowserExt) m_pBrowserExt->emit enableAction("copy", false); else m_pActEditCopy->setEnabled(false); m_pActEditFindNext->setEnabled(false); m_pActEditDeselect->setEnabled(false); m_pActViewNodeUp->setEnabled(false); m_pActViewExpNode->setEnabled(false); m_pActViewColNode->setEnabled(false); m_pActBookmarksToggle->setEnabled(false); m_pActBookmarksPrev->setEnabled(false); m_pActBookmarksNext->setEnabled(false); if ( fReadWrite ) { m_pActEditCut->setEnabled(false); m_pActEditPaste->setEnabled(true); m_pActXmlElementInsert->setEnabled(true); m_pActXmlAttributesAdd->setEnabled(false); m_pActXmlAttributesDel->setEnabled(false); m_pActXmlProcInstrInsert->setEnabled(true); m_pActInsertText->setEnabled(false); m_pActInsertCDATA->setEnabled(false); m_pActInsertComment->setEnabled(false); m_pActXmlMoveNodeUp->setEnabled(false); m_pActXmlMoveNodeDown->setEnabled(false); m_pActDelete->setEnabled(false); m_pActProperties->setEnabled(false); m_pActEditRawXml->setEnabled(false); } m_pTabWidget->setTabEnabled( m_pViewElement, false ); m_pTabWidget->setTabEnabled( m_pViewContents, false ); m_pTabWidget->setTabEnabled( m_pViewProcInstr, false ); setReadWrite(fReadWrite); // configuring splitter sizes TQValueList list = instance()->config()->readIntListEntry(CONFIG_MAIN_SPLITTER_SIZES); if (!list.isEmpty()) pSplitter->setSizes(list); ////////////////////////////// // INIT DCOP object (if any) ////////////////////////////// //m_pDCOPIface = NULL; //m_pDCOPIface = new KXMLEditorPartIfaceReadOnly(this); m_pDCOPIface = new KXMLEditorPartIfaceReadWrite(this); // temporarly to test openUrl setDocument(pDocument); } KXMLEditorPart::~KXMLEditorPart() { // saving splitter configuration TDEConfig *pConfig = instance()->config(); pConfig->writeEntry( CONFIG_MAIN_SPLITTER_SIZES, pSplitter->sizes() ); if (m_pDCOPIface) delete m_pDCOPIface; if (m_pDlgSearch) delete m_pDlgSearch; if (m_pPrinter) delete m_pPrinter; if (document()) delete document(); delete m_pCmdHistory; } ///////////////////////////////////////////////////////////////////// // KPART FUNCTIONALITY ///////////////////////////////////////////////////////////////////// bool KXMLEditorPart::openFile() { if( isModified() ) kdError() << "KXMLEditorPart::openFile the current document is modified." << endl; document()->setURL(m_url); bool bResult = document()->open(m_file); updateActions(); return bResult; } bool KXMLEditorPart::saveFile() { emit setStatusBarText( i18n("Saving file...") ); if( url().isEmpty() ) { return slotFileSaveAs(); } // delegate this operation to underlying document object document()->setURL(m_url); bool bRetVal = document()->save(m_file); emit setStatusBarText( i18n("Ready.") ); return bRetVal; } void KXMLEditorPart::setModified( bool bModified ) { KParts::ReadWritePart::setModified( bModified ); // base functionality if ( m_bAlreadyModified != bModified ) { m_bAlreadyModified = bModified; TQString szNewCaption = m_url.prettyURL(); emit setWindowCaption( szNewCaption ); } // get a handle on our Save action and make sure it is valid TDEAction *pActFileSave = actionCollection()->action(KStdAction::stdName(KStdAction::Save)); if(!pActFileSave) return; // if so, we either enable or disable it based on the current state pActFileSave->setEnabled(bModified); // Update others actions updateActions(); } void KXMLEditorPart::setReadWrite( bool fReadWrite ) { m_pViewTree->setReadWrite(fReadWrite); m_pViewElement->setReadWrite(fReadWrite); KParts::ReadWritePart::setReadWrite( fReadWrite ); // base functionality } void KXMLEditorPart::started() { kdDebug() << "KXMLEditorPart::started" << endl; } void KXMLEditorPart::completed() { kdDebug() << "KXMLEditorPart::completed" << endl; } void KXMLEditorPart::canceled() { kdDebug() << "KXMLEditorPart::canceled" << endl; } ///////////////////////////////////////////////////////////////////// // ACTION SLOTS ///////////////////////////////////////////////////////////////////// void KXMLEditorPart::slotActPrint() { // this slot is called whenever the File->Print menu is selected, // the Print shortcut is pressed (usually CTRL+P) or the Print toolbar // button is clicked if (!m_pPrinter) m_pPrinter = new KPrinter; if (m_pPrinter->setup(widget())) print(m_pPrinter); } void KXMLEditorPart::slotActProperties() { TQDomNode* pNode = m_pViewTree->getSelectedNode(); if (pNode) { if (pNode->isElement()) slotXmlElementEdit(); else if (pNode->isCharacterData()) slotXmlCharDataEdit(); else if (pNode->isProcessingInstruction()) slotXmlProcInstrEdit(); else kdError() << "Unknown node selected."; } } void KXMLEditorPart::slotActDelete() { TQDomNode* pNode = m_pViewTree->getSelectedNode(); if (!m_pViewElement->hasFocus()) { // delete nodes selected there if (pNode) { KCommand *pCmd = new KXEDeleteNodeCommand(document(), *pNode); m_pCmdHistory->addCommand(pCmd); } } else { // we can have also delete attribute selected on a element view TQDomAttr domAttr = m_pViewElement->getSelectedAttribute(); if (!domAttr.isNull()) { TQDomElement domElement = pNode->toElement(); TQDomAttr domAttr = m_pViewElement->getSelectedAttribute(); KCommand *pCmd = new KXEDeleteAttrCommand(document(), domElement, domAttr); m_pCmdHistory->addCommand(pCmd); } } } void KXMLEditorPart::slotEditCut() { kdDebug() << "KXMLEditor " << k_funcinfo << endl; if(! isReadWrite()) { kdError() << "KXMLEditorPart::slotEditCut called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if(pNode) { // copy to clipboard slotEditCopy(); // and cut it KCommand *pCmd = new KXECutCommand(document(), *pNode); m_pCmdHistory->addCommand(pCmd); } } void KXMLEditorPart::slotEditCopy() { kdDebug() << "KXMLEditor " << k_funcinfo << endl; TQDomNode * pNode = m_pViewTree->getSelectedNode(); if(pNode) { TQTextDrag *pDrag = copyNode(m_pViewTree->getSelectedNode()); if(pDrag) TQApplication::clipboard()->setData(pDrag); } else kdError() << "KXMLEditorPart::slotEditCopy no element selected." << endl; } void KXMLEditorPart::slotEditPaste() { kdDebug() << "KXMLEditor " << k_funcinfo << endl; if(!isReadWrite()) { kdError() << "KXMLEditorPart::slotEditPaste called in readonly mode." << endl; return; } if (document()->documentElement().isNull()) { pasteNode(0, TQApplication::clipboard()->data()); } else { pasteNode(m_pViewTree->getSelectedNode(), TQApplication::clipboard()->data()); } } void KXMLEditorPart::slotEditFind() { emit setStatusBarText( i18n("Search in XML tree ...") ); if ( ! m_pDlgSearch ) { m_pDlgSearch = new KXESearchDialog( widget(), "search dialog", true ); } if ( m_pDlgSearch->exec() == KXESearchDialog::Accepted ) slotEditFindNext(); m_pActEditFindNext->setEnabled(true); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotEditFindNext() { emit setStatusBarText( i18n("Search in XML tree ...") ); if ( ! m_pDlgSearch ) { kdDebug() << "KXMLEditorPart::slotEditFindNext implementation error - no search dialog" << endl; emit setStatusBarText( i18n("Ready.") ); return; } // get node to start with (either the next node of the item selected at the tree view or documents root node) TQDomNode node = ( (m_pViewTree->getSelectedNode()) && (! m_pViewTree->getSelectedNode()->isNull()) ) ? domTool_nextNode(* m_pViewTree->getSelectedNode()) : document()->documentElement(); // start testing til the last node while( ! node.isNull() ) { if ( domTool_match( node, m_pDlgSearch ) ) { m_pViewTree->selectNode(node); emit setStatusBarText( i18n("Ready.") ); return; } node = domTool_nextNode(node); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlElementInsert() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlElementInsert called in readonly mode." << endl; return; } emit setStatusBarText( i18n("Inserting XML element into document...") ); KXEElementDialog dlg( widget(), "XML element dialog" ); if ( document()->documentElement().isNull() ) // the document doesn't { // have a root element yet if ( dlg.exec( false, true, false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEElementCommand(document(), document(), dlg.nsURI(), dlg.prefix(), dlg.name()); m_pCmdHistory->addCommand(pCmd); } } else // the document seems to { // have a root element TQDomNode * pParentNode = m_pViewTree->getSelectedNode(); if ( (pParentNode) && (pParentNode->isElement()) ) { TQDomElement domParentElement = pParentNode->toElement(); if ( dlg.exec( false, false, false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEElementCommand(document(), domParentElement, dlg.nsURI(), dlg.prefix(), dlg.name(), dlg.atTop()); m_pCmdHistory->addCommand(pCmd); } } else kdError() << "KXMLEditorPart::slotXmlElementInsert no element selected." << endl; } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlElementEdit() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlElementEdit called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotXmlElementEdit no node selected or selected node is no XML element." << endl; return; } emit setStatusBarText( i18n("Editing XML element...") ); TQDomElement domElement = pNode->toElement(); KXEElementDialog dlg( widget(), "XML element dialog" ); dlg.setPrefix(domElement.prefix()); dlg.setName(domElement.tagName()); if(!domElement.namespaceURI().isNull()) dlg.setNsURI(domElement.namespaceURI() ); if ( dlg.exec( true, false, domElement.namespaceURI().isNull() ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEEditElementCommand(document(), domElement, dlg.prefix(), dlg.name()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotActEditRawXml() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotActEditRawXml called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotActEditRawXml no node selected or selected node is no XML element." << endl; return; } emit setStatusBarText( i18n("Editing raw XML...") ); TQDomElement domElement = pNode->toElement(); TQString strXML; TQTextStream streamXML(&strXML, IO_WriteOnly); int iIndent = KXMLEditorFactory::configuration()->textview()->indentSteps(); pNode->save(streamXML, iIndent); KXETextEditorDialog dlg(0, "Text dialog"); dlg.setEditorText(strXML); if((dlg.exec() == TQDialog::Accepted) && (strXML != dlg.editorText())) { TQString strXML = "" + dlg.editorText() + ""; // create XML documemt from text TQString strErrorMsg; int iErrorLine, iErrorColumn; TQDomDocument doc; if(!doc.setContent(strXML, true, &strErrorMsg, &iErrorLine, &iErrorColumn) ) { kdDebug() << "KXMLEditorPart::slotActEditRawXml: Failed parsing the file." << endl; KMessageBox::error(m_pViewTree, i18n("%1 in line %2, column %3").arg(strErrorMsg).arg(iErrorLine).arg(iErrorColumn), i18n("Parsing error !")); return; } // check if root item already exists if(!doc.firstChild().firstChild().isElement()) { KMessageBox::sorry(m_pViewTree, i18n("You are changed root element to another node type, while editing !")); return; } TQDomElement domNewElement = doc.firstChild().firstChild().toElement(); KCommand *pCmd = new KXEEditRawXmlCommand(document(), domElement, domNewElement); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlAttributesAdd() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlAttributesAdd called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotXmlAttributesAdd no node selected or selected node is no XML element." << endl; return; } emit setStatusBarText( i18n("Add attribute...") ); KXEAttributeDialog dlg( widget(), "attribute dialog" ); TQDomElement domOwnerElement = pNode->toElement(); if ( dlg.exec( ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEAttributeCommand(document(), domOwnerElement, dlg.attributeNamespace(), dlg.QName(), dlg.Value()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlAttributesDel() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlAttributesDel called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotXmlAttributesDel no node selected or selected node is no XML element." << endl; return; } if(KMessageBox::questionYesNo(0, i18n("Remove all attributes from selected node ?")) != KMessageBox::Yes) return; emit setStatusBarText( i18n("Delete all attributes...") ); TQDomElement domOwnerElement = pNode->toElement(); KCommand *pCmd = new KXEDeleteAllAttribCommand(document(), domOwnerElement); m_pCmdHistory->addCommand(pCmd); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlAttributeDel() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlAttributeDel called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotXmlAttributeDel no node selected or selected node is no XML element." << endl; return; } emit setStatusBarText( i18n("Delete attribute...") ); TQDomElement domElement = pNode->toElement(); TQDomAttr domAttr = m_pViewElement->getSelectedAttribute(); KCommand *pCmd = new KXEDeleteAttrCommand(document(), domElement, domAttr); m_pCmdHistory->addCommand(pCmd); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlProcInstrInsert() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlProcInstrInsert called in readonly mode." << endl; return; } KXEProcInstrDialog dlg( widget(), "proc. instr. dialog" ); TQDomNode * pParentNode = m_pViewTree->getSelectedNode(); if ( (pParentNode) && (!pParentNode->isElement()) ) { kdError() << k_funcinfo << " The selected node is no XML element." << endl; return; } else { if ( ! pParentNode ) // no node selected -> the new node should be a direct child of the document { if ( dlg.exec( false, true ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEProcInstrCommand(document(), document(), dlg.atTop(), dlg.target(), dlg.data()); m_pCmdHistory->addCommand(pCmd); } } else { if ( dlg.exec( false, false ) == TQDialog::Accepted ) { TQDomElement domParentElement = pParentNode->toElement(); KCommand *pCmd = new KXEProcInstrCommand(document(), domParentElement, dlg.atTop(), dlg.target(), dlg.data()); m_pCmdHistory->addCommand(pCmd); } } } emit setStatusBarText( i18n("Inserting processing instruction into document...") ); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlProcInstrEdit() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlProcInstrEdit called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isProcessingInstruction()) ) { kdError() << "KXMLEditorPart::slotXmlProcInstrEdit no node selected or selected node is no processing instruction." << endl; return; } emit setStatusBarText( i18n("Editing processing instruction...") ); TQDomProcessingInstruction domProcInstr = pNode->toProcessingInstruction(); // We have two different kinds of processing instructions: // - a special one - defining the documents XML version and encoding // - others // and both cases require different dialogs. if( domProcInstr.target() == "xml" ) // 1st case (special proc.instr.) document()->actVersionEncoding(); else // 2nd case (others) { KXEProcInstrDialog dlg( widget(), "proc. instr. dialog" ); dlg.setTarget(domProcInstr.target()); dlg.setData(domProcInstr.data()); if ( dlg.exec( true, false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEEditProcInstrCommand(document(), domProcInstr, dlg.data()); m_pCmdHistory->addCommand(pCmd); } } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotActInsertText() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotActInsertText called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotActInsertText no element selected." << endl; return; } emit setStatusBarText( i18n("Inserting text into document...") ); KXECharDataDialog dlg( widget()); dlg.setCaption(i18n("Insert text")); TQDomElement domParentElement = pNode->toElement(); if ( dlg.exec( false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXECharDataCommand(document(), domParentElement, dlg.atTop(), CharDataTextNode, dlg.contents()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotActInsertCDATA() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotActInsertCDATA called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotActInsertCDATA no element selected." << endl; return; } emit setStatusBarText( i18n("Inserting CDATA into document...") ); KXECharDataDialog dlg( widget()); dlg.setCaption(i18n("Insert CDATA")); TQDomElement domParentElement = pNode->toElement(); if ( dlg.exec( false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXECharDataCommand(document(), domParentElement, dlg.atTop(), CharDataCDATASection, dlg.contents()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotActInsertComment() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotActInsertComment called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isElement()) ) { kdError() << "KXMLEditorPart::slotActInsertComment no element selected." << endl; return; } emit setStatusBarText( i18n("Inserting comment into document...") ); KXECharDataDialog dlg( widget()); dlg.setCaption(i18n("Insert comment")); TQDomElement domParentElement = pNode->toElement(); if ( dlg.exec( false ) == TQDialog::Accepted ) { KCommand *pCmd = new KXECharDataCommand(document(), domParentElement, dlg.atTop(), CharDataComment, dlg.contents()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlCharDataEdit() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlCharDataEdit called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( (!pNode) || (!pNode->isCharacterData()) ) { kdError() << "KXMLEditorPart::slotXmlCharDataEdit no node selected or selected node is no character data." << endl; return; } emit setStatusBarText( i18n("Editing character data...") ); TQDomCharacterData domCharData = pNode->toCharacterData(); KXECharDataDialog dlg( widget() ); CharDataKind eCharDataKind; if(domCharData.isText()) eCharDataKind = CharDataTextNode; else { if(domCharData.isCDATASection()) eCharDataKind = CharDataCDATASection; else eCharDataKind = CharDataComment; } // dlg.setCharDataKind(eCharDataKind); dlg.setContents(domCharData.data()); if ( dlg.exec( true ) == TQDialog::Accepted ) { KCommand *pCmd = new KXEEditCharDataCommand(document(), domCharData, dlg.contents()); m_pCmdHistory->addCommand(pCmd); } emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlMoveNodeUp() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlMoveNodeUp called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( ! pNode ) { kdError() << "KXMLEditorPart::slotXmlMoveNodeUp no node selected." << endl; return; } emit setStatusBarText( i18n("Moving node up...") ); KCommand *pCmd = new KXEUpCommand(document(), * pNode); m_pCmdHistory->addCommand(pCmd); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotXmlMoveNodeDown() { if ( ! isReadWrite() ) { kdError() << "KXMLEditorPart::slotXmlMoveNodeDown called in readonly mode." << endl; return; } TQDomNode * pNode = m_pViewTree->getSelectedNode(); if ( ! pNode ) { kdError() << "KXMLEditorPart::slotXmlMoveNodeDown no node selected." << endl; return; } emit setStatusBarText( i18n("Moving node down...") ); KCommand *pCmd = new KXEDownCommand(document(), * pNode); m_pCmdHistory->addCommand(pCmd); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotBookmarksToggle() { m_pViewTree->bookmarksToggle(); m_pActBookmarksPrev->setEnabled(m_pViewTree->containsBookmarkedItems()); m_pActBookmarksNext->setEnabled(m_pViewTree->containsBookmarkedItems()); } void KXMLEditorPart::slotConfigure() { emit setStatusBarText( i18n("Configure KXML Editor ...") ); KXMLEditorFactory::configuration()->showDialog(); emit setStatusBarText( i18n("Ready.") ); } void KXMLEditorPart::slotPathSelected( ) { } void KXMLEditorPart::slotPathSelected( const TQString & strPath ) { TQDomNode node = domTool_matchingNode( document()->toDocument(), strPath ); if(node.isNull()) { // node don't exists, remove item from combo m_pActPathCombo->removeItem(strPath); m_pActPathCombo->slotClearEdit(); return; } if(!m_pViewTree->selectNode(node)) { // node not found, remove item from combo m_pActPathCombo->removeItem(strPath); m_pActPathCombo->slotClearEdit(); } } void KXMLEditorPart::slotPathClear() { slotEditDeselect(); m_pActPathCombo->slotFocusEdit(); } void KXMLEditorPart::slotItemRenamedInplace( TQListViewItem * pItem ) { KXE_TreeViewItem * pXMLItem = static_cast (pItem); if ( ! pXMLItem->xmlNode()->isElement() ) // check, if it really represents an XML element { kdFatal() << "KXMLEditorPart " << k_funcinfo << " the given item doesn't represent an XML element." << endl; return; } TQDomElement domElement = pXMLItem->xmlNode()->toElement(); if ( domElement.nodeName() != pItem->text(0) ) // if really something was changed { // else the element is "namespaced" int nPosColon = pItem->text(0).find(':'); if ( nPosColon == -1 ) // if no namespace prefix was entered, { // check name TQString strMessage = KXEElementDialog::checkName(pItem->text(0)); if(strMessage.length() > 0) { // restore old name m_pViewTree->updateNodeChanged(domElement); KMessageBox::sorry(m_pViewTree, strMessage); return; } // clear the elements namespace prefix // and set the entered text as its tag name KCommand *pCmd = new KXEEditElementCommand(document(), domElement, TQString::null, pItem->text(0)); m_pCmdHistory->addCommand(pCmd); } else { // otherwise split up the entered text by the first colon and TQString strPrefix(pItem->text(0).left(nPosColon)); TQString strName(pItem->text(0).right( pItem->text(0).length() - nPosColon - 1 )); // check name TQString strMessage = KXEElementDialog::checkName(strName); if(strMessage.length() > 0) { // restore old name m_pViewTree->updateNodeChanged(domElement); KMessageBox::sorry(m_pViewTree, strMessage); return; } KCommand *pCmd = new KXEEditElementCommand( document(), domElement, strPrefix, strName ); m_pCmdHistory->addCommand(pCmd); } if ( m_pViewTree->selectedItem() == pItem ) // and if the item is still selected { m_pActPathCombo->insertItem( domTool_getIconForNodeType(pXMLItem->xmlNode()->nodeType(), false), domTool_getPath(*pXMLItem->xmlNode()) ); // the path combo } } } void KXMLEditorPart::slotAttributeNameChangedInplace( const TQDomAttr & domAttr, const TQString strNewName ) { if ( *m_pViewTree->getSelectedNode() == domAttr.ownerElement() ) // if the corresponding element { // is still selected KCommand *pCmd = new KXEEditAttrNameCommand(document(), domAttr, strNewName); m_pCmdHistory->addCommand(pCmd); } } void KXMLEditorPart::slotAttributeValueChangedInplace( const TQDomAttr & domAttr, const TQString strNewValue ) { if ( *m_pViewTree->getSelectedNode() == domAttr.ownerElement() ) // if the corresponding element { // is still selected KCommand *pCmd = new KXEEditAttrValueCommand(document(), domAttr, strNewValue); m_pCmdHistory->addCommand(pCmd); } } ///////////////////////////////////////////////////////////////////// // MISC FUNCTIONS ///////////////////////////////////////////////////////////////////// /** Copy XML node into clipboard */ TQTextDrag * KXMLEditorPart::copyNode(TQDomNode * pNode) { TQTextDrag *pDrag = 0; TQString strXML; TQTextStream streamXML(&strXML, IO_WriteOnly); int iIndent = KXMLEditorFactory::configuration()->textview()->indentSteps(); pNode->save(streamXML, iIndent); pDrag = new TQTextDrag(strXML, m_pViewTree); /*if(pNode->isElement()) pDrag->setSubtype(KXE_TreeViewItem::m_strSubtypeXML); if(pNode->isProcessingInstruction()) pDrag->setSubtype(KXE_TreeViewItem::m_strSubtypeXML_procins); if(pNode->isText()) pDrag->setSubtype(KXE_TreeViewItem::m_strSubtypeXML_text); if(pNode->isCDATASection()) pDrag->setSubtype(KXE_TreeViewItem::m_strSubtypeXML_cdata); if(pNode->isComment()) pDrag->setSubtype(KXE_TreeViewItem::m_strSubtypeXML_comment); */ return pDrag; } //----------------------------------------------------------------------------- // // Paste XML node from clipboard into document // // pTargetNode - target node // data - data to pasted // //----------------------------------------------------------------------------- bool KXMLEditorPart::pasteNode(TQDomNode * pTargetNode, TQMimeSource *data) { TQString strText; // Drop XML Processing Instruction if(TQTextDrag::decode(data, strText)) { if(strText.find("" + strText + ""; // Paste clipboard contents as XML element TQString strErrorMsg; int iErrorLine, iErrorColumn; TQDomDocument doc; if(!doc.setContent(strXML, true, &strErrorMsg, &iErrorLine, &iErrorColumn) ) { kdDebug() << "KXMLEditorPart::pasteNode: Failed parsing the file." << endl; KMessageBox::error(m_pViewTree, i18n("%1 in line %2, column %3").arg(strErrorMsg).arg(iErrorLine).arg(iErrorColumn), i18n("Parsing error !")); return false; } // Import parsed document to main document if(doc.hasChildNodes()) { if(pTargetNode == 0) { // check if root item already exists if(!document()->documentElement().isNull() /*(this->documentElement().isElement())*/ && (doc.firstChild().firstChild().isElement()) ) { KMessageBox::sorry(m_pViewTree, i18n("Root element already exists !")); return false; } if(doc.documentElement().firstChild().isElement() == false) { KMessageBox::sorry(m_pViewTree, i18n("Node pasted to document must be element !")); return false; } // Append it as root node TQDomElement newNode = doc.documentElement().firstChild().cloneNode(true).toElement(); KCommand *pCmd = new KXEPasteToDocumentCommand(document(), document(), newNode); m_pCmdHistory->addCommand(pCmd); } else { TQDomNode sourceNode = doc.firstChild().firstChild().cloneNode(true); /* L.V. TESTING CODE FOR [ 925668 ] Attribute values in a copied element can't be changed. if(sourceNode.isElement()) { TQDomElement domSourceElement = sourceNode.toElement(); TQDomNamedNodeMap list = domSourceElement.attributes(); unsigned int iLength = list.length(); for ( unsigned int iRow = 0; iRow < iLength; iRow++ ) { TQDomAttr a = list.item(iRow).toAttr(); TQDomElement domOwnerElement = a.ownerElement(); if(domOwnerElement.isNull()) KMessageBox::sorry(m_pViewTree, i18n("Cloned owner is null !")); }*/ //--- if(pTargetNode->isElement()) { TQDomElement domTargetElement = pTargetNode->toElement(); KCommand *pCmd = new KXEPasteToElementCommand(document(), domTargetElement, sourceNode); m_pCmdHistory->addCommand(pCmd); return true; } if(pTargetNode->isProcessingInstruction() && sourceNode.isProcessingInstruction()) { // Replace contents of selected node TQDomProcessingInstruction domTargetProcInstr = pTargetNode->toProcessingInstruction(); TQDomProcessingInstruction domSourceProcInstr = sourceNode.toProcessingInstruction(); KCommand *pCmd = new KXEPasteToProcInstrCommand(document(), domTargetProcInstr, domSourceProcInstr); m_pCmdHistory->addCommand(pCmd); return true; } if(pTargetNode->isCharacterData() && sourceNode.isCharacterData()) { // Replace contents of selected node TQDomCharacterData domTargetCharData = pTargetNode->toCharacterData(); TQDomCharacterData domSourceCharData = sourceNode.toCharacterData(); KCommand *pCmd = new KXEPasteToCharDataCommand(document(), domTargetCharData, domSourceCharData); m_pCmdHistory->addCommand(pCmd); return true; } KMessageBox::sorry(m_pViewTree, i18n("Incompactible node types for drag&drop !")); return false; } } return true; } return false; } //----------------------------------------------------------------------------- // // Drag & Drop MOVE operation // // domTrgetElement - target element // domSourceNode - source node // //----------------------------------------------------------------------------- bool KXMLEditorPart::dropMoveNode(TQDomElement & domTargetElement, TQDomNode & domSourceNode) { KCommand *pCmd = new KXEDragDropMoveCommand(document(), domTargetElement, domSourceNode); m_pCmdHistory->addCommand(pCmd); return true; } ///////////////////////////////////////////////////////////////////// // PRINTING ///////////////////////////////////////////////////////////////////// // these defines should rather stay fixed and not configurable by the user. #define headerMargin 30; #define footerMargin 50; #define m_printLinespace 0.4 // percent of font size used to make line indent int headerHeight, footerHeight; // used in few functions, nevertheless temporary... void KXMLEditorPart::print(KPrinter* pPrinter) { // setup the printer. with TQt, you always "print" to a // TQPainter.. whether the output medium is a pixmap, a screen, or paper TQPainter p; TQPainter *painter = &p; TQFont font( KXMLEditorFactory::configuration()->print()->fontFamily(), KXMLEditorFactory::configuration()->print()->fontSize() ); TQPaintDeviceMetrics metrics((TQPrinter*)pPrinter); // determining int width = metrics.width(); // width and int height = metrics.height(); // height of the page footerHeight = font.pointSize()+footerMargin; headerHeight = font.pointSize()+headerMargin; int pageNumber = 0; painter->begin(pPrinter); // start print job painter->setFont(font); // set up fonts for printout printHeader(painter,pageNumber,0,width); // draw header on a first page while (printPage (painter,pageNumber, headerHeight,width, height-headerHeight-footerHeight)) // and start printing loop { printFooter(painter, pageNumber, height-footerHeight,width); // draw footer at the end of that page pageNumber++; pPrinter->newPage(); printHeader(painter,pageNumber,0,width); // draw header on new page } printFooter(painter,pageNumber,height-footerHeight,width); // draw footer on last page painter->end(); // finish print job } void KXMLEditorPart::printHeader(TQPainter* painter,int pageNumber, int ypos, int width) { pageNumber = pageNumber; if ( KXMLEditorFactory::configuration()->print()->hasHeader() ) { painter->drawText(0,ypos,m_url.prettyURL()); painter->drawLine(0,ypos,width,ypos); } } bool KXMLEditorPart::printPage(TQPainter* painter,int pageNumber, int top, int width, int height) { width = width; if (pageNumber==0) { // initialization of working variables is done when // first page is about to be printed m_printLineNumber = 0; m_printLines = TQStringList::split( "\n", document()->toString(KXMLEditorFactory::configuration()->print()->indentSteps()) ); } int lineHeight = (int)(painter->font().pointSize()*(1+m_printLinespace)); int y = top; while ( y <= height ) { painter->drawText(0,y,m_printLines[m_printLineNumber]); if (m_printLineNumber++==m_printLines.size()) return false; // no more pages to print y += lineHeight; } return true; // there are still some pages to print } void KXMLEditorPart::printFooter(TQPainter* painter,int pageNumber, int ypos, int width) { if ( KXMLEditorFactory::configuration()->print()->hasFooter() ) { int fh = painter->font().pointSize(); painter->drawText(0,ypos,i18n("Page %1").arg(pageNumber+1)); painter->drawLine(0,ypos-fh,width,ypos-fh); } } ///////////////////////////////////////////////////////////////////// // OTHER SLOTS ///////////////////////////////////////////////////////////////////// void KXMLEditorPart::slotTreeViewKeyPressed(TQKeyEvent *e) { // few keypresses are recognized and proper actions // are executed. switch (e->key()) { case TQt::Key_Delete : slotActDelete(); break; case TQt::Key_Return : case TQt::Key_Enter : slotActProperties(); break; } } void KXMLEditorPart::slotSelectionCleared(bool bRootElementExists) { // Enable/Disable actions if(m_pBrowserExt) m_pBrowserExt->emit enableAction( "copy", false ); else m_pActEditCopy->setEnabled(false); m_pActEditDeselect->setEnabled(false); m_pActViewNodeUp->setEnabled(false); m_pActViewExpNode->setEnabled(false); m_pActViewColNode->setEnabled(false); m_pActBookmarksToggle->setEnabled(false); if ( isReadWrite() ) { m_pActEditCut->setEnabled(false ); m_pActEditPaste->setEnabled(true ); m_pActXmlElementInsert->setEnabled(!bRootElementExists); m_pActXmlAttributesAdd->setEnabled(false); m_pActXmlAttributesDel->setEnabled(false); m_pActXmlProcInstrInsert->setEnabled(true); m_pActInsertText->setEnabled(false); m_pActInsertCDATA->setEnabled(false); m_pActInsertComment->setEnabled(false); m_pActXmlMoveNodeUp->setEnabled(false); m_pActXmlMoveNodeDown->setEnabled(false); m_pActDelete->setEnabled(false); m_pActProperties->setEnabled(false); m_pActEditRawXml->setEnabled(false); } m_pActPathCombo->slotClearEdit(); // change views m_pViewContents->clear(); m_pTabWidget->setTabEnabled( m_pViewElement, false ); m_pTabWidget->setTabEnabled( m_pViewContents, false ); m_pTabWidget->setTabEnabled( m_pViewProcInstr, false ); m_pTabWidget->showPage( m_pViewContents ); // change path combo m_pActPathCombo->slotClearEdit(); } void KXMLEditorPart::slotSelectionChanged( const TQDomElement & selectedNode) { // Enable/Disable actions if(m_pBrowserExt) m_pBrowserExt->emit enableAction( "copy", true ); else m_pActEditCopy->setEnabled(true); m_pActEditDeselect->setEnabled(true); m_pActViewNodeUp->setEnabled( ! selectedNode.parentNode().isNull() ); // disable if it's a root item m_pActViewExpNode->setEnabled( ! selectedNode.firstChild().isNull() ); // no childs -> disable m_pActViewColNode->setEnabled( ! selectedNode.firstChild().isNull() ); // no childs -> disable m_pActBookmarksToggle->setEnabled(true); if ( isReadWrite() ) { m_pActEditCut->setEnabled(true); m_pActEditPaste->setEnabled(true); m_pActXmlElementInsert->setEnabled(true); m_pActXmlAttributesAdd->setEnabled(true); m_pActXmlAttributesDel->setEnabled( (selectedNode.attributes().count() != 0) ); m_pActXmlProcInstrInsert->setEnabled(true); // m_pActXmlCharDataInsert->setEnabled(true); m_pActInsertText->setEnabled(true); m_pActInsertCDATA->setEnabled(true); m_pActInsertComment->setEnabled(true); m_pActDelete->setEnabled(true); m_pActProperties->setEnabled(true); m_pActEditRawXml->setEnabled(true); if ( selectedNode.parentNode().isDocument() ) { m_pActXmlMoveNodeUp->setEnabled(false); m_pActXmlMoveNodeDown->setEnabled(false); } else { m_pActXmlMoveNodeUp->setEnabled( ! selectedNode.previousSibling().isNull() ); m_pActXmlMoveNodeDown->setEnabled( ! selectedNode.nextSibling().isNull() ); } } // change views m_pViewElement->slotChange(selectedNode); m_pTabWidget->setTabEnabled( m_pViewElement, true ); m_pTabWidget->setTabEnabled( m_pViewContents, false ); m_pTabWidget->setTabEnabled( m_pViewProcInstr, false ); m_pTabWidget->showPage(m_pViewElement); // change path combo m_pActPathCombo->insertItem( domTool_getIconForNodeType(selectedNode.nodeType(), false), domTool_getPath(selectedNode) ); } void KXMLEditorPart::slotSelectionChanged( const TQDomCharacterData & selectedNode ) { // Enable/Disable actions if(m_pBrowserExt) m_pBrowserExt->emit enableAction( "copy", true ); else m_pActEditCopy->setEnabled(true); m_pActEditDeselect->setEnabled(true); m_pActViewNodeUp->setEnabled( ! selectedNode.parentNode().isNull() ); // disable if it's a root item m_pActViewExpNode->setEnabled(false); m_pActViewColNode->setEnabled(false); m_pActBookmarksToggle->setEnabled(true); if ( isReadWrite() ) { m_pActEditCut->setEnabled(true); m_pActEditPaste->setEnabled(true); m_pActXmlElementInsert->setEnabled(false); m_pActXmlAttributesAdd->setEnabled(false); m_pActXmlAttributesDel->setEnabled(false); m_pActXmlProcInstrInsert->setEnabled(false); m_pActInsertText->setEnabled(false); m_pActInsertCDATA->setEnabled(false); m_pActInsertComment->setEnabled(false); m_pActXmlMoveNodeUp->setEnabled( ! selectedNode.previousSibling().isNull() ); m_pActXmlMoveNodeDown->setEnabled( ! selectedNode.nextSibling().isNull() ); m_pActDelete->setEnabled(true); m_pActProperties->setEnabled(true); m_pActEditRawXml->setEnabled(false); } // change views m_pViewContents->setText( selectedNode.data() ); m_pTabWidget->setTabEnabled( m_pViewElement, false ); m_pTabWidget->setTabEnabled( m_pViewContents, true ); m_pTabWidget->setTabEnabled( m_pViewProcInstr, false ); m_pTabWidget->showPage( m_pViewContents ); // change path combo m_pActPathCombo->insertItem( domTool_getIconForNodeType(selectedNode.nodeType(), false), domTool_getPath(selectedNode) ); } void KXMLEditorPart::slotSelectionChanged( const TQDomProcessingInstruction & selectedNode ) { // Enable/Disable actions if(m_pBrowserExt) m_pBrowserExt->emit enableAction( "copy", true ); else m_pActEditCopy->setEnabled(true); m_pActEditDeselect->setEnabled(true); m_pActViewNodeUp->setEnabled( ! selectedNode.parentNode().isNull() ); // disable if it's a root item m_pActViewExpNode->setEnabled(false); m_pActViewColNode->setEnabled(false); m_pActBookmarksToggle->setEnabled(true); if ( isReadWrite() ) { m_pActEditCut->setEnabled(true); m_pActEditPaste->setEnabled(true); m_pActXmlAttributesAdd->setEnabled(false); m_pActXmlAttributesDel->setEnabled(false); m_pActXmlProcInstrInsert->setEnabled(false); m_pActInsertText->setEnabled(false); m_pActInsertCDATA->setEnabled(false); m_pActInsertComment->setEnabled(false); m_pActDelete->setEnabled(true); m_pActProperties->setEnabled(true); m_pActEditRawXml->setEnabled(false); m_pActXmlElementInsert->setEnabled(selectedNode.parentNode().isDocument() && document()->documentElement().isNull()); if ( selectedNode.parentNode().isDocument() ) { m_pActXmlMoveNodeUp->setEnabled(false); m_pActXmlMoveNodeDown->setEnabled(false); } else { m_pActXmlMoveNodeUp->setEnabled( ! selectedNode.previousSibling().isNull() ); m_pActXmlMoveNodeDown->setEnabled( ! selectedNode.nextSibling().isNull() ); } } // change views m_pViewProcInstr->setText( selectedNode.data() ); m_pTabWidget->setTabEnabled( m_pViewElement, false ); m_pTabWidget->setTabEnabled( m_pViewContents, false ); m_pTabWidget->setTabEnabled( m_pViewProcInstr, true ); m_pTabWidget->showPage( m_pViewProcInstr ); // change path combo m_pActPathCombo->insertItem( domTool_getIconForNodeType(selectedNode.nodeType(), false), domTool_getPath(selectedNode) ); } void KXMLEditorPart::slotContextMenuRequested( const TQString & szMenuName, const TQPoint & pos ) { TQWidget * pContainer = hostContainer(szMenuName); if ( ! pContainer ) { kdError() << "KXMLEditor " << k_funcinfo << " Couldn't get a container widget for the given menu name (" << szMenuName << ")" << endl; return; } if ( ! pContainer->inherits("TDEPopupMenu") ) { kdError() << "KXMLEditor " << k_funcinfo << " Wrong container widget" << endl; return; } TDEPopupMenu * pMenu = static_cast (pContainer); pMenu->popup( pos ); } ///////////////////////////////////////////////////////////////////// // FUNCTIONS CALLED FROM KXECommand CHILD CLASSES ///////////////////////////////////////////////////////////////////// void KXMLEditorPart::updateNodeCreated(const TQDomNode & node) { m_pViewTree->updateNodeCreated(node); } void KXMLEditorPart::updateNodeDeleted( const TQDomNode & node ) { m_pViewTree->updateNodeDeleted(node); // if root element deleted, enable Insert Element if(node.isElement() && (m_pViewTree->firstChild() == 0) && (isReadWrite())) m_pActXmlElementInsert->setEnabled(true); } void KXMLEditorPart::updateNodeChanged( const TQDomElement & domElement ) { m_pViewTree->updateNodeChanged(domElement); m_pViewElement->slotChange(domElement); } void KXMLEditorPart::updateNodeChanged( const TQDomCharacterData & domCharData ) { m_pViewTree->updateNodeChanged(domCharData); m_pViewContents->setText( domCharData.data() ); } void KXMLEditorPart::updateNodeChanged( const TQDomProcessingInstruction &domProcInstr ) { m_pViewTree->updateNodeChanged(domProcInstr); m_pViewProcInstr->setText( domProcInstr.data() ); } void KXMLEditorPart::updateNodeMoved( const TQDomNode & domNode ) { m_pViewTree->updateNodeMoved(domNode); } bool KXMLEditorPart::slotFileSaveAs() { emit setStatusBarText( i18n("Saving file with a new filename...") ); KFileDialog dlg( TQDir::currentDirPath(), // start dir. i18n(FILE_DIALOG_FILTER), // filter widget(), // parent "file dialog for saving", // name true ); // modal dlg.setCaption( i18n("Save as...") ); dlg.setOperationMode( KFileDialog::Saving ); dlg.exec(); KURL url = dlg.selectedURL(); bool bRetVal = false; if(!url.isEmpty()) { // append filetype if necessary if(dlg.currentFilter() != "*.*") { TQString strExtension = dlg.currentFilter(); strExtension.remove('*'); if(strExtension != url.fileName().right(strExtension.length())) url.setFileName(url.fileName() + strExtension ); } if((bRetVal = saveAs(url))) // something may go wrong { emit sigAddRecentURL(url); setModified(false); } } emit setStatusBarText( i18n("Ready.") ); return bRetVal; } void KXMLEditorPart::slotDocOpened() { // I temporary introduced code to measure the loading time using // the different tree view item initialization modes. // Simply open a document, remember the measured time difference, // change the mode (in the configuration dialog), load the // same document again and compare the measurements. // Olaf // // TODO: the three lines operating with the TQTime objects // can be removed later // update the view m_pViewTree->updateClear(); int i = document()->childNodes().length(); //TQTime t1 = TQTime::currentTime(); //TODO: remove this line later (Olaf) while ( i > 0 ) { i--; m_pViewTree->updateNodeCreated( document()->childNodes().item(i) ); } //TQTime t2 = TQTime::currentTime(); //TODO: remove this and the next line later (Olaf) //kdDebug() << "KXMLEditorPart::slotDocOpened() time difference: " << t1.msecsTo(t2) << " msecs" << endl; m_pActPathCombo->slotClear(); } void KXMLEditorPart::setDocument(KXEDocument *pDocument) { // detach previously used document if (m_pDocument) { disconnect (m_pDocument,0,this,0); } m_pDocument = pDocument; if (pDocument) { // open document notification connect(pDocument,TQ_SIGNAL(sigOpened()),this,TQ_SLOT(slotDocOpened())); // document modification is also dispatched connect(pDocument,TQ_SIGNAL(sigModified(bool)),this,TQ_SLOT(setModified(bool))); // update notifications connect(pDocument,TQ_SIGNAL(sigNodeChanged(const TQDomElement&)),this,TQ_SLOT(updateNodeChanged(const TQDomElement&))); connect(pDocument,TQ_SIGNAL(sigNodeChanged(const TQDomProcessingInstruction&)),this,TQ_SLOT(updateNodeChanged(const TQDomProcessingInstruction&))); connect(pDocument,TQ_SIGNAL(sigNodeChanged(const TQDomCharacterData&)),this,TQ_SLOT(updateNodeChanged(const TQDomCharacterData&))); connect(pDocument,TQ_SIGNAL(sigNodeCreated(const TQDomNode&)),this,TQ_SLOT(updateNodeCreated(const TQDomNode&))); connect(pDocument,TQ_SIGNAL(sigNodeDeleted(const TQDomNode&)),this,TQ_SLOT(updateNodeDeleted(const TQDomNode&))); connect(pDocument,TQ_SIGNAL(sigNodeMoved(const TQDomNode&)),this,TQ_SLOT(updateNodeMoved(const TQDomNode&))); // merging document action collection insertChildClient(pDocument); } } void KXMLEditorPart::slotActRedo() { m_pCmdHistory->redo(); } void KXMLEditorPart::slotActUndo() { m_pCmdHistory->undo(); } void KXMLEditorPart::slotActDetachStylesheet() { KCommand *pCmd = m_pDocument->actDetachStylesheet(); if(pCmd) m_pCmdHistory->addCommand(pCmd); } void KXMLEditorPart::slotActAttachStylesheet() { KCommand *pCmd = m_pDocument->actAttachStylesheet(); if(pCmd) m_pCmdHistory->addCommand(pCmd); } void KXMLEditorPart::slotActDetachSchema() { KCommand *pCmd = m_pDocument->actDetachSchema(); if(pCmd) m_pCmdHistory->addCommand(pCmd); } void KXMLEditorPart::slotActAttachSchema() { KCommand *pCmd = m_pDocument->actAttachSchema(); if(pCmd) m_pCmdHistory->addCommand(pCmd); } // Instert or edit special processing instruction void KXMLEditorPart::slotActVersionEncoding() { KCommand *pCmd = m_pDocument->actVersionEncoding(); if(pCmd) m_pCmdHistory->addCommand(pCmd); } void KXMLEditorPart::updateActions() { if(!m_pDocument) return; if(!m_pActAttachSchema) return; // not in read-write mode // Schema bool bSchemaExists = !m_pDocument->documentElement().isNull() && // that's a question why it works with negated condition ?????? !m_pDocument->documentElement().hasAttributeNS(SCHEMA_NAMESPACE,SCHEMA_ATTRIBUTE); m_pActAttachSchema->setEnabled(!m_pDocument->documentElement().isNull() && !bSchemaExists); m_pActDetachSchema->setEnabled(bSchemaExists); // Stylesheet m_pActDetachStylesheet->setEnabled(!m_pDocument->getSpecProcInstr("xml-stylesheet").isNull()); } #include "kxmleditorpart.moc"