21#include <QSortFilterProxyModel>
24#include <QTextBrowser>
27#include <QTreeWidgetItem>
35#define P3D_CONFIG_ENVVAR "P3D_CONFIG_PATH"
51 for (
unsigned int i = 0; i <
children.size(); i++)
57 if (this->path ==
path)
72 for (
unsigned int i = 0; i <
children.size(); i++) {
85 QFileInfoList infos = QDir(
path).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
88 for (QList<QFileInfo>::ConstIterator it = infos.constBegin(); it != infos.constEnd(); ++it) {
89 const QFileInfo *fi = &*it;
90 if (fi->isDir() || fi->fileName().endsWith(QString::fromLatin1(
".se"))) {
106 if (row < 0 || row > (
int)
children.size()) {
120 std::vector<QString> labels;
121 std::vector<QString> paths;
123 labels.push_back(i->label);
124 paths.push_back(i->path);
129 for (
unsigned int i = 0; i < labels.size(); i++)
171 void addPath(
const char *label,
const char *path)
178 if (!
index.isValid())
182 if (parentItem ==
root)
185 return createIndex(parentItem->
row, 0, parentItem);
188 QModelIndex
index(
int row,
int column,
const QModelIndex &
parent = QModelIndex())
const override
190 if (!hasIndex(row, column,
parent))
192 else if (!
parent.isValid())
196 return createIndex(row, column, item->getChild(row));
214 return item->getChildCount();
218 QVariant
data(
const QModelIndex &
index,
int role = Qt::DisplayRole)
const override
220 if (!
index.isValid())
222 if (role != Qt::DisplayRole)
228 return QVariant(item->label);
242 return createIndex(item->
row, 0, item);
253 : QSortFilterProxyModel(parent)
265 if (sourceParent.isValid() && sourceModel()->data(sourceParent).toString().contains(filterRegularExpression()))
267 QString data = sourceModel()->data(sourceModel()->index(sourceRow, 0, sourceParent)).toString();
268 bool keep = data.contains(filterRegularExpression());
270 QModelIndex subIndex = sourceModel()->index(sourceRow, 0, sourceParent);
271 if (subIndex.isValid()) {
272 for (
int i = 0; i < sourceModel()->rowCount(subIndex); ++i)
287 , _context(QString())
288 , _searchPath(QString())
289 , _applyOnSelect(true)
291 auto *rootLayout =
new QVBoxLayout;
292 rootLayout->setContentsMargins({});
293 this->setLayout(rootLayout);
295 auto *searchAndClearLayout =
new QHBoxLayout();
298 searchAndClearLayout->addWidget(
exprFilter, 2);
299 auto *clearFilterButton =
new QPushButton(tr(
"X"));
300 clearFilterButton->setFixedWidth(24);
301 searchAndClearLayout->addWidget(clearFilterButton, 1);
302 rootLayout->addLayout(searchAndClearLayout);
303 connect(clearFilterButton, SIGNAL(clicked()), SLOT(
clearFilter()));
312 treeNew->setHeaderHidden(
true);
313 rootLayout->addWidget(
treeNew);
315 treeNew->setSelectionMode(QAbstractItemView::SingleSelection);
316 connect(
treeNew->selectionModel(), SIGNAL(currentChanged(
const QModelIndex &,
const QModelIndex &)), SLOT(
handleSelection(
const QModelIndex &,
const QModelIndex &)));
321 labels.append(QString::fromStdString(name));
322 paths.append(QString::fromStdString(path));
334 QModelIndex sel =
treeNew->currentIndex();
336 QModelIndex realCurrent =
proxyModel->mapToSource(sel);
337 auto *item = (
ExprTreeItem *)realCurrent.internalPointer();
338 return item->path.toStdString();
340 return std::string(
"");
345 QModelIndex index =
treeModel->
find(QString::fromLatin1(path));
358 if (current.isValid()) {
359 QModelIndex realCurrent =
proxyModel->mapToSource(current);
360 auto *item = (
ExprTreeItem *)realCurrent.internalPointer();
361 QString path = item->path;
362 if (path.endsWith(QString::fromLatin1(
".se"))) {
364 if (file.open(QIODevice::ReadOnly)) {
365 QTextStream fileContents(&file);
393 proxyModel->setFilterRegularExpression(QRegularExpression(str));
395 if (!str.isEmpty()) {
404 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save Expression"), QString::fromStdString(
_userExprDir), tr(
"*.se"));
406 if (path.length() > 0) {
407 std::ofstream file(path.toStdString().c_str());
409 QString msg = tr(
"Could not open file %1 for writing").arg(path);
410 QMessageBox::warning(
this, tr(
"Error"), QString::fromLatin1(
"<font face=fixed>%1</font>").arg(msg));
423 QString path = QFileDialog::getSaveFileName(
this, tr(
"Save Expression"), QString::fromStdString(
_localExprDir), tr(
"*.se"));
425 if (path.length() > 0) {
426 std::ofstream file(path.toStdString().c_str());
428 QString msg = tr(
"Could not open file %1 for writing").arg(path);
429 QMessageBox::warning(
this, tr(
"Error"), QString::fromLatin1(
"<font face=fixed>%1</font>").arg(msg));
443 if (path.length() == 0) {
447 std::ofstream file(path.c_str());
449 QString msg = tr(
"Could not open file %1 for writing. Is it read-only?").arg(QString::fromStdString(path));
450 QMessageBox::warning(
this, tr(
"Error"), tr(
"<font face=fixed>%1</font>").arg(msg));
470 char *homepath = getenv(
"HOME");
472 std::string path = std::string(homepath) +
"/" + context +
"/expressions/";
473 if (QDir(QString::fromStdString(path)).exists()) {
475 addPath(
"My Expressions", path);
487 const char *env =
nullptr;
488 bool enableLocal =
false;
508 std::string configFile = std::string(env) +
"/config.txt";
509 std::ifstream file(configFile.c_str());
516 std::array<char, 1024> buffer{};
517 file.getline(buffer.data(), 1024);
519 if (key ==
"ExpressionDir") {
524 if (QDir(QString::fromStdString(path)).exists())
526 }
else if (key ==
"ExpressionSubDir") {
530 if (QDir(QString::fromStdString(path)).exists()) {
537 }
else if (key ==
"GlobalRepo") {
540 path +=
"/expressions/";
541 if (QDir(QString::fromStdString(path)).exists())
543 }
else if (key ==
"LocalRepo") {
546 path +=
"/expressions/";
548 if (QDir(QString::fromStdString(path)).exists()) {
581 std::array<char, 1024> buffer {};
582 file.getline(buffer.data(), 1024);
#define P3D_CONFIG_ENVVAR
void expandToDepth(int depth)
void setSearchPath(const QString &context, const QString &path)
void handleSelection(const QModelIndex ¤t, const QModelIndex &previous)
void saveLocalExpressionAs()
void filterChanged(const QString &str)
ExprBrowser(QWidget *parent, ExprEditor *editor)
void addUserExpressionPath(const std::string &context)
void addPath(const std::string &name, const std::string &path)
std::string getSelectedPath()
ExprTreeFilterModel * proxyModel
void selectPath(const char *path)
std::string _localExprDir
ExprTreeModel * treeModel
void setExpr(const QString &expression, bool apply=false)
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
ExprTreeFilterModel(QWidget *parent=nullptr)
ExprTreeItem * getChild(const int row)
ExprTreeItem(ExprTreeItem *parent, const QString &label, const QString &path)
std::vector< ExprTreeItem * > children
void addChild(ExprTreeItem *child)
ExprTreeItem * find(QString path)
~ExprTreeModel() override
QModelIndex parent(const QModelIndex &index) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QModelIndex find(QString path)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int columnCount(const QModelIndex &) const override
void addPath(const char *label, const char *path)