1 /*****************************************************************************
2 * resizablepopup.cpp - QStarDict, a StarDict clone written with using Qt *
3 * Copyright (C) 2007 Alexander Rodin *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License along *
16 * with this program; if not, write to the Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 *****************************************************************************/
20 #include "resizablepopup.h"
22 #include <QApplication>
24 #include <QDesktopWidget>
25 #include <QMouseEvent>
26 #include <QTimerEvent>
30 const int CornerSize = 10;
36 ResizablePopup::ResizablePopup(QWidget *parent)
37 : QFrame(parent, Qt::Popup)
40 m_resizeDirection = None;
41 m_timeoutBeforeHide = 0;
45 setMouseTracking(true);
48 setFrameStyle(QFrame::Box);
49 setFrameShadow(QFrame::Raised);
52 void ResizablePopup::popup()
54 if (m_defaultSize != size())
55 resize(m_defaultSize);
56 QPoint newPosition = QCursor::pos() - QPoint(30, 30);
57 if (newPosition.x() < 0)
59 else if (newPosition.x() + width() > QApplication::desktop()->width())
60 newPosition.setX(QApplication::desktop()->width() - width());
61 if (newPosition.y() < 0)
63 else if (newPosition.y() + height() > QApplication::desktop()->height())
64 newPosition.setY(QApplication::desktop()->height() - height());
70 void ResizablePopup::enterEvent(QEvent*)
74 killTimer(m_timerCloseId);
79 void ResizablePopup::leaveEvent(QEvent*)
81 if (geometry().contains(QCursor::pos()))
83 if (m_resizeDirection)
85 if (m_timeoutBeforeHide < 0)
87 if (m_timeoutBeforeHide == 0)
92 else if (! m_timerCloseId)
93 m_timerCloseId = startTimer(m_timeoutBeforeHide);
96 void ResizablePopup::mouseMoveEvent(QMouseEvent *event)
98 Qt::CursorShape cursorShape = Qt::ArrowCursor;
99 if ((event->x() >= 0 && event->x() < CornerSize &&
100 event->y() >= 0 && event->y() < CornerSize) ||
101 (event->x() < width() && event->x() >= width() - CornerSize &&
102 event->y() < height() && event->y() >= height() - CornerSize))
103 cursorShape = Qt::SizeFDiagCursor;
104 else if ((event->x() < width() && event->x() >= width() - CornerSize &&
105 event->y() >= 0 && event->y() < CornerSize) ||
106 (event->x() >= 0 && event->x() < CornerSize &&
107 event->y() < height() && event->y() >= height() - CornerSize))
108 cursorShape = Qt::SizeBDiagCursor;
109 else if ((event->x() >= 0 && event->x() < frameWidth()) ||
110 (event->x() < width() && event->x() >= width() - frameWidth()))
111 cursorShape = Qt::SizeHorCursor;
112 else if ((event->y() >= 0 && event->y() < frameWidth()) ||
113 (event->y() < height() && event->y() >= height() - frameWidth()))
114 cursorShape = Qt::SizeVerCursor;
116 if (cursor().shape() != cursorShape)
117 setCursor(cursorShape);
119 if (event->buttons().testFlag(Qt::LeftButton))
122 move(pos() + (event->globalPos() - m_oldCursorPos));
123 m_oldCursorPos = event->globalPos();
129 void ResizablePopup::mousePressEvent(QMouseEvent *event)
131 if (! geometry().contains(event->globalPos()))
135 killTimer(m_timerCloseId);
143 if (event->buttons().testFlag(Qt::LeftButton))
145 if (event->x() < CornerSize && event->y() < CornerSize)
146 m_resizeDirection = TopLeft;
147 else if (event->x() >= width() - CornerSize && event->y() < CornerSize)
148 m_resizeDirection = TopRight;
149 else if (event->x() < CornerSize && event->y() >= height() - CornerSize)
150 m_resizeDirection = BottomLeft;
151 else if (event->x() >= width() - CornerSize && event->y() >= height() - CornerSize)
152 m_resizeDirection = BottomRight;
153 else if (event->x() < frameWidth())
154 m_resizeDirection = Left;
155 else if (event->x() >= width() - frameWidth())
156 m_resizeDirection = Right;
157 else if (event->y() < frameWidth())
158 m_resizeDirection = Top;
159 else if (event->y() >= height() - frameWidth())
160 m_resizeDirection = Bottom;
162 m_resizeDirection = None;
163 if (m_resizeDirection)
164 m_timerResizeId = startTimer(8);
168 m_oldCursorPos = event->globalPos();
171 void ResizablePopup::mouseReleaseEvent(QMouseEvent*)
176 void ResizablePopup::mouseDoubleClickEvent(QMouseEvent*)
181 killTimer(m_timerCloseId);
187 void ResizablePopup::timerEvent(QTimerEvent *event)
189 if (event->timerId() == m_timerResizeId)
193 else if (event->timerId() == m_timerCloseId)
197 killTimer(m_timerCloseId);
203 void ResizablePopup::doResize()
205 if (! QApplication::mouseButtons().testFlag(Qt::LeftButton))
208 if (m_resizeDirection)
210 QRect newGeometry = geometry();
211 switch (m_resizeDirection)
214 newGeometry.setTopLeft(QCursor::pos());
217 newGeometry.setTopRight(QCursor::pos());
220 newGeometry.setBottomLeft(QCursor::pos());
223 newGeometry.setBottomRight(QCursor::pos());
226 newGeometry.setLeft(QCursor::pos().x());
229 newGeometry.setRight(QCursor::pos().x());
232 newGeometry.setTop(QCursor::pos().y());
235 newGeometry.setBottom(QCursor::pos().y());
240 if (newGeometry.width() < minimumSize().width())
242 newGeometry.setWidth(width());
243 newGeometry.moveLeft(geometry().left());
245 if (newGeometry.height() < minimumSize().height())
247 newGeometry.setHeight(height());
248 newGeometry.moveTop(geometry().top());
250 if (newGeometry != geometry())
251 setGeometry(newGeometry);
255 void ResizablePopup::stopResize()
257 if (m_resizeDirection)
259 m_resizeDirection = None;
260 killTimer(m_timerResizeId);
265 bool ResizablePopup::event(QEvent *event)
267 if (event->type() == QEvent::WindowUnblocked && m_isPopuped)
271 killTimer(m_timerCloseId);
278 return QFrame::event(event);
283 // vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab cindent textwidth=120 formatoptions=tc