Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
mlz
BornAgain
Commits
ea7a3b04
Commit
ea7a3b04
authored
Jun 08, 2022
by
Mikhail Svechnikov
Browse files
temp
parent
e7d6cb1f
Changes
13
Hide whitespace changes
Inline
Side-by-side
GUI/Model/BaseItem/SessionItem.h
View file @
ea7a3b04
...
...
@@ -200,7 +200,7 @@ class GroupInfo;
//! \endcode
//!
//! This code part again shows the (highly error-prone) string-based type checking.
#include
<QDebug>
class
BA_CORE_API_
SessionItem
{
friend
class
SessionModel
;
...
...
GUI/Model/Data/DataItem.cpp
View file @
ea7a3b04
...
...
@@ -96,7 +96,7 @@ QString DataItem::selectedCoords() const
void
DataItem
::
setAxesUnits
(
const
ComboProperty
&
units
)
{
setItemValue
(
P_AXES_UNITS
,
units
.
variant
());
qInfo
()
<<
"axesUnitsChanged"
<<
endl
;
emit
axesUnitsChanged
(
units
);
}
...
...
@@ -107,7 +107,19 @@ SessionItem* DataItem::getAxesUnitsItem() const
SelectionDescriptor
<
QString
>
DataItem
::
axesUnits
()
const
{
return
SelectionDescriptor
<
QString
>
(
getItem
(
P_AXES_UNITS
));
SessionItem
*
item
=
getAxesUnitsItem
();
SelectionDescriptor
<
QString
>
d
=
SelectionDescriptor
<
QString
>
(
item
);
d
.
currentIndexSetter
=
[
=
](
int
index
)
{
ComboProperty
comboProperty
=
item
->
value
().
value
<
ComboProperty
>
();
if
(
comboProperty
.
currentIndex
()
!=
index
)
{
comboProperty
.
setCurrentIndex
(
index
);
qInfo
()
<<
"new setter : DataItem"
<<
endl
;
const_cast
<
DataItem
*>
(
this
)
->
setAxesUnits
(
comboProperty
);
}
};
return
d
;
}
bool
DataItem
::
isAxesUnitsPropertyName
(
const
QString
&
name
)
...
...
GUI/Model/Data/DataItem.h
View file @
ea7a3b04
...
...
@@ -81,6 +81,7 @@ signals:
void
rawDataVectorChanged
(
const
std
::
vector
<
double
>&
data
);
void
fileNameChanged
(
const
QString
&
filename
);
void
axesUnitsChanged
(
const
ComboProperty
&
units
);
void
axesUnitsReplotRequested
();
protected:
explicit
DataItem
(
const
QString
&
modelType
);
...
...
GUI/Model/Data/IntensityDataItem.cpp
View file @
ea7a3b04
...
...
@@ -80,6 +80,7 @@ void IntensityDataItem::setDatafield(Datafield* data)
updateAxesLabels
();
updateDataRange
();
// qInfo() << "setDatafield\n------------------------\n" << endl;
emitDataChanged
();
}
...
...
GUI/Model/Data/JobItemUtils.cpp
View file @
ea7a3b04
...
...
@@ -45,11 +45,15 @@ void GUI::Model::JobItemUtils::updateDataAxes(DataItem* intensityItem,
return
;
}
qInfo
()
<<
"a"
<<
intensityItem
<<
intensityItem
->
getDatafield
()
<<
endl
;
if
(
!
intensityItem
->
getDatafield
())
return
;
qInfo
()
<<
"b"
<<
endl
;
Coords
requested_units
=
GUI
::
Util
::
CoordName
::
coordFromName
(
intensityItem
->
selectedCoords
());
qInfo
()
<<
"selected"
<<
intensityItem
->
selectedCoords
()
<<
endl
;
auto
*
const
converter
=
instrumentItem
->
createCoordSystem
();
auto
newData
=
std
::
make_unique
<
Datafield
>
(
converter
->
convertedAxes
(
requested_units
));
...
...
GUI/View/Mask/MaskEditorPropertyPanel.cpp
View file @
ea7a3b04
...
...
@@ -107,7 +107,7 @@ void MaskEditorPropertyPanel::setMaskContext(SessionModel* model,
connect
(
m_listView
->
selectionModel
(),
&
QItemSelectionModel
::
selectionChanged
,
this
,
&
MaskEditorPropertyPanel
::
onSelectionChanged
,
Qt
::
UniqueConnection
);
m_plotPropertyEditor
->
setItem
(
m_intensityDataItem
);
m_plotPropertyEditor
->
setItem
(
{
m_intensityDataItem
}
);
}
void
MaskEditorPropertyPanel
::
resetContext
()
...
...
@@ -117,7 +117,7 @@ void MaskEditorPropertyPanel::resetContext()
m_intensityDataItem
=
nullptr
;
m_listView
->
setModel
(
nullptr
);
setCurrentMaskItem
(
nullptr
);
m_plotPropertyEditor
->
setItem
(
nullptr
);
m_plotPropertyEditor
->
setItem
(
{
nullptr
}
);
}
QItemSelectionModel
*
MaskEditorPropertyPanel
::
selectionModel
()
...
...
@@ -136,13 +136,13 @@ void MaskEditorPropertyPanel::setPanelHidden(bool hidden)
if
(
hidden
)
{
setCurrentMaskItem
(
nullptr
);
m_plotPropertyEditor
->
setItem
(
nullptr
);
m_plotPropertyEditor
->
setItem
(
{
nullptr
}
);
}
else
{
QModelIndexList
indexes
=
selectionModel
()
->
selectedIndexes
();
if
(
!
indexes
.
empty
())
setCurrentMaskItem
(
maskItemForIndex
(
indexes
.
front
()));
m_plotPropertyEditor
->
setItem
(
m_intensityDataItem
);
m_plotPropertyEditor
->
setItem
(
{
m_intensityDataItem
}
);
}
}
...
...
GUI/View/Plot2D/IntensityDataWidget.cpp
View file @
ea7a3b04
...
...
@@ -53,14 +53,42 @@ IntensityDataWidget::IntensityDataWidget(QWidget* parent)
m_propertyWidget
->
setVisible
(
false
);
}
void
IntensityDataWidget
::
setItem
(
SessionItem
*
jobItem
)
void
IntensityDataWidget
::
setItem
(
SessionItem
*
job
_
Item
)
{
SessionItemWidget
::
setItem
(
jobItem
);
SessionItemWidget
::
setItem
(
job_Item
);
// now we can access to JobItem
// m_intensityCanvas->setItem(intensityDataItem());
// m_propertyWidget->setItem({intensityDataItem(),
// realIntensityDataItem(),
// diffIntensityDataItem()});
m_intensityCanvas
->
setItem
(
intensityDataItem
());
m_propertyWidget
->
setItem
(
intensityDataItem
());
m_propertyWidget
->
setItem
(
{
intensityDataItem
()
}
);
m_fftPresenter
->
reset
();
}
JobItem
*
IntensityDataWidget
::
jobItem
()
{
return
dynamic_cast
<
JobItem
*>
(
currentItem
());
}
IntensityDataItem
*
IntensityDataWidget
::
realIntensityDataItem
()
{
if
(
jobItem
())
return
jobItem
()
->
realDataItem
()
->
intensityDataItem
();
else
return
nullptr
;
}
IntensityDataItem
*
IntensityDataWidget
::
diffIntensityDataItem
()
{
if
(
jobItem
())
return
dynamic_cast
<
IntensityDataItem
*>
(
jobItem
()
->
diffDataItem
());
else
return
nullptr
;
}
QList
<
QAction
*>
IntensityDataWidget
::
actionList
()
{
return
m_intensityCanvas
->
actionList
()
+
m_fftPresenter
->
actionList
()
...
...
@@ -83,11 +111,11 @@ void IntensityDataWidget::onFFTAction()
if
(
m_fftPresenter
->
inFFTMode
())
{
auto
*
fftItem
=
m_fftPresenter
->
fftItem
(
intensityDataItem
());
m_intensityCanvas
->
setItem
(
fftItem
);
m_propertyWidget
->
setItem
(
fftItem
);
m_propertyWidget
->
setItem
(
{
fftItem
}
);
}
else
{
// returning ColorMap to non-fft presentation
m_intensityCanvas
->
setItem
(
intensityDataItem
());
m_propertyWidget
->
setItem
(
intensityDataItem
());
m_propertyWidget
->
setItem
(
{
intensityDataItem
()
}
);
}
}
...
...
GUI/View/Plot2D/IntensityDataWidget.h
View file @
ea7a3b04
...
...
@@ -25,6 +25,7 @@ class IntensityDataItem;
class
QAction
;
class
QContextMenuEvent
;
class
IntensityDataFFTPresenter
;
class
JobItem
;
//! A common widget to display color map (IntensityDataCanvas) and properties
//! (ItemPropertyWidget) of intensity data item.
...
...
@@ -35,7 +36,10 @@ class IntensityDataWidget : public SessionItemWidget {
public:
IntensityDataWidget
(
QWidget
*
parent
=
nullptr
);
void
setItem
(
SessionItem
*
jobItem
)
override
;
void
setItem
(
SessionItem
*
job_Item
)
override
;
JobItem
*
jobItem
();
IntensityDataItem
*
realIntensityDataItem
();
IntensityDataItem
*
diffIntensityDataItem
();
QList
<
QAction
*>
actionList
()
override
;
...
...
GUI/View/PlotComparison/FitComparisonWidget.cpp
View file @
ea7a3b04
...
...
@@ -95,7 +95,7 @@ void FitComparisonWidget::subscribeToItem()
m_comparisonController
->
setItem
(
jobItem
());
m_realDataPlot
->
setItem
(
realDataItem
());
m_simulatedDataPlot
->
setItem
(
simulatedDataItem
());
m_relativeDiffPlot
->
setItem
(
m_comparisonController
->
diffItem
());
m_relativeDiffPlot
->
setItem
(
diffItem
());
m_fitFlowWidget
->
setItem
(
jobItem
()
->
fitSuiteItem
());
m_statusLabel
->
reset
();
...
...
@@ -103,7 +103,7 @@ void FitComparisonWidget::subscribeToItem()
m_statusLabel
->
addPlot
(
m_simulatedDataPlot
->
colorMap
());
m_statusLabel
->
addPlot
(
m_relativeDiffPlot
->
colorMap
());
m_propertyWidget
->
setItem
(
simulatedDataItem
(),
realDataItem
());
m_propertyWidget
->
setItem
(
{
simulatedDataItem
()
/*
, realDataItem()
, diffItem()*/
}
);
}
void
FitComparisonWidget
::
unsubscribeFromItem
()
...
...
GUI/View/PlotUtil/ColorMap.cpp
View file @
ea7a3b04
...
...
@@ -206,8 +206,21 @@ void ColorMap::onTimeToReplot()
void
ColorMap
::
subscribeToItem
()
{
// qInfo() << "ColorMap" << intensityItem() << endl;
setColorMapFromItem
(
intensityItem
());
// connect(intensityItem(), &IntensityDataItem::axesUnitsReplotRequested, this, [=]() {
// setAxesRangeConnected(false);
// m_customPlot->xAxis->setRange(GUI::View::RangeUtils::itemZoomX(intensityItem()));
// m_customPlot->yAxis->setRange(GUI::View::RangeUtils::itemZoomY(intensityItem()));
// setAxesRangeConnected(true);
// setAxesRangeFromItem(intensityItem());
// setDataFromItem(intensityItem());
// replot();
// });
intensityItem
()
->
mapper
()
->
setOnPropertyChange
(
[
this
](
const
QString
&
name
)
{
onPropertyChanged
(
name
);
},
this
);
...
...
GUI/View/PlotUtil/IntensityDataPropertyWidget.cpp
View file @
ea7a3b04
...
...
@@ -30,7 +30,6 @@
IntensityDataPropertyWidget
::
IntensityDataPropertyWidget
(
QWidget
*
parent
)
:
QWidget
(
parent
)
,
parent
(
parent
)
,
m_item
(
nullptr
)
{
setWindowTitle
(
"Properties"
);
setAttribute
(
Qt
::
WA_StyledBackground
,
true
);
...
...
@@ -43,28 +42,50 @@ IntensityDataPropertyWidget::IntensityDataPropertyWidget(QWidget* parent)
IntensityDataPropertyWidget
::~
IntensityDataPropertyWidget
()
{
if
(
m_item
)
m_item
->
mapper
()
->
unsubscribe
(
this
);
unsubscribe
();
}
void
IntensityDataPropertyWidget
::
setItem
(
IntensityDataItem
*
mainItem
,
IntensityDataItem
*
realItem
)
void
IntensityDataPropertyWidget
::
unsubscribe
(
)
{
if
(
m_item
)
m_item
->
mapper
()
->
unsubscribe
(
this
);
for
(
IntensityDataItem
*
item
:
m_items_vec
)
if
(
item
)
disconnect
(
item
,
nullptr
,
this
,
nullptr
);
}
void
IntensityDataPropertyWidget
::
setItem
(
QVector
<
IntensityDataItem
*>
itemsVec
)
{
if
(
itemsVec
.
size
()
==
0
)
return
;
unsubscribe
();
GUI
::
Util
::
Layout
::
clearLayout
(
m_mainLayout
);
m_updaters
.
clear
();
m_item
=
mainItem
;
m_updaters
.
clear
();
if
(
!
m_item
)
m_items_vec
=
itemsVec
;
IntensityDataItem
*&
first_item
=
itemsVec
.
first
();
if
(
!
first_item
)
return
;
m_mainLayout
->
addRow
(
"Axes units:"
,
createComboBox
(
m_item
->
axesUnits
()));
m_mainLayout
->
addRow
(
"Color scheme:"
,
createComboBox
(
m_item
->
gradient
()));
m_mainLayout
->
addRow
(
createCheckBox
(
"Interpolate"
,
[
=
]()
{
return
m_item
->
isInterpolated
();
},
[
=
](
bool
b
)
{
m_item
->
setInterpolated
(
b
);
}));
m_mainLayout
->
addRow
(
"Axes units:"
,
createComboBox
(
first_item
->
axesUnits
(),
[
=
](
int
newIndex
){
for
(
IntensityDataItem
*
item
:
m_items_vec
)
if
(
item
)
{
item
->
axesUnits
().
setCurrentIndex
(
newIndex
);
}
}));
m_mainLayout
->
addRow
(
"Color scheme:"
,
createComboBox
(
first_item
->
gradient
(),
[
=
](
int
newIndex
){
for
(
IntensityDataItem
*
item
:
m_items_vec
)
if
(
item
)
item
->
gradient
().
setCurrentIndex
(
newIndex
);
}));
m_mainLayout
->
addRow
(
createCheckBox
(
"Interpolate"
,
[
=
]()
{
return
first_item
->
isInterpolated
();
},
[
=
](
bool
b
)
{
for
(
IntensityDataItem
*
item
:
m_items_vec
)
if
(
item
)
item
->
setInterpolated
(
b
);
}));
// -- x-axis
auto
*
xGroup
=
new
QGroupBox
(
"X axis"
,
this
);
...
...
@@ -72,9 +93,9 @@ void IntensityDataPropertyWidget::setItem(IntensityDataItem* mainItem, Intensity
xFormLayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
xFormLayout
->
setSpacing
(
5
);
xFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
m
_item
->
xAxisItem
()
->
min
()));
xFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
m
_item
->
xAxisItem
()
->
max
()));
xFormLayout
->
addRow
(
"Title:"
,
createTextEdit
(
m
_item
->
xAxisItem
()
->
titleItem
()));
xFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
first
_item
->
xAxisItem
()
->
min
()));
xFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
first
_item
->
xAxisItem
()
->
max
()));
xFormLayout
->
addRow
(
"Title:"
,
createTextEdit
(
first
_item
->
xAxisItem
()
->
titleItem
()));
m_mainLayout
->
addRow
(
xGroup
);
...
...
@@ -84,9 +105,9 @@ void IntensityDataPropertyWidget::setItem(IntensityDataItem* mainItem, Intensity
yFormLayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
yFormLayout
->
setSpacing
(
5
);
yFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
m
_item
->
yAxisItem
()
->
min
()));
yFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
m
_item
->
yAxisItem
()
->
max
()));
yFormLayout
->
addRow
(
"Title:"
,
createTextEdit
(
m
_item
->
yAxisItem
()
->
titleItem
()));
yFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
first
_item
->
yAxisItem
()
->
min
()));
yFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
first
_item
->
yAxisItem
()
->
max
()));
yFormLayout
->
addRow
(
"Title:"
,
createTextEdit
(
first
_item
->
yAxisItem
()
->
titleItem
()));
m_mainLayout
->
addRow
(
yGroup
);
...
...
@@ -96,35 +117,42 @@ void IntensityDataPropertyWidget::setItem(IntensityDataItem* mainItem, Intensity
zFormLayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
zFormLayout
->
setSpacing
(
5
);
zFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
m
_item
->
zAxisItem
()
->
min
()));
zFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
m
_item
->
zAxisItem
()
->
max
()));
zFormLayout
->
addRow
(
createCheckBox
(
"log10"
,
m
_item
->
zAxisItem
()
->
logScaleItem
()));
zFormLayout
->
addRow
(
createCheckBox
(
"Visible"
,
m
_item
->
zAxisItem
()
->
visibilityItem
()));
zFormLayout
->
addRow
(
"Min:"
,
createDoubleSpinbox
(
first
_item
->
zAxisItem
()
->
min
()));
zFormLayout
->
addRow
(
"Max:"
,
createDoubleSpinbox
(
first
_item
->
zAxisItem
()
->
max
()));
zFormLayout
->
addRow
(
createCheckBox
(
"log10"
,
first
_item
->
zAxisItem
()
->
logScaleItem
()));
zFormLayout
->
addRow
(
createCheckBox
(
"Visible"
,
first
_item
->
zAxisItem
()
->
visibilityItem
()));
m_mainLayout
->
addRow
(
zGroup
);
updateUIValues
();
// react on external changes (e.g. zooming in customplot shall update the axis values)
m
_item
->
mapper
()
->
setOnChildPropertyChange
(
first
_item
->
mapper
()
->
setOnChildPropertyChange
(
[
=
](
SessionItem
*
,
const
QString
&
)
{
updateUIValues
();
},
this
);
// update coordinates on axes units change
m_item
->
mapper
()
->
setOnPropertyChange
(
// connect(first_item, &IntensityDataItem::axesUnitsChanged, this, [=](const ComboProperty&){
// if(jobItem()) {
// for(IntensityDataItem* item : m_items_vec)
// if(item) {
// item->blockSignals(true);
// item->updateCoords(jobItem()->instrumentItem());
// item->blockSignals(false);
// emit item->axesUnitsReplotRequested();
// }
// qInfo() << ".-.-.-.-.-.-.-.-.-.-.-.-.-.-." << endl;
// }
// });
first_item
->
mapper
()
->
setOnPropertyChange
(
[
this
](
SessionItem
*
item
,
const
QString
&
name
)
{
if
(
jobItem
())
DataItem
::
updateAxesUnits
(
item
,
name
,
jobItem
()
->
instrumentItem
());
},
this
);
if
(
realItem
)
realItem
->
mapper
()
->
setOnPropertyChange
(
[
this
](
SessionItem
*
item
,
const
QString
&
name
)
{
if
(
jobItem
())
DataItem
::
updateAxesUnits
(
item
,
name
,
jobItem
()
->
instrumentItem
());
},
this
);
m_item
->
mapper
()
->
setOnItemDestroy
([
this
](
SessionItem
*
)
{
m_item
=
nullptr
;
},
this
);
for
(
int
i
=
0
;
i
<
itemsVec
.
size
();
i
++
)
connect
(
itemsVec
[
i
],
&
IntensityDataItem
::
destroyed
,
this
,
[
=
](){
m_items_vec
[
i
]
=
nullptr
;
});
}
const
JobItem
*
IntensityDataPropertyWidget
::
jobItem
()
const
...
...
@@ -178,14 +206,17 @@ QWidget* IntensityDataPropertyWidget::createCheckBox(const QString& title, funct
return
checkBox
;
}
QWidget
*
IntensityDataPropertyWidget
::
createComboBox
(
SelectionDescriptor
<
QString
>
d
)
QWidget
*
IntensityDataPropertyWidget
::
createComboBox
(
SelectionDescriptor
<
QString
>
d
,
function
<
void
(
int
)
>
slot
)
{
auto
*
combo
=
new
QComboBox
(
this
);
combo
->
addItems
(
d
.
options
);
combo
->
setMaxCount
(
d
.
options
.
size
());
connect
(
combo
,
qOverload
<
int
>
(
&
QComboBox
::
currentIndexChanged
),
[
=
](
int
newIndex
)
{
d
.
setCurrentIndex
(
newIndex
);
});
connect
(
combo
,
qOverload
<
int
>
(
&
QComboBox
::
currentIndexChanged
),[
=
]
(
int
newIndex
)
{
if
(
slot
)
slot
(
newIndex
);
});
m_updaters
<<
[
=
]()
{
QSignalBlocker
b
(
combo
);
...
...
GUI/View/PlotUtil/IntensityDataPropertyWidget.h
View file @
ea7a3b04
...
...
@@ -36,7 +36,7 @@ public:
explicit
IntensityDataPropertyWidget
(
QWidget
*
parent
=
nullptr
);
~
IntensityDataPropertyWidget
();
void
setItem
(
IntensityDataItem
*
mainItem
,
IntensityDataItem
*
realItem
=
nullptr
);
void
setItem
(
QVector
<
IntensityDataItem
*
>
itemsVec
);
const
JobItem
*
jobItem
()
const
;
private:
...
...
@@ -45,13 +45,14 @@ private:
QWidget
*
createCheckBox
(
const
QString
&
title
,
SessionItem
*
item
);
QWidget
*
createCheckBox
(
const
QString
&
title
,
function
<
bool
()
>
getter
,
function
<
void
(
bool
)
>
setter
);
QWidget
*
createComboBox
(
SelectionDescriptor
<
QString
>
d
);
QWidget
*
createComboBox
(
SelectionDescriptor
<
QString
>
d
,
function
<
void
(
int
)
>
slot
=
nullptr
);
void
updateUIValues
();
void
unsubscribe
();
private:
QWidget
*
parent
;
IntensityDataItem
*
m_item
;
QVector
<
IntensityDataItem
*
>
m_item
s_vec
;
QFormLayout
*
m_mainLayout
;
QList
<
function
<
void
()
>>
m_updaters
;
};
...
...
GUI/View/Projection/ProjectionsEditor.cpp
View file @
ea7a3b04
...
...
@@ -65,7 +65,7 @@ void ProjectionsEditor::setContext(SessionModel* model, const QModelIndex& shape
delete
m_selectionModel
;
m_selectionModel
=
new
QItemSelectionModel
(
model
,
this
);
m_propertyPanel
->
setItem
(
intensityItem
);
m_propertyPanel
->
setItem
(
{
intensityItem
}
);
m_projectionsCanvas
->
setSelectionModel
(
m_selectionModel
);
m_projectionsCanvas
->
setContext
(
model
,
shapeContainerIndex
,
intensityItem
);
m_projectionsWidget
->
setItem
(
intensityItem
);
...
...
@@ -76,7 +76,7 @@ void ProjectionsEditor::setContext(SessionModel* model, const QModelIndex& shape
void
ProjectionsEditor
::
resetContext
()
{
m_propertyPanel
->
setItem
(
nullptr
);
m_propertyPanel
->
setItem
(
{
nullptr
}
);
m_projectionsCanvas
->
resetContext
();
m_projectionsWidget
->
setItem
(
nullptr
);
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment