Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move GPS Tools GPSbabel device configuration widget to new page
in global settings dialog
  • Loading branch information
nyalldawson committed Jul 31, 2021
1 parent 612af1f commit c907f56
Show file tree
Hide file tree
Showing 10 changed files with 695 additions and 400 deletions.
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -224,6 +224,7 @@ set(QGIS_APP_SRCS

options/qgsadvancedoptions.cpp
options/qgscodeeditoroptions.cpp
options/qgsgpsdeviceoptions.cpp
options/qgsoptions.cpp
options/qgsoptionsutils.cpp

Expand Down
244 changes: 244 additions & 0 deletions src/app/options/qgsgpsdeviceoptions.cpp
@@ -0,0 +1,244 @@
/***************************************************************************
qgsgpsdeviceoptions.cpp
-------------------------
begin : July 2021
copyright : (C) 2021 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsgpsdeviceoptions.h"
#include "qgsbabelgpsdevice.h"
#include "qgssettings.h"
#include "qgsapplication.h"
#include "qgsbabelformatregistry.h"

#include <QMessageBox>

//
// QgsGpsDeviceOptionsWidget
//

QgsGpsDeviceOptionsWidget::QgsGpsDeviceOptionsWidget( QWidget *parent )
: QgsOptionsPageWidget( parent )
{
setupUi( this );

connect( mButtonAddDevice, &QToolButton::clicked, this, &QgsGpsDeviceOptionsWidget::addNewDevice );
connect( mButtonRemoveDevice, &QToolButton::clicked, this, &QgsGpsDeviceOptionsWidget::removeCurrentDevice );
connect( mListDevices, &QListWidget::currentItemChanged, this, &QgsGpsDeviceOptionsWidget::selectedDeviceChanged );

mDescriptionBrowser->setHtml( QStringLiteral( "<p>%1</p><ul>"
"<li>%babel - %2</li>"
"<li>%in - %3</li>"
"<li>%out - %4</li>"
"</ul>" ).arg( tr( "In the download and upload commands there can be special words that will be replaced by "
"QGIS when the commands are used. These words are:" ),
tr( "the path to GPSBabel" ),
tr( "the GPX filename when uploading or the port when downloading" ),
tr( "the port when uploading or the GPX filename when downloading" ) ) );

const QMap< QString, QgsBabelGpsDeviceFormat * > registeredDevices = QgsApplication::gpsBabelFormatRegistry()->devices();
for ( auto it = registeredDevices.constBegin(); it != registeredDevices.constEnd(); ++it )
{
if ( !it.value() )
continue;

const QString wptDownload =
it.value()->importCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Waypoint, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );
const QString wptUpload =
it.value()->exportCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Waypoint, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );
const QString rteDownload =
it.value()->importCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Route, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );
const QString rteUpload =
it.value()->exportCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Route, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );
const QString trkDownload =
it.value()->importCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Track, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );
const QString trkUpload =
it.value()->exportCommand( QStringLiteral( "%babel" ), Qgis::GpsFeatureType::Track, QStringLiteral( "%in" ), QStringLiteral( "%out" ) ).join( QLatin1Char( ' ' ) );

mDevices.insert( it.key(), {wptDownload, wptUpload, rteDownload, rteUpload, trkDownload, trkUpload } );
}

updateDeviceList();

connect( leWptDown, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leWptUp, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leRteDown, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leRteUp, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leTrkDown, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leTrkUp, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::updateCurrentDevice );
connect( leDeviceName, &QLineEdit::textEdited, this, &QgsGpsDeviceOptionsWidget::renameCurrentDevice );
}

void QgsGpsDeviceOptionsWidget::apply()
{
QStringList deviceNames;
QgsSettings settings;
QString devPath = QStringLiteral( "/Plugin-GPS/devices/%1" );
settings.remove( QStringLiteral( "/Plugin-GPS/devices" ) );

for ( auto iter = mDevices.constBegin(); iter != mDevices.constEnd(); ++iter )
{
const QString name = iter.key();
deviceNames << name;
const QStringList commands = iter.value();
settings.setValue( devPath.arg( name ) + "/wptdownload", commands.value( 0 ) );
settings.setValue( devPath.arg( name ) + "/wptupload", commands.value( 1 ) );
settings.setValue( devPath.arg( name ) + "/rtedownload", commands.value( 2 ) );
settings.setValue( devPath.arg( name ) + "/rteupload", commands.value( 3 ) );
settings.setValue( devPath.arg( name ) + "/trkdownload", commands.value( 4 ) );
settings.setValue( devPath.arg( name ) + "/trkupload", commands.value( 5 ) );
}
settings.setValue( QStringLiteral( "/Plugin-GPS/devicelist" ), deviceNames );

QgsApplication::gpsBabelFormatRegistry()->reloadFromSettings();
}

void QgsGpsDeviceOptionsWidget::addNewDevice()
{
QString deviceName = tr( "New device %1" );
int i = 1;
for ( auto iter = mDevices.constBegin(); iter != mDevices.constEnd(); ++i )
iter = mDevices.constFind( deviceName.arg( i ) );
deviceName = deviceName.arg( i - 1 );
mDevices[deviceName] = QStringList() << QString() << QString() << QString() << QString() << QString() << QString();
updateDeviceList( deviceName );
}

void QgsGpsDeviceOptionsWidget::removeCurrentDevice()
{
if ( QMessageBox::warning( this, tr( "Delete Device" ),
tr( "Are you sure that you want to delete this device?" ),
QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Ok )
{
auto iter = mDevices.find( mListDevices->currentItem()->text() );
if ( iter != mDevices.end() )
{
mDevices.erase( iter );
updateDeviceList();
}
}
}

void QgsGpsDeviceOptionsWidget::updateDeviceList( const QString &selection )
{
QString selected;
if ( selection.isEmpty() )
{
QListWidgetItem *item = mListDevices->currentItem();
selected = ( item ? item->text() : QString() );
}
else
{
selected = selection;
}

// We're going to be changing the selected item, so disable our
// notification of that.
disconnect( mListDevices, &QListWidget::currentItemChanged,
this, &QgsGpsDeviceOptionsWidget::selectedDeviceChanged );

mListDevices->clear();
for ( auto iter = mDevices.constBegin(); iter != mDevices.constEnd(); ++iter )
{
QListWidgetItem *item = new QListWidgetItem( iter.key(), mListDevices );
if ( iter.key() == selected )
{
mListDevices->setCurrentItem( item );
}
}

if ( !mListDevices->currentItem() && mListDevices->count() > 0 )
mListDevices->setCurrentRow( 0 );

// Update the display and reconnect the selection changed signal
selectedDeviceChanged( mListDevices->currentItem() );
connect( mListDevices, &QListWidget::currentItemChanged,
this, &QgsGpsDeviceOptionsWidget::selectedDeviceChanged );
}

void QgsGpsDeviceOptionsWidget::selectedDeviceChanged( QListWidgetItem *current )
{
if ( mListDevices->count() > 0 )
{
QString devName = current->text();

mBlockStoringChanges = true;
leDeviceName->setText( devName );
const QStringList commands = mDevices.value( devName );
leWptDown->setText( commands.value( 0 ) );
leWptUp->setText( commands.value( 1 ) );
leRteDown->setText( commands.value( 2 ) );
leRteUp->setText( commands.value( 3 ) );
leTrkDown->setText( commands.value( 4 ) );
leTrkUp->setText( commands.value( 5 ) );
mBlockStoringChanges = false;
}
}

void QgsGpsDeviceOptionsWidget::updateCurrentDevice()
{
if ( mBlockStoringChanges )
return;

const QString name = mListDevices->currentItem()->text();
mDevices.insert( name, {leWptDown->text(),
leWptUp->text(),
leRteDown->text(),
leRteUp->text(),
leTrkDown->text(),
leTrkUp->text()
} );
}

void QgsGpsDeviceOptionsWidget::renameCurrentDevice()
{
if ( mBlockStoringChanges )
return;

const QString prevName = mListDevices->currentItem()->text();
const QString newName = leDeviceName->text();
mDevices.remove( prevName );

mDevices.insert( newName, {leWptDown->text(),
leWptUp->text(),
leRteDown->text(),
leRteUp->text(),
leTrkDown->text(),
leTrkUp->text()
} );

mListDevices->currentItem()->setText( newName );
}

//
// QgsGpsDeviceOptionsFactory
//
QgsGpsDeviceOptionsFactory::QgsGpsDeviceOptionsFactory()
: QgsOptionsWidgetFactory( tr( "GPSBabel" ), QIcon() )
{

}

QIcon QgsGpsDeviceOptionsFactory::icon() const
{
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconGps.svg" ) );
}

QgsOptionsPageWidget *QgsGpsDeviceOptionsFactory::createWidget( QWidget *parent ) const
{
return new QgsGpsDeviceOptionsWidget( parent );
}

QStringList QgsGpsDeviceOptionsFactory::path() const
{
return {QStringLiteral( "gps" ) };
}

73 changes: 73 additions & 0 deletions src/app/options/qgsgpsdeviceoptions.h
@@ -0,0 +1,73 @@
/***************************************************************************
qgsgpsdeviceoptions.h
-------------------------
begin : July 2021
copyright : (C) 2021 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGPSDEVICEOPTIONS_H
#define QGSGPSDEVICEOPTIONS_H

#include "ui_qgsgpsdevicedialogbase.h"
#include "qgsoptionswidgetfactory.h"
#include "qgscodeeditor.h"

class QgsBabelGpsDeviceFormat;

/**
* \ingroup app
* \class QgsGpsDeviceOptionsWidget
* \brief An options widget showing GPS device configuration.
*
* \since QGIS 3.22
*/
class QgsGpsDeviceOptionsWidget : public QgsOptionsPageWidget, private Ui::QgsGpsDeviceWidgetBase
{
Q_OBJECT

public:

/**
* Constructor for QgsGpsDeviceOptionsWidget with the specified \a parent widget.
*/
QgsGpsDeviceOptionsWidget( QWidget *parent );

void apply() override;

private slots:
void addNewDevice();
void removeCurrentDevice();
void updateDeviceList( const QString &selection = QString() );
void selectedDeviceChanged( QListWidgetItem *current );
void updateCurrentDevice();
void renameCurrentDevice();

private:
QMap<QString, QStringList > mDevices;
bool mBlockStoringChanges = false;
};


class QgsGpsDeviceOptionsFactory : public QgsOptionsWidgetFactory
{
Q_OBJECT

public:

QgsGpsDeviceOptionsFactory();

QIcon icon() const override;
QgsOptionsPageWidget *createWidget( QWidget *parent = nullptr ) const override;
QStringList path() const override;

};


#endif // QGSGPSDEVICEOPTIONS_H
7 changes: 7 additions & 0 deletions src/app/options/qgsoptions.cpp
Expand Up @@ -129,6 +129,13 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
mTreeModel->appendRow( createItem( tr( "Variables" ), tr( "Variables" ), QStringLiteral( "mIconExpression.svg" ) ) );
mTreeModel->appendRow( createItem( tr( "Authentication" ), tr( "Authentication" ), QStringLiteral( "locked.svg" ) ) );
mTreeModel->appendRow( createItem( tr( "Network" ), tr( "Network" ), QStringLiteral( "propertyicons/network_and_proxy.svg" ) ) );

QStandardItem *gpsGroup = new QStandardItem( tr( "GPS" ) );
gpsGroup->setData( QStringLiteral( "gps" ) );
gpsGroup->setToolTip( tr( "GPS" ) );
gpsGroup->setSelectable( false );
mTreeModel->appendRow( gpsGroup );

mTreeModel->appendRow( createItem( tr( "Locator" ), tr( "Locator" ), QStringLiteral( "search.svg" ) ) );
mTreeModel->appendRow( createItem( tr( "Acceleration" ), tr( "GPU acceleration" ), QStringLiteral( "mIconGPU.svg" ) ) );

Expand Down
2 changes: 2 additions & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -109,6 +109,7 @@
#include "qgsgeometrycheckregistry.h"

#include "options/qgscodeeditoroptions.h"
#include "options/qgsgpsdeviceoptions.h"

#ifdef HAVE_3D
#include "qgs3d.h"
Expand Down Expand Up @@ -1697,6 +1698,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
} );

mCodeEditorWidgetFactory.reset( std::make_unique< QgsCodeEditorOptionsFactory >() );
mBabelGpsDevicesWidgetFactory.reset( std::make_unique< QgsGpsDeviceOptionsFactory >() );

#ifdef HAVE_3D
m3DOptionsWidgetFactory.reset( std::make_unique< Qgs3DOptionsFactory >() );
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.h
Expand Up @@ -2673,6 +2673,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsScopedDevToolWidgetFactory mStartupProfilerWidgetFactory;

QgsScopedOptionsWidgetFactory mCodeEditorWidgetFactory;
QgsScopedOptionsWidgetFactory mBabelGpsDevicesWidgetFactory;
QgsScopedOptionsWidgetFactory m3DOptionsWidgetFactory;

class QgsCanvasRefreshBlocker
Expand Down
1 change: 0 additions & 1 deletion src/plugins/gps_importer/CMakeLists.txt
Expand Up @@ -9,7 +9,6 @@ set (GPS_SRCS

set (GPS_UIS
qgsgpspluginguibase.ui
qgsgpsdevicedialogbase.ui
)

set (GPS_RCCS qgsgps_plugin.qrc)
Expand Down

0 comments on commit c907f56

Please sign in to comment.