Explains how to add edit and remove functionality.
Now we look at ways to modify the contents of contacts stored in the address book.
					
						We now have an address book that not only holds contacts in an organized manner, but also allows navigation. It would be convenient to include edit and remove functions so that a contact's details can be changed when needed. However, this requires a little improvement, in the form of enums. We defined two modes:
						
AddingMode
						
						and
						
NavigationMode
						
						, but they were not defined as enum values. Instead, we enabled and disabled the corresponding buttons manually, resulting in multiple lines of repeated code.
					
						Here we define the
						
模式
						
						enum with three different values:
					
						The
						
addressbook.h
						
						file is updated to contain the
						
模式
						
						枚举:
					
    enum Mode { NavigationMode, AddingMode, EditingMode };
					
					
						We also add two new slots,
						
editContact()
						
						and
						
removeContact()
						
						, to our current list of public slots.
					
    void editContact();
    void removeContact();
					
					
						In order to switch between modes, we introduce the
						
updateInterface()
						
						function to control the enabling and disabling of all
						
							QPushButton
						
						objects. We also add two new push buttons,
						
editButton
						
						and
						
removeButton
						
						, for the edit and remove functions mentioned earlier.
					
    void updateInterface(Mode mode);
    ...
    QPushButton *editButton;
    QPushButton *removeButton;
    ...
    Mode currentMode;
					
					
						Lastly, we declare
						
currentMode
						
						to keep track of the enum's current mode.
						
					
						We now implement the mode-changing features of the address book. The
						
editButton
						
						and
						
removeButton
						
						are instantiated and disabled by default. The address book starts with zero contacts in memory.
					
    editButton = new QPushButton(tr("&Edit"));
    editButton->setEnabled(false);
    removeButton = new QPushButton(tr("&Remove"));
    removeButton->setEnabled(false);
					
					
						These buttons are then connected to their respective slots,
						
editContact()
						
						and
						
removeContact()
						
						, and we add them to
						
buttonLayout1
						
						.
					
    connect(editButton, &QPushButton::clicked,
            this, &AddressBook::editContact);
    connect(removeButton, &QPushButton::clicked,
            this, &AddressBook::removeContact);
    ...
    buttonLayout1->addWidget(editButton);
    buttonLayout1->addWidget(removeButton);
					
					
						The
						
editContact()
						
						function stores the contact's old details in
						
oldName
						
						and
						
oldAddress
						
						, before switching the mode to
						
EditingMode
						
						. In this mode, the
						
submitButton
						
						and
						
cancelButton
						
						are both enabled, hence, the user can change the contact's details and click either button.
					
void AddressBook::editContact() { oldName = nameLine->text(); oldAddress = addressText->toPlainText(); updateInterface(EditingMode); }
						The
						
submitContact()
						
						function has been divided in two with an
						
if-else
						
						statement. We check
						
currentMode
						
						to see if it's in
						
AddingMode
						
						. If it is, we proceed with our adding process.
					
void AddressBook::submitContact() { ... if (currentMode == AddingMode) { if (!contacts.contains(name)) { contacts.insert(name, address); QMessageBox::information(this, tr("Add Successful"), tr("\"%1\" has been added to your address book.").arg(name)); } else { QMessageBox::information(this, tr("Add Unsuccessful"), tr("Sorry, \"%1\" is already in your address book.").arg(name)); }
						Otherwise, we check to see if
						
currentMode
						
						是在
						
EditingMode
						
						. If it is, we compare
						
oldName
						
						with
						
名称
						
						. If the name has changed, we remove the old contact from
						
contacts
						
						and insert the newly updated contact.
					
    } else if (currentMode == EditingMode) {
        if (oldName != name) {
            if (!contacts.contains(name)) {
                QMessageBox::information(this, tr("Edit Successful"),
                    tr("\"%1\" has been edited in your address book.").arg(oldName));
                contacts.remove(oldName);
                contacts.insert(name, address);
            } else {
                QMessageBox::information(this, tr("Edit Unsuccessful"),
                    tr("Sorry, \"%1\" is already in your address book.").arg(name));
            }
        } else if (oldAddress != address) {
            QMessageBox::information(this, tr("Edit Successful"),
                tr("\"%1\" has been edited in your address book.").arg(name));
            contacts[name] = address;
        }
    }
    updateInterface(NavigationMode);
}
					
					
						If only the address has changed (i.e.,
						
oldAddress
						
						is not the same as
						
address
						
						), we update the contact's address. Lastly, we set
						
currentMode
						
						to
						
NavigationMode
						
						. This is an important step as it re-enables all the disabled push buttons.
					
						To remove a contact from the address book, we implement the
						
removeContact()
						
						function. This function checks to see if the contact exists in
						
contacts
						
						.
					
void AddressBook::removeContact() { QString name = nameLine->text(); QString address = addressText->toPlainText(); if (contacts.contains(name)) { int button = QMessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove \"%1\"?").arg(name), QMessageBox::Yes | QMessageBox::No); if (button == QMessageBox::Yes) { previous(); contacts.remove(name); QMessageBox::information(this, tr("Remove Successful"), tr("\"%1\" has been removed from your address book.").arg(name)); } } updateInterface(NavigationMode); }
						If it does, we display a
						
							QMessageBox
						
						, to confirm the removal with the user. Once the user has confirmed, we call
						
previous()
						
						to ensure that the user interface shows another contact, and we remove the contact using
						
							QMap
						
						's
						
							remove()
						
						function. As a courtesy, we display a
						
							QMessageBox
						
						to inform the user. Both the message boxes used in this function are shown below:
					
					
					
						We mentioned the
						
updateInterface()
						
						function earlier as a means to enable and disable the push buttons depending on the current mode. The function updates the current mode according to the
						
mode
						
						argument passed to it, assigning it to
						
currentMode
						
						before checking its value.
					
						Each of the push buttons is then enabled or disabled, depending on the current mode. The code for
						
AddingMode
						
						and
						
EditingMode
						
						展示如下:
					
void AddressBook::updateInterface(Mode mode) { currentMode = mode; switch (currentMode) { case AddingMode: case EditingMode: nameLine->setReadOnly(false); nameLine->setFocus(Qt::OtherFocusReason); addressText->setReadOnly(false); addButton->setEnabled(false); editButton->setEnabled(false); removeButton->setEnabled(false); nextButton->setEnabled(false); previousButton->setEnabled(false); submitButton->show(); cancelButton->show(); break;
						For
						
NavigationMode
						
						, however, we include conditions within the parameters of the
						
							QPushButton::setEnabled
						
						() function. This is to ensure that
						
editButton
						
						and
						
removeButton
						
						are enabled when there is at least one contact in the address book;
						
nextButton
						
						and
						
previousButton
						
						are only enabled when there is more than one contact in the address book.
					
    case NavigationMode:
        if (contacts.isEmpty()) {
            nameLine->clear();
            addressText->clear();
        }
        nameLine->setReadOnly(true);
        addressText->setReadOnly(true);
        addButton->setEnabled(true);
        int number = contacts.size();
        editButton->setEnabled(number >= 1);
        removeButton->setEnabled(number >= 1);
        nextButton->setEnabled(number > 1);
        previousButton->setEnabled(number >1 );
        submitButton->hide();
        cancelButton->hide();
        break;
    }
}
					
					By setting the mode and updating the user interface in the same function, we avoid the possibility of the user interface getting out of sync with the internal state of the application.