mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 05:11:35 +00:00
Attempt to add autocomplete+calltips to the qt version of fteqccgui.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5649 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
d0b7519242
commit
19a2ecb99e
3 changed files with 612 additions and 202 deletions
|
@ -19,6 +19,7 @@ void GUI_RevealOptions(void);
|
|||
int GUIprintf(const char *msg, ...);
|
||||
|
||||
pbool GenBuiltinsList(char *buffer, int buffersize);
|
||||
pbool GenAutoCompleteList(char *prefix, char *buffer, int buffersize);
|
||||
|
||||
extern char parameters[16384];
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
/*Todo (in no particular order):
|
||||
tooltips for inspecting variables/types.
|
||||
variables/watch list.
|
||||
calltips for argument info
|
||||
autocompletion calltips, for people who can't remember function names
|
||||
initial open project prompt
|
||||
shpuld's styling
|
||||
decompiler output saving
|
||||
|
@ -47,6 +45,9 @@ extern int fl_tabsize;
|
|||
extern char enginebinary[MAX_OSPATH];
|
||||
extern char enginebasedir[MAX_OSPATH];
|
||||
extern char enginecommandline[8192];
|
||||
|
||||
extern QCC_def_t *sourcefilesdefs[];
|
||||
extern int sourcefilesnumdefs;
|
||||
};
|
||||
static char *cmdlineargs;
|
||||
|
||||
|
@ -60,7 +61,7 @@ template<class T> inline T cpprealloc(T p, size_t s) {return static_cast<T>(real
|
|||
#define STRINGIFY2(s) #s
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
|
||||
|
||||
static QProcess *qcdebugger;
|
||||
static void DebuggerStop(void);
|
||||
static bool DebuggerSendCommand(const char *msg, ...);
|
||||
static void DebuggerStart(void);
|
||||
|
@ -407,9 +408,120 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class WrappedQsciScintilla:public QsciScintilla
|
||||
{
|
||||
public:
|
||||
WrappedQsciScintilla(QWidget *parent):QsciScintilla(parent){}
|
||||
|
||||
char *WordUnderCursor(char *word, int wordsize, char *term, int termsize, int position)
|
||||
{
|
||||
unsigned char linebuf[1024];
|
||||
long charidx;
|
||||
long lineidx;
|
||||
long len;
|
||||
pbool noafter = (position==-2);
|
||||
|
||||
if (position == -3)
|
||||
{
|
||||
len = SendScintilla(QsciScintillaBase::SCI_GETSELTEXT, NULL);
|
||||
if (len > 0 && len < wordsize)
|
||||
{
|
||||
len = SendScintilla(QsciScintillaBase::SCI_GETSELTEXT, word);
|
||||
if (len>0)
|
||||
return word;
|
||||
}
|
||||
}
|
||||
|
||||
if (position < 0)
|
||||
position = SendScintilla(QsciScintillaBase::SCI_GETCURRENTPOS);
|
||||
|
||||
lineidx = SendScintilla(QsciScintillaBase::SCI_LINEFROMPOSITION, position);
|
||||
charidx = position - SendScintilla(QsciScintillaBase::SCI_POSITIONFROMLINE, lineidx);
|
||||
|
||||
len = SendScintilla(QsciScintillaBase::SCI_LINELENGTH, lineidx);
|
||||
if (len >= sizeof(linebuf))
|
||||
{
|
||||
*word = 0;
|
||||
return word;
|
||||
}
|
||||
len = SendScintilla(QsciScintillaBase::SCI_GETLINE, lineidx, linebuf);
|
||||
linebuf[len] = 0;
|
||||
if (charidx >= len)
|
||||
charidx = len-1;
|
||||
|
||||
if (noafter) //truncate it here if we're not meant to be reading anything after.
|
||||
linebuf[charidx] = 0;
|
||||
|
||||
if (word)
|
||||
{
|
||||
//skip back to the start of the word
|
||||
while(charidx > 0 && (
|
||||
(linebuf[charidx-1] >= 'a' && linebuf[charidx-1] <= 'z') ||
|
||||
(linebuf[charidx-1] >= 'A' && linebuf[charidx-1] <= 'Z') ||
|
||||
(linebuf[charidx-1] >= '0' && linebuf[charidx-1] <= '9') ||
|
||||
linebuf[charidx-1] == '_' || linebuf[charidx-1] == ':' ||
|
||||
linebuf[charidx-1] >= 128
|
||||
))
|
||||
{
|
||||
charidx--;
|
||||
}
|
||||
//copy the result out
|
||||
lineidx = 0;
|
||||
wordsize--;
|
||||
while (wordsize && (
|
||||
(linebuf[charidx] >= 'a' && linebuf[charidx] <= 'z') ||
|
||||
(linebuf[charidx] >= 'A' && linebuf[charidx] <= 'Z') ||
|
||||
(linebuf[charidx] >= '0' && linebuf[charidx] <= '9') ||
|
||||
linebuf[charidx] == '_' || linebuf[charidx] == ':' ||
|
||||
linebuf[charidx] >= 128
|
||||
))
|
||||
{
|
||||
word[lineidx++] = linebuf[charidx++];
|
||||
wordsize--;
|
||||
}
|
||||
word[lineidx++] = 0;
|
||||
}
|
||||
|
||||
if (term)
|
||||
{
|
||||
//skip back to the start of the word
|
||||
while(charidx > 0 && (
|
||||
(linebuf[charidx-1] >= 'a' && linebuf[charidx-1] <= 'z') ||
|
||||
(linebuf[charidx-1] >= 'A' && linebuf[charidx-1] <= 'Z') ||
|
||||
(linebuf[charidx-1] >= '0' && linebuf[charidx-1] <= '9') ||
|
||||
linebuf[charidx-1] == '_' || linebuf[charidx-1] == ':' || linebuf[charidx-1] == '.' ||
|
||||
linebuf[charidx-1] == '[' || linebuf[charidx-1] == ']' ||
|
||||
linebuf[charidx-1] >= 128
|
||||
))
|
||||
{
|
||||
charidx--;
|
||||
}
|
||||
//copy the result out
|
||||
lineidx = 0;
|
||||
termsize--;
|
||||
while (termsize && (
|
||||
(linebuf[charidx] >= 'a' && linebuf[charidx] <= 'z') ||
|
||||
(linebuf[charidx] >= 'A' && linebuf[charidx] <= 'Z') ||
|
||||
(linebuf[charidx] >= '0' && linebuf[charidx] <= '9') ||
|
||||
linebuf[charidx] == '_' || linebuf[charidx] == ':' || linebuf[charidx] == '.' ||
|
||||
linebuf[charidx] == '[' || linebuf[charidx] == ']' ||
|
||||
linebuf[charidx] >= 128
|
||||
))
|
||||
{
|
||||
term[lineidx++] = linebuf[charidx++];
|
||||
termsize--;
|
||||
}
|
||||
term[lineidx++] = 0;
|
||||
}
|
||||
return word;
|
||||
}
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *event);
|
||||
};
|
||||
|
||||
class documentlist : public QAbstractListModel
|
||||
{
|
||||
QsciScintilla *s; //this is the widget that we load our documents into
|
||||
WrappedQsciScintilla *s; //this is the widget that we load our documents into
|
||||
|
||||
int numdocuments;
|
||||
struct document_s
|
||||
|
@ -480,7 +592,7 @@ class documentlist : public QAbstractListModel
|
|||
}
|
||||
void UpdateTitle(void);
|
||||
public:
|
||||
documentlist(QsciScintilla *editor)
|
||||
documentlist(WrappedQsciScintilla *editor)
|
||||
{
|
||||
s = editor;
|
||||
numdocuments = 0;
|
||||
|
@ -868,6 +980,18 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
connect(s, &QsciScintillaBase::SCN_CHARADDED, [=](int charadded)
|
||||
{
|
||||
if (charadded == '(')
|
||||
{
|
||||
int pos = s->SendScintilla(QsciScintillaBase::SCI_GETCURRENTPOS);
|
||||
char *tooltext = GetCalltipForLine(pos-1);
|
||||
//tooltip_editor = NULL;
|
||||
if (tooltext)
|
||||
s->SendScintilla(QsciScintillaBase::SCI_CALLTIPSHOW, pos, tooltext);
|
||||
}
|
||||
});
|
||||
|
||||
s->setUtf8(ed->savefmt != UTF_ANSI);
|
||||
s->setText(QString(file));
|
||||
|
||||
|
@ -927,6 +1051,155 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
char *GetCalltipForLine(int cursorpos) //calltips are used for tooltips too, so there's some extra weirdness in here
|
||||
{
|
||||
static char buffer[1024];
|
||||
char wordbuf[256], *text;
|
||||
char term[256];
|
||||
char *defname;
|
||||
defname = s->WordUnderCursor(wordbuf, sizeof(wordbuf), term, sizeof(term), cursorpos);
|
||||
if (!*defname)
|
||||
return NULL;
|
||||
else if (globalstable.numbuckets)
|
||||
{
|
||||
QCC_def_t *def;
|
||||
int fno;
|
||||
int line;
|
||||
int best, bestline;
|
||||
char *macro = QCC_PR_CheckCompConstTooltip(defname, buffer, buffer + sizeof(buffer));
|
||||
if (macro && *macro)
|
||||
return macro;
|
||||
|
||||
/*if (dwell)
|
||||
{
|
||||
tooltip_editor = NULL;
|
||||
*tooltip_variable = 0;
|
||||
tooltip_position = 0;
|
||||
*tooltip_type = 0;
|
||||
*tooltip_comment = 0;
|
||||
}*/
|
||||
|
||||
line = s->SendScintilla(QsciScintillaBase::SCI_LINEFROMPOSITION, cursorpos);
|
||||
|
||||
for (best = 0,bestline=0, fno = 1; fno < numfunctions; fno++)
|
||||
{
|
||||
if (line > functions[fno].line && bestline < functions[fno].line)
|
||||
{
|
||||
if (!strcmp(curdoc->fname, functions[fno].filen))
|
||||
{
|
||||
best = fno;
|
||||
bestline = functions[fno].line;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best)
|
||||
{
|
||||
if (strstr(functions[best].name, "::"))
|
||||
{
|
||||
QCC_type_t *type;
|
||||
char tmp[256];
|
||||
char *c;
|
||||
QC_strlcpy(tmp, functions[best].name, sizeof(tmp));
|
||||
c = strstr(tmp, "::");
|
||||
if (c)
|
||||
*c = 0;
|
||||
type = QCC_TypeForName(tmp);
|
||||
|
||||
if (type->type == ev_entity)
|
||||
{
|
||||
QCC_def_t *def;
|
||||
QC_snprintfz(tmp, sizeof(tmp), "%s::__m%s", type->name, term);
|
||||
|
||||
for (fno = 0, def = NULL; fno < sourcefilesnumdefs && !def; fno++)
|
||||
{
|
||||
for (def = sourcefilesdefs[fno]; def; def = def->next)
|
||||
{
|
||||
if (def->scope && def->scope != &functions[best])
|
||||
continue;
|
||||
// OutputDebugString(def->name);
|
||||
// OutputDebugString("\n");
|
||||
if (!strcmp(def->name, tmp))
|
||||
{
|
||||
//FIXME: look at the scope's function to find the start+end of the function and filter based upon that, to show locals
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (def && def->type->type == ev_field)
|
||||
{
|
||||
// QC_strlcpy(tmp, term, sizeof(tmp));
|
||||
QC_snprintfz(term, sizeof(term), "self.%s", tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (fno = 0, def = NULL; fno < sourcefilesnumdefs && !def; fno++)
|
||||
{
|
||||
for (def = sourcefilesdefs[fno]; def; def = def->next)
|
||||
{
|
||||
if (def->scope && def->scope != &functions[best])
|
||||
continue;
|
||||
if (!strcmp(def->name, term))
|
||||
{
|
||||
//FIXME: look at the scope's function to find the start+end of the function and filter based upon that, to show locals
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (def && def->type->type == ev_field)
|
||||
{
|
||||
QC_strlcpy(tmp, term, sizeof(tmp));
|
||||
QC_snprintfz(term, sizeof(term), "self.%s", tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: we may need to display types too
|
||||
for (fno = 0, def = NULL; fno < sourcefilesnumdefs && !def; fno++)
|
||||
{
|
||||
for (def = sourcefilesdefs[fno]; def; def = def->next)
|
||||
{
|
||||
if (def->scope)
|
||||
continue;
|
||||
if (!strcmp(def->name, defname))
|
||||
{
|
||||
//FIXME: look at the scope's function to find the start+end of the function and filter based upon that, to show locals
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (def)
|
||||
{
|
||||
char typebuf[1024];
|
||||
char valuebuf[1024];
|
||||
if (def->constant && def->type->type == ev_float)
|
||||
QC_snprintfz(valuebuf, sizeof(valuebuf), " = %g", def->symboldata[def->ofs]._float);
|
||||
else if (def->constant && def->type->type == ev_integer)
|
||||
QC_snprintfz(valuebuf, sizeof(valuebuf), " = %i", def->symboldata[def->ofs]._int);
|
||||
else if (def->constant && def->type->type == ev_vector)
|
||||
QC_snprintfz(valuebuf, sizeof(valuebuf), " = '%g %g %g'", def->symboldata[def->ofs].vector[0], def->symboldata[def->ofs].vector[1], def->symboldata[def->ofs].vector[2]);
|
||||
else
|
||||
*valuebuf = 0;
|
||||
//note function argument names do not persist beyond the function def. we might be able to read the function's localdefs for them, but that's unreliable/broken with builtins where they're most needed.
|
||||
if (def->comment)
|
||||
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s%s\r\n%s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name, valuebuf, def->comment);
|
||||
else
|
||||
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s%s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name, valuebuf);
|
||||
|
||||
text = buffer;
|
||||
}
|
||||
else
|
||||
text = NULL;
|
||||
|
||||
return text;
|
||||
}
|
||||
else
|
||||
return NULL;//"Type info not available. Compile first.";
|
||||
}
|
||||
|
||||
bool annotate(const char *line)
|
||||
{
|
||||
auto filename = line+6;
|
||||
|
@ -1124,6 +1397,47 @@ public:
|
|||
|
||||
DebuggerSendCommand("qcbreakpoint %i \"%s\" %i\n", mode, curdoc->fname, curdoc->cursorline);
|
||||
}
|
||||
/*void setMarkerLine(int linenum)
|
||||
{ //moves the 'current-line' marker to the active document and current line
|
||||
for (int i = 0; i < numdocuments; i++)
|
||||
{
|
||||
docstacklock lock(this, docs[i]);
|
||||
s->SendScintilla(QsciScintillaBase::SCI_MARKERDELETEALL, 1);
|
||||
s->SendScintilla(QsciScintillaBase::SCI_MARKERDELETEALL, 2);
|
||||
}
|
||||
|
||||
if (linenum <= 0)
|
||||
return;
|
||||
s->SendScintilla(QsciScintillaBase::SCI_MARKERADD, linenum-1, 1);
|
||||
s->SendScintilla(QsciScintillaBase::SCI_MARKERADD, linenum-1, 2);
|
||||
}*/
|
||||
void setNextStatement(void)
|
||||
{
|
||||
if (!curdoc)
|
||||
return;
|
||||
if (!qcdebugger)
|
||||
return; //can't move it if we're not running.
|
||||
|
||||
DebuggerSendCommand("qcjump \"%s\" %i\n", curdoc->fname, curdoc->cursorline);
|
||||
}
|
||||
void autoComplete(void)
|
||||
{
|
||||
if (!curdoc)
|
||||
return;
|
||||
|
||||
char word[256];
|
||||
char suggestions[65536];
|
||||
s->WordUnderCursor(word, sizeof(word), NULL, 0, -2);
|
||||
if (*word && GenAutoCompleteList(word, suggestions, sizeof(suggestions)))
|
||||
{
|
||||
s->SendScintilla(QsciScintillaBase::SCI_AUTOCSETFILLUPS, ".,[<>(*/+-=\t\n");
|
||||
s->SendScintilla(QsciScintillaBase::SCI_AUTOCSHOW, strlen(word), suggestions);
|
||||
}
|
||||
|
||||
//s->SendScintilla(QsciScintillaBase::SCI_CALLTIPSHOW, (int)0, "hello world");
|
||||
|
||||
//SCI_CALLTIPSHOW pos, "text"
|
||||
}
|
||||
void setNext(void)
|
||||
{
|
||||
if (!curdoc)
|
||||
|
@ -1304,7 +1618,7 @@ public:
|
|||
static class guimainwindow : public QMainWindow
|
||||
{
|
||||
public:
|
||||
QsciScintilla s;
|
||||
WrappedQsciScintilla s;
|
||||
QSplitter leftrightsplit;
|
||||
QSplitter logsplit;
|
||||
QSplitter leftsplit;
|
||||
|
@ -1318,215 +1632,231 @@ public:
|
|||
private:
|
||||
void CreateMenus(void)
|
||||
{
|
||||
auto fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
{
|
||||
auto fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
|
||||
//editor UI things
|
||||
auto fileopen = new QAction(tr("Open"), this);
|
||||
fileMenu->addAction(fileopen);
|
||||
fileopen->setShortcuts(QKeySequence::listFromString("Ctrl+O"));
|
||||
connect(fileopen, &QAction::triggered, [=]()
|
||||
{
|
||||
GUIprintf("Ctrl+O hit\n");
|
||||
});
|
||||
auto filesave = new QAction(tr("Save"), this);
|
||||
fileMenu->addAction(filesave);
|
||||
filesave->setShortcuts(QKeySequence::listFromString("Ctrl+S"));
|
||||
connect(filesave, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!docs.saveDocument(NULL))
|
||||
QMessageBox::critical(nullptr, "Error", QString::asprintf("Unable to save"));
|
||||
});
|
||||
|
||||
auto prefs = new QAction(tr("&Preferences"), this);
|
||||
fileMenu->addAction(prefs);
|
||||
prefs->setShortcuts(QKeySequence::Preferences);
|
||||
prefs->setStatusTip(tr("Reconfigure stuff"));
|
||||
connect(prefs, &QAction::triggered, [](){(new optionswindow())->show();});
|
||||
|
||||
auto goline = new QAction(tr("Go to line"), this);
|
||||
fileMenu->addAction(goline);
|
||||
goline->setShortcuts(QKeySequence::listFromString("Ctrl+G"));
|
||||
goline->setStatusTip(tr("Jump to line"));
|
||||
connect(goline, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
//editor UI things
|
||||
auto fileopen = new QAction(tr("Open"), this);
|
||||
fileMenu->addAction(fileopen);
|
||||
fileopen->setShortcuts(QKeySequence::listFromString("Ctrl+O"));
|
||||
connect(fileopen, &QAction::triggered, [=]()
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(QString(""));
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("FTEQCC Go To Line");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
ctx.mw->docs.EditFile(NULL, atoi(ctx.t->text().toUtf8().data()));
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
|
||||
auto godef = new QAction(tr("Go To Definition"), this);
|
||||
fileMenu->addAction(godef);
|
||||
godef->setShortcuts(QKeySequence::listFromString("F12"));
|
||||
connect(godef, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
GUIprintf("Ctrl+O hit\n");
|
||||
});
|
||||
auto filesave = new QAction(tr("Save"), this);
|
||||
fileMenu->addAction(filesave);
|
||||
filesave->setShortcuts(QKeySequence::listFromString("Ctrl+S"));
|
||||
connect(filesave, &QAction::triggered, [=]()
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("Go To Definition");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
GoToDefinition(ctx.t->text().toUtf8().data());
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
if (!docs.saveDocument(NULL))
|
||||
QMessageBox::critical(nullptr, "Error", QString::asprintf("Unable to save"));
|
||||
});
|
||||
|
||||
auto find = new QAction(tr("Find"), this);
|
||||
fileMenu->addAction(find);
|
||||
find->setShortcuts(QKeySequence::listFromString("Ctrl+F"));
|
||||
find->setStatusTip(tr("Search through all project files"));
|
||||
connect(find, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
auto prefs = new QAction(tr("&Preferences"), this);
|
||||
fileMenu->addAction(prefs);
|
||||
prefs->setShortcuts(QKeySequence::Preferences);
|
||||
prefs->setStatusTip(tr("Reconfigure stuff"));
|
||||
connect(prefs, &QAction::triggered, [](){(new optionswindow())->show();});
|
||||
|
||||
auto goline = new QAction(tr("Go to line"), this);
|
||||
fileMenu->addAction(goline);
|
||||
goline->setShortcuts(QKeySequence::listFromString("Ctrl+G"));
|
||||
goline->setStatusTip(tr("Jump to line"));
|
||||
connect(goline, &QAction::triggered, [=]()
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("FTEQCC Find");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
struct grepargs_s
|
||||
{
|
||||
ctx.mw->s.findFirst(ctx.t->text(), false, false, false, true);
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
connect(new QShortcut(QKeySequence(tr("F3", "File|FindNext")), this), &QShortcut::activated,
|
||||
[=]()
|
||||
{
|
||||
s.findNext();
|
||||
});
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(QString(""));
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("FTEQCC Go To Line");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
ctx.mw->docs.EditFile(NULL, atoi(ctx.t->text().toUtf8().data()));
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
|
||||
auto grep = new QAction(tr("Grep"), this);
|
||||
fileMenu->addAction(grep);
|
||||
grep->setShortcuts(QKeySequence::listFromString("Ctrl+Shift+G"));
|
||||
grep->setStatusTip(tr("Search through all project files"));
|
||||
connect(grep, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
auto find = new QAction(tr("Find In File"), this);
|
||||
fileMenu->addAction(find);
|
||||
find->setShortcuts(QKeySequence::listFromString("Ctrl+F"));
|
||||
find->setStatusTip(tr("Search for a token in the current file"));
|
||||
connect(find, &QAction::triggered, [=]()
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("FTEQCC Grep Project Files");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
struct grepargs_s
|
||||
{
|
||||
ctx.mw->files.GrepAll(ctx.t->text().toUtf8().data());
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("Find In File");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
ctx.mw->s.findFirst(ctx.t->text(), false, false, false, true);
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
connect(new QShortcut(QKeySequence(tr("F3", "File|FindNext")), this), &QShortcut::activated,
|
||||
[=]()
|
||||
{
|
||||
s.findNext();
|
||||
});
|
||||
|
||||
//convert to utf-8 chars
|
||||
//convert to Quake chars
|
||||
auto grep = new QAction(tr("Find In Project"), this);
|
||||
fileMenu->addAction(grep);
|
||||
grep->setShortcuts(QKeySequence::listFromString("Ctrl+Shift+F"));
|
||||
grep->setStatusTip(tr("Search through all project files"));
|
||||
connect(grep, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("Find In Project");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
ctx.mw->files.GrepAll(ctx.t->text().toUtf8().data());
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
|
||||
auto convertunix = new QAction(tr("Convert to Unix Endings"), this);
|
||||
fileMenu->addAction(convertunix);
|
||||
connect(convertunix, &QAction::triggered, [=]()
|
||||
{
|
||||
s.convertEols(QsciScintilla::EolUnix);
|
||||
s.setEolVisibility(false);
|
||||
});
|
||||
auto convertdos = new QAction(tr("Convert to DOS Endings"), this);
|
||||
fileMenu->addAction(convertdos);
|
||||
connect(convertdos, &QAction::triggered, [=]()
|
||||
{
|
||||
s.convertEols(QsciScintilla::EolWindows);
|
||||
s.setEolVisibility(false);
|
||||
});
|
||||
auto quit = new QAction(tr("Quit"), this);
|
||||
fileMenu->addAction(quit);
|
||||
connect(quit, &QAction::triggered, [=]()
|
||||
{
|
||||
this->close();
|
||||
});
|
||||
}
|
||||
{
|
||||
auto editMenu = menuBar()->addMenu(tr("&Edit"));
|
||||
|
||||
auto quit = new QAction(tr("Quit"), this);
|
||||
fileMenu->addAction(quit);
|
||||
connect(quit, &QAction::triggered, [=]()
|
||||
{
|
||||
this->close();
|
||||
});
|
||||
//undo
|
||||
//redo
|
||||
|
||||
auto godef = new QAction(tr("Go To Definition"), this);
|
||||
editMenu->addAction(godef);
|
||||
godef->setShortcuts(QKeySequence::listFromString("F12"));
|
||||
connect(godef, &QAction::triggered, [=]()
|
||||
{
|
||||
struct grepargs_s
|
||||
{
|
||||
guimainwindow *mw;
|
||||
QDialog *d;
|
||||
QLineEdit *t;
|
||||
} args = {this, new QDialog()};
|
||||
args.t = new QLineEdit(this->s.selectedText());
|
||||
auto l = new QVBoxLayout;
|
||||
l->addWidget(args.t);
|
||||
args.d->setLayout(l);
|
||||
args.d->setWindowTitle("Go To Definition");
|
||||
args.t->installEventFilter(new keyEnterReceiver<grepargs_s>([](grepargs_s &ctx)
|
||||
{
|
||||
GoToDefinition(ctx.t->text().toUtf8().data());
|
||||
ctx.d->done(0);
|
||||
}, args));
|
||||
args.d->show();
|
||||
});
|
||||
|
||||
auto debugMenu = menuBar()->addMenu(tr("&Debug"));
|
||||
auto debugrebuild = new QAction(tr("Rebuild"), this);
|
||||
debugMenu->addAction(debugrebuild);
|
||||
debugrebuild->setShortcuts(QKeySequence::listFromString("F7"));
|
||||
connect(debugrebuild, &QAction::triggered, [=]()
|
||||
{
|
||||
RunCompiler("", false);
|
||||
});
|
||||
auto debugsetnext = new QAction(tr("Set Next Statement"), this);
|
||||
debugMenu->addAction(debugsetnext);
|
||||
debugsetnext->setShortcuts(QKeySequence::listFromString("F8"));
|
||||
connect(debugsetnext, &QAction::triggered, [=]()
|
||||
{
|
||||
//FIXME
|
||||
});
|
||||
auto debugresume = new QAction(tr("Resume"), this);
|
||||
debugMenu->addAction(debugresume);
|
||||
debugresume->setShortcuts(QKeySequence::listFromString("F5"));
|
||||
connect(debugresume, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcresume\n"))
|
||||
DebuggerStart(); //unable to send? assume its not running.
|
||||
});
|
||||
auto debugover = new QAction(tr("Step Over"), this);
|
||||
debugMenu->addAction(debugover);
|
||||
debugover->setShortcuts(QKeySequence::listFromString("F10"));
|
||||
connect(debugover, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep over\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debuginto = new QAction(tr("Step Into"), this);
|
||||
debugMenu->addAction(debuginto);
|
||||
debuginto->setShortcuts(QKeySequence::listFromString("F11"));
|
||||
connect(debuginto, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep into\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debugout = new QAction(tr("Step Out"), this);
|
||||
debugMenu->addAction(debugout);
|
||||
debugout->setShortcuts(QKeySequence::listFromString("Shift+F11"));
|
||||
connect(debugout, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep out\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debugbreak = new QAction(tr("Toggle Breakpoint"), this);
|
||||
debugMenu->addAction(debugbreak);
|
||||
debugbreak->setShortcuts(QKeySequence::listFromString("F9"));
|
||||
connect(debugbreak, &QAction::triggered, [=]()
|
||||
{
|
||||
docs.toggleBreak();
|
||||
});
|
||||
auto autocomplete = new QAction(tr("AutoComplete"), this);
|
||||
editMenu->addAction(autocomplete);
|
||||
autocomplete->setShortcuts(QKeySequence::listFromString("Ctrl+Space"));
|
||||
connect(autocomplete, &QAction::triggered, [=]()
|
||||
{
|
||||
docs.autoComplete();
|
||||
});
|
||||
auto convertunix = new QAction(tr("Convert to Unix Endings"), this);
|
||||
editMenu->addAction(convertunix);
|
||||
connect(convertunix, &QAction::triggered, [=]()
|
||||
{
|
||||
s.convertEols(QsciScintilla::EolUnix);
|
||||
s.setEolVisibility(false);
|
||||
});
|
||||
auto convertdos = new QAction(tr("Convert to DOS Endings"), this);
|
||||
editMenu->addAction(convertdos);
|
||||
connect(convertdos, &QAction::triggered, [=]()
|
||||
{
|
||||
s.convertEols(QsciScintilla::EolWindows);
|
||||
s.setEolVisibility(false);
|
||||
});
|
||||
|
||||
//convert to utf-8 chars
|
||||
//convert to Quake chars
|
||||
}
|
||||
{
|
||||
auto debugMenu = menuBar()->addMenu(tr("&Debug"));
|
||||
|
||||
auto debugrebuild = new QAction(tr("Rebuild"), this);
|
||||
debugMenu->addAction(debugrebuild);
|
||||
debugrebuild->setShortcuts(QKeySequence::listFromString("F7"));
|
||||
connect(debugrebuild, &QAction::triggered, [=]()
|
||||
{
|
||||
RunCompiler("", false);
|
||||
});
|
||||
auto debugsetnext = new QAction(tr("Set Next Statement"), this);
|
||||
debugMenu->addAction(debugsetnext);
|
||||
debugsetnext->setShortcuts(QKeySequence::listFromString("F8"));
|
||||
connect(debugsetnext, &QAction::triggered, [=]()
|
||||
{
|
||||
docs.setNextStatement();
|
||||
});
|
||||
auto debugresume = new QAction(tr("Resume"), this);
|
||||
debugMenu->addAction(debugresume);
|
||||
debugresume->setShortcuts(QKeySequence::listFromString("F5"));
|
||||
connect(debugresume, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcresume\n"))
|
||||
DebuggerStart(); //unable to send? assume its not running.
|
||||
});
|
||||
auto debugover = new QAction(tr("Step Over"), this);
|
||||
debugMenu->addAction(debugover);
|
||||
debugover->setShortcuts(QKeySequence::listFromString("F10"));
|
||||
connect(debugover, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep over\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debuginto = new QAction(tr("Step Into"), this);
|
||||
debugMenu->addAction(debuginto);
|
||||
debuginto->setShortcuts(QKeySequence::listFromString("F11"));
|
||||
connect(debuginto, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep into\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debugout = new QAction(tr("Step Out"), this);
|
||||
debugMenu->addAction(debugout);
|
||||
debugout->setShortcuts(QKeySequence::listFromString("Shift+F11"));
|
||||
connect(debugout, &QAction::triggered, [=]()
|
||||
{
|
||||
if (!DebuggerSendCommand("qcstep out\n"))
|
||||
DebuggerStart();
|
||||
});
|
||||
auto debugbreak = new QAction(tr("Toggle Breakpoint"), this);
|
||||
debugMenu->addAction(debugbreak);
|
||||
debugbreak->setShortcuts(QKeySequence::listFromString("F9"));
|
||||
connect(debugbreak, &QAction::triggered, [=]()
|
||||
{
|
||||
docs.toggleBreak();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1597,6 +1927,52 @@ public:
|
|||
}
|
||||
} *mainwnd;
|
||||
|
||||
|
||||
void WrappedQsciScintilla::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
QMenu *menu = createStandardContextMenu();
|
||||
static char blah[256];
|
||||
|
||||
if (*WordUnderCursor(blah, sizeof(blah), NULL, 0, -3))
|
||||
{
|
||||
menu->addSeparator();
|
||||
connect(menu->addAction(tr("Go to definition")), &QAction::triggered, [=]()
|
||||
{
|
||||
GoToDefinition(blah);
|
||||
});
|
||||
connect(menu->addAction(tr("Find Usages")), &QAction::triggered, [=]()
|
||||
{
|
||||
mainwnd->files.GrepAll(blah);
|
||||
});
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
connect(menu->addAction(tr("Toggle Breakpoint")), &QAction::triggered, [=]()
|
||||
{
|
||||
mainwnd->docs.toggleBreak();
|
||||
});
|
||||
if (qcdebugger)
|
||||
{
|
||||
connect(menu->addAction(tr("Set Next Statement")), &QAction::triggered, [=]()
|
||||
{
|
||||
mainwnd->docs.setNextStatement();
|
||||
});
|
||||
connect(menu->addAction(tr("Resume")), &QAction::triggered, [=]()
|
||||
{
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
connect(menu->addAction(tr("Start Debugging")), &QAction::triggered, [=]()
|
||||
{
|
||||
DebuggerStart();
|
||||
});
|
||||
}
|
||||
|
||||
menu->exec(event->globalPos());
|
||||
delete menu;
|
||||
}
|
||||
|
||||
//called when progssrcname has changed.
|
||||
//progssrcname should already have been set.
|
||||
void UpdateFileList(void)
|
||||
|
@ -2043,7 +2419,6 @@ int GUIFileSize(const char *fname)
|
|||
|
||||
|
||||
|
||||
static QProcess *qcdebugger;
|
||||
static void DebuggerStop(void)
|
||||
{
|
||||
if (qcdebugger)
|
||||
|
|
|
@ -201,6 +201,40 @@ void GoToDefinition(const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
pbool GenAutoCompleteList(char *prefix, char *buffer, int buffersize)
|
||||
{
|
||||
QCC_def_t *def;
|
||||
int prefixlen = strlen(prefix);
|
||||
int usedbuffer = 0;
|
||||
int l;
|
||||
int fno;
|
||||
for (fno = 0; fno < sourcefilesnumdefs; fno++)
|
||||
{
|
||||
for (def = sourcefilesdefs[fno]; def; def = def->next)
|
||||
{
|
||||
if (def->scope)
|
||||
continue; //ignore locals, because we don't know where we are, and they're probably irrelevent.
|
||||
|
||||
//make sure it has the right prefix
|
||||
if (!strncmp(def->name, prefix, prefixlen))
|
||||
//but ignore it if its one of those special things that you're not meant to know about.
|
||||
if (strcmp(def->name, "IMMEDIATE") && !strchr(def->name, ':') && !strchr(def->name, '.') && !strchr(def->name, '*') && !strchr(def->name, '['))
|
||||
{
|
||||
l = strlen(def->name);
|
||||
if (l && usedbuffer+2+l < buffersize)
|
||||
{
|
||||
if (usedbuffer)
|
||||
buffer[usedbuffer++] = ' ';
|
||||
memcpy(buffer+usedbuffer, def->name, l);
|
||||
usedbuffer += l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer[usedbuffer] = 0;
|
||||
return usedbuffer>0;
|
||||
}
|
||||
|
||||
static void GUI_WriteConfigLine(FILE *file, char *part1, char *part2, char *part3, char *desc)
|
||||
{
|
||||
int align = 0;
|
||||
|
|
Loading…
Reference in a new issue