diff options
author | Slávek Banko <[email protected]> | 2016-03-26 13:50:43 +0100 |
---|---|---|
committer | Slávek Banko <[email protected]> | 2016-03-26 13:50:43 +0100 |
commit | d62c8c002c51fb7c36487839eeeb4ac89f044dee (patch) | |
tree | bb4d1f5c631ab1f22a3018ba39e6a806035f80fd /part/kxmleditorpart.cpp | |
download | kxmleditor-d62c8c002c51fb7c36487839eeeb4ac89f044dee.tar.gz kxmleditor-d62c8c002c51fb7c36487839eeeb4ac89f044dee.zip |
Initial import of kxmleditor 1.1.4
Diffstat (limited to 'part/kxmleditorpart.cpp')
-rw-r--r-- | part/kxmleditorpart.cpp | 1923 |
1 files changed, 1923 insertions, 0 deletions
diff --git a/part/kxmleditorpart.cpp b/part/kxmleditorpart.cpp new file mode 100644 index 0000000..6abe508 --- /dev/null +++ b/part/kxmleditorpart.cpp @@ -0,0 +1,1923 @@ +/*************************************************************************** + kxmleditorpart.cpp - description + ------------------- + begin : Wed Sep 19 2001 + copyright : (C) 2001, 2002, 2003 by The KXMLEditor Team + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <kinstance.h> +#include <kdebug.h> +#include <klocale.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kpopupmenu.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kprinter.h> +#include <ktar.h> +#include <kzip.h> +#include <ktempfile.h> +#include <kconfig.h> +#include <kurlrequester.h> +#include <kcommand.h> +#include <ktoolbar.h> +#include <kfiledialog.h> + +#include <qregexp.h> +#include <qtextcodec.h> +#include <qstringlist.h> +#include <qsplitter.h> +#include <qtabwidget.h> +#include <qtextedit.h> +#include <qcombobox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qclipboard.h> +#include <qdragobject.h> +#include <qapplication.h> +#include <qbuffer.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qpaintdevicemetrics.h> +#include <qevent.h> + +#include "dcopiface_part_ro.h" // DCOP Iface + +#define CONFIG_MAIN_SPLITTER_SIZES "Main splitter sizes" + + +KXMLEditorPart::KXMLEditorPart( bool fReadWrite, KXEDocument* pDocument, QWidget * 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, SLOT(save()), actionCollection()); + KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection()); + } + + // edit actions + m_pActEditFind = KStdAction::find( this, SLOT(slotEditFind()), actionCollection()); + m_pActEditFindNext = KStdAction::findNext( this, SLOT(slotEditFindNext()), actionCollection()); + m_pActEditDeselect = new KAction( i18n("D&eselect Node"), CTRL+Key_E, this, + SLOT(slotEditDeselect()), actionCollection(), "deselect" ); + + // view actions + m_pActViewNodeUp = new KAction( i18n("To &Parent Node"), "up", 0, this, + SLOT(slotViewNodeUp()), actionCollection(), "treeitem_up" ); + + m_pActViewExpNode = new KToolBarPopupAction( i18n("&Expand Node"), "expand_node", CTRL+Key_Plus, this, + SLOT(slotViewExpNode()), actionCollection(), "treeitem_expand" ); + KPopupMenu * pMenuExpNode = m_pActViewExpNode->popupMenu(); + connect( pMenuExpNode, SIGNAL(activated(int)), this, SLOT(slotViewExpNode(int)) ); + for ( uint i = 1; i <= 8; i++ ) + pMenuExpNode->insertItem( i18n("Expand To Level %1").arg(i), i-1 ); + + m_pActViewColNode = new KToolBarPopupAction( i18n("&Collapse Node"), "collapse_node", CTRL+Key_Minus, this, + SLOT(slotViewColNode()), actionCollection(), "treeitem_collapse" ); + KPopupMenu * pMenuColNode = m_pActViewColNode->popupMenu(); + connect( pMenuColNode, SIGNAL(activated(int)), this, 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 KAction( i18n("&Toggle Bookmark"), "bookmark_add", CTRL+Key_B, this, + SLOT(slotBookmarksToggle()), actionCollection(), "bookmark_toggle" ); + m_pActBookmarksPrev = new KAction( i18n("&Previous Bookmark"), "bookmark_prev", SHIFT+Key_F5, this, + SLOT(slotBookmarksPrev()), actionCollection(), "bookmark_prev" ); + m_pActBookmarksNext = new KAction( i18n("&Next Bookmark"), "bookmark_next", Key_F5, this, + SLOT(slotBookmarksNext()), actionCollection(), "bookmark_next" ); + + // settings actions + new KAction( i18n("&Configure KXMLEditor..."), "configure", 0, this, + SLOT (slotConfigure()), actionCollection(), "configure" ); + + // path toolbar + m_pActPathCombo = new KXmlEditorComboAction( i18n("Path Bar"), 0, this, + SLOT(slotPathSelected(const QString &)), actionCollection(), "path_combo" ); + new KAction( i18n("Clear Path Bar"), BarIcon("locationbar_erase", 16), 0, this, + SLOT(slotPathClear()), actionCollection(), "path_clear" ); + QLabel *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, SLOT(slotEditCut()), actionCollection(), "cut" ); + KStdAction::copy( m_pBrowserExt, SLOT(slotEditCopy()), actionCollection(), "copy" ); + KStdAction::paste( m_pBrowserExt, 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 KAction( i18n("&Version && Encoding..."), 0, 0, this, SLOT(slotActVersionEncoding()), actionCollection(), "xml_ins_spec_procins" ); + m_pActAttachSchema = new KAction(i18n("Attach Schema..."),0,0,this,SLOT(slotActAttachSchema()), actionCollection(), "xml_attach_schema"); + m_pActDetachSchema = new KAction(i18n("Detach Schema"),0,0,this,SLOT(slotActDetachSchema()), actionCollection(), "xml_detach_schema"); + m_pActAttachStylesheet = new KAction(i18n("Attach Stylesheet..."),0,0,this,SLOT(slotActAttachStylesheet()), actionCollection(), "xml_attach_stylesheet"); + m_pActDetachStylesheet = new KAction(i18n("Detach Stylesheet"),0,0,this,SLOT(slotActDetachStylesheet()), actionCollection(), "xml_detach_stylesheet"); + + KStdAction::print( this, SLOT(slotActPrint()), actionCollection(), "print" ); + + m_pActAttachSchema->setEnabled(false); + m_pActDetachSchema->setEnabled(false); + m_pActDetachStylesheet->setEnabled(false); + + + // undo & redo + KStdAction::undo(this, SLOT(slotActUndo()), actionCollection()); + KStdAction::redo(this, SLOT(slotActRedo()), actionCollection()); + + m_pCmdHistory = new KCommandHistory(actionCollection()); + + m_pActEditCut = KStdAction::cut( this, SLOT(slotEditCut()), actionCollection()); + m_pActEditCopy = KStdAction::copy( this, SLOT(slotEditCopy()), actionCollection()); + m_pActEditPaste = KStdAction::paste( this, SLOT(slotEditPaste()), actionCollection()); + + // Move node Up & Down + m_pActXmlMoveNodeUp = new KAction( i18n("&Move Up"), "xml_move_item_up", CTRL+Key_U, this, SLOT(slotXmlMoveNodeUp()), actionCollection(), "xml_move_item_up" ); + m_pActXmlMoveNodeDown = new KAction( i18n("Move &Down"), "xml_move_item_down", CTRL+Key_D, this, SLOT(slotXmlMoveNodeDown()), actionCollection(), "xml_move_item_down" ); + + // Insert actions + m_pActXmlElementInsert = new KAction( i18n("&Element..."), "xml_insert_element", CTRL+SHIFT+Key_E, this, SLOT(slotXmlElementInsert()), actionCollection(), "xml_ins_element" ); + m_pActXmlAttributesAdd = new KAction( i18n("&Attribute..."), "xml_insert_attribute", CTRL+SHIFT+Key_A, this, SLOT(slotXmlAttributesAdd()), actionCollection(), "xml_add_attribute" ); + m_pActInsertText = new KAction( i18n("&Text..."), "xml_text", CTRL+SHIFT+Key_T, this, SLOT(slotActInsertText()), actionCollection(), "insert_text" ); + m_pActInsertCDATA = new KAction( i18n("C&DATA..."), "xml_cdata", CTRL+SHIFT+Key_D, this, SLOT(slotActInsertCDATA()), actionCollection(), "insert_cdata" ); + m_pActInsertComment = new KAction( i18n("&Comment..."), "xml_comment", CTRL+SHIFT+Key_C, this, SLOT(slotActInsertComment()), actionCollection(), "insert_comment" ); + m_pActXmlProcInstrInsert = new KAction( i18n("&Processing Instruction..."), "xml_insert_procins", CTRL+SHIFT+Key_P, this, SLOT(slotXmlProcInstrInsert()), actionCollection(), "xml_ins_procins" ); + + // Edit node properties + m_pActProperties = new KAction(i18n("&Properties..."),"edit",0,this,SLOT(slotActProperties()),actionCollection(),"edit_properties"); + m_pActEditRawXml = new KAction(i18n("Edit &raw XML..."), 0, 0, this, SLOT(slotActEditRawXml()),actionCollection(),"edit_as_raw_xml"); + + // delete actions + m_pActXmlAttributeDel = new KAction( i18n("&Delete"), "editdelete", 0, this, SLOT(slotXmlAttributeDel()), actionCollection(), "xml_del_attribute" ); + m_pActXmlAttributesDel = new KAction( i18n("Delete all Attributes..."), 0, 0, this, SLOT(slotXmlAttributesDel()), actionCollection(), "xml_del_attributes" ); + m_pActDelete = new KAction(i18n("&Delete"),"editdelete",0,this,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 QSplitter( pParent, "KXMLEditorPart main widget (Splitter)" ); + pSplitter->setFocusPolicy( QWidget::NoFocus ); + pSplitter->setOpaqueResize(true); + setWidget( pSplitter ); + + // create the tree view ------------------- + m_pViewTree = new KXE_TreeView( this, pSplitter, "KXMLEditorPart treeview" ); + + connect( m_pViewTree, SIGNAL(sigSelectionCleared(bool)), this, SLOT(slotSelectionCleared(bool)) ); + connect( m_pViewTree, SIGNAL(sigSelectionChanged(const QDomElement &)), this, SLOT(slotSelectionChanged(const QDomElement &)) ); + connect( m_pViewTree, SIGNAL(sigSelectionChanged(const QDomCharacterData &)), this, SLOT(slotSelectionChanged(const QDomCharacterData &)) ); + connect( m_pViewTree, SIGNAL(sigSelectionChanged(const QDomProcessingInstruction &)), this, SLOT(slotSelectionChanged(const QDomProcessingInstruction &)) ); + connect( m_pViewTree, SIGNAL(sigContextMenuRequested(const QString&,const QPoint&)), this, SLOT(slotContextMenuRequested(const QString&,const QPoint&)) ); + connect( m_pViewTree, SIGNAL(itemRenamed(QListViewItem *)), this, SLOT(slotItemRenamedInplace(QListViewItem *)) ); + connect( m_pViewTree, SIGNAL(sigKeyPressed(QKeyEvent* )),this,SLOT(slotTreeViewKeyPressed(QKeyEvent*))); + + // create tab widget ---------------------- + m_pTabWidget = new QTabWidget( pSplitter, "KXMLEditorPart tabwidget"); + m_pTabWidget->setFocusPolicy( QWidget::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, SIGNAL(sigContextMenuRequested(const QString&,const QPoint&)), this, SLOT(slotContextMenuRequested(const QString&,const QPoint&)) ); + connect( m_pViewElement, SIGNAL(sigAttributeNameChangedInplace(const QDomAttr&, const QString)), this, SLOT(slotAttributeNameChangedInplace(const QDomAttr&, const QString)) ); + connect( m_pViewElement, SIGNAL(sigAttributeValueChangedInplace(const QDomAttr&, const QString)), this, SLOT(slotAttributeValueChangedInplace(const QDomAttr&, const QString)) ); + + // create edit widget, that display XML character data contents + m_pViewContents = new QTextEdit( m_pTabWidget, "KXMLEditorPart contents view" ); + m_pTabWidget->addTab( m_pViewContents, g_iconText, i18n("Contents") ); + m_pViewContents->setReadOnly( true ); + m_pViewContents->setWordWrap( QTextEdit::NoWrap ); + m_pViewContents->setTextFormat(QTextEdit::PlainText); + + // create proc.instr. view + m_pViewProcInstr = new QTextEdit( m_pTabWidget, "KXMLEditorPart proc.instr. view" ); + m_pTabWidget->addTab( m_pViewProcInstr, g_iconProcessingInstruction, i18n("Proc.Instruction") ); + m_pViewProcInstr->setReadOnly( true ); + m_pViewProcInstr->setWordWrap( QTextEdit::NoWrap ); + + connect( this, SIGNAL(started(KIO::Job*)), this, SLOT(started()) ); + connect( this, SIGNAL(completed()), this, SLOT(completed()) ); + connect( this, SIGNAL(canceled(const QString &)), this, 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 + QValueList<int> 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 + KConfig *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; + + QString szNewCaption = m_url.prettyURL(); + emit setWindowCaption( szNewCaption ); + } + + // get a handle on our Save action and make sure it is valid + KAction *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() +{ + QDomNode* 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() +{ + QDomNode* 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 + QDomAttr domAttr = m_pViewElement->getSelectedAttribute(); + if (!domAttr.isNull()) + { + QDomElement domElement = pNode->toElement(); + QDomAttr 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; + } + + QDomNode * 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; + + QDomNode * pNode = m_pViewTree->getSelectedNode(); + + if(pNode) + { + QTextDrag *pDrag = copyNode(m_pViewTree->getSelectedNode()); + if(pDrag) + QApplication::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, QApplication::clipboard()->data()); + } + else + { + pasteNode(m_pViewTree->getSelectedNode(), QApplication::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) + QDomNode 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 ) == QDialog::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 + QDomNode * pParentNode = m_pViewTree->getSelectedNode(); + + if ( (pParentNode) && (pParentNode->isElement()) ) + { + QDomElement domParentElement = pParentNode->toElement(); + + if ( dlg.exec( false, false, false ) == QDialog::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; + } + + QDomNode * 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...") ); + + QDomElement 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() ) == QDialog::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; + } + + QDomNode * 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...") ); + + QDomElement domElement = pNode->toElement(); + + QString strXML; + + QTextStream 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() == QDialog::Accepted) && (strXML != dlg.editorText())) + { + QString strXML = "<root>" + dlg.editorText() + "</root>"; + + // create XML documemt from text + QString strErrorMsg; + int iErrorLine, iErrorColumn; + QDomDocument 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; + } + + QDomElement 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; + } + + QDomNode * 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" ); + + QDomElement domOwnerElement = pNode->toElement(); + if ( dlg.exec( ) == QDialog::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; + } + + QDomNode * 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...") ); + + QDomElement 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; + } + + QDomNode * 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...") ); + + QDomElement domElement = pNode->toElement(); + QDomAttr 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" ); + + QDomNode * 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 ) == QDialog::Accepted ) + { + KCommand *pCmd = new KXEProcInstrCommand(document(), document(), dlg.atTop(), dlg.target(), dlg.data()); + m_pCmdHistory->addCommand(pCmd); + } + } + else + { + if ( dlg.exec( false, false ) == QDialog::Accepted ) + { + QDomElement 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; + } + + QDomNode * 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...") ); + + QDomProcessingInstruction 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 ) == QDialog::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; + } + + QDomNode * 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")); + + QDomElement domParentElement = pNode->toElement(); + + if ( dlg.exec( false ) == QDialog::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; + } + + QDomNode * 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")); + + QDomElement domParentElement = pNode->toElement(); + + if ( dlg.exec( false ) == QDialog::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; + } + + QDomNode * 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")); + + QDomElement domParentElement = pNode->toElement(); + + if ( dlg.exec( false ) == QDialog::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; + } + + QDomNode * 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...") ); + + QDomCharacterData 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 ) == QDialog::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; + } + + QDomNode * 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; + } + + QDomNode * 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 QString & strPath ) +{ + QDomNode 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( QListViewItem * pItem ) +{ + KXE_TreeViewItem * pXMLItem = static_cast <KXE_TreeViewItem*> (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; + } + + QDomElement 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 + QString 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, QString::null, pItem->text(0)); + m_pCmdHistory->addCommand(pCmd); + } + else + { + // otherwise split up the entered text by the first colon and + QString strPrefix(pItem->text(0).left(nPosColon)); + QString strName(pItem->text(0).right( pItem->text(0).length() - nPosColon - 1 )); + + // check name + QString 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 QDomAttr & domAttr, const QString 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 QDomAttr & domAttr, const QString 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 */ +QTextDrag * KXMLEditorPart::copyNode(QDomNode * pNode) +{ + QTextDrag *pDrag = 0; + QString strXML; + + QTextStream streamXML(&strXML, IO_WriteOnly); + int iIndent = KXMLEditorFactory::configuration()->textview()->indentSteps(); + pNode->save(streamXML, iIndent); + pDrag = new QTextDrag(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(QDomNode * pTargetNode, QMimeSource *data) +{ + QString strText; + + // Drop XML Processing Instruction + if(QTextDrag::decode(data, strText)) + { if(strText.find("<?xml ") == 0) + { + KMessageBox::sorry(0, i18n("This processing instruction cannot be pasted here !")); + return false; + } + + //--- + + QString strXML = "<root>" + strText + "</root>"; + + // Paste clipboard contents as XML element + QString strErrorMsg; + int iErrorLine, iErrorColumn; + QDomDocument 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 + QDomElement newNode = doc.documentElement().firstChild().cloneNode(true).toElement(); + + KCommand *pCmd = new KXEPasteToDocumentCommand(document(), document(), newNode); + m_pCmdHistory->addCommand(pCmd); + } + else + { QDomNode 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()) + { + QDomElement domSourceElement = sourceNode.toElement(); + + QDomNamedNodeMap list = domSourceElement.attributes(); + unsigned int iLength = list.length(); + + + for ( unsigned int iRow = 0; iRow < iLength; iRow++ ) + { + QDomAttr a = list.item(iRow).toAttr(); + + QDomElement domOwnerElement = a.ownerElement(); + if(domOwnerElement.isNull()) + KMessageBox::sorry(m_pViewTree, i18n("Cloned owner is null !")); + }*/ + //--- + + if(pTargetNode->isElement()) + { + QDomElement 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 + QDomProcessingInstruction domTargetProcInstr = pTargetNode->toProcessingInstruction(); + QDomProcessingInstruction 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 + QDomCharacterData domTargetCharData = pTargetNode->toCharacterData(); + QDomCharacterData 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(QDomElement & domTargetElement, QDomNode & 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 Qt, you always "print" to a + // QPainter.. whether the output medium is a pixmap, a screen, or paper + QPainter p; + QPainter *painter = &p; + QFont font( KXMLEditorFactory::configuration()->print()->fontFamily(), + KXMLEditorFactory::configuration()->print()->fontSize() ); + + QPaintDeviceMetrics metrics((QPrinter*)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(QPainter* 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(QPainter* 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 = QStringList::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(QPainter* 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(QKeyEvent *e) +{ + // few keypresses are recognized and proper actions + // are executed. + switch (e->key()) + { + case Qt::Key_Delete : slotActDelete(); break; + case Qt::Key_Return : + case Qt::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 QDomElement & 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 QDomCharacterData & 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 QDomProcessingInstruction & 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 QString & szMenuName, const QPoint & pos ) +{ + QWidget * 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("KPopupMenu") ) + { + kdError() << "KXMLEditor " << k_funcinfo << " Wrong container widget" << endl; + return; + } + + KPopupMenu * pMenu = static_cast <KPopupMenu*> (pContainer); + pMenu->popup( pos ); +} + + +///////////////////////////////////////////////////////////////////// +// FUNCTIONS CALLED FROM KXECommand CHILD CLASSES +///////////////////////////////////////////////////////////////////// + +void KXMLEditorPart::updateNodeCreated(const QDomNode & node) +{ + m_pViewTree->updateNodeCreated(node); +} + +void KXMLEditorPart::updateNodeDeleted( const QDomNode & 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 QDomElement & domElement ) +{ + m_pViewTree->updateNodeChanged(domElement); + m_pViewElement->slotChange(domElement); +} + +void KXMLEditorPart::updateNodeChanged( const QDomCharacterData & domCharData ) +{ + m_pViewTree->updateNodeChanged(domCharData); + m_pViewContents->setText( domCharData.data() ); +} + +void KXMLEditorPart::updateNodeChanged( const QDomProcessingInstruction &domProcInstr ) +{ + m_pViewTree->updateNodeChanged(domProcInstr); + m_pViewProcInstr->setText( domProcInstr.data() ); +} + +void KXMLEditorPart::updateNodeMoved( const QDomNode & domNode ) +{ + m_pViewTree->updateNodeMoved(domNode); +} + + +bool KXMLEditorPart::slotFileSaveAs() +{ + emit setStatusBarText( i18n("Saving file with a new filename...") ); + + KFileDialog dlg( QDir::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() != "*.*") + { QString 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 QTime objects +// can be removed later + + // update the view + m_pViewTree->updateClear(); + int i = document()->childNodes().length(); + //QTime t1 = QTime::currentTime(); //TODO: remove this line later (Olaf) + while ( i > 0 ) + { + i--; + m_pViewTree->updateNodeCreated( document()->childNodes().item(i) ); + } + + //QTime t2 = QTime::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,SIGNAL(sigOpened()),this,SLOT(slotDocOpened())); + // document modification is also dispatched + connect(pDocument,SIGNAL(sigModified(bool)),this,SLOT(setModified(bool))); + // update notifications + connect(pDocument,SIGNAL(sigNodeChanged(const QDomElement&)),this,SLOT(updateNodeChanged(const QDomElement&))); + connect(pDocument,SIGNAL(sigNodeChanged(const QDomProcessingInstruction&)),this,SLOT(updateNodeChanged(const QDomProcessingInstruction&))); + connect(pDocument,SIGNAL(sigNodeChanged(const QDomCharacterData&)),this,SLOT(updateNodeChanged(const QDomCharacterData&))); + connect(pDocument,SIGNAL(sigNodeCreated(const QDomNode&)),this,SLOT(updateNodeCreated(const QDomNode&))); + connect(pDocument,SIGNAL(sigNodeDeleted(const QDomNode&)),this,SLOT(updateNodeDeleted(const QDomNode&))); + connect(pDocument,SIGNAL(sigNodeMoved(const QDomNode&)),this,SLOT(updateNodeMoved(const QDomNode&))); + // 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 <?xml ... ?> +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()); +} |