Skip to content

Commit

Permalink
Schematic editor: Provide more options when renaming segments
Browse files Browse the repository at this point in the history
  • Loading branch information
ubruhin committed Oct 8, 2019
1 parent e2bf30d commit 1d6c819
Show file tree
Hide file tree
Showing 5 changed files with 450 additions and 31 deletions.
3 changes: 3 additions & 0 deletions libs/librepcb/projecteditor/projecteditor.pro
Expand Up @@ -76,6 +76,7 @@ SOURCES += \
schematiceditor/fsm/ses_drawwire.cpp \
schematiceditor/fsm/ses_fsm.cpp \
schematiceditor/fsm/ses_select.cpp \
schematiceditor/renamenetsegmentdialog.cpp \
schematiceditor/schematicclipboard.cpp \
schematiceditor/schematiceditor.cpp \
schematiceditor/schematicpagesdock.cpp \
Expand Down Expand Up @@ -138,6 +139,7 @@ HEADERS += \
schematiceditor/fsm/ses_drawwire.h \
schematiceditor/fsm/ses_fsm.h \
schematiceditor/fsm/ses_select.h \
schematiceditor/renamenetsegmentdialog.h \
schematiceditor/schematicclipboard.h \
schematiceditor/schematiceditor.h \
schematiceditor/schematicpagesdock.h \
Expand All @@ -162,6 +164,7 @@ FORMS += \
newprojectwizard/newprojectwizardpage_initialization.ui \
newprojectwizard/newprojectwizardpage_metadata.ui \
newprojectwizard/newprojectwizardpage_versioncontrol.ui \
schematiceditor/renamenetsegmentdialog.ui \
schematiceditor/schematiceditor.ui \
schematiceditor/schematicpagesdock.ui \
schematiceditor/symbolinstancepropertiesdialog.ui \
Expand Down
34 changes: 3 additions & 31 deletions libs/librepcb/projecteditor/schematiceditor/fsm/ses_select.cpp
Expand Up @@ -22,22 +22,16 @@
******************************************************************************/
#include "ses_select.h"

#include "../../cmd/cmdchangenetsignalofschematicnetsegment.h"
#include "../../cmd/cmdcombinenetsignals.h"
#include "../../cmd/cmdmirrorselectedschematicitems.h"
#include "../../cmd/cmdmoveselectedschematicitems.h"
#include "../../cmd/cmdremoveselectedschematicitems.h"
#include "../../cmd/cmdrotateselectedschematicitems.h"
#include "../renamenetsegmentdialog.h"
#include "../schematiceditor.h"
#include "../symbolinstancepropertiesdialog.h"
#include "ui_schematiceditor.h"

#include <librepcb/common/undostack.h>
#include <librepcb/project/circuit/circuit.h>
#include <librepcb/project/circuit/cmd/cmdnetsignaladd.h>
#include <librepcb/project/circuit/cmd/cmdnetsignaledit.h>
#include <librepcb/project/circuit/componentinstance.h>
#include <librepcb/project/circuit/netsignal.h>
#include <librepcb/project/project.h>
#include <librepcb/project/schematics/items/si_netlabel.h>
#include <librepcb/project/schematics/items/si_netline.h>
Expand Down Expand Up @@ -471,30 +465,8 @@ void SES_Select::openSymbolPropertiesDialog(SI_Symbol& symbol) noexcept {
}

void SES_Select::openNetLabelPropertiesDialog(SI_NetLabel& netlabel) noexcept {
NetSignal& netsignal = netlabel.getNetSignalOfNetSegment();
QString name = QInputDialog::getText(&mEditor, tr("Change net of segment"),
tr("New net name:"), QLineEdit::Normal,
*netsignal.getName());
if (!name.isNull()) {
try {
// change netsignal of netsegment
CircuitIdentifier newName(name.trimmed()); // can throw
mUndoStack.beginCmdGroup(tr("Change netsignal of netsegment"));
NetSignal* newSignal = mCircuit.getNetSignalByName(name);
if (!newSignal) {
CmdNetSignalAdd* cmd = new CmdNetSignalAdd(
mProject.getCircuit(), netsignal.getNetClass(), newName);
mUndoStack.appendToCmdGroup(cmd);
newSignal = cmd->getNetSignal();
Q_ASSERT(newSignal);
}
mUndoStack.appendToCmdGroup(new CmdChangeNetSignalOfSchematicNetSegment(
netlabel.getNetSegment(), *newSignal));
mUndoStack.commitCmdGroup();
} catch (const Exception& e) {
QMessageBox::critical(&mEditor, tr("Error"), e.getMsg());
}
}
RenameNetSegmentDialog dialog(mUndoStack, netlabel.getNetSegment(), &mEditor);
dialog.exec(); // performs the rename, if needed
}

/*******************************************************************************
Expand Down
215 changes: 215 additions & 0 deletions libs/librepcb/projecteditor/schematiceditor/renamenetsegmentdialog.cpp
@@ -0,0 +1,215 @@
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*******************************************************************************
* Includes
******************************************************************************/
#include "renamenetsegmentdialog.h"

