From 5aac822c712ff07c158e7278abe1cdf537a8aaf3 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 16 Dec 2014 14:31:36 +0100 Subject: [PATCH] + issue #0001038: Improve and show List properties in Tree View --- src/Gui/Widgets.cpp | 193 +++++++++++++++++++++++- src/Gui/Widgets.h | 36 ++++- src/Gui/propertyeditor/PropertyItem.cpp | 2 + 3 files changed, 223 insertions(+), 8 deletions(-) diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 80651a24a..678fc24d3 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -980,9 +980,173 @@ void StatusWidget::adjustPosition(QWidget* w) // -------------------------------------------------------------------- +class LineNumberArea : public QWidget +{ +public: + LineNumberArea(PropertyListEditor *editor) : QWidget(editor) { + codeEditor = editor; + } + + QSize sizeHint() const { + return QSize(codeEditor->lineNumberAreaWidth(), 0); + } + +protected: + void paintEvent(QPaintEvent *event) { + codeEditor->lineNumberAreaPaintEvent(event); + } + +private: + PropertyListEditor *codeEditor; +}; + +PropertyListEditor::PropertyListEditor(QWidget *parent) : QPlainTextEdit(parent) +{ + lineNumberArea = new LineNumberArea(this); + + connect(this, SIGNAL(blockCountChanged(int)), + this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), + this, SLOT(updateLineNumberArea(QRect,int))); + connect(this, SIGNAL(cursorPositionChanged()), + this, SLOT(highlightCurrentLine())); + + updateLineNumberAreaWidth(0); + highlightCurrentLine(); +} + +int PropertyListEditor::lineNumberAreaWidth() +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; + + return space; +} + +void PropertyListEditor::updateLineNumberAreaWidth(int /* newBlockCount */) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +void PropertyListEditor::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + +void PropertyListEditor::resizeEvent(QResizeEvent *e) +{ + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + +void PropertyListEditor::highlightCurrentLine() +{ + QList extraSelections; + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::yellow).lighter(160); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +void PropertyListEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(lineNumberArea); + painter.fillRect(event->rect(), Qt::lightGray); + + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); + int bottom = top + (int) blockBoundingRect(block).height(); + + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + painter.setPen(Qt::black); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + (int) blockBoundingRect(block).height(); + ++blockNumber; + } +} + +class PropertyListDialog : public QDialog +{ + int type; + +public: + PropertyListDialog(int type, QWidget* parent) : QDialog(parent),type(type) + { + } + + void accept() + { + PropertyListEditor* edit = this->findChild(); + QStringList lines; + if (edit) { + QString inputText = edit->toPlainText(); + lines = inputText.split(QString::fromLatin1("\n")); + } + + if (type == 1) { // floats + bool ok; + int line=1; + for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it, ++line) { + it->toDouble(&ok); + if (!ok) { + QMessageBox::critical(this, tr("Invalid input"), tr("Input in line %1 is not a number").arg(line)); + return; + } + } + } + else if (type == 2) { // integers + bool ok; + int line=1; + for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it, ++line) { + it->toInt(&ok); + if (!ok) { + QMessageBox::critical(this, tr("Invalid input"), tr("Input in line %1 is not a number").arg(line)); + return; + } + } + } + + QDialog::accept(); + } +}; + +// -------------------------------------------------------------------- + LabelEditor::LabelEditor (QWidget * parent) : QWidget(parent) { + type = String; QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->setSpacing(2); @@ -1008,30 +1172,40 @@ LabelEditor::~LabelEditor() QString LabelEditor::text() const { - return lineEdit->text(); + return this->plainText; } void LabelEditor::setText(const QString& s) { - lineEdit->setText(s); + this->plainText = s; + + QStringList list = this->plainText.split(QString::fromLatin1("\n")); + QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + lineEdit->setText(text); } void LabelEditor::changeText() { - QDialog dlg(this); + PropertyListDialog dlg(static_cast(type), this); + dlg.setWindowTitle(tr("List")); QVBoxLayout* hboxLayout = new QVBoxLayout(&dlg); QDialogButtonBox* buttonBox = new QDialogButtonBox(&dlg); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - QPlainTextEdit *edit = new QPlainTextEdit(&dlg); - edit->setPlainText(this->lineEdit->text()); - + PropertyListEditor *edit = new PropertyListEditor(&dlg); + edit->setPlainText(this->plainText); + hboxLayout->addWidget(edit); hboxLayout->addWidget(buttonBox); connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject())); if (dlg.exec() == QDialog::Accepted) { - this->lineEdit->setText(edit->toPlainText()); + QString inputText = edit->toPlainText(); + this->plainText = inputText; + + QStringList list = this->plainText.split(QString::fromLatin1("\n")); + QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + lineEdit->setText(text); } } @@ -1054,4 +1228,9 @@ QString LabelEditor::buttonText() const return button->text(); } +void LabelEditor::setInputType(InputType t) +{ + this->type = t; +} + #include "moc_Widgets.cpp" diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h index 8302f89f5..6f9fe35c2 100644 --- a/src/Gui/Widgets.h +++ b/src/Gui/Widgets.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -341,6 +342,30 @@ private: // ---------------------------------------------------------------------- +class PropertyListEditor : public QPlainTextEdit +{ + Q_OBJECT + +public: + PropertyListEditor(QWidget *parent = 0); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + +protected: + void resizeEvent(QResizeEvent *event); + +private Q_SLOTS: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect &, int); + +private: + QWidget *lineNumberArea; +}; + +// ---------------------------------------------------------------------- + class GuiExport LabelEditor : public QWidget { Q_OBJECT @@ -349,11 +374,13 @@ class GuiExport LabelEditor : public QWidget Q_PROPERTY(QString buttonText READ buttonText WRITE setButtonText) public: + enum InputType {String, Float, Integer}; + LabelEditor (QWidget * parent = 0); virtual ~LabelEditor(); /** - * Returns the filename. + * Returns the text. */ QString text() const; @@ -362,6 +389,11 @@ public: */ QString buttonText() const; + /** + * Set the input type. + */ + void setInputType(InputType); + public Q_SLOTS: virtual void setText(const QString &); virtual void setButtonText (const QString &); @@ -373,6 +405,8 @@ private Q_SLOTS: void changeText(); private: + InputType type; + QString plainText; QLineEdit *lineEdit; QPushButton *button; }; diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 281c68667..aad753ff5 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -1853,6 +1853,7 @@ QWidget* PropertyFloatListItem::createEditor(QWidget* parent, const QObject* rec { Gui::LabelEditor* le = new Gui::LabelEditor(parent); le->setAutoFillBackground(true); + le->setInputType(Gui::LabelEditor::Float); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; } @@ -1920,6 +1921,7 @@ QWidget* PropertyIntegerListItem::createEditor(QWidget* parent, const QObject* r { Gui::LabelEditor* le = new Gui::LabelEditor(parent); le->setAutoFillBackground(true); + le->setInputType(Gui::LabelEditor::Integer); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; }