|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2002 Roberto Raggi *
|
|
|
|
* roberto@kdevelop.org *
|
|
|
|
* Copyright (C) 2002 by Bernd Gehrmann *
|
|
|
|
* bernd@kdevelop.org *
|
|
|
|
* Copyright (C) 2003 by Alexander Dymo *
|
|
|
|
* cloudtemple@mksat.net *
|
|
|
|
* *
|
|
|
|
* 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 "abbrevpart.h"
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqvbox.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdeparts/part.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <tdevgenericfactory.h>
|
|
|
|
#include <tdeaction.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <tdeio/netaccess.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <tdevplugininfo.h>
|
|
|
|
|
|
|
|
#include <tdetexteditor/document.h>
|
|
|
|
#include <tdetexteditor/editinterface.h>
|
|
|
|
#include <tdetexteditor/viewcursorinterface.h>
|
|
|
|
#include <tdetexteditor/codecompletioninterface.h>
|
|
|
|
|
|
|
|
#include "tdevcore.h"
|
|
|
|
#include "tdevpartcontroller.h"
|
|
|
|
#include "abbrevconfigwidget.h"
|
|
|
|
#include "tdeveditorutil.h"
|
|
|
|
|
|
|
|
static const TDevPluginInfo data("tdevabbrev");
|
|
|
|
|
|
|
|
class AbbrevFactory : public TDevGenericFactory<AbbrevPart>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AbbrevFactory()
|
|
|
|
: TDevGenericFactory<AbbrevPart>( data )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual TDEInstance *createInstance()
|
|
|
|
{
|
|
|
|
TDEInstance *instance = TDevGenericFactory<AbbrevPart>::createInstance();
|
|
|
|
TDEStandardDirs *dirs = instance->dirs();
|
|
|
|
dirs->addResourceType( "codetemplates",
|
|
|
|
TDEStandardDirs::kde_default( "data" ) + "tdevabbrev/templates/" );
|
|
|
|
dirs->addResourceType( "sources",
|
|
|
|
TDEStandardDirs::kde_default( "data" ) + "tdevabbrev/sources" );
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
K_EXPORT_COMPONENT_FACTORY( libtdevabbrev, AbbrevFactory )
|
|
|
|
|
|
|
|
AbbrevPart::AbbrevPart(TQObject *parent, const char *name, const TQStringList &)
|
|
|
|
: TDevPlugin(&data, parent, name ? name : "AbbrevPart")
|
|
|
|
{
|
|
|
|
setInstance(AbbrevFactory::instance());
|
|
|
|
setXMLFile("tdevabbrev.rc");
|
|
|
|
|
|
|
|
connect(partController(), TQT_SIGNAL(activePartChanged(KParts::Part*)),
|
|
|
|
this, TQT_SLOT(slotActivePartChanged(KParts::Part*)) );
|
|
|
|
|
|
|
|
connect(core(), TQT_SIGNAL(configWidget(KDialogBase*)), this, TQT_SLOT(configWidget(KDialogBase*)));
|
|
|
|
|
|
|
|
TDEAction *action;
|
|
|
|
action = new TDEAction( i18n("Expand Text"), CTRL + Key_J,
|
|
|
|
this, TQT_SLOT(slotExpandText()),
|
|
|
|
actionCollection(), "edit_expandtext" );
|
|
|
|
action->setToolTip( i18n("Expand current word") );
|
|
|
|
action->setWhatsThis( i18n("<b>Expand current word</b><p>Current word can be completed using the list of similar words in source files.") );
|
|
|
|
|
|
|
|
action = new TDEAction( i18n("Expand Abbreviation"), CTRL + Key_L,
|
|
|
|
this, TQT_SLOT(slotExpandAbbrev()),
|
|
|
|
actionCollection(), "edit_expandabbrev" );
|
|
|
|
action->setToolTip( i18n("Expand abbreviation") );
|
|
|
|
action->setWhatsThis( i18n("<b>Expand abbreviation</b><p>Enable and configure abbreviations in <b>TDevelop Settings</b>, <b>Abbreviations</b> tab.") );
|
|
|
|
|
|
|
|
load();
|
|
|
|
|
|
|
|
m_inCompletion = false;
|
|
|
|
docIface = 0;
|
|
|
|
editIface = 0;
|
|
|
|
viewCursorIface = 0;
|
|
|
|
completionIface = 0;
|
|
|
|
|
|
|
|
m_prevLine = -1;
|
|
|
|
m_prevColumn = -1;
|
|
|
|
m_sequenceLength = 0;
|
|
|
|
|
|
|
|
TDEConfig* config = AbbrevFactory::instance()->config();
|
|
|
|
TDEConfigGroupSaver group( config, "General" );
|
|
|
|
m_autoWordCompletionEnabled = config->readBoolEntry( "AutoWordCompletion", false );
|
|
|
|
|
|
|
|
updateActions();
|
|
|
|
|
|
|
|
slotActivePartChanged( partController()->activePart() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AbbrevPart::~AbbrevPart()
|
|
|
|
{
|
|
|
|
save();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AbbrevPart::autoWordCompletionEnabled() const
|
|
|
|
{
|
|
|
|
return m_autoWordCompletionEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::setAutoWordCompletionEnabled( bool enabled )
|
|
|
|
{
|
|
|
|
if( enabled == m_autoWordCompletionEnabled )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TDEConfig* config = AbbrevFactory::instance()->config();
|
|
|
|
TDEConfigGroupSaver group( config, "General" );
|
|
|
|
|
|
|
|
m_autoWordCompletionEnabled = enabled;
|
|
|
|
config->writeEntry( "AutoWordCompletion", m_autoWordCompletionEnabled );
|
|
|
|
config->sync();
|
|
|
|
|
|
|
|
if( !docIface || !docIface->widget() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
disconnect( docIface, 0, this, 0 );
|
|
|
|
disconnect( docIface->widget(), 0, this, 0 );
|
|
|
|
|
|
|
|
if( m_autoWordCompletionEnabled ){
|
|
|
|
connect( docIface->widget(), TQT_SIGNAL(completionAborted()),
|
|
|
|
this, TQT_SLOT(slotCompletionAborted()) );
|
|
|
|
connect( docIface->widget(), TQT_SIGNAL(completionDone()),
|
|
|
|
this, TQT_SLOT(slotCompletionDone()) );
|
|
|
|
connect( docIface->widget(), TQT_SIGNAL(aboutToShowCompletionBox()),
|
|
|
|
this, TQT_SLOT(slotAboutToShowCompletionBox()) );
|
|
|
|
|
|
|
|
connect( docIface, TQT_SIGNAL(textChanged()), this, TQT_SLOT(slotTextChanged()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void AbbrevPart::load()
|
|
|
|
{
|
|
|
|
TDEStandardDirs *dirs = AbbrevFactory::instance()->dirs();
|
|
|
|
TQString localTemplatesFile = locateLocal("codetemplates", "templates", AbbrevFactory::instance());
|
|
|
|
TQStringList files;
|
|
|
|
if (TQFileInfo(localTemplatesFile).exists())
|
|
|
|
files << localTemplatesFile;
|
|
|
|
else
|
|
|
|
files = dirs->findAllResources("codetemplates", TQString(), false, true);
|
|
|
|
|
|
|
|
TQString localSourcesFile = locateLocal("sources", "sources", AbbrevFactory::instance());
|
|
|
|
TQStringList sourceFiles;
|
|
|
|
if (TQFileInfo(localSourcesFile).exists())
|
|
|
|
sourceFiles << localSourcesFile;
|
|
|
|
else
|
|
|
|
sourceFiles = dirs->findAllResources("sources", TQString(), false, true);
|
|
|
|
kdDebug(9028) << "=========> sourceFiles: " << sourceFiles.join(" ") << endl;
|
|
|
|
|
|
|
|
this->m_completionFile = TQString();
|
|
|
|
for( TQStringList::Iterator it=sourceFiles.begin(); it!=sourceFiles.end(); ++it ) {
|
|
|
|
TQString fn = *it;
|
|
|
|
kdDebug(9028) << "===> load file: " << fn << endl;
|
|
|
|
TQFile f( fn );
|
|
|
|
if ( f.open(IO_ReadOnly) ) {
|
|
|
|
TQTextStream stream( &f );
|
|
|
|
m_completionFile += ( stream.read() + TQString("\n") );
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList::ConstIterator it;
|
|
|
|
for (it = files.begin(); it != files.end(); ++it) {
|
|
|
|
TQString fn = *it;
|
|
|
|
kdDebug(9028) << "fn = " << fn << endl;
|
|
|
|
TQFile f( fn );
|
|
|
|
if ( f.open(IO_ReadOnly) ) {
|
|
|
|
TQDomDocument doc;
|
|
|
|
doc.setContent( &f );
|
|
|
|
TQDomElement root = doc.firstChild().toElement();
|
|
|
|
TQDomElement e = root.firstChild().toElement();
|
|
|
|
while ( !e.isNull() ){
|
|
|
|
addTemplate( e.attribute("name"),
|
|
|
|
e.attribute("description"),
|
|
|
|
e.attribute("suffixes"),
|
|
|
|
e.attribute("code") );
|
|
|
|
e = e.nextSibling().toElement();
|
|
|
|
}
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::save()
|
|
|
|
{
|
|
|
|
TQString fn = AbbrevFactory::instance()->dirs()->saveLocation("codetemplates", "", true);
|
|
|
|
kdDebug(9028) << "fn = " << fn << endl;
|
|
|
|
|
|
|
|
TQDomDocument doc( "Templates" );
|
|
|
|
TQDomElement root = doc.createElement( "Templates" );
|
|
|
|
doc.appendChild( root );
|
|
|
|
|
|
|
|
TQPtrList<CodeTemplate> templates = m_templates.allTemplates();
|
|
|
|
CodeTemplate *templ;
|
|
|
|
for (templ = templates.first(); templ; templ = templates.next())
|
|
|
|
{
|
|
|
|
TQDomElement e = doc.createElement( "Template" );
|
|
|
|
e.setAttribute( "name", templ->name );
|
|
|
|
e.setAttribute( "description", templ->description );
|
|
|
|
e.setAttribute( "suffixes", templ->suffixes );
|
|
|
|
e.setAttribute( "code", templ->code );
|
|
|
|
root.appendChild( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile f( fn + "templates" );
|
|
|
|
if( f.open(IO_WriteOnly) ){
|
|
|
|
TQTextStream stream( &f );
|
|
|
|
stream << doc.toString();
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString AbbrevPart::currentWord() const
|
|
|
|
{
|
|
|
|
return TDevEditorUtil::currentWord( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::configWidget(KDialogBase *dlg)
|
|
|
|
{
|
|
|
|
TQVBox *vbox = dlg->addVBoxPage(i18n("Abbreviations"), i18n("Abbreviations"), BarIcon( info()->icon(), TDEIcon::SizeMedium) );
|
|
|
|
AbbrevConfigWidget *w = new AbbrevConfigWidget(this, vbox, "abbrev config widget");
|
|
|
|
connect(dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::slotExpandText()
|
|
|
|
{
|
|
|
|
if( !editIface || !completionIface || !viewCursorIface )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQString word = currentWord();
|
|
|
|
if (word.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQValueList<KTextEditor::CompletionEntry> entries = findAllWords(editIface->text(), word);
|
|
|
|
if (entries.count() == 0) {
|
|
|
|
; // some statusbar message?
|
|
|
|
// } else if (entries.count() == 1) {
|
|
|
|
// uint line, col;
|
|
|
|
// viewCursorIface->cursorPositionReal(&line, &col);
|
|
|
|
// TQString txt = entries[0].text.mid(word.length());
|
|
|
|
// editIface->insertText( line, col, txt );
|
|
|
|
// viewCursorIface->setCursorPositionReal( line, col + txt.length() );
|
|
|
|
} else {
|
|
|
|
m_inCompletion = true;
|
|
|
|
completionIface->showCompletionBox(entries, word.length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQValueList<KTextEditor::CompletionEntry> AbbrevPart::findAllWords(const TQString &text, const TQString &prefix)
|
|
|
|
{
|
|
|
|
TQValueList<KTextEditor::CompletionEntry> entries;
|
|
|
|
|
|
|
|
KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
|
|
|
|
TQWidget *view = partController()->activeWidget();
|
|
|
|
if (!part || !view) {
|
|
|
|
kdDebug(9028) << "no rw part" << endl;
|
|
|
|
return entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString suffix = part->url().url();
|
|
|
|
int pos = suffix.findRev('.');
|
|
|
|
if (pos != -1)
|
|
|
|
suffix.remove(0, pos+1);
|
|
|
|
kdDebug(9028) << "AbbrevPart::findAllWords with suffix " << suffix << endl;
|
|
|
|
|
|
|
|
TQMap<TQString, bool> map;
|
|
|
|
TQRegExp rx( TQString("\\b") + prefix + "[a-zA-Z0-9_]+\\b" );
|
|
|
|
|
|
|
|
int idx = 0;
|
|
|
|
pos = 0;
|
|
|
|
int len = 0;
|
|
|
|
while ( (pos = rx.search(text, idx)) != -1 ) {
|
|
|
|
len = rx.matchedLength();
|
|
|
|
TQString word = text.mid(pos, len);
|
|
|
|
if (map.find(word) == map.end()) {
|
|
|
|
KTextEditor::CompletionEntry e;
|
|
|
|
e.text = word;
|
|
|
|
entries << e;
|
|
|
|
map[ word ] = TRUE;
|
|
|
|
}
|
|
|
|
idx = pos + len + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
idx = 0;
|
|
|
|
pos = 0;
|
|
|
|
len = 0;
|
|
|
|
while ( (pos = rx.search(m_completionFile, idx)) != -1 ) {
|
|
|
|
len = rx.matchedLength();
|
|
|
|
TQString word = m_completionFile.mid(pos, len);
|
|
|
|
if (map.find(word) == map.end()) {
|
|
|
|
KTextEditor::CompletionEntry e;
|
|
|
|
e.text = word;
|
|
|
|
entries << e;
|
|
|
|
map[ word ] = TRUE;
|
|
|
|
}
|
|
|
|
idx = pos + len + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQMap<TQString, CodeTemplate*> m = m_templates[suffix];
|
|
|
|
for (TQMap<TQString, CodeTemplate*>::const_iterator it = m.begin(); it != m.end() ; ++it) {
|
|
|
|
KTextEditor::CompletionEntry e;
|
|
|
|
e.text = it.data()->description + " <abbrev>";
|
|
|
|
e.userdata = it.key();
|
|
|
|
entries << e;
|
|
|
|
}
|
|
|
|
|
|
|
|
return entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::slotExpandAbbrev()
|
|
|
|
{
|
|
|
|
KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
|
|
|
|
TQWidget *view = partController()->activeWidget();
|
|
|
|
if (!part || !view) {
|
|
|
|
kdDebug(9028) << "no rw part" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString suffix = part->url().url();
|
|
|
|
int pos = suffix.findRev('.');
|
|
|
|
if (pos != -1)
|
|
|
|
suffix.remove(0, pos+1);
|
|
|
|
|
|
|
|
KTextEditor::EditInterface *editiface
|
|
|
|
= dynamic_cast<KTextEditor::EditInterface*>(part);
|
|
|
|
if (!editiface) {
|
|
|
|
kdDebug(9028) << "no editiface" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
KTextEditor::ViewCursorInterface *cursoriface
|
|
|
|
= dynamic_cast<KTextEditor::ViewCursorInterface*>(view);
|
|
|
|
if (!cursoriface) {
|
|
|
|
kdDebug(9028) << "no viewcursoriface" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString word = currentWord();
|
|
|
|
kdDebug(9028) << "Expanding word " << word << " with suffix " << suffix << "." << endl;
|
|
|
|
|
|
|
|
TQMap<TQString, CodeTemplate*> m = m_templates[suffix];
|
|
|
|
for (TQMap<TQString, CodeTemplate*>::const_iterator it = m.begin(); it != m.end() ; ++it) {
|
|
|
|
if (it.key() != word)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
uint line, col;
|
|
|
|
cursoriface->cursorPositionReal(&line, &col);
|
|
|
|
|
|
|
|
TQString linestr = editIface->textLine(line);
|
|
|
|
int startPos = TQMAX( TQMIN( (int)col, (int)linestr.length()-1 ), 0 );
|
|
|
|
int endPos = startPos;
|
|
|
|
startPos--;
|
|
|
|
while (startPos >= 0 && ( linestr[startPos].isLetterOrNumber() || linestr[startPos] == '_' || linestr[startPos] == '~') )
|
|
|
|
startPos--;
|
|
|
|
while (endPos < (int)linestr.length() && ( linestr[endPos].isLetterOrNumber() || linestr[endPos] == '_' ) )
|
|
|
|
endPos++;
|
|
|
|
|
|
|
|
editiface->removeText( line, startPos+1, line, endPos );
|
|
|
|
insertChars(it.data()->code );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::insertChars( const TQString &chars )
|
|
|
|
{
|
|
|
|
unsigned line=0, col=0;
|
|
|
|
viewCursorIface->cursorPositionReal( &line, &col );
|
|
|
|
|
|
|
|
unsigned int currentLine=line, currentCol=col;
|
|
|
|
|
|
|
|
TQString spaces;
|
|
|
|
TQString s = editIface->textLine( currentLine );
|
|
|
|
uint i=0;
|
|
|
|
while( i<s.length() && s[ i ].isSpace() ){
|
|
|
|
spaces += s[ i ];
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool foundPipe = false;
|
|
|
|
TQString str;
|
|
|
|
TQTextStream stream( &str, IO_WriteOnly );
|
|
|
|
TQStringList lines = TQStringList::split( "\n", chars );
|
|
|
|
TQStringList::Iterator it = lines.begin();
|
|
|
|
line = currentLine;
|
|
|
|
while( it != lines.end() ){
|
|
|
|
TQString lineText = *it;
|
|
|
|
if( it != lines.begin() ){
|
|
|
|
stream << spaces;
|
|
|
|
if( !foundPipe )
|
|
|
|
currentCol += spaces.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
int idx = lineText.find( '|' );
|
|
|
|
if( idx != -1 ){
|
|
|
|
stream << lineText.left( idx ) << lineText.mid( idx+1 );
|
|
|
|
if( !foundPipe ){
|
|
|
|
foundPipe = true;
|
|
|
|
currentCol += lineText.left( idx ).length();
|
|
|
|
kdDebug(9007) << "found pipe at " << currentLine << ", " << currentCol << endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stream << lineText;
|
|
|
|
}
|
|
|
|
|
|
|
|
++it;
|
|
|
|
|
|
|
|
if( it != lines.end() ){
|
|
|
|
stream << "\n";
|
|
|
|
if( !foundPipe ){
|
|
|
|
++currentLine;
|
|
|
|
currentCol = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
editIface->insertText( line, col, str );
|
|
|
|
kdDebug(9007) << "go to " << currentLine << ", " << currentCol << endl;
|
|
|
|
viewCursorIface->setCursorPositionReal( currentLine, currentCol );
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::addTemplate( const TQString& templ,
|
|
|
|
const TQString& descr,
|
|
|
|
const TQString& suffixes,
|
|
|
|
const TQString& code)
|
|
|
|
{
|
|
|
|
m_templates.insert(templ, descr, code, suffixes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::removeTemplate( const TQString &suffixes, const TQString &name )
|
|
|
|
{
|
|
|
|
m_templates.remove( suffixes, name );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AbbrevPart::clearTemplates()
|
|
|
|
{
|
|
|
|
m_templates.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeTemplateList AbbrevPart::templates() const
|
|
|
|
{
|
|
|
|
return m_templates;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotActivePartChanged( KParts::Part* part )
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotActivePartChanged()" << endl;
|
|
|
|
KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>( part );
|
|
|
|
|
|
|
|
if( !doc || !part->widget() || doc == docIface )
|
|
|
|
{
|
|
|
|
actionCollection()->action( "edit_expandtext" )->setEnabled( false );
|
|
|
|
actionCollection()->action( "edit_expandabbrev" )->setEnabled( false );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
docIface = doc;
|
|
|
|
|
|
|
|
if( !docIface ){
|
|
|
|
docIface = 0;
|
|
|
|
editIface = 0;
|
|
|
|
viewCursorIface = 0;
|
|
|
|
completionIface = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
editIface = dynamic_cast<KTextEditor::EditInterface*>( part );
|
|
|
|
viewCursorIface = dynamic_cast<KTextEditor::ViewCursorInterface*>( part->widget() );
|
|
|
|
completionIface = dynamic_cast<KTextEditor::CodeCompletionInterface*>( part->widget() );
|
|
|
|
|
|
|
|
updateActions();
|
|
|
|
|
|
|
|
if( !editIface || !viewCursorIface || !completionIface )
|
|
|
|
return;
|
|
|
|
|
|
|
|
disconnect( part->widget(), 0, this, 0 );
|
|
|
|
disconnect( doc, 0, this, 0 );
|
|
|
|
|
|
|
|
connect( part->widget(), TQT_SIGNAL(filterInsertString(KTextEditor::CompletionEntry*, TQString*)),
|
|
|
|
this, TQT_SLOT(slotFilterInsertString(KTextEditor::CompletionEntry*, TQString*)) );
|
|
|
|
|
|
|
|
if( autoWordCompletionEnabled() ){
|
|
|
|
connect( part->widget(), TQT_SIGNAL(completionAborted()), this, TQT_SLOT(slotCompletionAborted()) );
|
|
|
|
connect( part->widget(), TQT_SIGNAL(completionDone()), this, TQT_SLOT(slotCompletionDone()) );
|
|
|
|
connect( part->widget(), TQT_SIGNAL(aboutToShowCompletionBox()), this, TQT_SLOT(slotAboutToShowCompletionBox()) );
|
|
|
|
connect( doc, TQT_SIGNAL(textChanged()), this, TQT_SLOT(slotTextChanged()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_prevLine = -1;
|
|
|
|
m_prevColumn = -1;
|
|
|
|
m_sequenceLength = 0;
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotActivePartChanged() -- OK" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotTextChanged()
|
|
|
|
{
|
|
|
|
if( m_inCompletion )
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned int line, col;
|
|
|
|
viewCursorIface->cursorPositionReal( &line, &col );
|
|
|
|
|
|
|
|
if( m_prevLine != int(line) || m_prevColumn+1 != int(col) || col == 0 ){
|
|
|
|
m_prevLine = line;
|
|
|
|
m_prevColumn = col;
|
|
|
|
m_sequenceLength = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString textLine = editIface->textLine( line );
|
|
|
|
TQChar ch = textLine[ col-1 ];
|
|
|
|
TQChar currentChar = textLine[ col ];
|
|
|
|
|
|
|
|
if( currentChar.isLetterOrNumber() || currentChar == TQChar('_') || !(ch.isLetterOrNumber() || ch == TQChar('_')) ){
|
|
|
|
// reset
|
|
|
|
m_prevLine = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_sequenceLength >= 3 )
|
|
|
|
slotExpandText();
|
|
|
|
|
|
|
|
++m_sequenceLength;
|
|
|
|
m_prevLine = line;
|
|
|
|
m_prevColumn = col;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotFilterInsertString( KTextEditor::CompletionEntry* entry, TQString* text )
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotFilterInsertString()" << endl;
|
|
|
|
KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
|
|
|
|
TQWidget *view = partController()->activeWidget();
|
|
|
|
if (!part || !view) {
|
|
|
|
kdDebug(9028) << "no rw part" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString suffix = part->url().url();
|
|
|
|
int pos = suffix.findRev('.');
|
|
|
|
if (pos != -1)
|
|
|
|
suffix.remove(0, pos+1);
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotFilterInsertString with suffix " << suffix << endl;
|
|
|
|
|
|
|
|
if( !entry || !text || !viewCursorIface || !editIface )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQString expand( " <abbrev>" );
|
|
|
|
if( !entry->userdata.isNull() && entry->text.endsWith(expand) ){
|
|
|
|
TQString macro = entry->text.left( entry->text.length() - expand.length() );
|
|
|
|
*text = "";
|
|
|
|
uint line, col;
|
|
|
|
viewCursorIface->cursorPositionReal( &line, &col );
|
|
|
|
editIface->removeText( line, col-currentWord().length(), line, col );
|
|
|
|
insertChars( m_templates[suffix][entry->userdata]->code );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::updateActions()
|
|
|
|
{
|
|
|
|
actionCollection()->action( "edit_expandtext" )->setEnabled( docIface != 0 );
|
|
|
|
actionCollection()->action( "edit_expandabbrev" )->setEnabled( docIface != 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotCompletionAborted()
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotCompletionAborted()" << endl;
|
|
|
|
m_inCompletion = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotCompletionDone()
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotCompletionDone()" << endl;
|
|
|
|
m_inCompletion = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbbrevPart::slotAboutToShowCompletionBox()
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "AbbrevPart::slotAboutToShowCompletionBox()" << endl;
|
|
|
|
m_inCompletion = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeTemplateList::CodeTemplateList( )
|
|
|
|
{
|
|
|
|
allCodeTemplates.setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeTemplateList::~ CodeTemplateList( )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMap< TQString, CodeTemplate * > CodeTemplateList::operator [ ]( TQString suffix )
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "CodeTemplateList::operator []" << endl;
|
|
|
|
TQMap< TQString, CodeTemplate * > selectedTemplates;
|
|
|
|
for (TQMap<TQString, TQMap<TQString, CodeTemplate* > >::const_iterator it = templates.begin(); it != templates.end(); ++it)
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "CodeTemplateList::operator [] - suffixes " << it.key() << endl;
|
|
|
|
if (TQStringList::split(",", it.key()).contains(suffix))
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "CodeTemplateList::operator [] - suffixes " << it.key() << " contains " << suffix << endl;
|
|
|
|
|
|
|
|
TQMap<TQString, CodeTemplate* > m = it.data();
|
|
|
|
for (TQMap<TQString, CodeTemplate* >::const_iterator itt = m.begin(); itt != m.end(); ++itt)
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "x" << endl;
|
|
|
|
selectedTemplates[itt.key()] = itt.data();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return selectedTemplates;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CodeTemplateList::insert( TQString name, TQString description, TQString code, TQString suffixes )
|
|
|
|
{
|
|
|
|
TQString origSuffixes = suffixes;
|
|
|
|
// TQStringList suffixList;
|
|
|
|
int pos = suffixes.find('(');
|
|
|
|
if (pos == -1)
|
|
|
|
return;
|
|
|
|
suffixes.remove(0, pos+1);
|
|
|
|
pos = suffixes.find(')');
|
|
|
|
if (pos == -1)
|
|
|
|
return;
|
|
|
|
suffixes.remove(pos, suffixes.length()-pos);
|
|
|
|
// suffixList = TQStringList::split(",", suffixes);
|
|
|
|
|
|
|
|
CodeTemplate *t;
|
|
|
|
if (templates.contains(suffixes) && templates[suffixes].contains(name))
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "found template for suffixes " << suffixes << " and name " << name << endl;
|
|
|
|
t = templates[suffixes][name];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug(9028) << "creating template for suffixes " << suffixes << " and name " << name << endl;
|
|
|
|
t = new CodeTemplate();
|
|
|
|
allCodeTemplates.append(t);
|
|
|
|
templates[suffixes][name] = t;
|
|
|
|
}
|
|
|
|
t->name = name;
|
|
|
|
t->description = description;
|
|
|
|
t->code = code;
|
|
|
|
t->suffixes = origSuffixes;
|
|
|
|
if (!m_suffixes.contains(origSuffixes))
|
|
|
|
m_suffixes.append(origSuffixes);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPtrList< CodeTemplate > CodeTemplateList::allTemplates( ) const
|
|
|
|
{
|
|
|
|
return allCodeTemplates;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CodeTemplateList::remove( const TQString & suffixes, const TQString & name )
|
|
|
|
{
|
|
|
|
allCodeTemplates.remove(templates[suffixes][name]);
|
|
|
|
templates[suffixes].remove(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CodeTemplateList::clear( )
|
|
|
|
{
|
|
|
|
templates.clear();
|
|
|
|
allCodeTemplates.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CodeTemplateList::suffixes( )
|
|
|
|
{
|
|
|
|
return m_suffixes;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "abbrevpart.moc"
|