You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1924 lines
61 KiB
1924 lines
61 KiB
9 years ago
|
/***************************************************************************
|
||
|
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 <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());
|
||
|
}
|