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
Telemetry
KUserFeedback
Commits
944123ca
Commit
944123ca
authored
Dec 20, 2016
by
Volker Krause
Browse files
Avoid model resets in ProductModel
This fixes losing the selection on product updates.
parent
aa1cf053
Changes
3
Hide whitespace changes
Inline
Side-by-side
analyzer/model/productmodel.cpp
View file @
944123ca
...
...
@@ -33,27 +33,33 @@ ProductModel::~ProductModel() = default;
void
ProductModel
::
setRESTClient
(
RESTClient
*
client
)
{
if
(
client
!=
m_restClient
)
clear
();
Q_ASSERT
(
client
);
m_restClient
=
client
;
connect
(
m_restClient
,
&
RESTClient
::
clientConnected
,
this
,
&
ProductModel
::
reload
);
if
(
m_restClient
->
isConnected
())
reload
();
reload
();
}
void
ProductModel
::
clear
()
{
if
(
m_products
.
isEmpty
())
return
;
beginRemoveRows
({},
0
,
m_products
.
size
()
-
1
);
m_products
.
clear
();
endRemoveRows
();
}
void
ProductModel
::
reload
()
{
qDebug
()
<<
Q_FUNC_INFO
;
Q_ASSERT
(
m_restClient
);
if
(
!
m_restClient
->
isConnected
())
if
(
!
m_restClient
||
!
m_restClient
->
isConnected
())
return
;
auto
reply
=
RESTApi
::
listProducts
(
m_restClient
);
connect
(
reply
,
&
QNetworkReply
::
finished
,
this
,
[
this
,
reply
]()
{
if
(
reply
->
error
()
==
QNetworkReply
::
NoError
)
{
beginResetModel
();
auto
json
=
reply
->
readAll
();
m_products
=
Product
::
fromJson
(
json
);
endResetModel
();
mergeProducts
(
Product
::
fromJson
(
json
));
}
});
}
...
...
@@ -88,3 +94,48 @@ QVariant ProductModel::headerData(int section, Qt::Orientation orientation, int
}
return
QAbstractListModel
::
headerData
(
section
,
orientation
,
role
);
}
void
ProductModel
::
mergeProducts
(
QVector
<
Product
>
&&
products
)
{
std
::
sort
(
products
.
begin
(),
products
.
end
(),
[](
const
Product
&
lhs
,
const
Product
&
rhs
)
{
Q_ASSERT
(
lhs
.
isValid
());
Q_ASSERT
(
rhs
.
isValid
());
return
lhs
.
name
()
<
rhs
.
name
();
});
auto
newIt
=
products
.
cbegin
();
auto
it
=
m_products
.
begin
();
while
(
it
!=
m_products
.
end
()
&&
newIt
!=
products
.
cend
())
{
const
auto
row
=
std
::
distance
(
m_products
.
begin
(),
it
);
if
((
*
newIt
).
name
()
<
(
*
it
).
name
())
{
beginInsertRows
({},
row
,
row
);
it
=
m_products
.
insert
(
it
,
(
*
newIt
));
endInsertRows
();
++
it
;
++
newIt
;
}
else
if
((
*
it
).
name
()
<
(
*
newIt
).
name
())
{
beginRemoveRows
({},
row
,
row
);
it
=
m_products
.
erase
(
it
);
endRemoveRows
();
}
else
{
emit
dataChanged
(
index
(
row
,
0
),
index
(
row
,
0
));
++
it
;
++
newIt
;
}
}
if
(
it
==
m_products
.
end
()
&&
newIt
!=
products
.
cend
())
{
// trailing insert
const
auto
count
=
std
::
distance
(
newIt
,
products
.
cend
());
beginInsertRows
({},
m_products
.
size
(),
m_products
.
size
()
+
count
-
1
);
while
(
newIt
!=
products
.
cend
())
m_products
.
push_back
(
*
newIt
++
);
endInsertRows
();
}
else
if
(
newIt
==
products
.
cend
()
&&
it
!=
m_products
.
end
())
{
// trailing remove
const
auto
start
=
std
::
distance
(
m_products
.
begin
(),
it
);
const
auto
end
=
m_products
.
size
()
-
1
;
beginRemoveRows
({},
start
,
end
);
m_products
.
resize
(
start
);
endResetModel
();
}
}
analyzer/model/productmodel.h
View file @
944123ca
...
...
@@ -42,6 +42,7 @@ public:
};
void
setRESTClient
(
RESTClient
*
client
);
void
clear
();
void
reload
();
int
rowCount
(
const
QModelIndex
&
parent
=
QModelIndex
())
const
override
;
...
...
@@ -49,6 +50,8 @@ public:
QVariant
headerData
(
int
section
,
Qt
::
Orientation
orientation
,
int
role
=
Qt
::
DisplayRole
)
const
override
;
private:
void
mergeProducts
(
QVector
<
Product
>
&&
products
);
RESTClient
*
m_restClient
=
nullptr
;
QVector
<
Product
>
m_products
;
};
...
...
tests/auto/productmodeltest.cpp
View file @
944123ca
...
...
@@ -17,6 +17,7 @@
#include "servercontroller.h"
#include <rest/restapi.h>
#include <rest/restclient.h>
#include <model/productmodel.h>
...
...
@@ -40,11 +41,17 @@ private:
{
ServerInfo
s
;
s
.
setUrl
(
m_server
.
url
());
s
.
setUserName
(
QStringLiteral
(
"orwell"
));
s
.
setPassword
(
QStringLiteral
(
"1984"
));
return
s
;
}
bool
waitForFinished
(
QNetworkReply
*
reply
)
{
Q_ASSERT
(
reply
);
QSignalSpy
spy
(
reply
,
&
QNetworkReply
::
finished
);
Q_ASSERT
(
spy
.
isValid
());
return
spy
.
wait
();
}
private
slots
:
void
initTestCase
()
{
...
...
@@ -58,12 +65,40 @@ private slots:
client
.
connectToServer
(
testServer
());
QVERIFY
(
client
.
isConnected
());
Product
p
;
p
.
setName
(
QStringLiteral
(
"org.kde.NewUnitTestProduct"
));
auto
reply
=
RESTApi
::
deleteProduct
(
&
client
,
p
);
waitForFinished
(
reply
);
ProductModel
model
;
ModelTest
modelTest
(
&
model
);
QSignalSpy
resetSpy
(
&
model
,
&
ProductModel
::
modelReset
);
QSignalSpy
insertSpy
(
&
model
,
&
ProductModel
::
rowsInserted
);
QSignalSpy
removeSpy
(
&
model
,
&
ProductModel
::
rowsRemoved
);
model
.
setRESTClient
(
&
client
);
QSignalSpy
spy
(
&
model
,
&
ProductModel
::
modelReset
);
QVERIFY
(
spy
.
wait
());
QVERIFY
(
insertSpy
.
wait
());
const
auto
baseCount
=
model
.
rowCount
();
insertSpy
.
clear
();
reply
=
RESTApi
::
createProduct
(
&
client
,
p
);
QVERIFY
(
waitForFinished
(
reply
));
resetSpy
.
clear
();
model
.
reload
();
QVERIFY
(
insertSpy
.
wait
());
QCOMPARE
(
model
.
rowCount
(),
baseCount
+
1
);
reply
=
RESTApi
::
deleteProduct
(
&
client
,
p
);
QVERIFY
(
waitForFinished
(
reply
));
resetSpy
.
clear
();
model
.
reload
();
QVERIFY
(
removeSpy
.
wait
());
QCOMPARE
(
model
.
rowCount
(),
baseCount
);
removeSpy
.
clear
();
model
.
clear
();
QCOMPARE
(
removeSpy
.
size
(),
1
);
QVERIFY
(
resetSpy
.
isEmpty
());
}
};
...
...
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