diff --git a/qucs/bitmaps/svg/viewmagsel.svg b/qucs/bitmaps/svg/viewmagsel.svg
new file mode 100644
index 000000000..865913e83
--- /dev/null
+++ b/qucs/bitmaps/svg/viewmagsel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/qucs/mouseactions.cpp b/qucs/mouseactions.cpp
index 4fde200d3..26be53162 100644
--- a/qucs/mouseactions.cpp
+++ b/qucs/mouseactions.cpp
@@ -1242,98 +1242,97 @@ void MouseActions::MPressRotate(Schematic *Doc, QMouseEvent*, float fX, float fY
// -----------------------------------------------------------
// insert component, diagram, painting into schematic ?!
-void MouseActions::MPressElement(Schematic *Doc, QMouseEvent *Event, float, float)
-{
- if(selElem == 0) return;
- //QPainter painter(Doc->viewport());
- //setPainter(Doc, &painter);
+void MouseActions::MPressElement(Schematic *Doc, QMouseEvent *Event, float, float) {
+ if (selElem == 0) return;
+ //QPainter painter(Doc->viewport());
+ //setPainter(Doc, &painter);
- int x1, y1, x2, y2, rot;
- if(selElem->Type & isComponent) {
- Component *Comp = (Component*)selElem;
+ int x1, y1, x2, y2, rot;
+ if (selElem->Type & isComponent) {
+ Component *Comp = (Component *) selElem;
// qDebug() << "+-+ got to switch:" << Comp->Name;
- QString entryName = Comp->Name;
-
- switch(Event->button()) {
- case Qt::LeftButton :
- // left mouse button inserts component into the schematic
- // give the component a pointer to the schematic it's a
- // part of
- Comp->setSchematic (Doc);
- Comp->textSize(x1, y1);
- Doc->insertComponent(Comp);
- Comp->textSize(x2, y2);
- if(Comp->tx < Comp->x1) Comp->tx -= x2 - x1;
-
- // Note: insertCopmponents does increment name1 -> name2
+ QString entryName = Comp->Name;
+
+ switch (Event->button()) {
+ case Qt::LeftButton :
+ // left mouse button inserts component into the schematic
+ // give the component a pointer to the schematic it's a
+ // part of
+ Comp->setSchematic(Doc);
+ Comp->textSize(x1, y1);
+ Doc->insertComponent(Comp);
+ Comp->textSize(x2, y2);
+ if (Comp->tx < Comp->x1) Comp->tx -= x2 - x1;
+
+ // Note: insertCopmponents does increment name1 -> name2
// qDebug() << " +-+ got to insert:" << Comp->Name;
- // enlarge viewarea if component lies outside the view
- Comp->entireBounds(x1,y1,x2,y2, Doc->textCorr());
- Doc->enlargeView(x1, y1, x2, y2);
+ // enlarge viewarea if component lies outside the view
+ Comp->entireBounds(x1, y1, x2, y2, Doc->textCorr());
+ Doc->enlargeView(x1, y1, x2, y2);
- drawn = false;
- Doc->viewport()->update();
- Doc->setChanged(true, true);
- rot = Comp->rotated;
+ drawn = false;
+ Doc->viewport()->update();
+ Doc->setChanged(true, true);
+ rot = Comp->rotated;
- // handle static and dynamic components
+ // handle static and dynamic components
// QucsApp::CompChoose;
- if (Module::vaComponents.contains(entryName)){
- QString filename = Module::vaComponents[entryName];
+ if (Module::vaComponents.contains(entryName)) {
+ QString filename = Module::vaComponents[entryName];
// qDebug() << " ===+ recast";
- Comp = dynamic_cast(Comp)->newOne(filename); //va component
- qDebug() << " => recast = Comp;" << Comp->Name << "filename: " << filename;
- }
- else {
- Comp = Comp->newOne(); // static component is used, so create a new one
- }
- rot -= Comp->rotated;
- rot &= 3;
- while(rot--) Comp->rotate(); // keep last rotation for single component
- break;
-
- case Qt::RightButton : // right mouse button rotates the component
- if(Comp->Ports.count() == 0)
- break; // do not rotate components without ports
- Comp->paintScheme(Doc); // erase old component scheme
- Comp->rotate();
- Comp->paintScheme(Doc); // paint new component scheme
- break;
-
- default: ; // avoids compiler warnings
- }
+ Comp = dynamic_cast(Comp)->newOne(filename); //va component
+ qDebug() << " => recast = Comp;" << Comp->Name << "filename: " << filename;
+ } else {
+ Comp = Comp->newOne(); // static component is used, so create a new one
+ }
+ rot -= Comp->rotated;
+ rot &= 3;
+ while (rot--) Comp->rotate(); // keep last rotation for single component
+ break;
+
+ case Qt::RightButton : // right mouse button rotates the component
+ if (Comp->Ports.count() == 0)
+ break; // do not rotate components without ports
+ Comp->paintScheme(Doc); // erase old component scheme
+ Doc->viewport()->repaint();
+ Comp->rotate();
+ Comp->paintScheme(Doc); // paint new component scheme
+ break;
+
+ default:; // avoids compiler warnings
+ }
// qDebug() << " => selElem = Comp;" << Comp->Name;
- // comp it getting empty
- selElem = Comp;
- return;
-
- } // of "if(isComponent)"
- else if(selElem->Type == isDiagram) {
- if(Event->button() != Qt::LeftButton) return;
+ // comp it getting empty
+ selElem = Comp;
+ return;
- Diagram *Diag = (Diagram*)selElem;
- QFileInfo Info(Doc->DocName);
- // dialog is Qt::WDestructiveClose !!!
- DiagramDialog *dia =
- new DiagramDialog(Diag, Doc);
- if(dia->exec() == QDialog::Rejected) { // don't insert if dialog canceled
- Doc->viewport()->update();
- drawn = false;
- return;
- }
+ } // of "if(isComponent)"
+ else if (selElem->Type == isDiagram) {
+ if (Event->button() != Qt::LeftButton) return;
+
+ Diagram *Diag = (Diagram *) selElem;
+ QFileInfo Info(Doc->DocName);
+ // dialog is Qt::WDestructiveClose !!!
+ DiagramDialog *dia =
+ new DiagramDialog(Diag, Doc);
+ if (dia->exec() == QDialog::Rejected) { // don't insert if dialog canceled
+ Doc->viewport()->update();
+ drawn = false;
+ return;
+ }
- Doc->Diagrams->append(Diag);
- Doc->enlargeView(Diag->cx, Diag->cy-Diag->y2, Diag->cx+Diag->x2, Diag->cy);
- Doc->setChanged(true, true); // document has been changed
+ Doc->Diagrams->append(Diag);
+ Doc->enlargeView(Diag->cx, Diag->cy - Diag->y2, Diag->cx + Diag->x2, Diag->cy);
+ Doc->setChanged(true, true); // document has been changed
- Doc->viewport()->repaint();
- Diag = Diag->newOne(); // the component is used, so create a new one
- Diag->paintScheme(Doc);
- selElem = Diag;
- return;
- } // of "if(isDiagram)"
+ Doc->viewport()->repaint();
+ Diag = Diag->newOne(); // the component is used, so create a new one
+ Diag->paintScheme(Doc);
+ selElem = Diag;
+ return;
+ } // of "if(isDiagram)"
// *********** it is a painting !!!
diff --git a/qucs/qucs.cpp b/qucs/qucs.cpp
index 1219cb2dd..aac024c24 100644
--- a/qucs/qucs.cpp
+++ b/qucs/qucs.cpp
@@ -2241,6 +2241,13 @@ void QucsApp::slotShowAll()
getDoc()->showAll();
}
+// --------------------------------------------------------------
+void QucsApp::slotZoomToSelection()
+{
+ slotHideEdit(); // disable text edit of component property
+ getDoc()->zoomToSelection();
+}
+
// -----------------------------------------------------------
// Sets the scale factor to 1.
void QucsApp::slotShowOne()
diff --git a/qucs/qucs.h b/qucs/qucs.h
index 90889a70d..6918964c7 100644
--- a/qucs/qucs.h
+++ b/qucs/qucs.h
@@ -140,6 +140,7 @@ public slots:
void slotPopHierarchy();
void slotShowAll();
+ void slotZoomToSelection();
void slotShowOne();
void slotZoomOut(); // Zoom out by 2
@@ -220,7 +221,7 @@ private slots:
QAction *fileNew, *textNew, *fileNewDpl, *fileOpen, *fileSave, *fileSaveAs,
*fileSaveAll, *fileClose, *fileExamples, *fileSettings, *filePrint, *fileQuit,
*projNew, *projOpen, *projDel, *projClose, *applSettings, *refreshSchPath,
- *editCut, *editCopy, *magAll, *magOne, *magMinus, *filePrintFit, *tune,
+ *editCut, *editCopy, *magAll, *magSel, *magOne, *magMinus, *filePrintFit, *tune,
*symEdit, *intoH, *popH, *simulate, *save_netlist, *dpl_sch, *undo, *redo, *dcbias;
QAction *exportAsImage;
diff --git a/qucs/qucs.qrc b/qucs/qucs.qrc
index bde552fc0..0bbc1fa9c 100644
--- a/qucs/qucs.qrc
+++ b/qucs/qucs.qrc
@@ -431,6 +431,7 @@
bitmaps/svg/editredo.svg
bitmaps/svg/editundo.svg
bitmaps/svg/viewmagfit.svg
+ bitmaps/svg/viewmagsel.svg
bitmaps/svg/viewmag1.svg
bitmaps/svg/viewmag+.svg
bitmaps/svg/viewmag-.svg
diff --git a/qucs/qucs_init.cpp b/qucs/qucs_init.cpp
index a63acbd8f..bbe7980ab 100644
--- a/qucs/qucs_init.cpp
+++ b/qucs/qucs_init.cpp
@@ -364,6 +364,12 @@ void QucsApp::initActions()
magAll->setWhatsThis(tr("View All\n\nShows the whole page content"));
connect(magAll, SIGNAL(triggered()), SLOT(slotShowAll()));
+ magSel = new QAction(QIcon((":/bitmaps/svg/viewmagsel.svg")), tr("Zoom to selection"), this);
+ magSel->setShortcut(tr("Z"));
+ magSel->setStatusTip(tr("Zoom to selected components"));
+ magSel->setWhatsThis(tr("Zoom to selection\n\nZoom to selected components"));
+ connect(magSel, SIGNAL(triggered()), SLOT(slotZoomToSelection()));
+
magOne = new QAction(QIcon((":/bitmaps/svg/viewmag1.svg")), tr("View 1:1"), this);
magOne->setShortcut(Qt::Key_1);
magOne->setStatusTip(tr("Views without magnification"));
@@ -778,6 +784,7 @@ void QucsApp::initMenuBar()
viewMenu = new QMenu(tr("&View")); // menuBar entry viewMenu
viewMenu->addAction(magAll);
+ viewMenu->addAction(magSel);
viewMenu->addAction(magOne);
viewMenu->addAction(magPlus);
viewMenu->addAction(magMinus);
@@ -904,6 +911,7 @@ void QucsApp::initToolBar()
viewToolbar = new QToolBar(tr("View"));
this->addToolBar(viewToolbar);
viewToolbar->addAction(magAll);
+ viewToolbar->addAction(magSel);
viewToolbar->addAction(magOne);
viewToolbar->addAction(magPlus);
viewToolbar->addAction(magMinus);
diff --git a/qucs/qucsdoc.h b/qucs/qucsdoc.h
index 602e7b5f7..ad0cab953 100644
--- a/qucs/qucsdoc.h
+++ b/qucs/qucsdoc.h
@@ -37,6 +37,7 @@ class QucsDoc {
virtual void becomeCurrent(bool) {};
virtual float zoomBy(float) { return 1.0; };
virtual void showAll() {};
+ virtual void zoomToSelection() {};
virtual void showNoZoom() {};
static QString fileSuffix (const QString&);
diff --git a/qucs/schematic.cpp b/qucs/schematic.cpp
index 0b7838a84..af7cbc36a 100644
--- a/qucs/schematic.cpp
+++ b/qucs/schematic.cpp
@@ -76,6 +76,8 @@ Schematic::Schematic(QucsApp *App_, const QString& Name_)
UsedX1 = UsedY1 = INT_MAX;
UsedX2 = UsedY2 = INT_MIN;
+ zx1 = zy1 = zx2 = zy2 = dx = dy = 0;
+
tmpPosX = tmpPosY = -100;
tmpUsedX1 = tmpUsedY1 = tmpViewX1 = tmpViewY1 = -200;
tmpUsedX2 = tmpUsedY2 = tmpViewX2 = tmpViewY2 = 200;
@@ -794,6 +796,42 @@ void Schematic::showAll()
zoom(xScale);
}
+// ------------------------------------------------------
+void Schematic::zoomToSelection() {
+ int x1, x2, y1, y2 = 0;
+ sizeOfSelection(x1, y1, x2, y2);
+ if (x1 == 0 && x2 == 0 && y1 == 0 && y2 == 0) {
+ showAll();
+ return;
+ }
+ //
+ if (zx1 == contentsX() && zx2 == contentsWidth() &&
+ zy1 == contentsY() && zy2 == contentsHeight() &&
+ dx == x2 - x1 &&
+ dy == y2 - y1) {
+ return;
+ }
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ float xScale = float(visibleWidth()) / std::abs(dx + 80);
+ float yScale = float(visibleHeight()) / std::abs(dy + 80);
+ float scale = qMin(xScale, yScale) / Scale;
+ zoom(scale);
+
+ ViewX1 = x1 - 40;
+ ViewY1 = y1 - 40;
+ ViewX2 = x2 + 40;
+ ViewY2 = y2 + 40;
+ zx1 = contentsX();
+ zy1 = contentsY();
+ zx2 = contentsWidth();
+ zy2 = contentsHeight();
+
+ //releaseKeyboard(); // allow keyboard inputs again
+}
+
// ---------------------------------------------------
void Schematic::showNoZoom()
{
@@ -1018,6 +1056,124 @@ void Schematic::sizeOfAll(int& xmin, int& ymin, int& xmax, int& ymax)
}
}
+void Schematic::sizeOfSelection(int& xmin, int& ymin, int& xmax, int& ymax)
+{
+ xmin=INT_MAX;
+ ymin=INT_MAX;
+ xmax=INT_MIN;
+ ymax=INT_MIN;
+ Component *pc;
+ Diagram *pd;
+ Wire *pw;
+ WireLabel *pl;
+ Painting *pp;
+
+ bool isAnySelected = false;
+
+ if(Components->isEmpty())
+ if(Wires->isEmpty())
+ if(Diagrams->isEmpty())
+ if(Paintings->isEmpty()) {
+ xmin = xmax = 0;
+ ymin = ymax = 0;
+ return;
+ }
+
+
+ float Corr = textCorr();
+ int x1, y1, x2, y2;
+ // find boundings of all components
+ for(pc = Components->first(); pc != 0; pc = Components->next()) {
+ if (!pc->isSelected) {
+ continue;
+ }
+ isAnySelected = true;
+ pc->entireBounds(x1, y1, x2, y2, Corr);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+ }
+
+ // find boundings of all wires
+ for(pw = Wires->first(); pw != 0; pw = Wires->next()) {
+ if (!pw->isSelected) {
+ continue;
+ }
+ isAnySelected = true;
+ if(pw->x1 < xmin) xmin = pw->x1;
+ if(pw->x2 > xmax) xmax = pw->x2;
+ if(pw->y1 < ymin) ymin = pw->y1;
+ if(pw->y2 > ymax) ymax = pw->y2;
+
+ pl = pw->Label;
+ if(pl) { // check position of wire label
+ pl->getLabelBounding(x1,y1,x2,y2);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+ }
+ }
+
+ // find boundings of all node labels
+ for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next()) {
+ if (!pn->isSelected) {
+ continue;
+ }
+ isAnySelected = true;
+ pl = pn->Label;
+ if(pl) { // check position of node label
+ pl->getLabelBounding(x1,y1,x2,y2);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+ }
+ }
+
+ // find boundings of all diagrams
+ for(pd = Diagrams->first(); pd != 0; pd = Diagrams->next()) {
+ if (!pd->isSelected) {
+ continue;
+ }
+ isAnySelected = true;
+ pd->Bounding(x1, y1, x2, y2);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+
+ for (Graph *pg : pd->Graphs)
+ // test all markers of diagram
+ for (Marker *pm : pg->Markers) {
+ pm->Bounding(x1, y1, x2, y2);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+ }
+ }
+
+ // find boundings of all Paintings
+ for(pp = Paintings->first(); pp != nullptr; pp = Paintings->next()) {
+ if (!pp->isSelected) {
+ continue;
+ }
+ isAnySelected = true;
+ pp->Bounding(x1, y1, x2, y2);
+ if(x1 < xmin) xmin = x1;
+ if(x2 > xmax) xmax = x2;
+ if(y1 < ymin) ymin = y1;
+ if(y2 > ymax) ymax = y2;
+ }
+
+ if (!isAnySelected) {
+ xmin = xmax = 0;
+ ymin = ymax = 0;
+ }
+}
+
// ---------------------------------------------------
// Rotates all selected components around their midpoint.
bool Schematic::rotateElements()
@@ -1911,7 +2067,6 @@ void Schematic::contentsWheelEvent(QWheelEvent *Event)
viewport()->update(); // because QScrollView thinks nothing has changed
App->view->drawn = false;
}
-
Event->accept(); // QScrollView must not handle this event
}
diff --git a/qucs/schematic.h b/qucs/schematic.h
index 328b8d31f..01ce20cac 100644
--- a/qucs/schematic.h
+++ b/qucs/schematic.h
@@ -93,6 +93,7 @@ class Schematic : public Q3ScrollView, public QucsDoc {
float textCorr();
bool sizeOfFrame(int&, int&);
void sizeOfAll(int&, int&, int&, int&);
+ void sizeOfSelection(int&, int&, int&, int&);
bool rotateElements();
bool mirrorXComponents();
bool mirrorYComponents();
@@ -102,6 +103,7 @@ class Schematic : public Q3ScrollView, public QucsDoc {
float zoom(float);
float zoomBy(float);
void showAll();
+ void zoomToSelection();
void showNoZoom();
void enlargeView(int, int, int, int);
void switchPaintMode();
@@ -145,6 +147,7 @@ class Schematic : public Q3ScrollView, public QucsDoc {
int GridX, GridY;
int ViewX1, ViewY1, ViewX2, ViewY2; // size of the document area
int UsedX1, UsedY1, UsedX2, UsedY2; // document area used by elements
+ int zx1, zy1, zx2, zy2, dx, dy = 0;
int showFrame;
QString Frame_Text0, Frame_Text1, Frame_Text2, Frame_Text3;
@@ -325,6 +328,7 @@ protected slots:
bool isAnalog;
bool isVerilog;
bool creatingLib;
+
};
#endif