File indexing completed on 2024-05-05 03:50:38
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2014 Calin Cruceru <crucerucalincristian@gmail.com> 0004 // 0005 0006 // Self 0007 #include "EditPolylineDialog.h" 0008 #include "ui_EditPolylineDialog.h" 0009 0010 // Qt 0011 #include <QColorDialog> 0012 #include <QMessageBox> 0013 0014 // Marble 0015 #include "GeoDataPlacemark.h" 0016 #include "GeoDataLineString.h" 0017 #include "GeoDataStyle.h" 0018 #include "GeoDataLineStyle.h" 0019 #include "NodeModel.h" 0020 #include "FormattedTextWidget.h" 0021 #include "NodeItemDelegate.h" 0022 #include "StyleBuilder.h" 0023 #include "osm/OsmTagEditorWidget.h" 0024 #include "osm/OsmPlacemarkData.h" 0025 #include "osm/OsmRelationManagerWidget.h" 0026 0027 0028 namespace Marble 0029 { 0030 0031 class Q_DECL_HIDDEN EditPolylineDialog::Private : public Ui::UiEditPolylineDialog 0032 { 0033 public: 0034 Private( GeoDataPlacemark *placemark); 0035 ~Private(); 0036 0037 QColorDialog *m_linesDialog; 0038 OsmTagEditorWidget *m_osmTagEditorWidget; 0039 OsmRelationManagerWidget *m_osmRelationManagerWidget; 0040 GeoDataPlacemark *m_placemark; 0041 0042 // Used to restore if the Cancel button is pressed. 0043 QString m_initialName; 0044 QString m_initialDescription; 0045 GeoDataLineStyle m_initialLineStyle; 0046 GeoDataLineString m_initialLineString; 0047 OsmPlacemarkData m_initialOsmData; 0048 bool m_hadInitialOsmData; 0049 0050 NodeItemDelegate *m_delegate; 0051 NodeModel *m_nodeModel; 0052 }; 0053 0054 EditPolylineDialog::Private::Private( GeoDataPlacemark *placemark ) : 0055 Ui::UiEditPolylineDialog(), 0056 m_linesDialog( nullptr ), 0057 m_osmTagEditorWidget( nullptr ), 0058 m_osmRelationManagerWidget( nullptr ), 0059 m_placemark( placemark ), 0060 m_nodeModel( new NodeModel ) 0061 { 0062 // nothing to do 0063 } 0064 0065 EditPolylineDialog::Private::~Private() 0066 { 0067 delete m_linesDialog; 0068 delete m_nodeModel; 0069 delete m_delegate; 0070 } 0071 0072 EditPolylineDialog::EditPolylineDialog( GeoDataPlacemark *placemark, 0073 const QHash<qint64, OsmPlacemarkData> *relations, 0074 QWidget *parent ) : 0075 QDialog( parent ) , 0076 d ( new Private( placemark ) ) 0077 { 0078 d->setupUi( this ); 0079 0080 // There's no point showing Relations and Tags tabs if the editor was not 0081 // loaded from the annotate plugin ( loaded from tourWidget.. ) 0082 if ( relations ) { 0083 // Adding the osm tag editor widget tab 0084 d->m_osmTagEditorWidget = new OsmTagEditorWidget( placemark, this ); 0085 d->tabWidget->addTab( d->m_osmTagEditorWidget, tr( "Tags" ) ); 0086 QObject::connect( d->m_osmTagEditorWidget, SIGNAL(placemarkChanged(GeoDataFeature*)), 0087 this, SLOT(updatePolyline()) ); 0088 0089 // Adding the osm relation editor widget tab 0090 d->m_osmRelationManagerWidget = new OsmRelationManagerWidget( placemark, relations, this ); 0091 d->tabWidget->addTab( d->m_osmRelationManagerWidget, tr( "Relations" ) ); 0092 QObject::connect( d->m_osmRelationManagerWidget, SIGNAL(relationCreated(OsmPlacemarkData)), 0093 this, SIGNAL(relationCreated(OsmPlacemarkData)) ); 0094 0095 adjustSize(); 0096 } 0097 0098 d->m_hadInitialOsmData = placemark->hasOsmData(); 0099 if ( d->m_hadInitialOsmData ) { 0100 d->m_initialOsmData = placemark->osmData(); 0101 } 0102 0103 // If the polygon has just been drawn, assign it a default name. 0104 if ( d->m_placemark->name().isNull() ) { 0105 d->m_placemark->setName( tr("Untitled Path") ); 0106 } 0107 0108 d->m_initialLineString = *(static_cast<GeoDataLineString*>( placemark->geometry() ) ); 0109 d->m_name->setText( placemark->name() ); 0110 d->m_initialName = d->m_name->text(); 0111 connect( d->m_name, SIGNAL(editingFinished()), this, SLOT(updatePolyline()) ); 0112 0113 d->m_formattedTextWidget->setText( placemark->description() ); 0114 d->m_initialDescription = d->m_formattedTextWidget->text(); 0115 0116 d->m_linesWidth->setRange( 0.1, 5.0 ); 0117 0118 0119 // Get the current style properties. 0120 const GeoDataLineStyle lineStyle = placemark->style()->lineStyle(); 0121 d->m_initialLineStyle = lineStyle; 0122 0123 d->m_linesWidth->setValue( lineStyle.width() ); 0124 connect( d->m_linesWidth, SIGNAL(valueChanged(double)), this, SLOT(handleChangingStyle()) ); 0125 0126 // Adjust the color button's icon to the current lines color. 0127 QPixmap linesPixmap( d->m_linesColorButton->iconSize() ); 0128 linesPixmap.fill( lineStyle.color() ); 0129 d->m_linesColorButton->setIcon( QIcon( linesPixmap ) ); 0130 0131 // Setting the NodeView's delegate: mainly used for the editing the polyline's nodes 0132 d->m_delegate = new NodeItemDelegate( d->m_placemark, d->m_nodeView ); 0133 0134 connect( d->m_delegate, SIGNAL(modelChanged(GeoDataPlacemark*)), 0135 this, SLOT(handleItemMoving(GeoDataPlacemark*)) ); 0136 connect( d->m_delegate, SIGNAL(geometryChanged()), 0137 this, SLOT(updatePolyline()) ); 0138 0139 d->m_nodeView->setItemDelegate( d->m_delegate ); 0140 d->m_nodeView->setEditTriggers( QAbstractItemView::AllEditTriggers ); 0141 0142 // Setup the color dialogs. 0143 d->m_linesDialog = new QColorDialog( this ); 0144 d->m_linesDialog->setOption( QColorDialog::ShowAlphaChannel ); 0145 d->m_linesDialog->setCurrentColor( lineStyle.color() ); 0146 connect( d->m_linesColorButton, SIGNAL(clicked()), d->m_linesDialog, SLOT(exec()) ); 0147 connect( d->m_linesDialog, SIGNAL(colorSelected(QColor)), this, SLOT(updateLinesDialog(QColor)) ); 0148 connect( d->m_linesDialog, SIGNAL(colorSelected(QColor)), this, SLOT(handleChangingStyle()) ); 0149 0150 if (const auto lineString = geodata_cast<GeoDataLineString>(placemark->geometry())) { 0151 for( int i = 0; i < lineString->size(); ++i ) { 0152 d->m_nodeModel->addNode( lineString->at( i ) ); 0153 } 0154 } 0155 d->m_nodeView->setModel( d->m_nodeModel ); 0156 0157 // Resize column to contents size for better UI. 0158 d->m_nodeView->resizeColumnToContents( 0 ); 0159 0160 // Promote "Ok" button to default button. 0161 d->buttonBox->button( QDialogButtonBox::Ok )->setDefault( true ); 0162 0163 connect( d->buttonBox->button( QDialogButtonBox::Ok ), SIGNAL(pressed()), this, SLOT(checkFields()) ); 0164 connect( this, SIGNAL(accepted()), SLOT(updatePolyline()) ); 0165 connect( this, SIGNAL(finished(int)), SLOT(restoreInitial(int)) ); 0166 0167 // Ensure that the dialog gets deleted when closing it (either when clicking OK or 0168 // Close). 0169 connect( this, SIGNAL(finished(int)), SLOT(deleteLater()) ); 0170 } 0171 0172 EditPolylineDialog::~EditPolylineDialog() 0173 { 0174 delete d; 0175 } 0176 0177 void EditPolylineDialog::handleAddingNode( const GeoDataCoordinates &node ) 0178 { 0179 d->m_nodeModel->addNode( node ); 0180 } 0181 0182 void EditPolylineDialog::handleItemMoving( GeoDataPlacemark *item ) 0183 { 0184 if( item == d->m_placemark ) { 0185 d->m_nodeModel->clear(); 0186 if (const auto lineString = geodata_cast<GeoDataLineString>(d->m_placemark->geometry())) { 0187 for( int i = 0; i < lineString->size(); ++i ) { 0188 d->m_nodeModel->addNode( lineString->at( i ) ); 0189 } 0190 } 0191 } 0192 } 0193 0194 void EditPolylineDialog::handleChangingStyle() 0195 { 0196 // The default style has been changed, thus the old style URL is no longer valid 0197 // The polyline is now considered to have a customStyle 0198 d->m_placemark->setStyleUrl(QString()); 0199 0200 GeoDataStyle::Ptr newStyle(new GeoDataStyle( *d->m_placemark->style() )); 0201 newStyle->lineStyle().setColor( d->m_linesDialog->currentColor() ); 0202 newStyle->lineStyle().setWidth( d->m_linesWidth->value() ); 0203 newStyle->setId(d->m_placemark->id() + QLatin1String("Style")); 0204 d->m_placemark->setStyle( newStyle ); 0205 0206 updatePolyline(); 0207 } 0208 0209 void EditPolylineDialog::updatePolyline() 0210 { 0211 d->m_placemark->setDescription( d->m_formattedTextWidget->text() ); 0212 d->m_placemark->setName( d->m_name->text() ); 0213 0214 // If there is no custom style initialized( default #polyline url is used ) and there is a osmTag-based style 0215 // available, set it 0216 const OsmPlacemarkData osmData = d->m_osmTagEditorWidget->placemarkData(); 0217 const GeoDataPlacemark::GeoDataVisualCategory category = StyleBuilder::determineVisualCategory(osmData); 0218 if (d->m_placemark->styleUrl() == QLatin1String("#polyline") && category != GeoDataPlacemark::None) { 0219 d->m_placemark->setStyle( GeoDataStyle::Ptr() ); // first clear style so style gets set by setVisualCategory() 0220 d->m_placemark->setVisualCategory( category ); 0221 } 0222 0223 emit polylineUpdated( d->m_placemark ); 0224 } 0225 0226 0227 void EditPolylineDialog::updateLinesDialog( const QColor &color ) 0228 { 0229 QPixmap linesPixmap( d->m_linesColorButton->iconSize().width(), 0230 d->m_linesColorButton->iconSize().height() ); 0231 linesPixmap.fill( color ); 0232 d->m_linesColorButton->setIcon( QIcon( linesPixmap ) ); 0233 } 0234 0235 void EditPolylineDialog::restoreInitial( int result ) 0236 { 0237 if ( result ) { 0238 return; 0239 } 0240 0241 GeoDataLineString* currentLineString = static_cast<GeoDataLineString*>( d->m_placemark->geometry() ); 0242 0243 if( *currentLineString != d->m_initialLineString ) { 0244 d->m_placemark->setGeometry( new GeoDataLineString( d->m_initialLineString ) ); 0245 } 0246 0247 if ( d->m_placemark->name() != d->m_initialName ) { 0248 d->m_placemark->setName( d->m_initialName ); 0249 } 0250 0251 if ( d->m_placemark->description() != d->m_initialDescription ) { 0252 d->m_placemark->setDescription( d->m_initialDescription ); 0253 } 0254 0255 if ( d->m_placemark->style()->lineStyle() != d->m_initialLineStyle ) { 0256 GeoDataStyle::Ptr newStyle(new GeoDataStyle( *d->m_placemark->style() )); 0257 newStyle->setLineStyle( d->m_initialLineStyle ); 0258 d->m_placemark->setStyle( newStyle ); 0259 } 0260 0261 if( d->m_hadInitialOsmData ) { 0262 d->m_placemark->setOsmData( d->m_initialOsmData ); 0263 } 0264 0265 emit polylineUpdated( d->m_placemark ); 0266 } 0267 0268 void EditPolylineDialog::checkFields() 0269 { 0270 bool ok = true; 0271 if ( d->m_name->text().isEmpty() ) { 0272 QMessageBox::warning( this, 0273 tr( "No name specified" ), 0274 tr( "Please specify a name for this polyline." ) ); 0275 ok = false; 0276 } else { 0277 if (const auto lineString = geodata_cast<GeoDataLineString>(d->m_placemark->geometry())) { 0278 if( lineString->size() < 2 ) { 0279 QMessageBox::warning( this, 0280 tr( "Not enough nodes specified." ), 0281 tr( "Please specify at least 2 nodes for the path by clicking on the map." ) ); 0282 ok = false; 0283 } 0284 } 0285 } 0286 if( ok ) { 0287 accept(); 0288 } 0289 } 0290 0291 } 0292 0293 #include "moc_EditPolylineDialog.cpp"