[prev in list] [next in list] [prev in thread] [next in thread]
List: kdevelop-devel
Subject: Re: Custom range for CodeCompletion
From: "Niko Sams" <niko.sams () gmail ! com>
Date: 2008-11-23 18:47:28
Message-ID: 629542d40811231047v603fa294k2867345dc488cd0c () mail ! gmail ! com
[Download RAW message or body]
And here comes the patch :D
["kdelibs.diff" (text/plain)]
Index: interfaces/ktexteditor/codecompletionmodel.h
===================================================================
--- interfaces/ktexteditor/codecompletionmodel.h (Revision 884497)
+++ interfaces/ktexteditor/codecompletionmodel.h (Arbeitskopie)
@@ -421,6 +421,7 @@
Q_SIGNALS:
void hasGroupsChanged(KTextEditor::CodeCompletionModel *model,bool hasGroups);
+ void modifyCompletionRange(const KTextEditor::Range& word, const QRegExp& \
allowedText);
protected:
void setHasGroups(bool hasGroups);
Index: kate/completion/katecompletionmodel.cpp
===================================================================
--- kate/completion/katecompletionmodel.cpp (Revision 884497)
+++ kate/completion/katecompletionmodel.cpp (Arbeitskopie)
@@ -586,7 +586,7 @@
Item item = Item(this, handler, ModelRow(handler.model(), \
QPersistentModelIndex(sourceIndex)));
if(g != m_argumentHints)
- item.match(m_currentMatch);
+ item.match();
g->addItem(item, notifyModel);
@@ -859,44 +859,47 @@
return QModelIndex();
}
-void KateCompletionModel::setCurrentCompletion( const QString & completion )
+void KateCompletionModel::setCurrentCompletion( KTextEditor::CodeCompletionModel* \
model, const QString & completion ) {
- if (m_currentMatch == completion)
+ if (m_currentMatch[model] == completion)
return;
if (!hasCompletionModel()) {
- m_currentMatch = completion;
+ m_currentMatch[model] = completion;
return;
}
changeTypes changeType = Change;
- if (m_currentMatch.length() > completion.length() && \
m_currentMatch.startsWith(completion, m_matchCaseSensitivity)) { + if \
(m_currentMatch[model].length() > completion.length() && \
m_currentMatch[model].startsWith(completion, m_matchCaseSensitivity)) { // Filter \
has been broadened changeType = Broaden;
- } else if (m_currentMatch.length() < completion.length() && \
completion.startsWith(m_currentMatch, m_matchCaseSensitivity)) { + } else if \
(m_currentMatch[model].length() < completion.length() && \
completion.startsWith(m_currentMatch[model], m_matchCaseSensitivity)) { // Filter \
has been narrowed changeType = Narrow;
}
- kDebug( 13035 ) << "Old match: " << m_currentMatch << ", new: " << completion << \
", type: " << changeType; + kDebug( 13035 ) << model << "Old match: " << \
m_currentMatch[model] << ", new: " << completion << ", type: " << changeType;
- if (!hasGroups())
- changeCompletions(m_ungrouped, completion, changeType);
- else {
- foreach (Group* g, m_rowTable)
+ m_currentMatch[model] = completion;
+
+ if (!hasGroups()) {
+ changeCompletions(m_ungrouped, changeType);
+ } else {
+ foreach (Group* g, m_rowTable) {
if(g != m_argumentHints)
- changeCompletions(g, completion, changeType);
- foreach (Group* g, m_emptyGroups)
+ changeCompletions(g, changeType);
+ }
+ foreach (Group* g, m_emptyGroups) {
if(g != m_argumentHints)
- changeCompletions(g, completion, changeType);
+ changeCompletions(g, changeType);
+ }
updateBestMatches();
}
clearExpanding(); //We need to do this, or be aware of expanding-widgets while \
filtering.
- m_currentMatch = completion;
emit contentGeometryChanged();
}
@@ -904,16 +907,16 @@
void KateCompletionModel::rematch()
{
if (!hasGroups()) {
- changeCompletions(m_ungrouped, m_currentMatch, Change);
+ changeCompletions(m_ungrouped, Change);
} else {
foreach (Group* g, m_rowTable)
if(g != m_argumentHints)
- changeCompletions(g, m_currentMatch, Change);
+ changeCompletions(g, Change);
foreach (Group* g, m_emptyGroups)
if(g != m_argumentHints)
- changeCompletions(g, m_currentMatch, Change);
+ changeCompletions(g, Change);
updateBestMatches();
}
@@ -940,7 +943,7 @@
rowAdd.clear(); \
}
-void KateCompletionModel::changeCompletions( Group * g, const QString & \
newCompletion, changeTypes changeType ) +void KateCompletionModel::changeCompletions( \
Group * g, changeTypes changeType ) {
QMutableListIterator<Item> filtered = g->filtered;
QMutableListIterator<Item> prefilter = g->prefilter;
@@ -956,7 +959,7 @@
if (filtered.peekNext().sourceRow() == prefilter.peekNext().sourceRow()) {
// Currently being displayed
if (changeType != Broaden) {
- if (prefilter.peekNext().match(newCompletion)) {
+ if (prefilter.peekNext().match()) {
// no change required to this item
COMPLETE_DELETE
COMPLETE_ADD
@@ -981,7 +984,7 @@
} else {
// Currently hidden
if (changeType != Narrow) {
- if (prefilter.peekNext().match(newCompletion)) {
+ if (prefilter.peekNext().match()) {
// needs to be made visible
COMPLETE_DELETE
@@ -1005,7 +1008,7 @@
} else {
// Currently hidden
if (changeType != Narrow) {
- if (prefilter.peekNext().match(newCompletion)) {
+ if (prefilter.peekNext().match()) {
// needs to be made visible
COMPLETE_DELETE
@@ -1716,19 +1719,17 @@
return matchFilters;
}
-bool KateCompletionModel::Item::match(const QString& newCompletion)
+bool KateCompletionModel::Item::match()
{
- // Hehe, everything matches nothing! (ie. everything matches a blank string)
- if (newCompletion.isEmpty())
- return true;
-
// Check to see if the item is matched by the current completion string
QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), \
CodeCompletionModel::Name);
- QString match = newCompletion;
- if (match.isEmpty())
- match = model->currentCompletion();
+ QString match = model->currentCompletion(m_sourceRow.first);
+ // Hehe, everything matches nothing! (ie. everything matches a blank string)
+ if (match.isEmpty())
+ return true;
+
matchCompletion = m_nameColumn.startsWith(match, model->matchCaseSensitivity());
return matchCompletion;
}
@@ -1827,9 +1828,9 @@
return m_sourceRow;
}
-const QString & KateCompletionModel::currentCompletion( ) const
+QString KateCompletionModel::currentCompletion( KTextEditor::CodeCompletionModel* \
model ) const {
- return m_currentMatch;
+ return m_currentMatch.value(model);
}
Qt::CaseSensitivity KateCompletionModel::matchCaseSensitivity( ) const
@@ -1887,6 +1888,8 @@
if (!model || m_completionModels.contains(model))
return;
+ m_currentMatch.remove(model);
+
clearGroups();
model->disconnect(this);
@@ -1979,6 +1982,8 @@
m_completionModels.clear();
+ m_currentMatch.clear();
+
clearGroups();
reset();
Index: kate/completion/katecompletionmodel.h
===================================================================
--- kate/completion/katecompletionmodel.h (Revision 884497)
+++ kate/completion/katecompletionmodel.h (Arbeitskopie)
@@ -61,8 +61,8 @@
KateView* view() const;
KateCompletionWidget* widget() const;
- const QString& currentCompletion() const;
- void setCurrentCompletion(const QString& completion);
+ QString currentCompletion(KTextEditor::CodeCompletionModel* model) const;
+ void setCurrentCompletion(KTextEditor::CodeCompletionModel* model, const \
QString& completion);
Qt::CaseSensitivity matchCaseSensitivity() const;
void setMatchCaseSensitivity( Qt::CaseSensitivity cs );
@@ -209,7 +209,7 @@
bool isMatching() const;
bool filter();
- bool match(const QString& newCompletion = QString());
+ bool match();
const ModelRow& sourceRow() const;
@@ -293,7 +293,7 @@
};
- void changeCompletions(Group* g, const QString& newCompletion, changeTypes \
changeType); + void changeCompletions(Group* g, changeTypes changeType);
void deleteRows(Group* g, QMutableListIterator<Item>& filtered, int \
countBackwards, int startRow);
void addRows(Group* g, QMutableListIterator<Item>& filtered, int startRow, const \
QList<Item>& newItems); @@ -314,7 +314,7 @@
// ### Runtime state
// General
QList<KTextEditor::CodeCompletionModel*> m_completionModels;
- QString m_currentMatch;
+ QMap<KTextEditor::CodeCompletionModel*, QString> m_currentMatch;
Qt::CaseSensitivity m_matchCaseSensitivity;
// Column merging
Index: kate/completion/katecompletionwidget.cpp
===================================================================
--- kate/completion/katecompletionwidget.cpp (Revision 884497)
+++ kate/completion/katecompletionwidget.cpp (Arbeitskopie)
@@ -56,7 +56,6 @@
KateCompletionWidget::KateCompletionWidget(KateView* parent)
: QFrame(parent, Qt::ToolTip)
, m_presentationModel(new KateCompletionModel(this))
- , m_completionRange(0L)
, m_entryList(new KateCompletionTree(this))
, m_argumentHintModel(new KateArgumentHintModel(this))
, m_argumentHintTree(new KateArgumentHintTree(this))
@@ -202,7 +201,12 @@
return;
}
- kDebug(13035) << word << " " << model;
+ QList<KTextEditor::CodeCompletionModel*> models;
+ if (model) {
+ models << model;
+ } else {
+ models = m_sourceModels;
+ }
if (!m_filterInstalled) {
if (!QApplication::activeWindow()) {
@@ -217,32 +221,14 @@
if (isCompletionActive())
abortCompletion();
- m_completionRange = view()->doc()->smartManager()->newSmartRange(word);
- m_completionRange->setInsertBehavior(KTextEditor::SmartRange::ExpandRight | \
KTextEditor::SmartRange::ExpandLeft);
- if(!m_completionRange->isValid()) {
- kWarning(13035) << "Could not construct valid smart-range from" << word << \
"instead got" << *m_completionRange;
- abortCompletion();
- return;
- }
+ m_presentationModel->setCompletionModels(models);
- connect(m_completionRange->smartStart().notifier(), \
SIGNAL(characterDeleted(KTextEditor::SmartCursor*, bool)), \
SLOT(startCharacterDeleted(KTextEditor::SmartCursor*, bool)));
-
- cursorPositionChanged();
-
- if (model)
+ foreach (KTextEditor::CodeCompletionModel* model, models) {
+ connect(model, SIGNAL(modifyCompletionRange(KTextEditor::Range, QRegExp)), \
SLOT(modifyCompletionRange(KTextEditor::Range, QRegExp))); \
model->completionInvoked(view(), word, invocationType);
- else
- foreach (KTextEditor::CodeCompletionModel* model, m_sourceModels)
- model->completionInvoked(view(), word, invocationType);
-
- kDebug( 13035 ) << "msdofjdsoifdsflkdsjf";
- if (model)
- m_presentationModel->setCompletionModel(model);
- else
- m_presentationModel->setCompletionModels(m_sourceModels);
-
- if (!m_presentationModel->completionModels().isEmpty()) {
- m_presentationModel->setCurrentCompletion(view()->doc()->text(KTextEditor::Range(m_completionRange->start(), \
view()->cursorPosition()))); + if (!m_completionRanges.contains(model)) { \
//completionInvoked might emit modifyCompletionRange + \
completionRangeChanged(model, word); + }
}
connect(this->model(), SIGNAL(contentGeometryChanged()), this, \
SLOT(modelContentChanged())); @@ -250,6 +236,40 @@
modelContentChanged();
}
+void KateCompletionWidget::modifyCompletionRange(const KTextEditor::Range& word, \
const QRegExp& allowedText) +{
+ KTextEditor::CodeCompletionModel* model = \
qobject_cast<KTextEditor::CodeCompletionModel*>(sender()); + Q_ASSERT(model);
+ kDebug() << model << word << allowedText;
+ m_allowedText[model] = allowedText;
+ completionRangeChanged(model, word);
+}
+
+void KateCompletionWidget::completionRangeChanged(KTextEditor::CodeCompletionModel* \
model, const KTextEditor::Range& word) +{
+ if (m_completionRanges.contains(model)) {
+ if (*m_completionRanges[model] == word) {
+ kDebug() << "ignoring, range not changed";
+ return;
+ }
+ delete m_completionRanges[model];
+ }
+
+ m_completionRanges[model] = view()->doc()->smartManager()->newSmartRange(word);
+ m_completionRanges[model]->setInsertBehavior(KTextEditor::SmartRange::ExpandRight \
| KTextEditor::SmartRange::ExpandLeft); + if(!m_completionRanges[model]->isValid()) \
{ + kWarning(13035) << "Could not construct valid smart-range from" << word << \
"instead got" << *m_completionRanges[model]; + abortCompletion();
+ return;
+ }
+ connect(m_completionRanges[model]->smartStart().notifier(), \
SIGNAL(characterDeleted(KTextEditor::SmartCursor*, bool)), + \
SLOT(startCharacterDeleted(KTextEditor::SmartCursor*, bool))); +
+ cursorPositionChanged();
+
+ m_presentationModel->setCurrentCompletion(model, \
view()->doc()->text(KTextEditor::Range(m_completionRanges[model]->start(), \
view()->cursorPosition()))); +}
+
void KateCompletionWidget::updateAndShow()
{
setUpdatesEnabled(false);
@@ -285,7 +305,10 @@
return false;
// kDebug() << "updating from" << geometry() << m_entryList->geometry();
- QPoint cursorPosition = view()->cursorToCoordinate(m_completionRange->start());
+ if (!completionRange()) {
+ return false;
+ }
+ QPoint cursorPosition = view()->cursorToCoordinate(completionRange()->start());
if (cursorPosition == QPoint(-1,-1)) {
// Start of completion range is now off-screen -> abort
abortCompletion();
@@ -403,23 +426,33 @@
KTextEditor::Cursor cursor = view()->cursorPosition();
- if (m_completionRange->start() > cursor || m_completionRange->end() < cursor)
- return abortCompletion();
+ foreach (KateSmartRange* range, m_completionRanges) {
+ if (range->start() > cursor || range->end() < cursor)
+ return abortCompletion();
+ }
- QString currentCompletion = \
view()->doc()->text(KTextEditor::Range(m_completionRange->start(), \
view()->cursorPosition())); + QMapIterator<KTextEditor::CodeCompletionModel*, \
KateSmartRange*> i(m_completionRanges); + while (i.hasNext()) {
+ i.next();
+ QString currentCompletion = \
view()->doc()->text(KTextEditor::Range(i.value()->start(), \
view()->cursorPosition()));
- // FIXME - allow client to specify this?
- static QRegExp allowedText("^(\\w*)");
- if (!allowedText.exactMatch(currentCompletion))
- return abortCompletion();
+ QRegExp allowedText("^(\\w*)");
+ if (m_allowedText.contains(i.key())) {
+ allowedText = m_allowedText[i.key()];
+ }
+ kDebug() << i.key() << i.value() << currentCompletion << allowedText;
+ if (!allowedText.exactMatch(currentCompletion))
+ return abortCompletion();
- m_presentationModel->setCurrentCompletion(currentCompletion);
+ m_presentationModel->setCurrentCompletion(i.key(), currentCompletion);
+ }
+
m_entryList->scheduleUpdate();
}
bool KateCompletionWidget::isCompletionActive( ) const
{
- return m_completionRange && isVisible();
+ return !m_completionRanges.isEmpty() && isVisible();
}
void KateCompletionWidget::abortCompletion( )
@@ -435,9 +468,6 @@
if(isVisible())
hide();
- delete m_completionRange;
- m_completionRange = 0L;
-
if (wasActive)
view()->sendCompletionAborted();
}
@@ -446,6 +476,8 @@
m_presentationModel->clearCompletionModels();
m_argumentHintTree->clearCompletion();
m_argumentHintModel->clear();
+ qDeleteAll(m_completionRanges);
+ m_completionRanges.clear();
}
bool KateCompletionWidget::embeddedWidgetAccept() {
@@ -491,8 +523,6 @@
return abortCompletion();
}
- KTextEditor::Cursor start = m_completionRange->start();
-
// encapsulate all editing as being from the code completion, and undo-able in one \
step. view()->doc()->editStart(true, Kate::CodeCompletionEdit);
@@ -501,17 +531,19 @@
KTextEditor::CodeCompletionModel2* model2 = \
dynamic_cast<KTextEditor::CodeCompletionModel2*>(model);
+ KTextEditor::Cursor start = m_completionRanges[model]->start();
+
//editStart locks the smart-mutex, but it must not be locked when calling external \
functions, //else we may get deadlock-issues.
view()->doc()->smartMutex()->unlock();
if(model2)
- model2->executeCompletionItem2(view()->document(), *m_completionRange, \
toExecute); + model2->executeCompletionItem2(view()->document(), \
*m_completionRanges[model], toExecute); else if(toExecute.parent().isValid())
//The normale CodeCompletionInterface cannot handle feedback for hierarchical \
models, so just do the replacement
- view()->document()->replaceText(*m_completionRange, \
model->data(toExecute.sibling(toExecute.row(), \
KTextEditor::CodeCompletionModel::Name)).toString()); + \
view()->document()->replaceText(*m_completionRanges[model], \
model->data(toExecute.sibling(toExecute.row(), \
KTextEditor::CodeCompletionModel::Name)).toString()); else
- model->executeCompletionItem(view()->document(), *m_completionRange, \
toExecute.row()); + model->executeCompletionItem(view()->document(), \
*m_completionRanges[model], toExecute.row());
//Relock, because editEnd expects it to be locked
view()->doc()->smartMutex()->lock();
@@ -547,11 +579,20 @@
abortCompletion();
}
-KateSmartRange * KateCompletionWidget::completionRange( ) const
+KateSmartRange * KateCompletionWidget::completionRange(KTextEditor::CodeCompletionModel* \
model) const {
- return m_completionRange;
+ if (!model) {
+ if (m_sourceModels.isEmpty()) return 0;
+ model = m_sourceModels.first();
+ }
+ return m_completionRanges[model];
}
+QMap<KTextEditor::CodeCompletionModel*, KateSmartRange*> \
KateCompletionWidget::completionRanges( ) const +{
+ return m_completionRanges;
+}
+
void KateCompletionWidget::modelReset( )
{
setUpdatesEnabled(false);
Index: kate/completion/katecompletionwidget.h
===================================================================
--- kate/completion/katecompletionwidget.h (Revision 884497)
+++ kate/completion/katecompletionwidget.h (Arbeitskopie)
@@ -83,7 +83,8 @@
int automaticInvocationDelay() const;
void setAutomaticInvocationDelay(int delay);
- KateSmartRange* completionRange() const;
+ KateSmartRange* completionRange(KTextEditor::CodeCompletionModel* model = 0) \
const; + QMap<KTextEditor::CodeCompletionModel*, KateSmartRange*> \
completionRanges( ) const;
// Navigation
void pageDown();
@@ -144,6 +145,7 @@
void startCharacterDeleted(KTextEditor::SmartCursor* cursor, bool \
deletedBefore); void rowsInserted(const QModelIndex& parent, int row, int rowEnd);
void viewFocusOut();
+ void modifyCompletionRange(const KTextEditor::Range& word, const QRegExp& \
allowedText); private:
void updateAndShow();
void updateArgumentHintGeometry();
@@ -153,11 +155,13 @@
//Switch cursor between argument-hint list / completion-list
void switchList();
KTextEditor::Range determineRange() const;
+ void completionRangeChanged(KTextEditor::CodeCompletionModel*, const \
KTextEditor::Range& word);
QList<KTextEditor::CodeCompletionModel*> m_sourceModels;
KateCompletionModel* m_presentationModel;
- KateSmartRange* m_completionRange;
+ QMap<KTextEditor::CodeCompletionModel*, KateSmartRange*> m_completionRanges;
+ QMap<KTextEditor::CodeCompletionModel*, QRegExp> m_allowedText;
KTextEditor::Cursor m_lastCursorPosition;
KateCompletionTree* m_entryList;
_______________________________________________
KDevelop-devel mailing list
KDevelop-devel@kdevelop.org
https://barney.cs.uni-potsdam.de/mailman/listinfo/kdevelop-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic