mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Improve Contacts: sorting, searching and unread
ChatHandler::handleUnreadMsgs(...) deprecate 'id' field in favour of 'chat_id' IdentityHandler::handleWildcard(...) reduce sleep time from 500 to 50 ms IdentityHandler::handleWildcard(...) expose 'is_contact' to JSON API Split contacts list delegate into GxsIdentityDelegate.qml Update to QtQuick.Controls 2.0 because 1.4 is not supported anymore and 2.1 is not available yet in Qt 5.7.1 ChatView.qml mark messages as read Set refreshTimer.triggeredOnStart=true to improve reponsiveness of views Contacts.qml use a Popup that is available in Controls 2.0 instead of a castrated Dialog to display full fingerprint TrustedNodesView.qml check if locations[*].is_online is an array before attempting calling reduce main.qml added menuentry to shutdown de core main.qml added menuantry to search contact
This commit is contained in:
parent
34dc1fac37
commit
abe84a4f81
@ -924,7 +924,7 @@ ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp)
|
||||
void ChatHandler::handleMessages(Request &req, Response &resp)
|
||||
{
|
||||
/* G10h4ck: Whithout this the request processing won't happen, copied from
|
||||
* ChatHandler::handleLobbies, is this a work around or is the right whay of
|
||||
* ChatHandler::handleLobbies, is this a work around or is the right way of
|
||||
* doing it? */
|
||||
tick();
|
||||
|
||||
@ -1118,7 +1118,8 @@ void ChatHandler::handleUnreadMsgs(Request &/*req*/, Response &resp)
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
|
||||
resp.mDataStream.getStreamToMember();
|
||||
for(std::map<ChatId, std::list<Msg> >::const_iterator mit = mMsgs.begin(); mit != mMsgs.end(); ++mit)
|
||||
for( std::map<ChatId, std::list<Msg> >::const_iterator mit = mMsgs.begin();
|
||||
mit != mMsgs.end(); ++mit )
|
||||
{
|
||||
uint32_t count = 0;
|
||||
for(std::list<Msg>::const_iterator lit = mit->second.begin(); lit != mit->second.end(); ++lit)
|
||||
@ -1130,7 +1131,10 @@ void ChatHandler::handleUnreadMsgs(Request &/*req*/, Response &resp)
|
||||
if(count && (mit2 != mChatInfo.end()))
|
||||
{
|
||||
resp.mDataStream.getStreamToMember()
|
||||
<< makeKeyValue("id", mit->first.toStdString())
|
||||
#warning @deprecated using "id" as key can cause problems in some JS based \
|
||||
languages like Qml @see chat_id instead
|
||||
<< makeKeyValue("id", mit->first.toStdString())
|
||||
<< makeKeyValue("chat_id", mit->first.toStdString())
|
||||
<< makeKeyValueReference("unread_count", count)
|
||||
<< mit2->second;
|
||||
}
|
||||
@ -1162,7 +1166,8 @@ void ChatHandler::handleInitiateDistantChatConnexion(Request& req, Response& res
|
||||
DistantChatPeerId distant_chat_id;
|
||||
uint32_t error_code;
|
||||
|
||||
if(mRsMsgs->initiateDistantChatConnexion(receiver_id, sender_id, distant_chat_id, error_code))
|
||||
if(mRsMsgs->initiateDistantChatConnexion(receiver_id, sender_id,
|
||||
distant_chat_id, error_code))
|
||||
resp.setOk();
|
||||
else resp.setFail("Failed to initiate distant chat");
|
||||
|
||||
|
@ -61,7 +61,9 @@ protected:
|
||||
{
|
||||
case BEGIN:{
|
||||
RsIdentityParameters params;
|
||||
req.mStream << makeKeyValueReference("name", params.nickname) << makeKeyValueReference("pgp_linked", params.isPgpLinked);
|
||||
req.mStream
|
||||
<< makeKeyValueReference("name", params.nickname)
|
||||
<< makeKeyValueReference("pgp_linked", params.isPgpLinked);
|
||||
|
||||
if(params.nickname == "")
|
||||
{
|
||||
@ -141,9 +143,9 @@ void IdentityHandler::handleWildcard(Request & /*req*/, Response &resp)
|
||||
)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
Sleep(500);
|
||||
Sleep(50);
|
||||
#else
|
||||
usleep(500*1000);
|
||||
usleep(50*1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -156,14 +158,18 @@ void IdentityHandler::handleWildcard(Request & /*req*/, Response &resp)
|
||||
RsGxsIdGroup& grp = *vit;
|
||||
//electron: not very happy about this, i think the flags should stay hidden in rsidentities
|
||||
bool own = (grp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN);
|
||||
bool pgp_linked = (grp.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility ) ;
|
||||
resp.mDataStream.getStreamToMember()
|
||||
<< makeKeyValueReference("id", grp.mMeta.mGroupId) /// @deprecated using "id" as key can cause problems in some JS based languages like Qml @see gxs_id instead
|
||||
bool pgp_linked = (grp.mMeta.mGroupFlags &
|
||||
RSGXSID_GROUPFLAG_REALID_kept_for_compatibility);
|
||||
resp.mDataStream.getStreamToMember()
|
||||
#warning @deprecated using "id" as key can cause problems in some JS based \
|
||||
languages like Qml @see gxs_id instead
|
||||
<< makeKeyValueReference("id", grp.mMeta.mGroupId)
|
||||
<< makeKeyValueReference("gxs_id", grp.mMeta.mGroupId)
|
||||
<< makeKeyValueReference("pgp_id",grp.mPgpId )
|
||||
<< makeKeyValueReference("name", grp.mMeta.mGroupName)
|
||||
<< makeKeyValueReference("own", own)
|
||||
<< makeKeyValueReference("pgp_linked", pgp_linked);
|
||||
<< makeKeyValueReference("pgp_linked", pgp_linked)
|
||||
<< makeKeyValueReference("is_contact", grp.mIsAContact);
|
||||
}
|
||||
}
|
||||
else ok = false;
|
||||
|
@ -91,11 +91,11 @@ class GxsReputation
|
||||
};
|
||||
|
||||
|
||||
class RsGxsIdGroup
|
||||
struct RsGxsIdGroup
|
||||
{
|
||||
public:
|
||||
RsGxsIdGroup(): mLastUsageTS(0), mPgpKnown(false),mIsAContact(false) { return; }
|
||||
~RsGxsIdGroup() { return; }
|
||||
RsGxsIdGroup() :
|
||||
mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {}
|
||||
~RsGxsIdGroup() {}
|
||||
|
||||
|
||||
RsGroupMetaData mMeta;
|
||||
|
@ -13,5 +13,10 @@
|
||||
<file>qml/icons/remove-link.png</file>
|
||||
<file>qml/icons/state-offline.png</file>
|
||||
<file>qml/icons/state-ok.png</file>
|
||||
<file>qml/GxsIdentityDelegate.qml</file>
|
||||
<file>qml/icons/edit-find.png</file>
|
||||
<file>qml/icons/edit-image-face-detect.png</file>
|
||||
<file>qml/icons/document-share.png</file>
|
||||
<file>qml/icons/application-menu.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
Item
|
||||
@ -27,8 +27,12 @@ Item
|
||||
|
||||
function refreshData()
|
||||
{
|
||||
rsApi.request( "/chat/messages/"+ chatId, "",
|
||||
function(par) { chatModel.json = par.response } )
|
||||
rsApi.request( "/chat/messages/"+chatId, "", function(par)
|
||||
{
|
||||
chatModel.json = par.response
|
||||
if(visible) rsApi.request("/chat/mark_chat_as_read/"+chatId, "",
|
||||
null)
|
||||
} )
|
||||
}
|
||||
|
||||
onFocusChanged: focus && refreshData()
|
||||
@ -89,6 +93,7 @@ Item
|
||||
id: refreshTimer
|
||||
interval: 800
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: if(chatView.visible) chatView.refreshData()
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQml.Models 2.2
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
Item
|
||||
@ -26,6 +27,8 @@ Item
|
||||
id: contactsView
|
||||
property string own_gxs_id: ""
|
||||
property string own_nick: ""
|
||||
property bool searching: false
|
||||
property var unreadMessages: ({})
|
||||
|
||||
Component.onCompleted: refreshOwn()
|
||||
|
||||
@ -33,7 +36,7 @@ Item
|
||||
{
|
||||
function refreshCallback(par)
|
||||
{
|
||||
locationsModel.json = par.response
|
||||
gxsIdsModel.json = par.response
|
||||
if(contactsView.own_gxs_id == "") refreshOwn()
|
||||
}
|
||||
rsApi.request("/identity/*/", "", refreshCallback)
|
||||
@ -54,113 +57,174 @@ Item
|
||||
function startChatCallback(par)
|
||||
{
|
||||
var chId = JSON.parse(par.response).data.chat_id
|
||||
stackView.push({
|
||||
item:"qrc:/qml/ChatView.qml",
|
||||
properties: {chatId: chId}
|
||||
})
|
||||
stackView.push("qrc:/qml/ChatView.qml", {'chatId': chId})
|
||||
}
|
||||
|
||||
function refreshUnread()
|
||||
{
|
||||
rsApi.request("/chat/unread_msgs", "", function(par)
|
||||
{
|
||||
var jsonData = JSON.parse(par.response).data
|
||||
var dataLen = jsonData.length
|
||||
if(JSON.stringify(unreadMessages) != JSON.stringify(jsonData))
|
||||
{
|
||||
unreadMessages = {}
|
||||
for ( var i=0; i<dataLen; ++i)
|
||||
{
|
||||
var el = jsonData[i]
|
||||
if(el.is_distant_chat_id)
|
||||
unreadMessages[el.remote_author_id] = el.unread_count
|
||||
}
|
||||
|
||||
visualModel.resetSorting()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** This must be equivalent to
|
||||
p3GxsTunnelService::makeGxsTunnelId(...) */
|
||||
function getChatId(from_gxs, to_gxs)
|
||||
{
|
||||
return from_gxs < to_gxs ? from_gxs + to_gxs : to_gxs + from_gxs
|
||||
}
|
||||
|
||||
|
||||
|
||||
onFocusChanged: focus && refreshData()
|
||||
|
||||
JSONListModel
|
||||
{
|
||||
id: locationsModel
|
||||
id: gxsIdsModel
|
||||
query: "$.data[*]"
|
||||
}
|
||||
|
||||
DelegateModel
|
||||
{
|
||||
/* More documentation about this is available at:
|
||||
* http://doc.qt.io/qt-5/qml-qtqml-models-delegatemodel.html
|
||||
* http://doc.qt.io/qt-5/qtquick-tutorials-dynamicview-dynamicview4-example.html
|
||||
* http://imaginativethinking.ca/use-qt-quicks-delegatemodelgroup/
|
||||
*/
|
||||
id: visualModel
|
||||
model: gxsIdsModel.model
|
||||
|
||||
property var lessThan:
|
||||
[
|
||||
function(left, right)
|
||||
{
|
||||
var lfun = unreadMessages.hasOwnProperty(left.gxs_id) ?
|
||||
unreadMessages[left.gxs_id] : 0
|
||||
var rgun = unreadMessages.hasOwnProperty(right.gxs_id) ?
|
||||
unreadMessages[right.gxs_id] : 0
|
||||
if( lfun !== rgun ) return lfun > rgun
|
||||
if(left.name !== right.name) return left.name < right.name
|
||||
return left.gxs_id < right.gxs_id
|
||||
},
|
||||
function(left, right)
|
||||
{
|
||||
if(searchText.length > 0)
|
||||
{
|
||||
var mtc = searchText.text.toLowerCase()
|
||||
var lfn = left.name.toLowerCase()
|
||||
var rgn = right.name.toLowerCase()
|
||||
var lfml = lfn.indexOf(mtc)
|
||||
var rgml = rgn.indexOf(mtc)
|
||||
if ( lfml !== rgml )
|
||||
{
|
||||
lfml = lfml >= 0 ? lfml : Number.MAX_VALUE
|
||||
rgml = rgml >= 0 ? rgml : Number.MAX_VALUE
|
||||
return lfml < rgml
|
||||
}
|
||||
}
|
||||
return lessThan[0](left, right)
|
||||
}
|
||||
]
|
||||
|
||||
property int sortOrder: contactsView.searching ? 1 : 0
|
||||
onSortOrderChanged: resetSorting()
|
||||
|
||||
property bool isSorting: false
|
||||
|
||||
function insertPosition(lessThan, item)
|
||||
{
|
||||
var lower = 0
|
||||
var upper = items.count
|
||||
while (lower < upper)
|
||||
{
|
||||
var middle = Math.floor(lower + (upper - lower) / 2)
|
||||
var result = lessThan(item.model, items.get(middle).model);
|
||||
if (result) upper = middle
|
||||
else lower = middle + 1
|
||||
}
|
||||
return lower
|
||||
}
|
||||
|
||||
function resetSorting() { items.setGroups(0, items.count, "unsorted") }
|
||||
|
||||
function sort()
|
||||
{
|
||||
while (unsortedItems.count > 0)
|
||||
{
|
||||
var item = unsortedItems.get(0)
|
||||
var index = insertPosition(lessThan[visualModel.sortOrder],
|
||||
item)
|
||||
item.groups = ["items"]
|
||||
items.move(item.itemsIndex, index)
|
||||
}
|
||||
}
|
||||
|
||||
items.includeByDefault: false
|
||||
|
||||
groups:
|
||||
[
|
||||
DelegateModelGroup
|
||||
{
|
||||
id: unsortedItems
|
||||
name: "unsorted"
|
||||
|
||||
includeByDefault: true
|
||||
onChanged: visualModel.sort()
|
||||
}
|
||||
]
|
||||
|
||||
delegate: GxsIdentityDelegate {}
|
||||
}
|
||||
|
||||
ListView
|
||||
{
|
||||
id: locationsListView
|
||||
width: parent.width
|
||||
height: 300
|
||||
model: locationsModel.model
|
||||
delegate: Item
|
||||
height: contactsView.searching ?
|
||||
parent.height - searchBox.height : parent.height
|
||||
model: visualModel
|
||||
anchors.top: contactsView.searching ? searchBox.bottom : parent.top
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: searchBox
|
||||
visible: contactsView.searching
|
||||
|
||||
height: searchText.height
|
||||
width: searchText.width
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
|
||||
Image
|
||||
{
|
||||
height: 40
|
||||
width: parent.width
|
||||
id: searchIcon
|
||||
height: searchText.height - 4
|
||||
width: searchText.height - 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: "qrc:/qml/icons/edit-find.png"
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onClicked:
|
||||
{
|
||||
console.log("Contacts view onclicked:", model.name,
|
||||
model.gxs_id)
|
||||
if(model.own) contactsView.own_gxs_id = model.gxs_id
|
||||
else
|
||||
{
|
||||
var jsonData = { "own_gxs_hex": contactsView.own_gxs_id,
|
||||
"remote_gxs_hex": model.gxs_id }
|
||||
rsApi.request("/chat/initiate_distant_chat",
|
||||
JSON.stringify(jsonData),
|
||||
contactsView.startChatCallback)
|
||||
}
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
id: colorHash
|
||||
height: parent.height - 4
|
||||
width: height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 2
|
||||
color: "white"
|
||||
property int childHeight : height/2
|
||||
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(1, 9)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(9, 17)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(17, 25)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.slice(-8)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onPressAndHold:
|
||||
{
|
||||
fingerPrintDialog.nick = model.name
|
||||
fingerPrintDialog.gxs_id = model.gxs_id
|
||||
fingerPrintDialog.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Text
|
||||
{
|
||||
id: nickText
|
||||
color: model.own ? "blue" : "black"
|
||||
text: model.name
|
||||
anchors.left: colorHash.right
|
||||
anchors.leftMargin: 5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
TextField
|
||||
{
|
||||
id: searchText
|
||||
anchors.left: searchIcon.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onTextChanged: visualModel.resetSorting()
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,11 +243,16 @@ Item
|
||||
id: refreshTimer
|
||||
interval: 5000
|
||||
repeat: true
|
||||
onTriggered: if(contactsView.visible) contactsView.refreshData()
|
||||
triggeredOnStart: true
|
||||
onTriggered:
|
||||
if(contactsView.visible)
|
||||
{
|
||||
contactsView.refreshUnread()
|
||||
contactsView.refreshData()
|
||||
}
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
|
||||
|
||||
Dialog
|
||||
{
|
||||
id: createIdentityDialog
|
||||
@ -207,14 +276,17 @@ Item
|
||||
}
|
||||
}
|
||||
|
||||
Dialog
|
||||
Popup
|
||||
{
|
||||
id: fingerPrintDialog
|
||||
visible: false
|
||||
property string nick
|
||||
property string gxs_id
|
||||
title: nick + " fingerprint:"
|
||||
standardButtons: StandardButton.NoButton
|
||||
width: fingerPrintText.contentWidth + 20
|
||||
height: fingerPrintText.contentHeight + 20
|
||||
x: parent.x + parent.width/2 - width/2
|
||||
y: parent.y + parent.height/2 - height/2
|
||||
|
||||
Text
|
||||
{
|
||||
id: fingerPrintText
|
||||
|
139
retroshare-qml-app/src/qml/GxsIdentityDelegate.qml
Normal file
139
retroshare-qml-app/src/qml/GxsIdentityDelegate.qml
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
Item
|
||||
{
|
||||
height: 40
|
||||
width: parent.width
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onClicked:
|
||||
{
|
||||
console.log("Contacts view onclicked:", model.name,
|
||||
model.gxs_id)
|
||||
contactsView.searching = false
|
||||
if(model.own) contactsView.own_gxs_id = model.gxs_id
|
||||
else
|
||||
{
|
||||
var jsonData = { "own_gxs_hex": contactsView.own_gxs_id,
|
||||
"remote_gxs_hex": model.gxs_id }
|
||||
rsApi.request("/chat/initiate_distant_chat",
|
||||
JSON.stringify(jsonData),
|
||||
contactsView.startChatCallback)
|
||||
}
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
id: colorHash
|
||||
height: parent.height - 4
|
||||
width: height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 2
|
||||
color: "white"
|
||||
property int childHeight : height/2
|
||||
|
||||
Image
|
||||
{
|
||||
source: "qrc:/qml/icons/edit-image-face-detect.png"
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(1, 9)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(9, 17)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.substring(17, 25)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: '#' + model.gxs_id.slice(-8)
|
||||
height: parent.childHeight
|
||||
width: height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onPressAndHold:
|
||||
{
|
||||
fingerPrintDialog.nick = model.name
|
||||
fingerPrintDialog.gxs_id = model.gxs_id
|
||||
fingerPrintDialog.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Text
|
||||
{
|
||||
id: nickText
|
||||
color: model.own ? "blue" : "black"
|
||||
text: model.name
|
||||
anchors.left: colorHash.right
|
||||
anchors.leftMargin: 5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
visible: contactsView.unreadMessages.hasOwnProperty(model.gxs_id)
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "cornflowerblue"
|
||||
antialiasing: true
|
||||
border.color: "blue"
|
||||
border.width: 1
|
||||
radius: height/2
|
||||
height: parent.height - 10
|
||||
width: height
|
||||
|
||||
Text
|
||||
{
|
||||
color: "white"
|
||||
font.bold: true
|
||||
text: contactsView.unreadMessages.hasOwnProperty(model.gxs_id) ?
|
||||
contactsView.unreadMessages[model.gxs_id] : ''
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
Item
|
||||
@ -182,6 +182,7 @@ Item
|
||||
id: attemptTimer
|
||||
interval: 500
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered:
|
||||
{
|
||||
if(locationView.focus)
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQml 2.2
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Dialogs 1.2
|
||||
import "jsonpath.js" as JSONPath
|
||||
|
||||
@ -40,8 +40,10 @@ Item
|
||||
function isOnline(pgpId)
|
||||
{
|
||||
var qr = "$.data[?(@.pgp_id=='"+pgpId+"')].locations[*].is_online"
|
||||
var locArr = JSONPath.jsonPath(JSON.parse(jsonModel.json), qr)
|
||||
return locArr.reduce(function(cur,acc){return cur || acc}, false)
|
||||
var locOn = JSONPath.jsonPath(JSON.parse(jsonModel.json), qr)
|
||||
if (Array.isArray(locOn))
|
||||
return locOn.reduce(function(cur,acc){return cur || acc}, false)
|
||||
return Boolean(locOn)
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +67,8 @@ Item
|
||||
|
||||
height: parent.height - 4
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.leftMargin: 6
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 3
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text
|
||||
@ -130,7 +133,7 @@ Item
|
||||
id: bottomButton
|
||||
text: "Add Trusted Node"
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: stackView.push({item:"qrc:/qml/AddTrustedNode.qml"})
|
||||
onClicked: stackView.push("qrc:/qml/AddTrustedNode.qml")
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
@ -138,6 +141,7 @@ Item
|
||||
{
|
||||
interval: 800
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: if(trustedNodesView.visible) trustedNodesView.refreshData()
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
|
BIN
retroshare-qml-app/src/qml/icons/application-menu.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/application-menu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 387 B |
BIN
retroshare-qml-app/src/qml/icons/document-share.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/document-share.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
BIN
retroshare-qml-app/src/qml/icons/edit-find.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/edit-find.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
retroshare-qml-app/src/qml/icons/edit-image-face-detect.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/edit-image-face-detect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.0
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
|
||||
ApplicationWindow
|
||||
@ -28,8 +28,10 @@ ApplicationWindow
|
||||
width: 400
|
||||
height: 400
|
||||
|
||||
toolBar: ToolBar
|
||||
header: ToolBar
|
||||
{
|
||||
id: toolBar
|
||||
|
||||
Image
|
||||
{
|
||||
id: rsIcon
|
||||
@ -45,22 +47,48 @@ ApplicationWindow
|
||||
anchors.left: rsIcon.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
}
|
||||
|
||||
menuBar: MenuBar
|
||||
{
|
||||
Menu
|
||||
MouseArea
|
||||
{
|
||||
MenuItem
|
||||
height: parent.height
|
||||
width: parent.height
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
onClicked: menu.open()
|
||||
|
||||
Image
|
||||
{
|
||||
text: "Trusted Nodes"
|
||||
onTriggered:
|
||||
stackView.push({item:"qrc:/qml/TrustedNodesView.qml"})
|
||||
source: "qrc:/qml/icons/application-menu.png"
|
||||
height: parent.height - 10
|
||||
width: parent.height - 10
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
MenuItem
|
||||
|
||||
Menu
|
||||
{
|
||||
text: "StackView State"
|
||||
onTriggered: console.log(stackView.state, stackView.enabled)
|
||||
id: menu
|
||||
y: parent.y + parent.height
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: qsTr("Trusted Nodes")
|
||||
//iconSource: "qrc:/qml/icons/document-share.png"
|
||||
onTriggered:
|
||||
stackView.push("qrc:/qml/TrustedNodesView.qml")
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: qsTr("Search Contacts")
|
||||
onTriggered:
|
||||
stackView.push(
|
||||
"qrc:/qml/Contacts.qml", {'searching': true} )
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: "Terminate Core"
|
||||
onTriggered: rsApi.request("/control/shutdown")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,6 +130,7 @@ ApplicationWindow
|
||||
id: refreshTimer
|
||||
interval: 800
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: if(stackView.visible) stackView.checkCoreStatus()
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
@ -123,7 +152,7 @@ ApplicationWindow
|
||||
{
|
||||
console.log("StateChangeScript waiting_account_select")
|
||||
stackView.clear()
|
||||
stackView.push({item:"qrc:/qml/Locations.qml"})
|
||||
stackView.push("qrc:/qml/Locations.qml")
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -137,7 +166,7 @@ ApplicationWindow
|
||||
{
|
||||
console.log("StateChangeScript waiting_account_select")
|
||||
stackView.clear()
|
||||
stackView.push({item: "qrc:/qml/Contacts.qml"})
|
||||
stackView.push("qrc:/qml/Contacts.qml")
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -12,6 +12,8 @@ RESOURCES += qml.qrc
|
||||
|
||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
||||
#QML_IMPORT_PATH =
|
||||
#QML2_IMPORT_PATH =
|
||||
|
||||
|
||||
# Default rules for deployment.
|
||||
include(deployment.pri)
|
||||
|
Loading…
Reference in New Issue
Block a user