##// END OF EJS Templates
Started to refactor the API to allow integrating different plot types
Tero Ahola -
r19:b231f8e5fa43
parent child
Show More
@@ -0,0 +1,53
1 #include "qchartwidget.h"
2 #include "qxyseries.h"
3 #include "xylinechart_p.h"
4 #include <QGraphicsView>
5 #include <QGraphicsScene>
6
7 QCHART_BEGIN_NAMESPACE
8
9 class QChartWidgetPrivate
10 {
11 public:
12 QChartWidgetPrivate(QWidget *parent) : m_view(0), m_scene(0), m_chart(0) {
13 m_scene = new QGraphicsScene();
14 m_view = new QGraphicsView(m_scene, parent);
15 m_view->resize(490, 300);
16 m_view->show();
17 }
18 ~QChartWidgetPrivate() {
19 delete m_view;
20 delete m_scene;
21 }
22
23 QGraphicsView *m_view;
24 QGraphicsScene *m_scene;
25 QChart* m_chart;
26 };
27
28 QChartWidget::QChartWidget(QWidget *parent) :
29 QWidget(parent),
30 d(new QChartWidgetPrivate(this))
31 {
32 setMinimumSize(d->m_view->size());
33 }
34
35 QChartWidget::~QChartWidget()
36 {
37 delete d;
38 }
39
40 void QChartWidget::addDataSeries(
41 QChart::DataSeriesType dataSeriesType,
42 QList<QXYSeries*> dataset)
43 {
44 // TODO: implement management of several data series of different types
45
46 d->m_chart = QChart::createXYLineChart(dataset);
47 d->m_scene->addItem(d->m_chart);
48 d->m_chart->setSize(this->size());
49 }
50
51 #include "moc_qchartwidget.cpp"
52
53 QCHART_END_NAMESPACE
@@ -0,0 +1,36
1 #ifndef QCHARTWIDGET_H
2 #define QCHARTWIDGET_H
3
4 #include "qchartconfig.h"
5 #include "qchart.h"
6 #include <QWidget>
7
8 QCHART_BEGIN_NAMESPACE
9
10 class QXYSeries;
11 class QChartWidgetPrivate;
12
13 class QCHART_EXPORT QChartWidget : public QWidget
14 {
15 Q_OBJECT
16 public:
17 explicit QChartWidget(QWidget *parent = 0);
18 ~QChartWidget();
19 // TODO: replace QXYSeries list with a charts data API
20 // TODO: return QChartDataSeries
21 void addDataSeries(QChart::DataSeriesType dataSeriesType, QList<QXYSeries*> dataset);
22
23 signals:
24
25 public slots:
26
27 private:
28 friend class QChartWidgetPrivate;
29 Q_DISABLE_COPY(QChartWidget)
30 // Q_DECLARE_PRIVATE(QChartWidget)
31 QChartWidgetPrivate * const d;
32 };
33
34 QCHART_END_NAMESPACE
35
36 #endif // QCHARTWIDGET_H
@@ -0,0 +1,24
1 #include "dataseriedialog.h"
2 #include <QDialogButtonBox>
3 #include <QAbstractButton>
4 #include <QDebug>
5
6 DataSerieDialog::DataSerieDialog(QWidget *parent) :
7 QDialog(parent)
8 {
9 QDialogButtonBox *addSeriesBox = new QDialogButtonBox(Qt::Vertical, this);
10 addSeriesBox->addButton("Line", QDialogButtonBox::AcceptRole);
11 addSeriesBox->addButton("Area", QDialogButtonBox::AcceptRole);
12 addSeriesBox->addButton("Bar", QDialogButtonBox::AcceptRole);
13 addSeriesBox->addButton("Pie", QDialogButtonBox::AcceptRole);
14 addSeriesBox->addButton("Scatter", QDialogButtonBox::AcceptRole);
15 addSeriesBox->addButton("Spline", QDialogButtonBox::AcceptRole);
16 connect(addSeriesBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(addSeries(QAbstractButton *)));
17 this->setFixedSize(addSeriesBox->sizeHint());
18 }
19
20 void DataSerieDialog::addSeries(QAbstractButton *button)
21 {
22 addSeries(button->text().toAscii());
23 accept();
24 }
@@ -0,0 +1,21
1 #ifndef DATASERIEDIALOG_H
2 #define DATASERIEDIALOG_H
3
4 #include <QDialog>
5
6 class QAbstractButton;
7
8 class DataSerieDialog : public QDialog
9 {
10 Q_OBJECT
11 public:
12 explicit DataSerieDialog(QWidget *parent = 0);
13
14 signals:
15 void addSeries(QString series);
16
17 public slots:
18 void addSeries(QAbstractButton *button);
19 };
20
21 #endif // DATASERIEDIALOG_H
1 NO CONTENT: file renamed from src/xylinechart/axis.cpp to src/axis.cpp
NO CONTENT: file renamed from src/xylinechart/axis.cpp to src/axis.cpp
1 NO CONTENT: file renamed from src/xylinechart/axis_p.h to src/axis_p.h
NO CONTENT: file renamed from src/xylinechart/axis_p.h to src/axis_p.h
@@ -14,17 +14,16 QChart::~QChart(){}
14
14
15 QChart* QChart::createXYLineChart(const QList<QXYSeries*>& dataset)
15 QChart* QChart::createXYLineChart(const QList<QXYSeries*>& dataset)
16 {
16 {
17
18 XYLineChart* chart = new XYLineChart();
17 XYLineChart* chart = new XYLineChart();
19 foreach (const QXYSeries* series,dataset) {
18 foreach (const QXYSeries* series,dataset) {
20 chart->addXYSeries(series);
19 chart->addXYSeries(series);
21 }
20 }
22 return chart;
21 return chart;
23 }
22 }
24
23
25 void QChart::setMargin(int margin)
24 void QChart::setMargin(int margin)
26 {
25 {
27 m_marginSize=margin;
26 m_marginSize = margin;
28 }
27 }
29
28
30 QCHART_END_NAMESPACE
29 QCHART_END_NAMESPACE
@@ -9,6 +9,15 QCHART_BEGIN_NAMESPACE
9
9
10 class QCHART_EXPORT QChart : public QGraphicsItem
10 class QCHART_EXPORT QChart : public QGraphicsItem
11 {
11 {
12 public:
13 enum DataSeriesType {
14 DataSeriesTypeLine = 0,
15 DataSeriesTypeArea,
16 DataSeriesTypeBar,
17 DataSeriesTypePie,
18 DataSeriesTypeScatter,
19 DataSeriesTypeSpline
20 };
12
21
13 protected:
22 protected:
14 QChart(QGraphicsItem* parent =0);
23 QChart(QGraphicsItem* parent =0);
@@ -4,27 +4,28 QT += core \
4 gui
4 gui
5 CONFIG += debug_and_release
5 CONFIG += debug_and_release
6 CONFIG(debug, debug|release):TARGET = QChartd
6 CONFIG(debug, debug|release):TARGET = QChartd
7
7 SOURCES += \
8 SOURCES += \
8 xylinechart/qchartwidget.cpp \
9 xylinechart/qchartgraphicswidget.cpp \
9 xylinechart/qchart.cpp \
10 xylinechart/qxyseries.cpp \
10 xylinechart/qxyseries.cpp \
11 xylinechart/axis.cpp \
12 xylinechart/xylinechart.cpp \
11 xylinechart/xylinechart.cpp \
13 xylinechart/xygrid.cpp \
12 xylinechart/xygrid.cpp \
14 xylinechart/xyplotdata.cpp
13 xylinechart/xyplotdata.cpp \
14 qchart.cpp \
15 axis.cpp \
16 qchartwidget.cpp
15
17
16 PRIVATE_HEADERS += \
18 PRIVATE_HEADERS += \
17 xylinechart/xylinechart_p.h \
19 xylinechart/xylinechart_p.h \
18 xylinechart/axis_p.h \
19 xylinechart/xygrid_p.h \
20 xylinechart/xygrid_p.h \
20 xylinechart/xyplotdata_p.h
21 xylinechart/xyplotdata_p.h \
21
22 axis_p.h
22 PUBLIC_HEADERS += \
23 PUBLIC_HEADERS += \
23 xylinechart/qchart.h \
24 xylinechart/qxyseries.h \
24 xylinechart/qxyseries.h \
25 xylinechart/qchartwidget.h \
25 xylinechart/qchartgraphicswidget.h \
26 qchartconfig.h
26 qchart.h \
27
27 qchartwidget.h \
28 qchartconfig.h
28 HEADERS += $$PUBLIC_HEADERS
29 HEADERS += $$PUBLIC_HEADERS
29 HEADERS += $$PRIVATE_HEADERS
30 HEADERS += $$PRIVATE_HEADERS
30
31
@@ -1,38 +1,38
1 #include "qchartwidget.h"
1 #include "qchartgraphicswidget.h"
2 #include "qchart.h"
2 #include "qchart.h"
3
3
4 QCHART_BEGIN_NAMESPACE
4 QCHART_BEGIN_NAMESPACE
5
5
6
6
7 class QChartWidgetPrivate
7 class QChartGraphicsWidgetPrivate
8 {
8 {
9 public:
9 public:
10 QChart* chart;
10 QChart* chart;
11 //Q_DECLARE_PUBLIC(ChartWidget)
11 //Q_DECLARE_PUBLIC(ChartWidget)
12 QChartWidgetPrivate() {}
12 QChartGraphicsWidgetPrivate() {}
13 };
13 };
14
14
15 ////////////////////////////////////////////////////////////////////////////
15 ////////////////////////////////////////////////////////////////////////////
16
16
17 QChartWidget::QChartWidget(QGraphicsItem *parent,Qt::WindowFlags wFlags)
17 QChartGraphicsWidget::QChartGraphicsWidget(QGraphicsItem *parent,Qt::WindowFlags wFlags)
18 : QGraphicsWidget(parent,wFlags),
18 : QGraphicsWidget(parent,wFlags),
19 d_ptr(new QChartWidgetPrivate())
19 d_ptr(new QChartGraphicsWidgetPrivate())
20 {
20 {
21 }
21 }
22
22
23 QChartWidget::~QChartWidget()
23 QChartGraphicsWidget::~QChartGraphicsWidget()
24 {
24 {
25 delete d_ptr;
25 delete d_ptr;
26 }
26 }
27
27
28
28
29 void QChartWidget::addChart(QChart *chart)
29 void QChartGraphicsWidget::addChart(QChart *chart)
30 {
30 {
31 d_ptr->chart=chart;
31 d_ptr->chart=chart;
32 chart->setParentItem(this);
32 chart->setParentItem(this);
33 }
33 }
34
34
35 void QChartWidget::setGeometry(const QRectF & rect)
35 void QChartGraphicsWidget::setGeometry(const QRectF & rect)
36 {
36 {
37 d_ptr->chart->setSize(rect.size());
37 d_ptr->chart->setSize(rect.size());
38 QGraphicsWidget::setGeometry(rect);
38 QGraphicsWidget::setGeometry(rect);
@@ -1,5 +1,5
1 #ifndef QCHARTWIDGET_H
1 #ifndef QCHARTGRAPHICSWIDGET_H
2 #define QCHARTWIDGET_H
2 #define QCHARTGRAPHICSWIDGET_H
3
3
4 #include <qchartconfig.h>
4 #include <qchartconfig.h>
5 #include <QGraphicsWidget>
5 #include <QGraphicsWidget>
@@ -9,14 +9,14 class QGraphicsItem;
9 QCHART_BEGIN_NAMESPACE
9 QCHART_BEGIN_NAMESPACE
10
10
11 class QChart;
11 class QChart;
12 class QChartWidgetPrivate;
12 class QChartGraphicsWidgetPrivate;
13
13
14 class QCHART_EXPORT QChartWidget : public QGraphicsWidget
14 class QCHART_EXPORT QChartGraphicsWidget : public QGraphicsWidget
15 {
15 {
16
16
17 public:
17 public:
18 explicit QChartWidget(QGraphicsItem *parent = 0,Qt::WindowFlags wFlags = 0);
18 explicit QChartGraphicsWidget(QGraphicsItem *parent = 0,Qt::WindowFlags wFlags = 0);
19 ~QChartWidget();
19 ~QChartGraphicsWidget();
20
20
21 QChart* chart() const;
21 QChart* chart() const;
22 void addChart(QChart* chart);
22 void addChart(QChart* chart);
@@ -24,9 +24,9 public:
24 virtual void setGeometry(const QRectF & rect);
24 virtual void setGeometry(const QRectF & rect);
25
25
26 private:
26 private:
27 Q_DISABLE_COPY(QChartWidget)
27 Q_DISABLE_COPY(QChartGraphicsWidget)
28 Q_DECLARE_PRIVATE(QChartWidget)
28 Q_DECLARE_PRIVATE(QChartGraphicsWidget)
29 QChartWidgetPrivate * const d_ptr;
29 QChartGraphicsWidgetPrivate * const d_ptr;
30 };
30 };
31
31
32 QCHART_END_NAMESPACE
32 QCHART_END_NAMESPACE
@@ -1,7 +1,9
1 #include "qxyseries.h"
1 #include "qxyseries.h"
2
2
3 QCHART_BEGIN_NAMESPACE
4
3 QXYSeries::QXYSeries():
5 QXYSeries::QXYSeries():
4 m_color(Qt::black)
6 m_color(Qt::black)
5 {
7 {
6 }
8 }
7
9
@@ -57,3 +59,5 QDebug operator<< (QDebug debug, const QXYSeries series)
57 }
59 }
58 return debug.space();
60 return debug.space();
59 }
61 }
62
63 QCHART_END_NAMESPACE
@@ -1,10 +1,13
1 #ifndef QXYSERIES_H_
1 #ifndef QXYSERIES_H_
2 #define QXYSERIES_H_
2 #define QXYSERIES_H_
3
4 #include "qchartconfig.h"
3 #include <QDebug>
5 #include <QDebug>
4 #include <QColor>
6 #include <QColor>
5
7
8 QCHART_BEGIN_NAMESPACE
6
9
7 class QXYSeries
10 class QCHART_EXPORT QXYSeries
8 {
11 {
9 public:
12 public:
10 QXYSeries();
13 QXYSeries();
@@ -25,4 +28,6 private:
25
28
26 };
29 };
27
30
31 QCHART_END_NAMESPACE
32
28 #endif
33 #endif
@@ -7,22 +7,23 contains(QT_MAJOR_VERSION, 5) {
7 }
7 }
8
8
9 CONFIG += charts
9 CONFIG += charts
10 CHARTS += widget
11
10
12 OBJECTS_DIR = tmp
11 OBJECTS_DIR = tmp
13 MOC_DIR = tmp
12 MOC_DIR = tmp
14
13
15 SOURCES += main.cpp \
14 SOURCES += main.cpp \
16 mainwidget.cpp \
15 mainwidget.cpp \
17 qscatterseries.cpp \
16 # qscatterseries.cpp \
18 qchartwidget.cpp \
17 # qseriespointgraphicsitem.cpp \
19 qseriespointgraphicsitem.cpp
18 dataseriedialog.cpp
20
19
21 HEADERS += \
20 HEADERS += \
22 mainwidget.h \
21 mainwidget.h \
23 qscatterseries.h \
22 # qscatterseries.h \
24 qchartwidget.h \
23 # qseriespointgraphicsitem.h \
25 qseriespointgraphicsitem.h
24 dataseriedialog.h
25
26
26
27
27
28
28
29
@@ -1,6 +1,6
1 #include "mainwidget.h"
1 #include "mainwidget.h"
2 #include "qchartwidget.h"
2 #include "dataseriedialog.h"
3 //#include <chartwidget.h>
3 #include <qxyseries.h>
4 #include <QPushButton>
4 #include <QPushButton>
5 #include <QComboBox>
5 #include <QComboBox>
6 #include <QSpinBox>
6 #include <QSpinBox>
@@ -13,6 +13,8
13 #include <cmath>
13 #include <cmath>
14 #include <QDebug>
14 #include <QDebug>
15
15
16 QCHART_USE_NAMESPACE
17
16 MainWidget::MainWidget(QWidget *parent) :
18 MainWidget::MainWidget(QWidget *parent) :
17 QWidget(parent)
19 QWidget(parent)
18 {
20 {
@@ -22,15 +24,18 MainWidget::MainWidget(QWidget *parent) :
22 // Chart type
24 // Chart type
23 // TODO: How about multiple types?
25 // TODO: How about multiple types?
24 // Should the type be a property of a graph instead of the chart?
26 // Should the type be a property of a graph instead of the chart?
25 QComboBox *chartTypeCombo = new QComboBox(this);
27 // QComboBox *chartTypeCombo = new QComboBox(this);
26 chartTypeCombo->addItem("Line");
28 // chartTypeCombo->addItem("Line");
27 chartTypeCombo->addItem("Area");
29 // chartTypeCombo->addItem("Area");
28 chartTypeCombo->addItem("Bar");
30 // chartTypeCombo->addItem("Bar");
29 chartTypeCombo->addItem("Pie");
31 // chartTypeCombo->addItem("Pie");
30 chartTypeCombo->addItem("Scatter");
32 // chartTypeCombo->addItem("Scatter");
31 chartTypeCombo->addItem("Spline");
33 // chartTypeCombo->addItem("Spline");
32 connect(chartTypeCombo, SIGNAL(currentIndexChanged(int)),
34 // connect(chartTypeCombo, SIGNAL(currentIndexChanged(int)),
33 this, SLOT(chartTypeChanged(int)));
35 // this, SLOT(chartTypeChanged(int)));
36
37 QPushButton *addSeriesButton = new QPushButton("Add series");
38 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
34
39
35 // Test data selector
40 // Test data selector
36 QComboBox *testDataCombo = new QComboBox(this);
41 QComboBox *testDataCombo = new QComboBox(this);
@@ -78,8 +83,10 MainWidget::MainWidget(QWidget *parent) :
78
83
79 QGridLayout *grid = new QGridLayout();
84 QGridLayout *grid = new QGridLayout();
80 QHBoxLayout *hbox = new QHBoxLayout();
85 QHBoxLayout *hbox = new QHBoxLayout();
81 grid->addWidget(new QLabel("Chart type:"), 0, 0);
86 //grid->addWidget(new QLabel("Add series:"), 0, 0);
82 grid->addWidget(chartTypeCombo, 0, 1);
87 grid->addWidget(addSeriesButton, 0, 1);
88 // grid->addWidget(new QLabel("Chart type:"), 0, 0);
89 // grid->addWidget(chartTypeCombo, 0, 1);
83 grid->addWidget(new QLabel("Data:"), 1, 0);
90 grid->addWidget(new QLabel("Data:"), 1, 0);
84 grid->addWidget(testDataCombo, 1, 1);
91 grid->addWidget(testDataCombo, 1, 1);
85 grid->addWidget(new QLabel("Background:"), 2, 0);
92 grid->addWidget(new QLabel("Background:"), 2, 0);
@@ -108,15 +115,39 MainWidget::MainWidget(QWidget *parent) :
108 testDataChanged(0);
115 testDataChanged(0);
109 }
116 }
110
117
118 void MainWidget::addSeries()
119 {
120 DataSerieDialog dialog(this);
121 connect(&dialog, SIGNAL(addSeries(QString)), this, SLOT(addSeries(QString)));
122 dialog.exec();
123 }
124
125 void MainWidget::addSeries(QString series)
126 {
127 if (series == "Scatter") {
128 QXYSeries* series0 = new QXYSeries();
129 series0->setColor(Qt::blue);
130 for (int x = 0; x < 100; x++)
131 series0->add(x, abs(sin(3.14159265358979 / 50 * x) * 100));
132 QList<QXYSeries*> dataset;
133 dataset << series0;
134 m_chartWidget->addDataSeries(QChart::DataSeriesTypeScatter, dataset);
135 //m_chartWidget->addDataSeries(dataset);
136 } else {
137 // TODO
138 qDebug() << "addSeries: " << series;
139 }
140 }
141
111 void MainWidget::chartTypeChanged(int itemIndex)
142 void MainWidget::chartTypeChanged(int itemIndex)
112 {
143 {
113 // TODO: change chart type
144 // TODO: change chart type
114 switch (itemIndex) {
145 switch (itemIndex) {
115 case 4:
146 case 4:
116 m_chartWidget->setType(4);
147 //m_chartWidget->setType(4);
117 break;
148 break;
118 default: {
149 default: {
119 m_chartWidget->setType(0);
150 //m_chartWidget->setType(0);
120 break;
151 break;
121 }
152 }
122 }
153 }
@@ -126,37 +157,36 void MainWidget::testDataChanged(int itemIndex)
126 {
157 {
127 qDebug() << "testDataChanged: " << itemIndex;
158 qDebug() << "testDataChanged: " << itemIndex;
128
159
129 switch (itemIndex) {
160 // switch (itemIndex) {
130 case 0: {
161 // case 0: {
131 QList<QChartDataPoint> data;
162 // QList<QChartDataPoint> data;
132 for (int x = 0; x < 20; x++) {
163 // for (int x = 0; x < 20; x++) {
133 data.append(QChartDataPoint() << x << x / 2);
164 // data.append(QChartDataPoint() << x << x / 2);
134 }
165 // }
135 m_chartWidget->setData(data);
166 // m_chartWidget->setData(data);
136 break;
167 // break;
137 }
168 // }
138 case 1: {
169 // case 1: {
139 QList<QChartDataPoint> data;
170 // QList<QChartDataPoint> data;
140 for (int x = 0; x < 100; x++) {
171 // for (int x = 0; x < 100; x++) {
141 data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100));
172 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100));
142 }
173 // }
143 m_chartWidget->setData(data);
174 // m_chartWidget->setData(data);
144 break;
175 // break;
145 }
176 // }
146 case 2: {
177 // case 2: {
147 QList<QChartDataPoint> data;
178 // QList<QChartDataPoint> data;
148 for (int x = 0; x < 1000; x++) {
179 // for (int x = 0; x < 1000; x++) {
149 data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
180 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
150 data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
181 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
151 data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
182 // data.append(QChartDataPoint() << x - 200 << 2 * (uint(sin(3.14159/50*x)*80) % 100) + (rand() % 100 * 0.2));
152 }
183 // }
153 m_chartWidget->setData(data);
184 // m_chartWidget->setData(data);
154 break;
185 // break;
155 }
186 // }
156 default:
187 // default:
157 break;
188 // break;
158 }
189 // }
159
160 }
190 }
161
191
162 void MainWidget::backgroundChanged(int itemIndex)
192 void MainWidget::backgroundChanged(int itemIndex)
@@ -1,12 +1,15
1 #ifndef MAINWIDGET_H
1 #ifndef MAINWIDGET_H
2 #define MAINWIDGET_H
2 #define MAINWIDGET_H
3
3
4 #include <qchartconfig.h>
5 #include <qchartwidget.h>
4 #include <QWidget>
6 #include <QWidget>
5
7
6 class QChartWidget;
7 class QSpinBox;
8 class QSpinBox;
8 class QCheckBox;
9 class QCheckBox;
9
10
11 QCHART_USE_NAMESPACE
12
10 class MainWidget : public QWidget
13 class MainWidget : public QWidget
11 {
14 {
12 Q_OBJECT
15 Q_OBJECT
@@ -17,6 +20,8 signals:
17
20
18 private slots:
21 private slots:
19 void chartTypeChanged(int itemIndex);
22 void chartTypeChanged(int itemIndex);
23 void addSeries();
24 void addSeries(QString series);
20 void testDataChanged(int itemIndex);
25 void testDataChanged(int itemIndex);
21 void backgroundChanged(int itemIndex);
26 void backgroundChanged(int itemIndex);
22 void autoScaleChanged(int value);
27 void autoScaleChanged(int value);
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now