mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Formula Editor Completer
.. edit formulas on LTM tool with autocompletion but not when in comments.
This commit is contained in:
147
src/LTMTool.cpp
147
src/LTMTool.cpp
@@ -22,6 +22,8 @@
|
||||
#include "Athlete.h"
|
||||
#include "Settings.h"
|
||||
#include "Units.h"
|
||||
#include "Tab.h"
|
||||
#include "RideNavigator.h"
|
||||
#include "HelpWhatsThis.h"
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
@@ -1502,6 +1504,12 @@ EditMetricDetailDialog::estimateName()
|
||||
/*----------------------------------------------------------------------
|
||||
* EDIT METRIC DETAIL DIALOG
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
static bool insensitiveLessThan(const QString &a, const QString &b)
|
||||
{
|
||||
return a.toLower() < b.toLower();
|
||||
}
|
||||
|
||||
EditMetricDetailDialog::EditMetricDetailDialog(Context *context, LTMTool *ltmTool, MetricDetail *metricDetail) :
|
||||
QDialog(context->mainWindow, Qt::Dialog), context(context), ltmTool(ltmTool), metricDetail(metricDetail)
|
||||
{
|
||||
@@ -1692,12 +1700,43 @@ EditMetricDetailDialog::EditMetricDetailDialog(Context *context, LTMTool *ltmToo
|
||||
//formulaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
QVBoxLayout *formulaLayout = new QVBoxLayout(formulaWidget);
|
||||
formulaLayout->addStretch();
|
||||
formulaEdit = new QTextEdit(this);
|
||||
formulaEdit = new DataFilterEdit(this);
|
||||
//formulaEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
formulaLayout->addWidget(formulaEdit);
|
||||
formulaLayout->addStretch();
|
||||
formulaEdit->setText(metricDetail->formula);
|
||||
|
||||
// get suitably formated list
|
||||
QList<QString> list;
|
||||
QString last;
|
||||
SpecialFields sp;
|
||||
|
||||
// get sorted list
|
||||
QStringList names = context->tab->rideNavigator()->logicalHeadings;
|
||||
qSort(names.begin(), names.end(), insensitiveLessThan);
|
||||
|
||||
foreach(QString name, names) {
|
||||
|
||||
// handle dups
|
||||
if (last == name) continue;
|
||||
last = name;
|
||||
|
||||
// Handle bikescore tm
|
||||
if (name.startsWith("BikeScore")) name = QString("BikeScore");
|
||||
|
||||
// Always use the "internalNames" in Filter expressions
|
||||
name = sp.internalName(name);
|
||||
|
||||
// we do very little to the name, just space to _ and lower case it for now...
|
||||
name.replace(' ', '_');
|
||||
list << name;
|
||||
}
|
||||
|
||||
// set new list
|
||||
// create an empty completer, configchanged will fix it
|
||||
DataFilterCompleter *completer = new DataFilterCompleter(list, this);
|
||||
formulaEdit->setCompleter(completer);
|
||||
|
||||
// stress selection
|
||||
stressTypeSelect = new QComboBox(this);
|
||||
stressTypeSelect->addItem(tr("Short Term Stress (STS/ATL)"), STRESS_STS);
|
||||
@@ -2259,4 +2298,110 @@ LTMTool::setFilter(QStringList files)
|
||||
filenames = files;
|
||||
|
||||
emit filterChanged();
|
||||
}
|
||||
|
||||
DataFilterEdit::DataFilterEdit(QWidget *parent)
|
||||
: QTextEdit(parent), c(0)
|
||||
{
|
||||
}
|
||||
|
||||
DataFilterEdit::~DataFilterEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void DataFilterEdit::setCompleter(QCompleter *completer)
|
||||
{
|
||||
if (c)
|
||||
QObject::disconnect(c, 0, this, 0);
|
||||
|
||||
c = completer;
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
c->setWidget(this);
|
||||
c->setCompletionMode(QCompleter::PopupCompletion);
|
||||
c->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
QObject::connect(c, SIGNAL(activated(QString)),
|
||||
this, SLOT(insertCompletion(QString)));
|
||||
}
|
||||
|
||||
QCompleter *DataFilterEdit::completer() const
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
void DataFilterEdit::insertCompletion(const QString& completion)
|
||||
{
|
||||
if (c->widget() != this)
|
||||
return;
|
||||
QTextCursor tc = textCursor();
|
||||
int extra = completion.length() - c->completionPrefix().length();
|
||||
tc.movePosition(QTextCursor::Left);
|
||||
tc.movePosition(QTextCursor::EndOfWord);
|
||||
tc.insertText(completion.right(extra));
|
||||
setTextCursor(tc);
|
||||
}
|
||||
|
||||
QString DataFilterEdit::textUnderCursor() const
|
||||
{
|
||||
QTextCursor tc = textCursor();
|
||||
tc.select(QTextCursor::WordUnderCursor);
|
||||
return tc.selectedText();
|
||||
}
|
||||
|
||||
void DataFilterEdit::focusInEvent(QFocusEvent *e)
|
||||
{
|
||||
if (c) c->setWidget(this);
|
||||
QTextEdit::focusInEvent(e);
|
||||
}
|
||||
|
||||
void DataFilterEdit::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (c && c->popup()->isVisible()) {
|
||||
// The following keys are forwarded by the completer to the widget
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Escape:
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
e->ignore();
|
||||
return; // let the completer do default behavior
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E
|
||||
if (!c || !isShortcut) // do not process the shortcut when we have a completer
|
||||
QTextEdit::keyPressEvent(e);
|
||||
|
||||
const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
|
||||
if (!c || (ctrlOrShift && e->text().isEmpty()))
|
||||
return;
|
||||
|
||||
static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word
|
||||
bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
|
||||
QString completionPrefix = textUnderCursor();
|
||||
|
||||
// are we in a comment ?
|
||||
QString line = textCursor().block().text().trimmed();
|
||||
for(int i=textCursor().positionInBlock(); i>=0; i--)
|
||||
if (line[i]=='#') return;
|
||||
|
||||
if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 1
|
||||
|| eow.contains(e->text().right(1)))) {
|
||||
c->popup()->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (completionPrefix != c->completionPrefix()) {
|
||||
c->setCompletionPrefix(completionPrefix);
|
||||
c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
|
||||
}
|
||||
QRect cr = cursorRect();
|
||||
cr.setWidth(c->popup()->sizeHintForColumn(0)
|
||||
+ c->popup()->verticalScrollBar()->sizeHint().width());
|
||||
c->complete(cr); // popup it up!
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#define SYS_DATE 1
|
||||
#define USER_DATE 2
|
||||
|
||||
class DataFilterEdit;
|
||||
|
||||
class LTMTool : public QWidget
|
||||
{
|
||||
@@ -205,7 +206,7 @@ class EditMetricDetailDialog : public QDialog
|
||||
QComboBox *stressTypeSelect; // STS, LTS, SB, RR et al
|
||||
|
||||
// formula
|
||||
QTextEdit *formulaEdit; // edit your formula
|
||||
DataFilterEdit *formulaEdit; // edit your formula
|
||||
|
||||
QComboBox *curveStyle,
|
||||
*curveSymbol;
|
||||
@@ -227,5 +228,29 @@ class EditMetricDetailDialog : public QDialog
|
||||
QList<RideFile::SeriesType> seriesList;
|
||||
};
|
||||
|
||||
#endif // _GC_LTMTool_h
|
||||
class DataFilterEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DataFilterEdit(QWidget *parent = 0);
|
||||
~DataFilterEdit();
|
||||
|
||||
void setCompleter(QCompleter *c);
|
||||
QCompleter *completer() const;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
|
||||
private slots:
|
||||
void insertCompletion(const QString &completion);
|
||||
|
||||
private:
|
||||
QString textUnderCursor() const;
|
||||
|
||||
private:
|
||||
QCompleter *c;
|
||||
};
|
||||
|
||||
#endif // _GC_LTMTool_h
|
||||
|
||||
@@ -45,6 +45,7 @@ class DataFilter;
|
||||
class GcMiniCalendar;
|
||||
class SearchBox;
|
||||
class RideTreeView;
|
||||
class EditMetricDetailDialog;
|
||||
|
||||
//
|
||||
// The RideNavigator
|
||||
@@ -71,6 +72,7 @@ class RideNavigator : public GcWindow
|
||||
friend class ::GcMiniCalendar;
|
||||
friend class ::DataFilter;
|
||||
friend class ::SearchBox;
|
||||
friend class ::EditMetricDetailDialog;
|
||||
|
||||
public:
|
||||
RideNavigator(Context *, bool mainwindow = false);
|
||||
|
||||
@@ -127,6 +127,7 @@ public:
|
||||
inline DataFilterCompleter(const QStringList& words, QObject * parent) :
|
||||
QCompleter(parent), m_list(words), m_model()
|
||||
{
|
||||
m_model.setStringList(words);
|
||||
setModel(&m_model);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user