Skip to content

Commit

Permalink
Merge pull request #5574 from opengisch/search-in-projects
Browse files Browse the repository at this point in the history
Search cloud projects list functionality
  • Loading branch information
nirvn authored Aug 20, 2024
2 parents 07b0d66 + 0974031 commit 0ddc4d7
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 8 deletions.
33 changes: 27 additions & 6 deletions src/core/qfieldcloudprojectsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2453,22 +2453,43 @@ bool QFieldCloudProjectsFilterModel::showLocalOnly() const

bool QFieldCloudProjectsFilterModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
{
if ( mShowLocalOnly && mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), QFieldCloudProjectsModel::LocalPathRole ).toString().isEmpty() )
const QModelIndex currentRowIndex = mSourceModel->index( source_row, 0, source_parent );
if ( mShowLocalOnly && mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::LocalPathRole ).toString().isEmpty() )
{
return false;
}

bool ok = false;
bool matchesProjectType = false;
switch ( mFilter )
{
case PrivateProjects:
// the list will include public "community" projects that are present locally so they can appear in the "My projects" list
ok = mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), QFieldCloudProjectsModel::UserRoleOriginRole ).toString() != QStringLiteral( "public" )
|| !mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), QFieldCloudProjectsModel::LocalPathRole ).toString().isEmpty();
matchesProjectType = mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::UserRoleOriginRole ).toString() != QStringLiteral( "public" )
|| !mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::LocalPathRole ).toString().isEmpty();
break;
case PublicProjects:
ok = mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), QFieldCloudProjectsModel::UserRoleOriginRole ).toString() == QStringLiteral( "public" );
matchesProjectType = mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::UserRoleOriginRole ).toString() == QStringLiteral( "public" );
break;
}
return ok;

const QString name = mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::NameRole ).toString();
const QString description = mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::DescriptionRole ).toString();
const QString owner = mSourceModel->data( currentRowIndex, QFieldCloudProjectsModel::OwnerRole ).toString();

bool matchesTextFilter = mTextFilter.isEmpty() || name.contains( mTextFilter, Qt::CaseInsensitive ) || description.contains( mTextFilter, Qt::CaseInsensitive ) || owner.contains( mTextFilter, Qt::CaseInsensitive );

return matchesProjectType && matchesTextFilter;
}

void QFieldCloudProjectsFilterModel::setTextFilter( const QString &text )
{
if ( mTextFilter == text )
return;
mTextFilter = text;
invalidateFilter();
}

QString QFieldCloudProjectsFilterModel::textFilter() const
{
return mTextFilter;
}
16 changes: 15 additions & 1 deletion src/core/qfieldcloudprojectsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ class QFieldCloudProjectsFilterModel : public QSortFilterProxyModel
Q_PROPERTY( QFieldCloudProjectsModel *projectsModel READ projectsModel WRITE setProjectsModel NOTIFY projectsModelChanged )
Q_PROPERTY( ProjectsFilter filter READ filter WRITE setFilter NOTIFY filterChanged )
Q_PROPERTY( bool showLocalOnly READ showLocalOnly WRITE setShowLocalOnly NOTIFY showLocalOnlyChanged )
Q_PROPERTY( QString textFilter READ textFilter WRITE setTextFilter NOTIFY textFilterChanged )

public:
enum ProjectsFilter
Expand Down Expand Up @@ -539,7 +540,7 @@ class QFieldCloudProjectsFilterModel : public QSortFilterProxyModel
ProjectsFilter filter() const;

/**
* Sets the the cloud project \a filter.
* Sets the cloud project \a filter.
*/
void setFilter( ProjectsFilter filter );

Expand All @@ -553,11 +554,23 @@ class QFieldCloudProjectsFilterModel : public QSortFilterProxyModel
*/
void setShowLocalOnly( bool showLocalOnly );

/**
* Sets a \a text string filter projects by matching it against the project's name or description
* as well well as owner's name.
*/
void setTextFilter( const QString &text );

/**
* Returns the current text string used to filter projects.
*/
QString textFilter() const;

signals:

void projectsModelChanged();
void filterChanged();
void showLocalOnlyChanged();
void textFilterChanged();

