Skip to content

Commit 5d711af

Browse files
boutinbJorisGoosen
authored andcommitted
Auto Sort labels does bug and other label handling issues
1 parent d96a35d commit 5d711af

18 files changed

+164
-108
lines changed

CommonData/column.cpp

+77-32
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ void Column::setAutoSortByValuesByDefault(bool autoSort)
1717
_autoSortByValuesByDefault = autoSort;
1818
}
1919

20-
Column::Column(DataSet * data, int id)
20+
Column::Column(DataSet * data, int id, columnType colType, computedColumnType computedType, bool autoSort)
2121
: DataSetBaseNode(dataSetBaseNodeType::column, data->dataNode()),
2222
_data( data),
2323
_id( id),
@@ -29,19 +29,32 @@ Column::Column(DataSet * data, int id)
2929
db().columnSetAutoSort(_id, _autoSortByValue); //Store autosort in db
3030
}
3131

32-
Column::~Column()
32+
33+
Column* Column::addColumn(DataSet * data, int index, const std::string& name, columnType colType, computedColumnType computedType, bool alterDataSetTable)
3334
{
34-
labelsTempReset();
35-
delete _emptyValues;
36-
delete _doubleDummy;
35+
int id = data->db().columnInsert(data->id(), index, colType, computedType, Column::autoSortByValuesByDefault());
36+
Column* col = new Column(data, id, colType, computedType, Column::autoSortByValuesByDefault());
37+
38+
if (!name.empty())
39+
col->setName(name);
40+
41+
return col;
3742
}
3843

39-
void Column::dbCreate(int index)
44+
Column* Column::loadColumn(DataSet * data, int index)
4045
{
41-
JASPTIMER_SCOPE(Column::dbCreate);
46+
Column* col = new Column(data, index, columnType::unknown, computedColumnType::notComputed, Column::autoSortByValuesByDefault());
47+
col->dbLoadIndex(index, false);
4248

43-
assert(_id == -1);
44-
db().columnInsert(_id, index);
49+
return col;
50+
}
51+
52+
53+
Column::~Column()
54+
{
55+
labelsTempReset();
56+
delete _emptyValues;
57+
delete _doubleDummy;
4558
}
4659

4760
void Column::dbLoad(int id, bool getValues)
@@ -391,18 +404,17 @@ columnTypeChangeResult Column::changeType(columnType colType)
391404
if(codeType() == computedColumnType::analysis)
392405
return columnTypeChangeResult::generatedFromAnalysis;
393406

394-
setDefaultValues(colType);
407+
if (colType != columnType::unknown)
408+
setType(colType);
409+
setDefaultValues();
395410
invalidate();
396411
return columnTypeChangeResult::changed;
397412
}
398413
}
399414

