Loading files
/*
* 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 "projectsetupdialog.h"
#include "../editorcommandset.h"
#include "../undostack.h"
#include "cmd/cmdnetclassadd.h"
#include "cmd/cmdnetclassedit.h"
#include "cmd/cmdnetclassremove.h"
#include "cmd/cmdprojectedit.h"
#include "ui_projectsetupdialog.h"
#include <librepcb/core/application.h>
#include <librepcb/core/norms.h>
#include <librepcb/core/project/circuit/circuit.h>
#include <librepcb/core/project/circuit/netclass.h>
#include <librepcb/core/project/project.h>
#include <librepcb/core/utils/toolbox.h>
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
ProjectSetupDialog::ProjectSetupDialog(Project& project, UndoStack& undoStack,
QWidget* parent) noexcept
: QDialog(parent),
mProject(project),
mUndoStack(undoStack),
mAttributes(mProject.getAttributes()),
mUi(new Ui::ProjectSetupDialog) {
mUi->setupUi(this);
connect(mUi->buttonBox, &QDialogButtonBox::clicked, this,
&ProjectSetupDialog::buttonBoxClicked);
const EditorCommandSet& cmd = EditorCommandSet::instance();
// Tab: Metadata
mUi->edtProjectVersion->setValidator(
new QRegularExpressionValidator(FileProofNameConstraint::regex(), this));
// Tab: Attributes
mUi->edtProjectAttributes->setFrameStyle(QFrame::NoFrame);
mUi->edtProjectAttributes->setReferences(nullptr, &mAttributes);
// Tab: Locales & Norms
QMap<QString, QString> locales; // Map will be sorted by key.
foreach (const QString& locale, Application::getTranslationLocales()) {
locales.insert(Toolbox::prettyPrintLocale(locale), locale);
}
for (auto it = locales.begin(); it != locales.end(); it++) {
mUi->cbxLocales->addItem(it.key(), it.value());
}
mUi->cbxLocales->setCurrentIndex(-1);
connect(mUi->btnLocaleAdd, &QToolButton::clicked, this, [this]() {
const QString locale = mUi->cbxLocales->currentData().toString();
if (!locale.isEmpty()) {
QListWidgetItem* item = new QListWidgetItem(
Toolbox::prettyPrintLocale(locale), mUi->lstLocaleOrder);
item->setData(Qt::UserRole, locale);
}
});
connect(mUi->btnLocaleRemove, &QToolButton::clicked, this, [this]() {
foreach (auto item, mUi->lstLocaleOrder->selectedItems()) {
delete item;
}
});
connect(mUi->btnLocaleUp, &QToolButton::clicked, this, [this]() {
int row = mUi->lstLocaleOrder->currentRow();
if (row > 0) {
mUi->lstLocaleOrder->insertItem(row - 1,
mUi->lstLocaleOrder->takeItem(row));
mUi->lstLocaleOrder->setCurrentRow(row - 1);
}
});
connect(mUi->btnLocaleDown, &QToolButton::clicked, this, [this]() {
int row = mUi->lstLocaleOrder->currentRow();
if ((row >= 0) && (row < mUi->lstLocaleOrder->count() - 1)) {
mUi->lstLocaleOrder->insertItem(row + 1,
mUi->lstLocaleOrder->takeItem(row));
mUi->lstLocaleOrder->setCurrentRow(row + 1);
}
});
mUi->cbxNorms->addItems(getAvailableNorms());
mUi->cbxNorms->clearEditText();
connect(mUi->btnNormAdd, &QToolButton::clicked, this, [this]() {
const QString norm = mUi->cbxNorms->currentText().trimmed();
if (!norm.isEmpty()) {
mUi->lstNormOrder->addItem(norm);
}
});
connect(mUi->btnNormRemove, &QToolButton::clicked, this, [this]() {
foreach (auto item, mUi->lstNormOrder->selectedItems()) {
delete item;
}
});
connect(mUi->btnNormUp, &QToolButton::clicked, this, [this]() {
int row = mUi->lstNormOrder->currentRow();
if (row > 0) {
mUi->lstNormOrder->insertItem(row - 1, mUi->lstNormOrder->takeItem(row));
mUi->lstNormOrder->setCurrentRow(row - 1);
}
});
connect(mUi->btnNormDown, &QToolButton::clicked, this, [this]() {
int row = mUi->lstNormOrder->currentRow();
if ((row >= 0) && (row < mUi->lstNormOrder->count() - 1)) {
mUi->lstNormOrder->insertItem(row + 1, mUi->lstNormOrder->takeItem(row));
mUi->lstNormOrder->setCurrentRow(row + 1);
}
});
// Tab: Net Classes
mUi->lstNetClasses->addAction(cmd.remove.createAction(
mUi->lstNetClasses, this,
[this]() {
foreach (auto item, mUi->lstNetClasses->selectedItems()) {
if (item->checkState() != Qt::Checked) {
delete item;
}
}
},
EditorCommand::ActionFlag::QueuedConnection |
EditorCommand::ActionFlag::WidgetShortcut));
mUi->edtNetClassName->addAction(
cmd.inputAcceptAdd.createAction(
mUi->edtNetClassName, this,
[this]() {
const QString name = mUi->edtNetClassName->text().trimmed();
if (!name.isEmpty()) {
QListWidgetItem* item =
new QListWidgetItem(name, mUi->lstNetClasses);
item->setCheckState(Qt::Unchecked);
auto flags = item->flags();
flags |= Qt::ItemIsEditable;
flags &= ~Qt::ItemIsUserCheckable;
item->setFlags(flags);
}
},
EditorCommand::ActionFlag::WidgetShortcut),
QLineEdit::TrailingPosition);
// Tab: Assembly Variants.
mUi->edtAssemblyVariants->setFrameStyle(QFrame::NoFrame);
mUi->edtAssemblyVariants->setReferences(&mUndoStack, &project.getCircuit());
// Load all properties.
load();
// Load client settings.
QSettings cs;
const QSize windowSize =
cs.value("project_setup_dialog/window_size").toSize();
if (!windowSize.isEmpty()) {
resize(windowSize);
}
// Always open first tab.
mUi->tabWidget->setCurrentIndex(0);
// Set focus to name so the user can immediately start typing to change it-
mUi->edtProjectName->setFocus();
}
ProjectSetupDialog::~ProjectSetupDialog() {
// Save the window geometry.
QSettings cs;
cs.setValue("project_setup_dialog/window_size", size());
mUi->edtProjectAttributes->setReferences(nullptr, nullptr);
}
/*******************************************************************************
* Private Methods
******************************************************************************/
void ProjectSetupDialog::buttonBoxClicked(QAbstractButton* button) {
Q_ASSERT(button);
switch (mUi->buttonBox->buttonRole(button)) {
case QDialogButtonBox::ApplyRole:
apply();
break;
case QDialogButtonBox::AcceptRole:
if (apply()) {
accept();
}
break;
case QDialogButtonBox::RejectRole:
reject();
break;
default:
break;
}
}
void ProjectSetupDialog::load() noexcept {
// Tab: Metadata
mUi->edtProjectName->setText(*mProject.getName());
mUi->edtProjectAuthor->setText(mProject.getAuthor());
mUi->edtProjectVersion->setText(*mProject.getVersion());
mUi->lblProjectCreated->setText(
QLocale().toString(mProject.getCreated(), QLocale::LongFormat));
// Tab: Locales & Norms
mUi->lstLocaleOrder->clear();
foreach (const QString& locale, mProject.getLocaleOrder()) {
QListWidgetItem* item = new QListWidgetItem(
Toolbox::prettyPrintLocale(locale), mUi->lstLocaleOrder);
item->setData(Qt::UserRole, locale);
}
mUi->lstNormOrder->clear();
mUi->lstNormOrder->addItems(mProject.getNormOrder());
// Tab: Net Classes
mUi->lstNetClasses->clear();
foreach (NetClass* netClass, mProject.getCircuit().getNetClasses()) {
QListWidgetItem* item =
new QListWidgetItem(*netClass->getName(), mUi->lstNetClasses);
item->setData(Qt::UserRole, netClass->getUuid().toStr());
item->setCheckState(netClass->isUsed() ? Qt::Checked : Qt::Unchecked);
auto flags = item->flags();
flags |= Qt::ItemIsEditable;
flags &= ~Qt::ItemIsUserCheckable;
item->setFlags(flags);
}
}
bool ProjectSetupDialog::apply() noexcept {
try {
UndoStackTransaction transaction(mUndoStack, tr("Modify Project Setup"));
std::unique_ptr<CmdProjectEdit> cmd(new CmdProjectEdit(mProject));
// Tab: Metadata
cmd->setName(ElementName(
cleanElementName(mUi->edtProjectName->text()))); // can throw
cmd->setAuthor(mUi->edtProjectAuthor->text().trimmed());
cmd->setVersion(FileProofName(
cleanFileProofName(mUi->edtProjectVersion->text()))); // can throw
// Tab: Attributes
cmd->setAttributes(mAttributes);
// Tab: Locales & Norms
{
QStringList locales;
for (int i = 0; i < mUi->lstLocaleOrder->count(); i++) {
locales.append(
mUi->lstLocaleOrder->item(i)->data(Qt::UserRole).toString());
}
cmd->setLocaleOrder(locales);
}
{
QStringList norms;
for (int i = 0; i < mUi->lstNormOrder->count(); i++) {
norms.append(mUi->lstNormOrder->item(i)->text());
}
cmd->setNormOrder(norms);
}
transaction.append(cmd.release()); // can throw
// Tab: Net Classes
{
// Collect net classes.
QHash<QListWidgetItem*, NetClass*> items;
for (int i = 0; i < mUi->lstNetClasses->count(); ++i) {
if (QListWidgetItem* item = mUi->lstNetClasses->item(i)) {
const QString uuid = item->data(Qt::UserRole).toString();
NetClass* netClass = (!uuid.isEmpty())
? mProject.getCircuit().getNetClasses().value(
Uuid::fromString(uuid))
: nullptr;
items.insert(item, netClass);
}
}
// Remove no longer existing net classes.
foreach (NetClass* netClass,
Toolbox::toSet(mProject.getCircuit().getNetClasses().values()) -
Toolbox::toSet(items.values())) {
transaction.append(new CmdNetClassRemove(*netClass));
}
// Add new net classes.
for (auto it = items.begin(); it != items.end(); it++) {
if (!it.value()) {
const ElementName name(it.key()->text().trimmed()); // can throw
transaction.append(new CmdNetClassAdd(mProject.getCircuit(), name));
if (NetClass* obj = mProject.getCircuit().getNetClassByName(name)) {
it.key()->setData(Qt::UserRole, obj->getUuid().toStr());
}
}
}
// Apply renames.
for (auto it = items.begin(); it != items.end(); it++) {
const QString name = it.key()->text().trimmed();
if (it.value() && (name != *it.value()->getName())) {
std::unique_ptr<CmdNetClassEdit> cmd(
new CmdNetClassEdit(*it.value()));
cmd->setName(ElementName(name)); // can throw
transaction.append(cmd.release());
}
}
}
transaction.commit(); // can throw
return true;
} catch (const Exception& e) {
QMessageBox::warning(this, tr("Could not apply settings"), e.getMsg());
return false;
}
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb
94ec4b8feThis file is pinned to the selected release. Download the original to open it in your design tool.