![]() |
XML Mill
1.0.0
A GUI based XML editor with a memory.
|
00001 /* Copyright (c) 2012 - 2013 by William Hallatt. 00002 * 00003 * This file forms part of "XML Mill". 00004 * 00005 * The official website for this project is <http://www.goblincoding.com> and, 00006 * although not compulsory, it would be appreciated if all works of whatever 00007 * nature using this source code (in whole or in part) include a reference to 00008 * this site. 00009 * 00010 * Should you wish to contact me for whatever reason, please do so via: 00011 * 00012 * <http://www.goblincoding.com/contact> 00013 * 00014 * This program is free software: you can redistribute it and/or modify it under 00015 * the terms of the GNU General Public License as published by the Free Software 00016 * Foundation, either version 3 of the License, or (at your option) any later 00017 * version. 00018 * 00019 * This program is distributed in the hope that it will be useful, but WITHOUT 00020 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00021 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00022 * 00023 * You should have received a copy of the GNU General Public License along with 00024 * this program (GNUGPL.txt). If not, see 00025 * 00026 * <http://www.gnu.org/licenses/> 00027 */ 00028 00029 #include "gcremoveitemsform.h" 00030 #include "ui_gcremoveitemsform.h" 00031 #include "db/gcdatabaseinterface.h" 00032 #include "utils/gcmessagespace.h" 00033 #include "utils/gcglobalspace.h" 00034 #include "utils/gctreewidgetitem.h" 00035 00036 #include <QMessageBox> 00037 00038 /*--------------------------------------------------------------------------------------*/ 00039 00040 GCRemoveItemsForm::GCRemoveItemsForm( QWidget* parent ) 00041 : QDialog ( parent ), 00042 ui ( new Ui::GCRemoveItemsForm ), 00043 m_currentElement ( "" ), 00044 m_currentElementParent( "" ), 00045 m_currentAttribute ( "" ), 00046 m_deletedElements () 00047 { 00048 ui->setupUi( this ); 00049 ui->showAttributeHelpButton->setVisible( GCGlobalSpace::showHelpButtons() ); 00050 ui->showElementHelpButton->setVisible( GCGlobalSpace::showHelpButtons() ); 00051 00052 connect( ui->showElementHelpButton, SIGNAL( clicked() ), this, SLOT( showElementHelp() ) ); 00053 connect( ui->showAttributeHelpButton, SIGNAL( clicked() ), this, SLOT( showAttributeHelp() ) ); 00054 connect( ui->updateValuesButton, SIGNAL( clicked() ), this, SLOT( updateAttributeValues() ) ); 00055 connect( ui->deleteAttributeButton, SIGNAL( clicked() ), this, SLOT( deleteAttribute() ) ); 00056 connect( ui->deleteElementButton, SIGNAL( clicked() ), this, SLOT( deleteElement() ) ); 00057 connect( ui->removeFromParentButton, SIGNAL( clicked() ), this, SLOT( removeChildElement() ) ); 00058 00059 connect( ui->treeWidget, SIGNAL( gcCurrentItemSelected( GCTreeWidgetItem*, int ) ), this, SLOT( elementSelected( GCTreeWidgetItem*, int ) ) ); 00060 connect( ui->comboBox, SIGNAL( currentIndexChanged( QString ) ), this, SLOT( attributeActivated( QString ) ) ); 00061 00062 ui->treeWidget->populateFromDatabase(); 00063 00064 setAttribute( Qt::WA_DeleteOnClose ); 00065 } 00066 00067 /*--------------------------------------------------------------------------------------*/ 00068 00069 GCRemoveItemsForm::~GCRemoveItemsForm() 00070 { 00071 delete ui; 00072 } 00073 00074 /*--------------------------------------------------------------------------------------*/ 00075 00076 void GCRemoveItemsForm::elementSelected( GCTreeWidgetItem* item, int column ) 00077 { 00078 Q_UNUSED( column ) 00079 ; 00080 00081 if( item ) 00082 { 00083 if( item->gcParent() ) 00084 { 00085 m_currentElementParent = item->gcParent()->name(); 00086 } 00087 00088 m_currentElement = item->name(); 00089 00090 /* Since it isn't illegal to have elements with children of the same name, we cannot 00091 block it in the DB, however, if we DO have elements with children of the same name, 00092 we don't want the user to delete the element since bad things will happen. */ 00093 if( m_currentElement == m_currentElementParent ) 00094 { 00095 ui->deleteElementButton->setEnabled( false ); 00096 } 00097 else 00098 { 00099 ui->deleteElementButton->setEnabled( true ); 00100 } 00101 00102 QStringList attributes = GCDataBaseInterface::instance()->attributes( m_currentElement ); 00103 00104 ui->comboBox->clear(); 00105 ui->comboBox->addItems( attributes ); 00106 } 00107 } 00108 00109 /*--------------------------------------------------------------------------------------*/ 00110 00111 void GCRemoveItemsForm::attributeActivated( const QString& attribute ) 00112 { 00113 m_currentAttribute = attribute; 00114 QStringList attributeValues = GCDataBaseInterface::instance()->attributeValues( m_currentElement, m_currentAttribute ); 00115 00116 ui->plainTextEdit->clear(); 00117 00118 foreach( QString value, attributeValues ) 00119 { 00120 ui->plainTextEdit->insertPlainText( QString( "%1\n" ).arg( value ) ); 00121 } 00122 } 00123 00124 /*--------------------------------------------------------------------------------------*/ 00125 00126 void GCRemoveItemsForm::deleteElement( const QString& element ) 00127 { 00128 /* If the element name is empty, then this function was called directly by the user 00129 clicking on "delete" (as opposed to this function being called further down below 00130 during the recursive process of getting rid of the element's children) in that case, 00131 the first element to be removed is the current one (set in "elementSelected"). */ 00132 QString currentElement = ( element.isEmpty() ) ? m_currentElement : element; 00133 00134 QStringList children = GCDataBaseInterface::instance()->children( currentElement ); 00135 m_deletedElements.clear(); 00136 00137 /* Attributes and values must be removed before we can remove elements and we must also 00138 ensure that children are removed before their parents. To achieve this, we need to ensure 00139 that we clean the element tree from "the bottom up". */ 00140 if( !children.isEmpty() ) 00141 { 00142 foreach( QString child, children ) 00143 { 00144 if( GCDataBaseInterface::instance()->isUniqueChildElement( currentElement, child ) ) 00145 { 00146 deleteElement( child ); 00147 } 00148 } 00149 } 00150 00151 /* Remove all the attributes (and their known values) associated with this element. */ 00152 QStringList attributes = GCDataBaseInterface::instance()->attributes( currentElement ); 00153 00154 foreach( QString attribute, attributes ) 00155 { 00156 if( !GCDataBaseInterface::instance()->removeAttribute( currentElement, attribute ) ) 00157 { 00158 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00159 } 00160 } 00161 00162 /* Now we can remove the element itself. */ 00163 if( !GCDataBaseInterface::instance()->removeElement( currentElement ) ) 00164 { 00165 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00166 } 00167 else 00168 { 00169 m_deletedElements.append( currentElement ); 00170 } 00171 00172 /* Check if the user removed a root element. */ 00173 if( GCDataBaseInterface::instance()->knownRootElements().contains( currentElement ) ) 00174 { 00175 if( !GCDataBaseInterface::instance()->removeRootElement( currentElement ) ) 00176 { 00177 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00178 } 00179 } 00180 00181 /* Remove the element from all its parents' first level child lists. */ 00182 updateChildLists(); 00183 00184 ui->comboBox->clear(); 00185 ui->plainTextEdit->clear(); 00186 ui->treeWidget->populateFromDatabase(); 00187 } 00188 00189 /*--------------------------------------------------------------------------------------*/ 00190 00191 void GCRemoveItemsForm::removeChildElement() 00192 { 00193 if( !m_currentElementParent.isEmpty() ) 00194 { 00195 if( !GCDataBaseInterface::instance()->removeChildElement( m_currentElementParent, m_currentElement ) ) 00196 { 00197 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00198 } 00199 else 00200 { 00201 if( GCDataBaseInterface::instance()->isUniqueChildElement( m_currentElementParent, m_currentElement ) ) 00202 { 00203 bool accepted = GCMessageSpace::userAccepted( "RemoveUnlistedElement", 00204 "Element not used", 00205 QString( "\"%1\" is not assigned to any other element (i.e. " 00206 "it isn't used anywhere else in the profile).\n" 00207 "Would you like to remove the element completely?" ).arg( m_currentElement ), 00208 GCMessageSpace::YesNo, 00209 GCMessageSpace::No, 00210 GCMessageSpace::Question ); 00211 00212 if( accepted ) 00213 { 00214 deleteElement(); 00215 } 00216 } 00217 00218 ui->comboBox->clear(); 00219 ui->plainTextEdit->clear(); 00220 ui->treeWidget->populateFromDatabase(); 00221 } 00222 } 00223 } 00224 00225 /*--------------------------------------------------------------------------------------*/ 00226 00227 void GCRemoveItemsForm::updateAttributeValues() 00228 { 00229 QStringList attributes = ui->plainTextEdit->toPlainText().split( "\n" ); 00230 attributes.removeAll( "" ); 00231 00232 if( attributes.isEmpty() ) 00233 { 00234 bool accepted = GCMessageSpace::userAccepted( "UpdateEmptyAttributeValues", 00235 "Update with empty attribute values?", 00236 "All known values were removed. " 00237 "Would you like to remove the attribute completely?", 00238 GCMessageSpace::YesNo, 00239 GCMessageSpace::No, 00240 GCMessageSpace::Question ); 00241 00242 if( accepted ) 00243 { 00244 deleteAttribute(); 00245 } 00246 } 00247 else 00248 { 00249 /* All existing values will be replaced with whatever remained in the text edit by the time the 00250 user was done. */ 00251 if( !GCDataBaseInterface::instance()->updateAttributeValues( m_currentElement, m_currentAttribute, attributes, true ) ) 00252 { 00253 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00254 } 00255 else 00256 { 00257 QMessageBox::information( this, "Success", "Done!" ); 00258 } 00259 } 00260 } 00261 00262 /*--------------------------------------------------------------------------------------*/ 00263 00264 void GCRemoveItemsForm::deleteAttribute() 00265 { 00266 if( !GCDataBaseInterface::instance()->removeAttribute( m_currentElement, m_currentAttribute ) ) 00267 { 00268 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00269 } 00270 else 00271 { 00272 /* Purely for cosmetic effect - updates the tree item to reflect the correct node text when 00273 in "verbose" mode. */ 00274 ui->treeWidget->gcCurrentItem()->excludeAttribute( m_currentAttribute ); 00275 00276 ui->comboBox->removeItem( ui->comboBox->findText( m_currentAttribute ) ); 00277 } 00278 } 00279 00280 /*--------------------------------------------------------------------------------------*/ 00281 00282 void GCRemoveItemsForm::updateChildLists() 00283 { 00284 QStringList knownElements = GCDataBaseInterface::instance()->knownElements(); 00285 00286 foreach( QString element, knownElements ) 00287 { 00288 QStringList children = GCDataBaseInterface::instance()->children( element ); 00289 00290 if( !children.isEmpty() ) 00291 { 00292 foreach( QString deletedElement, m_deletedElements ) 00293 { 00294 if( children.contains( deletedElement ) ) 00295 { 00296 if( !GCDataBaseInterface::instance()->removeChildElement( element, deletedElement ) ) 00297 { 00298 GCMessageSpace::showErrorMessageBox( this, GCDataBaseInterface::instance()->lastError() ); 00299 } 00300 } 00301 } 00302 } 00303 } 00304 } 00305 00306 /*--------------------------------------------------------------------------------------*/ 00307 00308 void GCRemoveItemsForm::showElementHelp() 00309 { 00310 QMessageBox::information( this, 00311 "How this works...", 00312 "\"Remove Child\" will remove the currently highlighted element " 00313 "from its parent element's child list, i.e. it will only " 00314 "affect the relationship between the two elements, the element " 00315 "itself is not deleted in the process and will remain in the profile. \n\n" 00316 "\"Delete Element\" will delete the element, the element's children, " 00317 "the children's children (etc, etc), its associated attributes, the " 00318 "associated attributes of its children (and their children, etc, etc), all " 00319 "the known values for all the attributes thus deleted and finally also " 00320 "remove the element (and its children and the children's children, etc etc) " 00321 "from every single child list that contains it.\n\n" 00322 "None of this can be undone. " ); 00323 } 00324 00325 /*--------------------------------------------------------------------------------------*/ 00326 00327 void GCRemoveItemsForm::showAttributeHelp() 00328 { 00329 QMessageBox::information( this, 00330 "How this works...", 00331 "\"Delete Attribute\" will also delete all its known values.\n\n" 00332 "\"Update Attribute Values\" - Only those values remaining in the text edit when " 00333 "\"Update Attribute Values\" is clicked will be saved against the attribute shown " 00334 "in the drop down (this effectively means that you could also add new values " 00335 "to the attribute if you wish). Just make sure that all the values you want to " 00336 "associate with the attribute when you're done appear on separate lines." ); 00337 } 00338 00339 /*--------------------------------------------------------------------------------------*/