Browse Source

Change list of completion entries from a QLinkedList to a QList.
Implement code completion model.
Start porting completion.


git-svn-id: file:///var/svn/tigccpp/trunk@1118 9552661e-59e3-4036-b4f2-dbe53926924f

kevinkofler 17 years ago
parent
commit
e8a4e6a8f4
2 changed files with 112 additions and 26 deletions
  1. 92 23
      ktigcc/completion.cpp
  2. 20 3
      ktigcc/completion.h

+ 92 - 23
ktigcc/completion.cpp

@@ -20,6 +20,7 @@
 */
 
 #include <QString>
+#include <QList>
 #include <QLinkedList>
 #include <QPair>
 #include <QPoint>
@@ -33,6 +34,8 @@
 #include <kmessagebox.h>
 #include <ktexteditor/view.h>
 #include <ktexteditor/document.h>
+#include <ktexteditor/codecompletionmodel.h>
+#include <ktexteditor/codecompletioninterface.h>
 #include <kconfig.h>
 #include <cstring>
 #include "completion.h"
@@ -133,14 +136,14 @@ bool findSymbolInFile(const QString &symbol,
                                    symbolLine,systemHeader);
 }
 
-static void mergeCompletionEntries(QLinkedList<CompletionEntry> &dest,
-                                   const QLinkedList<CompletionEntry> &src)
+static void mergeCompletionEntries(QList<CompletionEntry> &dest,
+                                   const QList<CompletionEntry> &src)
 {
   foreach (const CompletionEntry &entry, src) dest.append(entry);
 }
 
 static void completionEntriesForSystemHeaders(const QStringList &systemHeaders,
-                                              QLinkedList<CompletionEntry> &result)
+                                              QList<CompletionEntry> &result)
 {
   foreach (const QString &headerName, systemHeaders) {
     // Avoid infinite recursion.
@@ -157,7 +160,7 @@ static void completionEntriesForSystemHeaders(const QStringList &systemHeaders,
 static bool completionEntriesForFileRecursive(const QString &fileText,
                                               const QString &fileName,
                                               MainForm *mainForm,
-                                              QLinkedList<CompletionEntry> &result)
+                                              QList<CompletionEntry> &result)
 {
   if (!projectCompletion.contains(fileName) || projectCompletion[fileName].dirty) {
     QFileInfo fileInfo(fileName);
@@ -184,28 +187,28 @@ static bool completionEntriesForFileRecursive(const QString &fileText,
 bool completionEntriesForFile(const QString &fileText,
                               const QString &fileName,
                               MainForm *mainForm,
-                              QLinkedList<CompletionEntry> &result)
+                              QList<CompletionEntry> &result)
 {
   resetSearchedFlags();
   return completionEntriesForFileRecursive(fileText,fileName,mainForm,result);
 }
 
-static QLinkedList<CompletionEntry> sortCompletionEntries(
-  const QLinkedList<CompletionEntry> &entries)
+static QList<CompletionEntry> sortCompletionEntries(
+  const QList<CompletionEntry> &entries)
 {
-  QMap<QString,QLinkedList<CompletionEntry> > map;
+  QMap<QString,QList<CompletionEntry> > map;
   foreach (const CompletionEntry &entry, entries) {
-    QLinkedList<CompletionEntry> &list=map[entry.text];
+    QList<CompletionEntry> &list=map[entry.text];
     if (!list.contains(entry)) list.append(entry);
   }
-  QLinkedList<CompletionEntry> result;
-  foreach (const QLinkedList<CompletionEntry> &entries, map)
+  QList<CompletionEntry> result;
+  foreach (const QList<CompletionEntry> &entries, map)
     mergeCompletionEntries(result,entries);
   return result;
 }
 
 static QStringList prototypesForIdentifier(const QString &identifier,
-  const QLinkedList<CompletionEntry> &entries)
+  const QList<CompletionEntry> &entries)
 {
   QStringList result;
   QStringList reservedIdentifiers=QString("__alignof__\n"
@@ -299,7 +302,7 @@ bool parseHelpSources(QWidget *parent, const QString &directory,
   QStringList headers=qdir.entryList("*.h",QDir::Dirs);
   foreach (const QString &header, headers) {
     CompletionInfo &completionInfo=sysHdrCompletion[header];
-    QLinkedList<CompletionEntry> &entries=completionInfo.entries;
+    QList<CompletionEntry> &entries=completionInfo.entries;
     QDir hdrQdir(QFileInfo(qdir,header).filePath());
     QStringList hsfs=hdrQdir.entryList("*.hsf *.ref",QDir::Files);
     foreach (const QString &hsf, hsfs) {
@@ -565,12 +568,72 @@ void TemplatePopup::QPopupMenu_activated(int id)
   } else view->insertText(code);
 }
 
+CompletionModel::CompletionModel(QObject *parent,
+                                 const QList<CompletionEntry> &entries)
+  : KTextEditor::CodeCompletionModel(parent), m_entries(entries)
+{
+}
+
+CompletionModel::~CompletionModel()
+{
+}
+
+int CompletionModel::rowCount(const QModelIndex &parent __attribute__((unused)))
+  const
+{
+  return m_entries.count();
+}
+
+QModelIndex CompletionModel::index(int row, int column,
+                                   const QModelIndex &parent) const
+{
+  if (row<0 || row>=m_entries.count() || column<0 || column>5 || parent.isValid())
+    return QModelIndex();
+  return createIndex(row,column);
+}
+
+QVariant CompletionModel::data(const QModelIndex &index, int role) const
+{
+  switch (role)
+  {
+    case Qt::DisplayRole:
+      switch (index.column()) {
+        case 0:
+          return m_entries[index.row()].prefix;
+        case 1:
+          return QVariant::Invalid; // icon
+        case 2:
+          return QVariant::Invalid; // scope
+        case 3:
+          return m_entries[index.row()].text;
+        case 4:
+          return QVariant::Invalid; // arguments (currently in postfix)
+        case 5:
+          return m_entries[index.row()].postfix;
+      }
+    case Qt::StatusTipRole:
+      return m_entries[index.row()].comment;
+    case CompletionRole:
+      return (int)Public|GlobalScope;
+    case ScopeIndex:
+      return -1;
+    case MatchType:
+      return true;
+    case HighlightingMethod:
+      return QVariant::Invalid;
+    case InheritanceDepth:
+      return 0;
+  }
+
+  return QVariant();
+}
+
 CompletionPopup::CompletionPopup(KTextEditor::View *parent, const QString &fileName,
                                  MainForm *mainForm, QObject *receiver)
   : QObject(parent), done(false), completionPopup(0)
 {
   connect(this,SIGNAL(closed()),receiver,SLOT(completionPopup_closed()));
-  QLinkedList<CompletionEntry> entries;
+  QList<CompletionEntry> entries;
   if (!completionEntriesForFile(parent->document()->text(),fileName,mainForm,
                                 entries)) {
     emit closed();
@@ -579,20 +642,26 @@ CompletionPopup::CompletionPopup(KTextEditor::View *parent, const QString &fileN
   }
   entries=sortCompletionEntries(entries);
   KTextEditor::Cursor cursor=parent->cursorPosition();
+  int line=cursor.line();
   int column=cursor.column();
-  int offset=0;
   if (column) {
-    QString textLine=parent->document()->line(cursor.line());
+    QString textLine=parent->document()->line(line);
     if (column<=textLine.length()) {
-      while (column && (textLine[--column].isLetterOrNumber()
-                        || textLine[column]=='_' || textLine[column]=='$'))
-        offset++;
+      while (column && (textLine[column-1].isLetterOrNumber()
+                        || textLine[column-1]=='_' || textLine[column-1]=='$'))
+        column--;
     }
   }
-#if 0 // FIXME: Port completion.
+#if 0 // FIXME: Finish porting completion.
   connect(parent,SIGNAL(completionAborted()),this,SLOT(slotDone()));
   connect(parent,SIGNAL(completionDone()),this,SLOT(slotDone()));
-  parent->showCompletionBox(entries,offset);
+  KTextEditor::CodeCompletionInterface *complIFace
+    =qobject_cast<KTextEditor::CodeCompletionInterface *>(parent);
+  qDebug("%s",parent->document()->text(KTextEditor::Range(
+                                KTextEditor::Cursor(line,column),cursor)).utf8().data());
+  complIFace->startCompletion(KTextEditor::Range(
+                                KTextEditor::Cursor(line,column),cursor),
+                              new CompletionModel(this,entries));
   // Unfortunately, Kate doesn't always send the completionAborted or
   // completionDone event when it closes its popup. Work around that.
   QWidgetList *list=QApplication::topLevelWidgets();
@@ -636,7 +705,7 @@ ArgHintPopup::ArgHintPopup(KTextEditor::View *parent, const QString &fileName,
                            MainForm *mainForm)
   : QObject(parent), done(false), argHintPopup(0)
 {
-  QLinkedList<CompletionEntry> entries;
+  QList<CompletionEntry> entries;
   if (!completionEntriesForFile(parent->document()->text(),fileName,mainForm,
                                 entries)) {
     nothingFound:
@@ -658,7 +727,7 @@ ArgHintPopup::ArgHintPopup(KTextEditor::View *parent, const QString &fileName,
   QString identifier=textLine.mid(startColumn,endColumn-startColumn);
   QStringList prototypes=prototypesForIdentifier(identifier,entries);
   if (prototypes.isEmpty()) goto nothingFound;  
-#if 0 // FIXME: Port completion.
+#if 0 // FIXME: Port argument hint.
   connect(parent,SIGNAL(argHintHidden()),this,SLOT(slotDone()));
   parent->showArgHint(prototypes,"()",",");
   // Unfortunately, Kate doesn't always send the argHintHidden event when it

+ 20 - 3
ktigcc/completion.h

@@ -27,9 +27,10 @@
 #include <QString>
 #include <QStringList>
 #include <Q3ValueList>
-#include <QLinkedList>
+#include <QList>
 #include <QEvent>
 #include <ktexteditor/view.h>
+#include <ktexteditor/codecompletionmodel.h>
 
 struct CompletionEntry
 {
@@ -58,7 +59,7 @@ struct CompletionInfo {
   QStringList includedSystem;
   QStringList included;
   QMap<QString,unsigned> lineNumbers;
-  QLinkedList<CompletionEntry> entries;
+  QList<CompletionEntry> entries;
 };
 
 // Maps file name to a CompletionInfo.
@@ -75,7 +76,7 @@ bool findSymbolInFile(const QString &symbol,
 bool completionEntriesForFile(const QString &fileText,
                               const QString &fileName,
                               MainForm *mainForm,
-                              QLinkedList<CompletionEntry> &result);
+                              QList<CompletionEntry> &result);
 
 class QWidget;
 bool parseHelpSources(QWidget *parent, const QString &directory,
@@ -98,6 +99,22 @@ class TemplatePopup : public Q3PopupMenu {
     KTextEditor::View *view;
 };
 
+class CompletionModel : public KTextEditor::CodeCompletionModel
+{
+  Q_OBJECT
+  public:
+    CompletionModel(QObject *parent, const QList<CompletionEntry> &entries);
+    ~CompletionModel();
+
+    virtual int rowCount(const QModelIndex &parent) const;
+    virtual QModelIndex index(int row, int column,
+                              const QModelIndex &parent=QModelIndex()) const;
+    virtual QVariant data(const QModelIndex &index, int role) const;
+
+  private:
+    const QList<CompletionEntry> m_entries;
+};
+
 class QEvent;
 class QWidget;
 class CompletionPopup : public QObject {