protected:
virtual bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override;
Expand All @@ -566,6 +579,7 @@ class QFieldCloudProjectsFilterModel : public QSortFilterProxyModel
QFieldCloudProjectsModel *mSourceModel = nullptr;
ProjectsFilter mFilter = PrivateProjects;
bool mShowLocalOnly = false;
QString mTextFilter;
};

Q_DECLARE_METATYPE( QFieldCloudProjectsFilterModel::ProjectsFilter )
Expand Down
11 changes: 10 additions & 1 deletion src/qml/QFieldCloudScreen.qml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ Page {
}
}

QfSearchBar {
id: searchBar
Layout.fillWidth: true
Layout.preferredHeight: 41
}

Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
Expand All @@ -197,7 +203,7 @@ Page {
projectsModel: cloudProjectsModel
filter: filterBar.currentIndex === 0 ? QFieldCloudProjectsFilterModel.PrivateProjects : QFieldCloudProjectsFilterModel.PublicProjects
showLocalOnly: cloudConnection.status !== QFieldCloudConnection.LoggedIn

textFilter: searchBar.searchTerm
onFilterChanged: {
if (cloudConnection.state === QFieldCloudConnection.Idle && cloudProjectsModel.busyProjectIds.length === 0) {
refreshProjectsList(filter === QFieldCloudProjectsFilterModel.PublicProjects);
Expand Down Expand Up @@ -422,6 +428,7 @@ Page {

MouseArea {
property Item pressedItem
propagateComposedEvents: true
anchors.fill: parent
onClicked: mouse => {
var item = table.itemAt(table.contentX + mouse.x, table.contentY + mouse.y);
Expand All @@ -435,13 +442,15 @@ Page {
cloudProjectsModel.projectPackageAndDownload(item.projectId);
}
}
mouse.accepted = false;
}
onPressed: mouse => {
var item = table.itemAt(table.contentX + mouse.x, table.contentY + mouse.y);
if (item) {
pressedItem = item;
pressedItem.isPressed = true;
}
mouse.accepted = false;
}
onCanceled: {
if (pressedItem) {
Expand Down
58 changes: 58 additions & 0 deletions src/qml/imports/Theme/QfSearchBar.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import QtQuick
import QtQuick.Controls
import org.qfield
import Theme

Item {
property alias searchTerm: searchBar.text

Rectangle {
width: parent.width
height: 40
radius: 6
border.width: 1
color: Theme.mainBackgroundColor
border.color: searchBar.activeFocus ? Theme.mainColor : "transparent"

QfToolButton {
id: clearButton
anchors.right: parent.right
width: 40
height: 40
iconSource: Theme.getThemeIcon('ic_close_black_24dp')
iconColor: Theme.mainTextColor
bgcolor: "transparent"
visible: searchBar.text !== ""
onClicked: {
searchBar.text = '';
}
}

QfToolButton {
id: searchButton
width: 40
height: 40
anchors.left: parent.left
bgcolor: "transparent"
iconSource: Theme.getThemeIcon("ic_baseline_search_black")
iconColor: Theme.mainTextColor
onClicked: {
searchBar.focus = true;
}
}

TextField {
id: searchBar
rightPadding: 7
anchors.left: searchButton.right
anchors.right: clearButton.left
anchors.leftMargin: -16
anchors.rightMargin: 4
height: 40
selectByMouse: true
placeholderText: (!searchBar.activeFocus && text === "" && displayText === "") ? qsTr("Search for project") : ""
background: Item {
}
}
}
}
1 change: 1 addition & 0 deletions src/qml/imports/Theme/qmldir
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ QfTabBar 1.0 QfTabBar.qml
QfSwipeAnimator 1.0 QfSwipeAnimator.qml
QfProgrerssRing 1.0 QfProgrerssRing.qml
QfScrollBar 1.0 QfScrollBar.qml
QfSearchBar 1.0 QfSearchBar.qml
1 change: 1 addition & 0 deletions src/qml/qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@
<file>QFieldGuide.qml</file>
<file>imports/Theme/QfProgrerssRing.qml</file>
<file>imports/Theme/QfScrollBar.qml</file>
<file>imports/Theme/QfSearchBar.qml</file>
</qresource>
</RCC>

1 comment on commit 0ddc4d7

@qfield-fairy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.