mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-11 14:44:15 +02:00
Revert "Add cable management: drawing, cores, numbering, cross-references and cable list"
This commit is contained in:
@@ -1,389 +0,0 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "cablepropertieseditorwidget.h"
|
||||
|
||||
#include "cablecreatedialog.h"
|
||||
#include "cablepart.h"
|
||||
#include "cablepropertieswidget.h"
|
||||
#include "editcablecommand.h"
|
||||
#include "../qeticons.h"
|
||||
#include "../qetproject.h"
|
||||
|
||||
#include <QAbstractItemView>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
#include <QSizePolicy>
|
||||
#include <QUndoStack>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::CablePropertiesEditorWidget
|
||||
@param cable the cable being edited
|
||||
@param part the line of that cable this panel was opened by, which
|
||||
is the line a core picked here is put down on
|
||||
@param parent parent widget
|
||||
*/
|
||||
CablePropertiesEditorWidget::CablePropertiesEditorWidget(Cable *cable,
|
||||
CablePart *part,
|
||||
QWidget *parent) :
|
||||
PropertiesEditorWidget(parent),
|
||||
m_fields(new CablePropertiesWidget(this)),
|
||||
m_info(new QLabel(this)),
|
||||
m_free_label(new QLabel(this)),
|
||||
m_free_cores(new QListWidget(this))
|
||||
{
|
||||
m_info->setWordWrap(true);
|
||||
|
||||
//The cores which stand nowhere yet, listed under the count of
|
||||
//wired ones: double-clicking one puts it down on this very line
|
||||
//without any dialog having to be opened for it. The list takes
|
||||
//no keyboard focus, so clicking it never takes the drawing away
|
||||
//from the user -- startPlacingCore() hands the focus to the
|
||||
//sheet itself, which is where Escape has to be heard.
|
||||
m_free_label->setText(tr("Unplaced cores:"));
|
||||
m_free_label->setVisible(false);
|
||||
m_free_cores->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_free_cores->setAlternatingRowColors(true);
|
||||
m_free_cores->setFocusPolicy(Qt::NoFocus);
|
||||
m_free_cores->setToolTip(tr("Double-click a core to place it on the "
|
||||
"line: the line follows the mouse and a "
|
||||
"click leaves it where you aimed."));
|
||||
m_free_cores->setVisible(false);
|
||||
m_free_cores->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_free_cores, &QWidget::customContextMenuRequested,
|
||||
this, &CablePropertiesEditorWidget::freeCoreMenu);
|
||||
connect(m_free_cores, &QListWidget::itemDoubleClicked,
|
||||
this, &CablePropertiesEditorWidget::placeRequested);
|
||||
connect(m_free_cores, &QListWidget::itemActivated,
|
||||
this, &CablePropertiesEditorWidget::placeRequested);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(4);
|
||||
layout->addWidget(m_fields);
|
||||
|
||||
//The button beside the type field: it opens the window which
|
||||
//opens when a cable line has just been drawn, in the mode where
|
||||
//it changes the type of this very cable.
|
||||
connect(m_fields, &CablePropertiesWidget::typeChangeRequested,
|
||||
this, &CablePropertiesEditorWidget::changeTypeRequested);
|
||||
|
||||
layout->addWidget(m_info);
|
||||
layout->addWidget(m_free_label);
|
||||
layout->addWidget(m_free_cores);
|
||||
layout->addStretch(1);
|
||||
|
||||
//Wide enough for the labels, the ticks, the fields, the buttons
|
||||
//setting how a text is written and the two distances nudging
|
||||
//the label and the row of colours -- they sit side by side.
|
||||
setMinimumWidth(250);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
|
||||
setDisabled(true);
|
||||
setCable(cable, part);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::setCable
|
||||
Set (or change) the cable whose properties are edited.
|
||||
@param cable
|
||||
@param part the line of that cable this panel was opened by: the one
|
||||
a core picked in the list is put down on, and null while no single
|
||||
line is selected -- then nothing can be put down and the list stays
|
||||
out of the way
|
||||
*/
|
||||
void CablePropertiesEditorWidget::setCable(Cable *cable, CablePart *part)
|
||||
{
|
||||
if (!cable) return;
|
||||
m_part = part;
|
||||
if (m_cable && m_cable != cable)
|
||||
disconnect(m_cable, nullptr, this, nullptr);
|
||||
|
||||
m_cable = cable;
|
||||
//Keep the panel in sync when the cable is edited elsewhere (the
|
||||
//dialog reached by double-clicking its line, for one): otherwise
|
||||
//the panel would write back what it held before that edit.
|
||||
connect(m_cable, &Cable::changed,
|
||||
this, &CablePropertiesEditorWidget::updateUi, Qt::UniqueConnection);
|
||||
setEnabled(true);
|
||||
updateUi();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::setLiveEdit
|
||||
In live-edit mode (how the panel uses every editor) an edit is
|
||||
applied as soon as a field is finished, rather than waiting for a
|
||||
call to apply(). On top of that the text itself is written onto the
|
||||
cable with every character, so what he types shows up on the drawing
|
||||
while he is still typing it -- the whole editing of one field stays
|
||||
one single undo step, which is worked out when the field is left.
|
||||
@param live_edit true to enable live edit
|
||||
@return always true
|
||||
*/
|
||||
bool CablePropertiesEditorWidget::setLiveEdit(bool live_edit)
|
||||
{
|
||||
if (m_live_edit == live_edit) return true;
|
||||
m_live_edit = live_edit;
|
||||
|
||||
if (m_live_edit) {
|
||||
m_live_connection = connect(m_fields, &CablePropertiesWidget::propertiesEdited,
|
||||
this, &CablePropertiesEditorWidget::apply);
|
||||
connect(m_fields, &CablePropertiesWidget::propertiesTyped,
|
||||
this, &CablePropertiesEditorWidget::applyLive);
|
||||
} else {
|
||||
disconnect(m_live_connection);
|
||||
disconnect(m_fields, &CablePropertiesWidget::propertiesTyped,
|
||||
this, &CablePropertiesEditorWidget::applyLive);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::applyLive
|
||||
Put what is being typed straight onto the cable, without pushing an
|
||||
undo step: the whole editing of one field is one step, which
|
||||
apply() works out from what the panel showed when the field is left.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::applyLive()
|
||||
{
|
||||
//Ignore the signals sent while the form is being filled in: at
|
||||
//that moment it holds a half loaded state.
|
||||
if (m_updating) return;
|
||||
if (!m_cable) return;
|
||||
|
||||
m_live_cable = m_cable;
|
||||
m_cable->setProperties(m_fields->properties());
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::changeTypeRequested
|
||||
Open the window which opens when a cable line has just been drawn,
|
||||
in the mode where it changes the type of this very cable: he picks
|
||||
the new type there out of the cable type file, and the cable takes
|
||||
it -- cores reworked, marks redrawn -- as one single undo step.
|
||||
|
||||
The form is filled in again afterwards rather than through the usual
|
||||
path: the type has just changed under it, and it may not go on
|
||||
offering the one which was left.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::changeTypeRequested()
|
||||
{
|
||||
if (!m_cable) return;
|
||||
|
||||
CableCreateDialog dialog(m_part ? m_part->diagram() : nullptr,
|
||||
m_cable,
|
||||
this);
|
||||
if (dialog.exec() != QDialog::Accepted) return;
|
||||
|
||||
m_updating = true;
|
||||
m_fields->setProperties(m_cable->properties());
|
||||
m_shown = m_cable->properties();
|
||||
m_updating = false;
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::apply
|
||||
Put what was typed onto the cable as one undo step.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::apply()
|
||||
{
|
||||
//Ignore the signals sent while the form is being filled in: at
|
||||
//that moment it holds a half loaded state.
|
||||
if (m_updating) return;
|
||||
if (!m_cable) return;
|
||||
|
||||
if (QUndoCommand *undo = associatedUndo())
|
||||
{
|
||||
auto *project = qobject_cast<QETProject *>(m_cable->parent());
|
||||
if (project && project->undoStack()) {
|
||||
project->undoStack()->push(undo);
|
||||
} else {
|
||||
m_cable->setProperties(m_fields->properties());
|
||||
delete undo;
|
||||
}
|
||||
}
|
||||
m_shown = m_fields->properties();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::associatedUndo
|
||||
@return the edit as one undo step, or nullptr when nothing changed
|
||||
*/
|
||||
QUndoCommand *CablePropertiesEditorWidget::associatedUndo() const
|
||||
{
|
||||
if (!m_cable) return nullptr;
|
||||
|
||||
const CableProperties after = m_fields->properties();
|
||||
if (after == m_shown) return nullptr;
|
||||
return new ChangeCablePropertiesCommand(m_cable, m_shown, after);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::reset
|
||||
Discard the edit in progress, putting back what the panel showed.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::reset()
|
||||
{
|
||||
if (!m_cable) return;
|
||||
m_updating = true;
|
||||
m_fields->setProperties(m_shown);
|
||||
m_updating = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::updateInfo
|
||||
Say how many cores of this cable are wired to a conductor.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::updateInfo()
|
||||
{
|
||||
if (!m_cable) return;
|
||||
|
||||
m_info->setText(tr("%1 of %2 cores wired to a conductor",
|
||||
"how many cores of this cable are wired",
|
||||
m_cable->usedCoreCount())
|
||||
.arg(m_cable->usedCoreCount())
|
||||
.arg(m_cable->coreCount()));
|
||||
|
||||
updateFreeCores();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::updateFreeCores
|
||||
List the cores the type of this cable offers which stand nowhere on
|
||||
the sheet yet: those are the ones he can still put down, and they
|
||||
come down straight from here, on the line this panel was opened by.
|
||||
|
||||
The list is of no use when there is none -- and it cannot work at
|
||||
all when no single line of the cable is the selected one, since a
|
||||
core then has no line to be put down on -- so it takes no room then.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::updateFreeCores()
|
||||
{
|
||||
if (!m_free_cores) return;
|
||||
|
||||
const bool usable = m_cable && m_part && m_part->cable() == m_cable;
|
||||
|
||||
m_free_cores->clear();
|
||||
if (usable)
|
||||
{
|
||||
for (int i = 0; i < m_cable->coreCount(); ++i)
|
||||
{
|
||||
if (m_cable->hasCore(i)) continue;
|
||||
|
||||
const QString color = m_cable->colorOfCore(i);
|
||||
auto *item = new QListWidgetItem(
|
||||
color.isEmpty() ? tr("Core %1").arg(i + 1)
|
||||
: tr("Core %1 — %2").arg(i + 1).arg(color),
|
||||
m_free_cores);
|
||||
item->setData(Qt::UserRole, i);
|
||||
}
|
||||
}
|
||||
|
||||
const bool any = usable && m_free_cores->count() > 0;
|
||||
m_free_label->setVisible(any);
|
||||
m_free_cores->setVisible(any);
|
||||
if (!any) return;
|
||||
|
||||
//As high as the entries it really shows, four of them at most:
|
||||
//the dock is small, and a handful of free cores must not turn
|
||||
//it into a wall.
|
||||
const int row = qMax(m_free_cores->sizeHintForRow(0), 18);
|
||||
m_free_cores->setFixedHeight(row * qMin(4, m_free_cores->count())
|
||||
+ 2 * m_free_cores->frameWidth() + 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::placeRequested
|
||||
He double-clicked one of the cores which stand nowhere: this very
|
||||
line takes the mouse and waits for the click which puts the core
|
||||
down. There is no dialog to close here -- the panel stays where it
|
||||
is, and it reads the cable back as soon as the core lands.
|
||||
|
||||
@param item the entry he double-clicked
|
||||
*/
|
||||
void CablePropertiesEditorWidget::placeRequested(QListWidgetItem *item)
|
||||
{
|
||||
if (!item || !m_part) return;
|
||||
|
||||
m_part->startPlacingCore(item->data(Qt::UserRole).toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::freeCoreMenu
|
||||
The small menu a right click on a core which stands nowhere opens:
|
||||
one entry, doing what a double click does -- the line takes the
|
||||
mouse, the mark shows on it at once and the mouse is put down there,
|
||||
so the very next click leaves the core standing on that line.
|
||||
|
||||
@param pos where he right-clicked, in list coordinates
|
||||
*/
|
||||
void CablePropertiesEditorWidget::freeCoreMenu(const QPoint &pos)
|
||||
{
|
||||
QListWidgetItem *item = m_free_cores ? m_free_cores->itemAt(pos) : nullptr;
|
||||
if (!item || !m_part) return;
|
||||
|
||||
m_free_cores->setCurrentItem(item);
|
||||
|
||||
QMenu menu(m_free_cores);
|
||||
QAction *place = menu.addAction(tr("Place this core on the line"));
|
||||
place->setIcon(QET::Icons::Cable);
|
||||
|
||||
if (menu.exec(m_free_cores->viewport()->mapToGlobal(pos)) == place) {
|
||||
//Gone before he is sent off: the mouse goes to the line
|
||||
//and nothing may be left standing over the place it is
|
||||
//sent to.
|
||||
menu.hide();
|
||||
placeRequested(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::updateUi
|
||||
Read the cable back into the panel.
|
||||
|
||||
Not while a field is being typed in: writing what was just typed
|
||||
back into that field would take the cursor away from the user with
|
||||
every key, and it would take back the state the whole editing of
|
||||
that field is measured against when the undo step is worked out.
|
||||
*/
|
||||
void CablePropertiesEditorWidget::updateUi()
|
||||
{
|
||||
if (!m_cable) return;
|
||||
|
||||
if (m_fields->editing() && m_live_cable == m_cable) {
|
||||
updateInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
m_updating = true;
|
||||
m_fields->setProperties(m_cable->properties());
|
||||
m_shown = m_cable->properties();
|
||||
updateInfo();
|
||||
m_updating = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CablePropertiesEditorWidget::title
|
||||
@return the panel title
|
||||
*/
|
||||
QString CablePropertiesEditorWidget::title() const
|
||||
{
|
||||
return tr("Cable");
|
||||
}
|
||||
Reference in New Issue
Block a user