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 @@ +S \ 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