Commit 5a1d4252 authored by Karel Slaný's avatar Karel Slaný

Merge branch 'search-db' into 'develop'

Find databox

See merge request !68
parents 349769c7 341a0159
......@@ -94,11 +94,13 @@ SOURCES += \
src/io/filesystem.cpp \
src/io/sqlite/db.cpp \
src/io/sqlite/table.cpp \
src/isds/isds_conversion.cpp \
src/locker.cpp \
src/log/log.cpp \
src/main.cpp \
src/messages.cpp \
src/models/accountmodel.cpp \
src/models/databoxmodel.cpp \
src/models/filemodel.cpp \
src/models/list_sort_filter_proxy_model.cpp \
src/models/messagemodel.cpp \
......@@ -127,6 +129,8 @@ SOURCES += \
src/worker/task_download_delivery_info.cpp \
src/worker/task_download_message.cpp \
src/worker/task_download_message_list.cpp \
src/worker/task_find_databox.cpp \
src/worker/task_find_databox_fulltext.cpp \
src/worker/task_keep_alive.cpp \
src/worker/task_send_sms.cpp
......@@ -143,10 +147,12 @@ HEADERS += \
src/io/filesystem.h \
src/io/sqlite/db.h \
src/io/sqlite/table.h \
src/isds/isds_conversion.h \
src/locker.h \
src/log/log.h \
src/messages.h \
src/models/accountmodel.h \
src/models/databoxmodel.h \
src/models/filemodel.h \
src/models/list_sort_filter_proxy_model.h \
src/models/messagemodel.h \
......@@ -176,6 +182,8 @@ HEADERS += \
src/worker/task_download_delivery_info.h \
src/worker/task_download_message.h \
src/worker/task_download_message_list.h \
src/worker/task_find_databox.h \
src/worker/task_find_databox_fulltext.h \
src/worker/task_keep_alive.h \
src/worker/task_send_sms.h
......
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
ListView {
id: root
/* These signals should be captured to implement databox interaction. */
signal dbClicked(string dbID, string dbType, string dbName, string dbAddress, string dbEffectiveOvm)
delegate: Rectangle {
id: dbItem
height: listItemHeight
width: parent.width
color: datovkaPalette.base
Item {
id: databoxData
anchors.fill: parent
anchors.margins: defaultMargin
GridLayout {
id: grid
columns: 2
rows: 3
rowSpacing: defaultMargin * 0.6
columnSpacing: defaultMargin * 2
anchors.verticalCenter: parent.verticalCenter
Text {
id: r1c1
text: rDbType
font.bold: true
}
Text {
id: r1c2
text: rDbName
color: headerColor
font.bold: true
}
Text {
id: r2c1
text: rDbID
}
Text {
id: r2c2
text: rDbAddress
}
Text {
id: r3c1
font.pointSize: textFontSizeSmall
text: rDbSendOption
}
Text {
id: r3c2
font.pointSize: textFontSizeSmall
text: (rDbIc == "") ? rDbIc : "IČ:" + rDbIc
}
Text {
id: hiddenText
visible: false
font.pointSize: textFontSizeSmall
text: rDbEffectiveOvm
}
}
} // Item
Rectangle {
id: next
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
height: parent.height
width: parent.width * 0.07
color: parent.color
Image {
id: nextImage
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: defaultMargin
sourceSize.height: navImgHeight
source: "qrc:/ui/next.svg"
}
ColorOverlay {
anchors.fill: nextImage
source: nextImage
color: datovkaPalette.windowText
}
} // Rectangle
MouseArea {
anchors.fill: parent
onClicked: {
root.dbClicked(rDbID, rDbType, rDbName, rDbAddress, rDbEffectiveOvm)
}
}
Rectangle {
anchors.top: parent.bottom
height: 1
width: parent.width
color: datovkaPalette.dark
}
} // Rectangle
ScrollIndicator.vertical: ScrollIndicator {}
} // ListView
......@@ -62,6 +62,8 @@ ApplicationWindow {
property Component pageAboutApp: PageAboutApp {}
property Component pageAccountDetail: PageAccountDetail {}
property Component pageChangePassword: PageChangePassword {}
property Component pageDataboxDetail: PageDataboxDetail {}
property Component pageDataboxSearch: PageDataboxSearch {}
property Component pageMenuAccount: PageMenuAccount {}
property Component pageMenuDatovkaSettings: PageMenuDatovkaSettings {}
property Component pageMenuMessage: PageMenuMessage {}
......
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
import QtQuick 2.7
import QtQuick.Controls 2.1
import cz.nic.mobileDatovka 1.0
Component {
id: pageDataboxDetail
Item {
id: dbDetailPage
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string userName
property string dbID
property string dbType
Component.onCompleted: {
isds.doIsdsAction("findDatabox", userName)
}
Connections {
target: isds
onRunFindDataboxSig: {
databoxDetailText.text = isds.findDatabox(userName, dbID, dbType)
}
}
PageHeader {
id: headerBar
title: qsTr("Databox info") + " (" + dbID + ")"
Item {
anchors.left: parent.left
width: parent.width * 0.5
height: parent.height
MouseArea {
anchors.fill: parent
onClicked: {
pageView.pop(StackView.Immediate)
}
}
}
} // PageHeader
Flickable {
id: flickable
z: 0
anchors.top: headerBar.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
contentHeight: flickContent.implicitHeight
Pane {
id: flickContent
anchors.fill: parent
Text {
id: databoxDetailText
color: datovkaPalette.text
width: parent.width
textFormat: TextEdit.RichText
wrapMode: Text.WordWrap
}
} // Pane
ScrollIndicator.vertical: ScrollIndicator {}
} // Flickable
}
}
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import cz.nic.mobileDatovka 1.0
import cz.nic.mobileDatovka.models 1.0
/*
* Roles are defined in DataboxListModel::roleNames() and are accessed directly
* via their names.
*/
Item {
id: pageDataboxSearch
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string userName
/* These properties remember choice of ComboBoxes */
property string searchType: "GENERAL"
property string searchScope: "ALL"
/* These properties remember origin search settings during pagination */
property int page: 0
property string searchTextTmp
property string searchTypeTmp
property string searchScopeTmp
Component.onCompleted: {
searchPhraseText.forceActiveFocus()
proxyDataboxModel.setSourceModel(databoxModel)
}
DataboxListModel {
id: databoxModel
Component.onCompleted: {
}
}
ListSortFilterProxyModel {
id: proxyDataboxModel
Component.onCompleted: {
setFilterRoles([DataboxListModel.ROLE_DB_NAME,
DataboxListModel.ROLE_DB_ADDRESS, DataboxListModel.ROLE_DB_IC,
DataboxListModel.ROLE_DB_ID])
}
}
PageHeader {
id: headerBar
title: qsTr("Find databox")
Item {
anchors.left: parent.left
width: parent.width * 0.5
height: parent.height
MouseArea {
anchors.fill: parent
onClicked: {
statusBar.visible = false
pageView.pop(StackView.Immediate)
}
}
}
Image {
id: actionButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: defaultMargin
sourceSize.height: imgHeight
source: "qrc:/ui/account-search.svg"
MouseArea {
anchors.fill: parent
onClicked: {
searchPhraseText.focus = false
searchPanel.doSearchRequest()
}
}
}
TextField {
id: filterPhraseText
placeholderText: qsTr("Set filter")
width: headerBar.width * 0.3
anchors.right: actionButton.left
anchors.rightMargin: defaultMargin
anchors.verticalCenter: parent.verticalCenter
font.pointSize: defaultTextFont.font.pointSize
inputMethodHints: Qt.ImhNoPredictiveText
/*
* Using explicit top, left, ... padding because plain padding
* does not centre the text properly.
*/
topPadding: 8.0
bottomPadding: 8.0
leftPadding: 8.0
rightPadding: 8.0
/* TODO - remove background if used materials */
background: Rectangle {
anchors.fill: parent
color: (filterPhraseText.text.length == 0) ? datovkaPalette.alternateBase :
(databoxList.count > 0) ? "#afffaf" : "#ffafaf"
border.color: filterPhraseText.activeFocus ? "#0066ff" :
"#bdbebf"
}
onTextChanged: {
proxyDataboxModel.setFilterRegExpStr(filterPhraseText.text)
}
}
} // PageHeader
Pane {
id: searchPanel
anchors.top: headerBar.bottom
width: parent.width
function doSearchRequest() {
isds.doIsdsAction("findDataboxFulltext", userName)
}
Column {
anchors.right: parent.right
anchors.left: parent.left
spacing: formItemVerticalSpacing
ComboBox {
id: searchScopeComboBox
currentIndex: 0
width: parent.width
height: inputItemHeight
textRole: "label"
font.pointSize: defaultTextFont.font.pointSize
delegate: ItemDelegate {
width: searchScopeComboBox.width
height: inputItemHeight
contentItem: Text {
text: label
color: datovkaPalette.text
font.pointSize: defaultTextFont.font.pointSize
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: searchScopeComboBox.highlightedIndex == index
}
model: ListModel {
id: searchScopeComboBoxModel
ListElement { label: qsTr("All databoxes"); value: "ALL" }
ListElement { label: qsTr("OVM"); value: "OVM" }
ListElement { label: qsTr("PO"); value: "PO" }
ListElement { label: qsTr("PFO"); value: "PFO" }
ListElement { label: qsTr("FO"); value: "FO" }
}
onCurrentIndexChanged: searchScope = searchScopeComboBoxModel.get(currentIndex).value
}
ComboBox {
id: searchTypeComboBox
currentIndex: 0
width: parent.width
height: inputItemHeight
textRole: "label"
font.pointSize: defaultTextFont.font.pointSize
delegate: ItemDelegate {
width: searchTypeComboBox.width
height: inputItemHeight
contentItem: Text {
text: label
color: datovkaPalette.text
font.pointSize: defaultTextFont.font.pointSize
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: searchTypeComboBox.highlightedIndex == index
}
model: ListModel {
id: searchTypeComboBoxModel
ListElement { label: qsTr("All fields"); value: "GENERAL" }
ListElement { label: qsTr("Address"); value: "ADDRESS" }
ListElement { label: qsTr(""); value: "ICO" }
ListElement { label: qsTr("Databox ID"); value: "DBID" }
}
onCurrentIndexChanged: searchType = searchTypeComboBoxModel.get(currentIndex).value
}
TextField {
id: searchPhraseText
placeholderText: qsTr("Enter phrase")
focus: true
width: parent.width
font.pointSize: defaultTextFont.font.pointSize
height: inputItemHeight
onAccepted: searchPanel.doSearchRequest()
InputLineMenu {
id: searchPhraseTextMenu
inputTextControl: searchPhraseText
isPassword: false
}
onPressAndHold: {
if (settings.useExplicitClipboardOperations()) {
searchPhraseTextMenu.implicitWidth = computeMenuWidth(searchPhraseTextMenu)
searchPhraseTextMenu.open()
}
}
}
Item {
id: searchResults
height: inputItemHeight
width: parent.width
visible: false
Rectangle {
id: searchResultPrevious
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
width: parent.width * 0.07
height: parent.height
color: "transparent"
Image {
id: previousImage
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.rightMargin: defaultMargin
sourceSize.height: navImgHeight * 1.2
source: "qrc:/ui/back.svg"
}
ColorOverlay {
anchors.fill: previousImage
source: previousImage
color: enabled ? headerColor : datovkaPalette.mid
}
MouseArea {
anchors.fill: parent
onClicked: {
if (page > 0) {
page = page-1
}
isds.findDataboxFulltext(userName, databoxModel, searchTextTmp, searchTypeTmp, searchScopeTmp, page)
}
}
}
Text {
id: searchResultText
color: datovkaPalette.text
text: ""
anchors.centerIn: parent
}
Rectangle {
id: searchResultNext
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
height: parent.height
width: parent.width * 0.07
color: "transparent"
Image {
id: nextImage
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: defaultMargin
sourceSize.height: navImgHeight * 1.2
source: "qrc:/ui/next.svg"
}
ColorOverlay {
anchors.fill: nextImage
source: nextImage
color: enabled ? headerColor : datovkaPalette.mid
}
MouseArea {
anchors.fill: parent
onClicked: {
page = page+1
isds.findDataboxFulltext(userName, databoxModel, searchTextTmp, searchTypeTmp, searchScopeTmp, page)
}
}
} // Rectangle
} // Item
} // Column
} // Pane
Text {
id: emptyList
visible: false
color: datovkaPalette.text
anchors.centerIn: parent
wrapMode: Text.Wrap
text: qsTr("No databox found for given search criteria.")
}
DataboxList {
id: databoxList
anchors.top: searchPanel.bottom
anchors.bottom: parent.bottom
clip: true
spacing: 1
opacity: 1
visible: true
width: parent.width
interactive: true
model: proxyDataboxModel
onDbClicked: {
statusBar.visible = false
pageView.push(pageDataboxDetail, {
"pageView": pageView,
"statusBar": statusBar,
"userName": userName,
"dbID": dbID,
"dbType": dbType
}, StackView.Immediate)
}
} // DataboxList
Connections {
target: isds
onRunFindDataboxFulltextSig: {
searchResults.visible = false
searchResultPrevious.enabled = false
searchResultNext.enabled = false
searchResultText.text = ""
page = 0
searchTextTmp = searchPhraseText.text
searchTypeTmp = searchType
searchScopeTmp = searchScope
emptyList.visible = (isds.findDataboxFulltext(userName, databoxModel, searchPhraseText.text, searchType, searchScope, page) <= 0)
}
}
Connections {
target: isds
onSendSearchResultsSig: {
searchResults.visible = true
searchResultNext.visible = (totalCount > 0) && (totalCount > currentCount)
searchResultPrevious.visible = (totalCount > 0) && (totalCount > currentCount)
searchResultNext.enabled = !lastPage
searchResultPrevious.enabled = (position > 0)
if ((totalCount > 0) && (totalCount > currentCount)) {
searchResultText.text = qsTr("Found") + ": " + totalCount + "; " + qsTr("Shown") + ": " + (position + 1) + "-" + (position + currentCount) + ";"
} else {