400-
void Column::setDefaultValues(enum columnType columnType)
415+
void Column::setDefaultValues()
401416
{
402417
JASPTIMER_SCOPE(Column::setDefaultValues);
403-
404-
if(columnType != columnType::unknown)
405-
setType(columnType);
406418

407419
for(size_t i=0; i<_ints.size(); i++)
408420
{
@@ -1723,7 +1735,7 @@ void Column::labelsOrderByValue(bool doDbUpdateEtc)
17231735
bool replaceAllDoubles = false;
17241736
static double dummy;
17251737

1726-
for(Label * label : labels())
1738+
for(Label * label : labels())
17271739
if(!label->isEmptyValue() && !(label->originalValue().isDouble() || ColumnUtils::getDoubleValue(label->originalValueAsString(), dummy)))
17281740
{
17291741
replaceAllDoubles = true;
@@ -1733,24 +1745,43 @@ void Column::labelsOrderByValue(bool doDbUpdateEtc)
17331745
if(replaceAllDoubles)
17341746
replaceDoublesTillLabelsRowWithLabels(labelsTempCount());
17351747

1736-
doublevec asc = valuesNumericOrdered();
1737-
size_t curMax = asc.size()+1;
1738-
std::map<double, int> orderMap;
1739-
1740-
for(size_t i=0; i<asc.size(); i++)
1741-
orderMap[asc[i]] = i;
1742-
1743-
//and now to write them back into the data
1744-
for(Label * label : _labels)
1748+
doublevec asc = valuesNumericOrdered();
1749+
1750+
if (asc.empty())
17451751
{
1746-
double aValue = EmptyValues::missingValueDouble;
1747-
1748-
if(label->originalValue().isDouble())
1749-
aValue = label->originalValue().asDouble();
1750-
else
1751-
ColumnUtils::getDoubleValue(label->originalValueAsString(), aValue);
1752-
1753-
label->setOrder(!std::isnan(aValue) ? orderMap[aValue] : curMax++);
1752+
stringvec orderedstrings = valuesAlphabeticOrdered();
1753+
size_t curMax = orderedstrings.size()+1;
1754+
std::map<std::string, int> orderMap;
1755+
1756+
for(size_t i=0; i<orderedstrings.size(); i++)
1757+
orderMap[orderedstrings[i]] = i;
1758+
1759+
for(Label * label : _labels)
1760+
{
1761+
std::string aValue = label->originalValueAsString();
1762+
label->setOrder(!isEmptyValue(aValue) ? orderMap[aValue] : curMax++);
1763+
}
1764+
}
1765+
else
1766+
{
1767+
size_t curMax = asc.size()+1;
1768+
std::map<double, int> orderMap;
1769+
1770+
for(size_t i=0; i<asc.size(); i++)
1771+
orderMap[asc[i]] = i;
1772+
1773+
//and now to write them back into the data
1774+
for(Label * label : _labels)
1775+
{
1776+
double aValue = EmptyValues::missingValueDouble;
1777+
1778+
if(label->originalValue().isDouble())
1779+
aValue = label->originalValue().asDouble();
1780+
else
1781+
ColumnUtils::getDoubleValue(label->originalValueAsString(), aValue);
1782+
1783+
label->setOrder(!std::isnan(aValue) ? orderMap[aValue] : curMax++);
1784+
}
17541785
}
17551786

17561787
_sortLabelsByOrder();
@@ -1779,6 +1810,20 @@ doublevec Column::valuesNumericOrdered()
17791810
return doublevec(values.begin(), values.end());
17801811
}
17811812

1813+
stringvec Column::valuesAlphabeticOrdered()
1814+
{
1815+
stringset values;
1816+
1817+
for(const Label * label : _labels)
1818+
{
1819+
std::string aValue = label->originalValueAsString();
1820+
if (!isEmptyValue(aValue))
1821+
values.insert(aValue);
1822+
}
1823+
1824+
return stringvec(values.begin(), values.end());
1825+
}
1826+
17821827
void Column::valuesReverse()
17831828
{
17841829
JASPTIMER_SCOPE(Column::valuesReverse);

CommonData/column.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,17 @@ class Column : public DataSetBaseNode
4444
typedef std::map<std::pair<std::string, std::string>, Label*> LabelByStrStr;
4545

4646
Column(DataSet * data, int id = -1);
47+
private:
48+
Column(DataSet * data, int id, columnType colType, computedColumnType computedType, bool autoSort);
49+
50+
public:
51+
static Column * addColumn(DataSet* data, int index = -1, const std::string & name = "", columnType colType = columnType::scale, computedColumnType computedType = computedColumnType::notComputed, bool alterDataSetTable = true);
52+
static Column * loadColumn(DataSet* data, int index);
4753
~Column();
4854

4955
DatabaseInterface & db();
5056
const DatabaseInterface & db() const;
5157

52-
void dbCreate( int index);
5358
void dbLoad( int id=-1, bool getValues = true); ///< Loads *and* reloads from DB!
5459
void dbLoadIndex(int index, bool getValues = true);
5560
void dbUpdateComputedColumnStuff();
@@ -72,7 +77,7 @@ class Column : public DataSetBaseNode
7277
void setIndex( int index );
7378
void setInvalidated( bool invalidated );
7479
void setCompColStuff( bool invalidated, bool forceSourceColType, computedColumnType codeType, const std::string & rCode, const std::string & error, const Json::Value & constructorJson);
75-
void setDefaultValues( enum columnType columnType = columnType::unknown);
80+
void setDefaultValues();
7681

7782
bool setAsNominalOrOrdinal( const intvec & values, bool is_ordinal = false);
7883
bool setAsNominalOrOrdinal( const intvec & values, intstrmap uniqueValues, bool is_ordinal = false);
@@ -242,7 +247,8 @@ class Column : public DataSetBaseNode
242247
columnTypeChangeResult _changeColumnToScale();
243248
void _convertVectorIntToDouble(intvec & intValues, doublevec & doubleValues);
244249
void _resetLabelValueMap();
245-
doublevec valuesNumericOrdered();
250+
doublevec valuesNumericOrdered();
251+
stringvec valuesAlphabeticOrdered();
246252

247253
private:
248254
DataSet * const _data;

CommonData/databaseinterface.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,11 @@ void DatabaseInterface::filterWrite(int filterIndex, const std::vector<bool> & v
398398
transactionWriteEnd();
399399
}
400400

401-
int DatabaseInterface::columnInsert(int dataSetId, int index, const std::string & name, columnType colType, bool alterTable)
401+
int DatabaseInterface::columnInsert(int dataSetId, int index, columnType colType, computedColumnType computedType, bool autoSort, bool alterTable)
402402
{
403403
JASPTIMER_SCOPE(DatabaseInterface::columnInsert);
404404
transactionWriteBegin();
405-
405+
406406
if(index == -1) index = columnLastFreeIndex(dataSetId);
407407
else columnIndexIncrements(dataSetId, index);
408408

@@ -411,14 +411,17 @@ int DatabaseInterface::columnInsert(int dataSetId, int index, const std::string
411411
#endif
412412

413413
//Create column entry
414-
int columnId = runStatementsId("INSERT INTO Columns (dataSet, name, columnType, colIdx, analysisId) VALUES (?, ?, ?, ?, -1) RETURNING id;", [&](sqlite3_stmt * stmt)
414+
int columnId = runStatementsId("INSERT INTO Columns (dataSet, columnType, codeType, autoSortByValue, colIdx, analysisId) VALUES (?, ?, ?, ?, ?, -1) RETURNING id;", [&](sqlite3_stmt * stmt)
415415
{
416416
sqlite3_bind_int(stmt, 1, dataSetId);
417-
sqlite3_bind_text(stmt, 2, name.c_str(), name.length(), SQLITE_TRANSIENT);
418417

419418
std::string colT = columnTypeToString(colType);
420-
sqlite3_bind_text(stmt, 3, colT.c_str(), colT.length(), SQLITE_TRANSIENT);
421-
sqlite3_bind_int(stmt, 4, index);
419+
std::string codeT = computedColumnTypeToString(computedType);
420+
421+
sqlite3_bind_text(stmt, 2, colT.c_str(), colT.length(), SQLITE_TRANSIENT);
422+
sqlite3_bind_text(stmt, 3, codeT.c_str(), codeT.length(), SQLITE_TRANSIENT);
423+
sqlite3_bind_int(stmt, 4, autoSort);
424+
sqlite3_bind_int(stmt, 5, index);
422425
});
423426

424427
#ifdef SIR_LOG_A_LOT

CommonData/databaseinterface.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class DatabaseInterface
110110

111111
//Columns & Data/Values
112112
//Index stuff:
113-
int columnInsert( int dataSetId, int index = -1, const std::string & name = "", columnType colType = columnType::unknown, bool alterTable=true); ///< Insert a row into Columns and create the corresponding columns in DataSet_? Also makes sure the indices are correct
113+
int columnInsert( int dataSetId, int index, columnType colType, computedColumnType computedType, bool autoSort, bool alterTable=true); ///< Insert a row into Columns and create the corresponding columns in DataSet_? Also makes sure the indices are correct
114114
int columnLastFreeIndex( int dataSetId);
115115
void columnIndexIncrements( int dataSetId, int index); ///< If index already is in use that column and all after are incremented by 1
116116
void columnIndexDecrements( int dataSetId, int index); ///< Indices bigger than index are decremented, assumption is that the previous one using it has been removed already

CommonData/dataset.cpp

+9-8
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,26 @@ void DataSet::removeColumn(const std::string & name)
172172
}
173173
}
174174

175-
void DataSet::insertColumn(size_t index, bool alterDataSetTable)
175+
Column* DataSet::insertColumn(size_t index, bool alterDataSetTable, const std::string & name, columnType colType, computedColumnType computedType)
176176
{
177-
178177
assert(_dataSetID > 0);
179178

180-
Column * newColumn = new Column(this, db().columnInsert(_dataSetID, index, "", columnType::unknown, alterDataSetTable));
179+
Column * newColumn = Column::addColumn(this, index, name, colType, computedType, alterDataSetTable);
181180

182181
_columns.insert(_columns.begin()+index, newColumn);
183182

184183
newColumn->setRowCount(_rowCount);
184+
newColumn->setDefaultValues();
185185

186186
incRevision();
187+
188+
return newColumn;
187189
}
188190

189191
Column * DataSet::newColumn(const std::string &name)
190192
{
191193
assert(_dataSetID > 0);
192-
Column * col = new Column(this, db().columnInsert(_dataSetID, -1, name));
193-
col->setName(name);
194+
Column * col = Column::addColumn(this, -1, name);
194195

195196
_columns.push_back(col);
196197

@@ -281,9 +282,9 @@ void DataSet::dbLoad(int index, std::function<void(float)> progressCallback, boo
281282
for(size_t i=0; i<colCount; i++)
282283
{
283284
if(_columns.size() == i)
284-
_columns.push_back(new Column(this));
285-
286-
_columns[i]->dbLoadIndex(i, false);
285+
_columns.push_back(Column::loadColumn(this, i));
286+
else
287+
_columns[i]->dbLoadIndex(i, false);
287288

288289
progressCallback(0.2 + (i * colProgressMult * 0.3)); //should end at 0.5
289290
}

CommonData/dataset.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class DataSet : public DataSetBaseNode
4444
void removeColumn( const std::string & name );
4545
void removeColumn( size_t index );
4646
void removeColumnById( size_t id );
47-
void insertColumn( size_t index, bool alterDataSetTable = true);
47+
Column * insertColumn(size_t index, bool alterDataSetTable = true, const std::string & name = "", columnType colType = columnType::unknown, computedColumnType computedType = computedColumnType::notComputed);
4848
Column * newColumn( const std::string & name);
4949
int getColumnIndex( const std::string & name ) const;
5050
int columnIndex( const Column * col ) const;

Desktop/components/JASP/Widgets/LabelEditorWindow.qml

+16-16
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ FocusScope
5757
target: columnModel
5858
function onChosenColumnChanged()
5959
{
60-
levelsTableView.lastRow = -1;
60+
levelsTableView.selectedRow = -1;
6161
}
6262
}
6363

6464
property real filterColWidth: 60 * jaspTheme.uiScale
6565
property real remainingWidth: width - filterColWidth
6666
property real valueColWidth: Math.min(columnModel.valueMaxWidth + 10, remainingWidth * 0.5) * jaspTheme.uiScale
6767
property real labelColWidth: Math.min(columnModel.labelMaxWidth + 10, remainingWidth * 0.5) * jaspTheme.uiScale
68-
property int lastRow: -1
68+
property int selectedRow: -1
6969

7070

7171
columnHeaderDelegate: Item
@@ -129,7 +129,7 @@ FocusScope
129129
{
130130
id: backgroundItem
131131

132-
onActiveFocusChanged: if(activeFocus) levelsTableView.lastRow = rowIndex
132+
onActiveFocusChanged: if(activeFocus) levelsTableView.selectedRow = rowIndex
133133

134134
MouseArea
135135
{
@@ -440,7 +440,7 @@ FocusScope
440440
iconSource: jaspTheme.iconPath + "menu-column-order-by-values.svg"
441441
onClicked: { forceActiveFocus(); columnModel.toggleAutoSortByValues(); }
442442

443-
toolTip: qsTr("Automatically order labels by their numeric value")
443+
toolTip: qsTr("Automatically order labels by their value")
444444

445445
height: buttonColumnVariablesWindow.buttonHeight
446446
implicitHeight: buttonColumnVariablesWindow.buttonHeight
@@ -458,49 +458,49 @@ FocusScope
458458
height: buttonColumnVariablesWindow.buttonHeight
459459
implicitHeight: buttonColumnVariablesWindow.buttonHeight
460460
width: height
461-
visible: !columnModel.autoSort || columnModel.firstNonNumericRow > 1 //if there are at least 2 numerics we have something to reverse
461+
visible: columnModel.hasSeveralNumericValues //if there are at least 2 numerics we have something to reverse
462462
}
463463

464464
RoundedButton
465465
{
466466
iconSource: jaspTheme.iconPath + "arrow-reverse.png"
467467
onClicked: { forceActiveFocus(); columnModel.reverse(); }
468468

469-
toolTip: columnModel.autoSort ? qsTr("Reverse order of the labels with non-numeric values") : qsTr("Reverse order of all labels")
469+
toolTip: qsTr("Reverse order of all labels")
470470

471471
height: buttonColumnVariablesWindow.buttonHeight
472472
implicitHeight: buttonColumnVariablesWindow.buttonHeight
473473
width: height
474-
visible: !columnModel.autoSort || columnModel.rowsTotal - columnModel.firstNonNumericRow > 1 //If there are at least 2 non numerics there is something to reverse
475-
474+
visible: !columnModel.autoSort
475+
enabled: columnModel.rowCount() > 1
476476
}
477477

478478
RoundedButton
479479
{
480480
iconSource: jaspTheme.iconPath + "arrow-up.png"
481481

482-
onClicked: { forceActiveFocus(); columnModel.moveSelectionUp(); levelsTableView.lastRow--; }
483-
toolTip: columnModel.autoSort ? qsTr("Move selected non-numeric labels up") : qsTr("Move selected labels up")
482+
onClicked: { forceActiveFocus(); columnModel.moveSelectionUp(); levelsTableView.selectedRow--; }
483+
toolTip: qsTr("Move selected labels up")
484484

485485
height: buttonColumnVariablesWindow.buttonHeight
486486
implicitHeight: buttonColumnVariablesWindow.buttonHeight
487487
width: height
488-
enabled: levelsTableView.lastRow == -1 ? false : columnModel.firstNonNumericRow < levelsTableView.lastRow
489-
visible: !columnModel.autoSort || columnModel.rowsTotal - columnModel.firstNonNumericRow > 1 //If there are at least 2 non numerics there is something to move up
488+
enabled: levelsTableView.selectedRow > 0
489+
visible: !columnModel.autoSort
490490
}
491491

492492
RoundedButton
493493
{
494494
iconSource: jaspTheme.iconPath + "arrow-down.png"
495495

496-
onClicked: { forceActiveFocus(); columnModel.moveSelectionDown(); levelsTableView.lastRow++; }
497-
toolTip: columnModel.autoSort ? qsTr("Move selected non-numeric labels down") : qsTr("Move selected labels down")
496+
onClicked: { forceActiveFocus(); columnModel.moveSelectionDown(); levelsTableView.selectedRow++; }
497+
toolTip: qsTr("Move selected labels down")
498498

499499
height: buttonColumnVariablesWindow.buttonHeight
500500
implicitHeight: buttonColumnVariablesWindow.buttonHeight
501501
width: height
502-
enabled: levelsTableView.lastRow == -1 ? false : ((columnModel.firstNonNumericRow <= levelsTableView.lastRow) && ( levelsTableView.lastRow < columnModel.rowsTotal - 1 ))
503-
visible: !columnModel.autoSort || columnModel.rowsTotal - columnModel.firstNonNumericRow > 1 //If there are at least 2 non numerics there is something to move down
502+
enabled: levelsTableView.selectedRow >= 0 && levelsTableView.selectedRow < columnModel.rowCount() - 1
503+
visible: !columnModel.autoSort
504504
}
505505

506506
RoundedButton

0 commit comments

Comments
 (0)