|
|
/***************************************************************************
|
|
|
quantadoc.cpp - description
|
|
|
-------------------
|
|
|
begin : <20><><EFBFBD><EFBFBD> 9 13:29:57 EEST 2000
|
|
|
copyright : (C) 2000 by Dmitry Poplavsky & Alexander Yakovlev & Eric Laffoon <pdima@users.sourceforge.net,yshurik@linuxfan.com,sequitur@easystreet.com>
|
|
|
(C) 2001-2003 Andras Mantia <amantia@kde.org>
|
|
|
***************************************************************************/
|
|
|
|
|
|
/***************************************************************************
|
|
|
* *
|
|
|
* 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 files for TQt
|
|
|
#include <tqdir.h>
|
|
|
#include <tqfileinfo.h>
|
|
|
#include <tqwidget.h>
|
|
|
#include <tqtabwidget.h>
|
|
|
#include <tqtabbar.h>
|
|
|
#include <tqlayout.h>
|
|
|
#include <tqdragobject.h>
|
|
|
#include <tqobject.h>
|
|
|
|
|
|
|
|
|
// include files for KDE
|
|
|
#include <klocale.h>
|
|
|
#include <kaction.h>
|
|
|
#include <tdeconfig.h>
|
|
|
#include <kpopupmenu.h>
|
|
|
#include <kmessagebox.h>
|
|
|
#include <kdirwatch.h>
|
|
|
#include <tdeversion.h>
|
|
|
#include <kdebug.h>
|
|
|
#include <kiconloader.h>
|
|
|
|
|
|
#include <tdetexteditor/view.h>
|
|
|
#include <tdetexteditor/configinterface.h>
|
|
|
#include <tdetexteditor/highlightinginterface.h>
|
|
|
#include <tdetexteditor/popupmenuinterface.h>
|
|
|
#include <tdetexteditor/markinterface.h>
|
|
|
#include <tdetexteditor/undointerface.h>
|
|
|
#include <tdetexteditor/viewcursorinterface.h>
|
|
|
#include <tdetexteditor/clipboardinterface.h>
|
|
|
#include <tdetexteditor/selectioninterface.h>
|
|
|
#include <tdetexteditor/encodinginterface.h>
|
|
|
#include <tdetexteditor/dynwordwrapinterface.h>
|
|
|
#include <tdetexteditor/editorchooser.h>
|
|
|
#include <tdetexteditor/editinterface.h>
|
|
|
|
|
|
#include <tdeparts/componentfactory.h>
|
|
|
|
|
|
#include <klibloader.h>
|
|
|
#include <ktrader.h>
|
|
|
|
|
|
|
|
|
// application specific includes
|
|
|
#include "document.h"
|
|
|
#include "quanta.h"
|
|
|
#include "quantadoc.h"
|
|
|
#include "quantaview.h"
|
|
|
#include "viewmanager.h"
|
|
|
|
|
|
#include "quantacommon.h"
|
|
|
#include "qextfileinfo.h"
|
|
|
#include "resource.h"
|
|
|
#include "debuggermanager.h"
|
|
|
|
|
|
#include "project.h"
|
|
|
//#include "dtds.h"
|
|
|
|
|
|
#include "undoredo.h"
|
|
|
#include "tagactionmanager.h"
|
|
|
#include "tagactionset.h"
|
|
|
|
|
|
QuantaDoc::QuantaDoc(TQWidget *parent, const char *name) : TQObject(parent, name)
|
|
|
{
|
|
|
fileWatcher = new KDirWatch(this);
|
|
|
|
|
|
attribMenu = new KPopupMenu();
|
|
|
attribMenu->insertTitle(i18n("Tag"));
|
|
|
connect( attribMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotInsertAttrib(int)));
|
|
|
}
|
|
|
|
|
|
QuantaDoc::~QuantaDoc()
|
|
|
{
|
|
|
//kdDebug(24000) << "QuantaDoc::~QuantaDoc: " << endl;
|
|
|
}
|
|
|
|
|
|
|
|
|
bool QuantaDoc::newDocument( const KURL& url, bool switchToExisting )
|
|
|
{
|
|
|
bool newfile = false;
|
|
|
if ( url.url().isEmpty() ) newfile = true;
|
|
|
Document *w = 0L;
|
|
|
QuantaView *view = ViewManager::ref()->isOpened(url);
|
|
|
if (!view || newfile)
|
|
|
{
|
|
|
w = ViewManager::ref()->activeDocument();
|
|
|
if (w && !newfile && !w->isModified() && w->isUntitled() && !w->busy)
|
|
|
ViewManager::ref()->removeActiveView(false);
|
|
|
|
|
|
/*
|
|
|
// no modi and new -> we can remove !!!!
|
|
|
w = ViewManager::ref()->activeDocument();
|
|
|
if (w && !w->isModified() &&
|
|
|
w->isUntitled() && !w->busy)
|
|
|
{
|
|
|
//workaround for some strange Katepart behavior. If there is a highlighting mode
|
|
|
//selected and new content is loaded, the highlighting is reset to None. To avoid this
|
|
|
//remove the untitled document and create a new one, where we don't set the
|
|
|
//highlighting
|
|
|
ViewManager::ref()->removeActiveView(false);
|
|
|
w = ViewManager::ref()->activeDocument();
|
|
|
|
|
|
if (w && !w->isModified() && w->isUntitled() && !w->busy)
|
|
|
return true;
|
|
|
}
|
|
|
*/
|
|
|
// now we can create new kwrite
|
|
|
ViewManager::ref()->createNewDocument();
|
|
|
view = ViewManager::ref()->activeView();
|
|
|
|
|
|
if (Project::ref()->hasProject())
|
|
|
view->document()->processDTD(Project::ref()->defaultDTD());
|
|
|
else
|
|
|
view->document()->processDTD(qConfig.defaultDocType);
|
|
|
}
|
|
|
else // select opened
|
|
|
if (switchToExisting)
|
|
|
{
|
|
|
view->document()->checkDirtyStatus();
|
|
|
if (view != ViewManager::ref()->activeView())
|
|
|
{
|
|
|
view->activate();
|
|
|
view->activated();
|
|
|
}
|
|
|
return false; // don't need loadURL
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void QuantaDoc::openDocument(const KURL& urlToOpen, const TQString &a_encoding,
|
|
|
bool switchToExisting, bool readOnly)
|
|
|
{
|
|
|
bool idleTimerStatus = quantaApp->slotEnableIdleTimer(false);
|
|
|
KURL url = urlToOpen;
|
|
|
if (url.isLocalFile())
|
|
|
{
|
|
|
TQString path = TQDir(url.path()).canonicalPath();
|
|
|
if (!path.isEmpty())
|
|
|
url.setPath(path);
|
|
|
}
|
|
|
TQString encoding = a_encoding;
|
|
|
if (!newDocument(url, switchToExisting))
|
|
|
{
|
|
|
quantaApp->slotEnableIdleTimer(idleTimerStatus);
|
|
|
return;
|
|
|
}
|
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
|
if (readOnly)
|
|
|
{
|
|
|
//might work only with Kate part
|
|
|
KAction *writeLockAction = w->view()->actionCollection()->action("tools_toggle_write_lock");
|
|
|
if (writeLockAction)
|
|
|
writeLockAction->activate();
|
|
|
}
|
|
|
if (!url.isEmpty())
|
|
|
{
|
|
|
if (QExtFileInfo::exists(url, true, quantaApp))
|
|
|
{
|
|
|
if (encoding.isEmpty())
|
|
|
encoding = quantaApp->defaultEncoding();
|
|
|
w->disconnect(TQT_SIGNAL(openingFailed(const KURL&)));
|
|
|
connect(w, TQT_SIGNAL(openingFailed(const KURL&)), this, TQT_SLOT(slotOpeningFailed(const KURL&)));
|
|
|
w->disconnect(TQT_SIGNAL(openingCompleted(const KURL&)));
|
|
|
connect(w, TQT_SIGNAL(openingCompleted(const KURL&)), this, TQT_SLOT(slotOpeningCompleted(const KURL&)));
|
|
|
w->open(url, encoding);
|
|
|
quantaApp->setTitle(url.prettyURL(0, KURL::StripFileProtocol));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
slotOpeningFailed(url);
|
|
|
}
|
|
|
} else
|
|
|
{
|
|
|
quantaApp->reparse(true);
|
|
|
KTextEditor::HighlightingInterface* highlightIf = dynamic_cast<KTextEditor::HighlightingInterface*>(w->doc());
|
|
|
if (highlightIf)
|
|
|
{
|
|
|
TQString hlName;
|
|
|
int htmlIdx = -1, xmlIdx = -1;
|
|
|
for (uint i = 0; i < highlightIf->hlModeCount(); i++)
|
|
|
{
|
|
|
hlName = highlightIf->hlModeName(i);
|
|
|
if (hlName == "HTML")
|
|
|
htmlIdx = i;
|
|
|
if (hlName == "XML")
|
|
|
xmlIdx = i;
|
|
|
}
|
|
|
const DTDStruct *dtd = w->defaultDTD();
|
|
|
if (dtd->family == 1)
|
|
|
{
|
|
|
if (dtd->singleTagStyle == "xml")
|
|
|
highlightIf->setHlMode(xmlIdx);
|
|
|
else
|
|
|
highlightIf->setHlMode(htmlIdx);
|
|
|
}
|
|
|
}
|
|
|
emit newStatus();
|
|
|
}
|
|
|
quantaApp->slotEnableIdleTimer(idleTimerStatus);
|
|
|
}
|
|
|
|
|
|
void QuantaDoc::slotOpeningFailed(const KURL &url)
|
|
|
{
|
|
|
Q_UNUSED(url);
|
|
|
bool signalStatus = signalsBlocked();
|
|
|
blockSignals(false);
|
|
|
emit hideSplash();
|
|
|
//Seems to be not needed anymore since KDE 3.2, but keep until it's completely verified
|
|
|
/*
|
|
|
KMessageBox::error(quantaApp, i18n("<qt>Cannot open document <b>%1</b>.</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)));
|
|
|
*/
|
|
|
ViewManager::ref()->removeActiveView();
|
|
|
blockSignals(signalStatus);
|
|
|
}
|
|
|
|
|
|
void QuantaDoc::slotOpeningCompleted(const KURL &url)
|
|
|
{
|
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
|
Project::ref()->loadBookmarks(w->url(), dynamic_cast<KTextEditor::MarkInterface*>(w->doc()));
|
|
|
|
|
|
quantaApp->fileRecent->addURL(url);
|
|
|
quantaApp->slotRepaintPreview();
|
|
|
quantaApp->reparse(true);
|
|
|
if (url.isLocalFile())
|
|
|
quantaApp->debugger()->fileOpened(url.prettyURL(0, KURL::StripFileProtocol));
|
|
|
quantaApp->slotNewStatus();
|
|
|
quantaApp->setTitle(url.prettyURL(0, KURL::StripFileProtocol));
|
|
|
Project::ref()->loadCursorPosition(w->url(), dynamic_cast<KTextEditor::ViewCursorInterface*>(w->view()));
|
|
|
emit eventHappened("after_open", url.url(), TQString());
|
|
|
|
|
|
bool flag = TagActionManager::canIndentDTD(w->defaultDTD()->name);
|
|
|
quantaApp->actionCollection()->action("apply_source_indentation")->setEnabled(flag);
|
|
|
}
|
|
|
|
|
|
/** show popup menu with list of attributes for current tag */
|
|
|
void QuantaDoc::slotAttribPopup()
|
|
|
{
|
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
|
if (!w) return;
|
|
|
|
|
|
attribMenu->clear();
|
|
|
uint line, col;
|
|
|
w->viewCursorIf->cursorPositionReal(&line, &col);
|
|
|
|
|
|
Node *node = parser->nodeAt(line, col, false);
|
|
|
if (node && node->tag)
|
|
|
{
|
|
|
Tag *tag = node->tag;
|
|
|
TQString tagName = tag->name;
|
|
|
TQStrIList attrList = TQStrIList();
|
|
|
TQString name;
|
|
|
|
|
|
for (int i=0; i < tag->attrCount(); i++ )
|
|
|
attrList.append( tag->attribute(i).ascii() );
|
|
|
|
|
|
if ( QuantaCommon::isKnownTag(w->getDTDIdentifier(),tagName) )
|
|
|
{
|
|
|
TQString caption = i18n("Attributes of <%1>").arg(tagName);
|
|
|
attribMenu->insertTitle( caption );
|
|
|
|
|
|
AttributeList *list = QuantaCommon::tagAttributes(w->getDTDIdentifier(),tagName );
|
|
|
uint menuId = 0;
|
|
|
for ( uint i = 0; i < list->count(); i++ )
|
|
|
{
|
|
|
name = list->at(i)->name;
|
|
|
attribMenu->insertItem( name , i);//list->findIndex(*item) );
|
|
|
if (attrList.contains(name.ascii()))
|
|
|
{
|
|
|
attribMenu->setItemEnabled( i , false );
|
|
|
}
|
|
|
menuId++;
|
|
|
}
|
|
|
|
|
|
TQTag* qtag = QuantaCommon::tagFromDTD(w->getDTDIdentifier(), tagName);
|
|
|
for (TQStringList::Iterator it = qtag->commonGroups.begin(); it != qtag->commonGroups.end(); ++it)
|
|
|
{
|
|
|
TQPopupMenu* popUpMenu = new TQPopupMenu(attribMenu, (*it).latin1());
|
|
|
AttributeList *attrs = qtag->parentDTD->commonAttrs->find(*it);
|
|
|
for (uint j = 0; j < attrs->count(); j++)
|
|
|
{
|
|
|
name = attrs->at(j)->name;
|
|
|
popUpMenu->insertItem(name, ++menuId);
|
|
|
if (attrList.contains(name.ascii()))
|
|
|
{
|
|
|
popUpMenu->setItemEnabled( menuId , false );
|
|
|
}
|
|
|
}
|
|
|
connect( popUpMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotInsertAttrib(int)));
|
|
|
attribMenu->insertItem(*it, popUpMenu);
|
|
|
}
|
|
|
|
|
|
if (menuId > 0) // don't show empty menu, may be core dumped
|
|
|
{
|
|
|
attribMenu->setActiveItem( 0);
|
|
|
|
|
|
TQPoint globalPos = w->view()->mapToGlobal(w->viewCursorIf->cursorCoordinates());
|
|
|
TQFont font = w->view()->font();
|
|
|
globalPos.setY(globalPos.y() + TQFontMetrics(font).height());
|
|
|
attribMenu->exec(globalPos);
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
TQString message = i18n("Unknown tag: %1").arg(tagName);
|
|
|
quantaApp->slotStatusMsg( message );
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void QuantaDoc::slotInsertAttrib( int id )
|
|
|
{
|
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
|
if (!w) return;
|
|
|
uint line, col;
|
|
|
w->viewCursorIf->cursorPositionReal(&line, &col);
|
|
|
Node *node = parser->nodeAt(line, col);
|
|
|
if (node && node->tag)
|
|
|
{
|
|
|
Tag *tag = node->tag;
|
|
|
TQString tagName = tag->name;
|
|
|
if ( QuantaCommon::isKnownTag(w->getDTDIdentifier(), tagName) )
|
|
|
{
|
|
|
int menuId;
|
|
|
AttributeList *list = QuantaCommon::tagAttributes(w->getDTDIdentifier(), tagName);
|
|
|
menuId = list->count();
|
|
|
TQString attrStr;
|
|
|
if (id <= menuId)
|
|
|
{
|
|
|
attrStr = list->at(id)->name;
|
|
|
} else
|
|
|
{
|
|
|
TQTag* qtag = QuantaCommon::tagFromDTD(w->getDTDIdentifier(), tagName);
|
|
|
for (TQStringList::Iterator it = qtag->commonGroups.begin(); it != qtag->commonGroups.end(); ++it)
|
|
|
{
|
|
|
AttributeList *attrs = qtag->parentDTD->commonAttrs->find(*it);
|
|
|
menuId += attrs->count();
|
|
|
if (id <= menuId)
|
|
|
{
|
|
|
attrStr = attrs->at(id - (menuId - attrs->count()) -1)->name;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//now insert the new attribute into the tag
|
|
|
int el, ec;
|
|
|
tag->endPos(el, ec);
|
|
|
w->viewCursorIf->setCursorPositionReal( el, ec );
|
|
|
w->insertTag( " " + QuantaCommon::attrCase(attrStr) + "="+qConfig.attrValueQuotation, qConfig.attrValueQuotation );
|
|
|
}
|
|
|
|
|
|
delete attribMenu;
|
|
|
attribMenu = new KPopupMenu();
|
|
|
attribMenu->insertTitle(i18n("Tag"));
|
|
|
connect( attribMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotInsertAttrib(int)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#include "quantadoc.moc"
|