X-Git-Url: http://git.code-monkey.de/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fwidgets%2Fpopup.cpp;h=13282cda25e458b6b624de563f09e1fc6668a6b5;hp=9863887ed5dab9595e69f6c8ba5b1308186223dd;hb=bb19aac49414cc772a2a1e52730cbb2ca24b425c;hpb=0bce86095e332bedff9643e3dfbe409259e2df5f diff --git a/pv/widgets/popup.cpp b/pv/widgets/popup.cpp index 9863887..13282cd 100644 --- a/pv/widgets/popup.cpp +++ b/pv/widgets/popup.cpp @@ -14,19 +14,21 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * along with this program; if not, see . */ #include +#include -#include - +#include +#include +#include #include -#include "popup.h" +#include "popup.hpp" -using namespace std; +using std::max; +using std::min; namespace pv { namespace widgets { @@ -37,42 +39,110 @@ const unsigned int Popup::MarginWidth = 6; Popup::Popup(QWidget *parent) : QWidget(parent, Qt::Popup | Qt::FramelessWindowHint), - _point(), - _pos(Left) + point_(), + pos_(Left) { } const QPoint& Popup::point() const { - return _point; + return point_; } Popup::Position Popup::position() const { - return _pos; + return pos_; } void Popup::set_position(const QPoint point, Position pos) { - _point = point, _pos = pos; + point_ = point, pos_ = pos; setContentsMargins( MarginWidth + ((pos == Right) ? ArrowLength : 0), MarginWidth + ((pos == Bottom) ? ArrowLength : 0), MarginWidth + ((pos == Left) ? ArrowLength : 0), MarginWidth + ((pos == Top) ? ArrowLength : 0)); +} + +bool Popup::eventFilter(QObject *obj, QEvent *event) +{ + QKeyEvent *keyEvent; + + (void)obj; + + if (event->type() == QEvent::KeyPress) { + keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Enter || + keyEvent->key() == Qt::Key_Return) { + close(); + return true; + } + } + + return false; +} + +void Popup::show() +{ + QLineEdit* le; + + QWidget::show(); + // We want to close the popup when the Enter key was + // pressed and the first editable widget had focus. + if ((le = this->findChild())) { + + // For combo boxes we need to hook into the parent of + // the line edit (i.e. the QComboBox). For edit boxes + // we hook into the widget directly. + if (le->parent()->metaObject()->className() == + this->metaObject()->className()) + le->installEventFilter(this); + else + le->parent()->installEventFilter(this); + + le->selectAll(); + le->setFocus(); + } +} + +bool Popup::space_for_arrow() const +{ + // Check if there is room for the arrow + switch (pos_) { + case Right: + if (point_.x() > x()) + return false; + return true; + + case Bottom: + if (point_.y() > y()) + return false; + return true; + + case Left: + if (point_.x() < (x() + width())) + return false; + return true; + + case Top: + if (point_.y() < (y() + height())) + return false; + return true; + } + + return true; } QPolygon Popup::arrow_polygon() const { QPolygon poly; - const QPoint p = mapFromGlobal(_point); - const int l = ArrowLength + ArrowOverlap; + const QPoint p = mapFromGlobal(point_); + const int l = ArrowLength + ArrowOverlap; - switch (_pos) - { + switch (pos_) { case Right: poly << QPoint(p.x() + l, p.y() - l); break; @@ -81,7 +151,7 @@ QPolygon Popup::arrow_polygon() const poly << QPoint(p.x() - l, p.y() + l); break; - case Left: + case Left: case Top: poly << QPoint(p.x() - l, p.y() - l); break; @@ -89,17 +159,16 @@ QPolygon Popup::arrow_polygon() const poly << p; - switch (_pos) - { + switch (pos_) { case Right: case Bottom: poly << QPoint(p.x() + l, p.y() + l); break; - case Left: + case Left: poly << QPoint(p.x() - l, p.y() + l); break; - + case Top: poly << QPoint(p.x() + l, p.y() - l); break; @@ -116,11 +185,11 @@ QRegion Popup::arrow_region() const QRect Popup::bubble_rect() const { return QRect( - QPoint((_pos == Right) ? ArrowLength : 0, - (_pos == Bottom) ? ArrowLength : 0), - QSize(width() - ((_pos == Left || _pos == Right) ? + QPoint((pos_ == Right) ? ArrowLength : 0, + (pos_ == Bottom) ? ArrowLength : 0), + QSize(width() - ((pos_ == Left || pos_ == Right) ? ArrowLength : 0), - height() - ((_pos == Top || _pos == Bottom) ? + height() - ((pos_ == Top || pos_ == Bottom) ? ArrowLength : 0))); } @@ -144,24 +213,34 @@ QRegion Popup::bubble_region() const QRegion Popup::popup_region() const { - return arrow_region().united(bubble_region()); + if (space_for_arrow()) + return arrow_region().united(bubble_region()); + else + return bubble_region(); } void Popup::reposition_widget() { QPoint o; - if (_pos == Right || _pos == Left) + const QRect screen_rect = QApplication::desktop()->availableGeometry( + QApplication::desktop()->screenNumber(point_)); + + if (pos_ == Right || pos_ == Left) o.ry() = -height() / 2; else o.rx() = -width() / 2; - if (_pos == Left) + if (pos_ == Left) o.rx() = -width(); - else if(_pos == Top) + else if (pos_ == Top) o.ry() = -height(); - move(_point + o); + o += point_; + move(max(min(o.x(), screen_rect.right() - width()), + screen_rect.left()), + max(min(o.y(), screen_rect.bottom() - height()), + screen_rect.top())); } void Popup::closeEvent(QCloseEvent*) @@ -177,6 +256,7 @@ void Popup::paintEvent(QPaintEvent*) const QColor outline_color(QApplication::palette().color( QPalette::Dark)); + // Draw the bubble const QRegion b = bubble_region(); const QRegion bubble_outline = QRegion(rect()).subtracted( b.translated(1, 0).intersected(b.translated(0, 1).intersected( @@ -186,12 +266,16 @@ void Popup::paintEvent(QPaintEvent*) painter.setBrush(QApplication::palette().brush(QPalette::Window)); painter.drawRect(rect()); + // Draw the arrow + if (!space_for_arrow()) + return; + const QPoint ArrowOffsets[] = { QPoint(1, 0), QPoint(0, -1), QPoint(-1, 0), QPoint(0, 1)}; const QRegion a(arrow_region()); const QRegion arrow_outline = a.subtracted( - a.translated(ArrowOffsets[_pos])); + a.translated(ArrowOffsets[pos_])); painter.setClipRegion(bubble_outline.subtracted(a).united( arrow_outline)); @@ -205,13 +289,13 @@ void Popup::resizeEvent(QResizeEvent*) setMask(popup_region()); } -void Popup::mouseReleaseEvent(QMouseEvent *e) +void Popup::mouseReleaseEvent(QMouseEvent *event) { - assert(e); + assert(event); // We need our own out-of-bounds click handler because QWidget counts // the drop-shadow region as inside the widget - if(!bubble_rect().contains(e->pos())) + if (!bubble_rect().contains(event->pos())) close(); } @@ -222,4 +306,3 @@ void Popup::showEvent(QShowEvent*) } // namespace widgets } // namespace pv -