#include "../cmd/cmdchangenetsignalofschematicnetsegment.h"
#include "../cmd/cmdcombinenetsignals.h"
#include "ui_renamenetsegmentdialog.h"

#include <librepcb/common/undostack.h>
#include <librepcb/project/circuit/circuit.h>
#include <librepcb/project/circuit/cmd/cmdnetsignaladd.h>
#include <librepcb/project/circuit/cmd/cmdnetsignaledit.h>
#include <librepcb/project/circuit/netsignal.h>
#include <librepcb/project/schematics/items/si_netsegment.h>

#include <QtCore>
#include <QtWidgets>

/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace project {
namespace editor {

/*******************************************************************************
* Constructors / Destructor
******************************************************************************/

RenameNetSegmentDialog::RenameNetSegmentDialog(UndoStack& undoStack,
SI_NetSegment& segment,
QWidget* parent) noexcept
: QDialog(parent),
mUndoStack(undoStack),
mNetSegment(segment),
mUi(new Ui::RenameNetSegmentDialog),
mAction(Action::NONE),
mNewNetName(),
mNewNetSignal(nullptr) {
mUi->setupUi(this);

// Change completer to popup mode since the default inline completer is
// annoying when you want to insert a new, non existing net name (you
// would have to explicitly remove the autocompleted suffix).
mUi->cbxNetName->completer()->setCompletionMode(QCompleter::PopupCompletion);

// Populate netsignal combobox
QStringList netsignals;
foreach (const NetSignal* signal, mNetSegment.getCircuit().getNetSignals()) {
Q_ASSERT(signal);
// Ignore auto-named signals since typically the user is interested only
// in manually named nets (and hundreds of auto-named nets would clutter
// the dropdown anyway).
if (!signal->hasAutoName()) {
netsignals.append(*signal->getName());
}
}
QCollator collator;
collator.setCaseSensitivity(Qt::CaseInsensitive);
collator.setIgnorePunctuation(false);
collator.setNumericMode(true);
std::sort(netsignals.begin(), netsignals.end(),
[&collator](const QString& lhs, const QString& rhs) {
return collator(lhs, rhs);
});
mUi->cbxNetName->addItems(netsignals);
int index = netsignals.indexOf(*segment.getNetSignal().getName());
if (index >= 0) {
mUi->cbxNetName->setCurrentIndex(index);
} else {
mUi->cbxNetName->setCurrentText(*segment.getNetSignal().getName());
}

int segmentCount = segment.getNetSignal().getSchematicNetSegments().count();
mUi->rbtnRenameWholeNet->setText(
QString(mUi->rbtnRenameWholeNet->text()).arg(segmentCount));
if (segmentCount <= 1) {
// segment == whole net, so the choice does not make sense
mUi->rbtnRenameWholeNet->setChecked(true);
mUi->rbtnRenameNetSegmentOnly->setEnabled(false);
}
updateAction(); // update description text

// Set focus to net name to allow typing right after opening the dialog.
mUi->cbxNetName->setFocus();
mUi->cbxNetName->lineEdit()->selectAll();

connect(mUi->cbxNetName, &QComboBox::currentTextChanged, this,
&RenameNetSegmentDialog::updateAction);
connect(mUi->rbtnRenameWholeNet, &QRadioButton::toggled, this,
&RenameNetSegmentDialog::updateAction);
}

RenameNetSegmentDialog::~RenameNetSegmentDialog() noexcept {
}

/*******************************************************************************
* Public Methods
******************************************************************************/

void RenameNetSegmentDialog::accept() noexcept {
try {
CircuitIdentifier name(mNewNetName); // can throw
switch (mAction) {
case Action::RENAME_NETSIGNAL: {
QScopedPointer<CmdNetSignalEdit> cmd(new CmdNetSignalEdit(
mNetSegment.getCircuit(), mNetSegment.getNetSignal()));
cmd->setName(name, false);
mUndoStack.execCmd(cmd.take()); // can throw
break;
}
case Action::MERGE_NETSIGNALS: {
Q_ASSERT(mNewNetSignal);
mUndoStack.execCmd(new CmdCombineNetSignals(
mNetSegment.getCircuit(), mNetSegment.getNetSignal(),
*mNewNetSignal)); // can throw
break;
}
case Action::MOVE_NETSEGMENT_TO_EXISTING_NET:
case Action::MOVE_NETSEGMENT_TO_NEW_NET: {
UndoStackTransaction transaction(
mUndoStack,
tr("Change net of net segment")); // can throw
if (!mNewNetSignal) {
CmdNetSignalAdd* cmd = new CmdNetSignalAdd(
mNetSegment.getCircuit(),
mNetSegment.getNetSignal().getNetClass(), name);
transaction.append(cmd); // can throw
mNewNetSignal = cmd->getNetSignal();
Q_ASSERT(mNewNetSignal);
}
transaction.append(new CmdChangeNetSignalOfSchematicNetSegment(
mNetSegment, *mNewNetSignal)); // can throw
transaction.commit(); // can throw
break;
}
default: { break; }
}
QDialog::accept();
} catch (const Exception& e) {
QMessageBox::critical(this, tr("Error"), e.getMsg());
}
}

/*******************************************************************************
* Private Methods
******************************************************************************/

void RenameNetSegmentDialog::updateAction() noexcept {
mNewNetName = cleanCircuitIdentifier(mUi->cbxNetName->currentText());
mNewNetSignal = mNetSegment.getCircuit().getNetSignalByName(mNewNetName);
bool renameWholeNet = mUi->rbtnRenameWholeNet->isChecked();

if (!mNewNetName.isEmpty()) {
QString desc;
if (mNewNetSignal == &mNetSegment.getNetSignal()) {
mAction = Action::NONE;
desc = tr("No change is made.");
} else if (renameWholeNet && (mNewNetSignal)) {
mAction = Action::MERGE_NETSIGNALS;
desc = QString(tr("The whole net '%1' will be merged into the net '%2'."))
.arg(*mNetSegment.getNetSignal().getName(), mNewNetName);
} else if (renameWholeNet && (!mNewNetSignal)) {
mAction = Action::RENAME_NETSIGNAL;
desc = QString(tr("The whole net '%1' will be renamed to '%2'."))
.arg(*mNetSegment.getNetSignal().getName(), mNewNetName);
} else if ((!renameWholeNet) && (mNewNetSignal)) {
mAction = Action::MOVE_NETSEGMENT_TO_EXISTING_NET;
desc = QString(tr("The segment will be moved to the existing net '%1'."))
.arg(mNewNetName);
} else if ((!renameWholeNet) && (!mNewNetSignal)) {
mAction = Action::MOVE_NETSEGMENT_TO_NEW_NET;
desc = QString(tr("The segment will be moved to the new net '%1'."))
.arg(mNewNetName);
} else {
mAction = Action::INVALID_NAME; // Not correct, but sufficient
desc = "UNKNOWN ERROR";
qCritical() << "Unhandled case in RenameNetSegmentDialog!";
}
mUi->lblDescription->setText(desc);
mUi->lblDescription->setStyleSheet("");
} else {
mAction = Action::INVALID_NAME;
mUi->lblDescription->setText(tr("Invalid name!"));
mUi->lblDescription->setStyleSheet("QLabel {color: red;}");
}
}

/*******************************************************************************
* End of File
******************************************************************************/

} // namespace editor
} // namespace project
} // namespace librepcb
100 changes: 100 additions & 0 deletions libs/librepcb/projecteditor/schematiceditor/renamenetsegmentdialog.h
@@ -0,0 +1,100 @@
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef LIBREPCB_PROJECT_EDITOR_RENAMENETSEGMENTDIALOG_H
#define LIBREPCB_PROJECT_EDITOR_RENAMENETSEGMENTDIALOG_H

/*******************************************************************************
* Includes
******************************************************************************/
#include <QtCore>
#include <QtWidgets>

/*******************************************************************************
* Namespace / Forward Declarations
******************************************************************************/
namespace librepcb {

class UndoStack;

namespace project {

class NetSignal;
class SI_NetSegment;

namespace editor {

namespace Ui {
class RenameNetSegmentDialog;
}

/*******************************************************************************
* Class RenameNetSegmentDialog
******************************************************************************/

/**
* @brief The RenameNetSegmentDialog class
*/
class RenameNetSegmentDialog final : public QDialog {
Q_OBJECT

enum class Action {
NONE,
INVALID_NAME,
RENAME_NETSIGNAL,
MERGE_NETSIGNALS,
MOVE_NETSEGMENT_TO_EXISTING_NET,
MOVE_NETSEGMENT_TO_NEW_NET,
};

public:
// Constructors / Destructor
RenameNetSegmentDialog() = delete;
RenameNetSegmentDialog(const RenameNetSegmentDialog& other) = delete;
RenameNetSegmentDialog(UndoStack& undoStack, SI_NetSegment& segment,
QWidget* parent = nullptr) noexcept;
~RenameNetSegmentDialog() noexcept;

// General Methods
virtual void accept() noexcept override;

// Operator Overloads
RenameNetSegmentDialog& operator=(const RenameNetSegmentDialog& rhs) = delete;

private: // Methods
void updateAction() noexcept;

private: // Data
UndoStack& mUndoStack;
SI_NetSegment& mNetSegment;
QScopedPointer<Ui::RenameNetSegmentDialog> mUi;
Action mAction;
QString mNewNetName;
NetSignal* mNewNetSignal;
};

/*******************************************************************************
* End of File
******************************************************************************/

} // namespace editor
} // namespace project
} // namespace librepcb

#endif // LIBREPCB_PROJECT_EDITOR_RENAMENETSEGMENTDIALOG_H

0 comments on commit 1d6c819

Please sign in to comment.