mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 16:39:57 +00:00
464 lines
15 KiB
C++
464 lines
15 KiB
C++
/*
|
|
* Copyright (c) 2014 Mark Liversedge (liversedge@gmail.com)
|
|
* (c) Aleksey Osipov (aliks-os@yandex.ru)
|
|
*
|
|
* Some of the code pinched from http://qt-project.org/wiki/Widget-moveable-and-resizeable
|
|
* coz it was simpler than starting from scratch.
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software Foundation, Inc., 51
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "GcOverlayWidget.h"
|
|
#include "GcScopeBar.h"
|
|
#include "DiaryWindow.h"
|
|
#include "DiarySidebar.h"
|
|
#include "Context.h"
|
|
#include "QtMacButton.h"
|
|
|
|
GcOverlayWidget::GcOverlayWidget(Context *context, QWidget *parent) : QWidget(parent), context(context)
|
|
{
|
|
// left / right scroller icon
|
|
static QIcon leftIcon = iconFromPNG(":images/mac/left.png");
|
|
static QIcon rightIcon = iconFromPNG(":images/mac/right.png");
|
|
|
|
setContentsMargins(4,0,4,4);
|
|
setAutoFillBackground(false);
|
|
setAttribute(Qt::WA_TranslucentBackground);
|
|
setMouseTracking(true);
|
|
setFocusPolicy(Qt::ClickFocus);
|
|
#ifdef GC_HAVE_MUMODEL
|
|
setMinimumSize(400,200); //XX temp for MU model...
|
|
#else
|
|
setMinimumSize(250,200);
|
|
#endif
|
|
setFocus();
|
|
mode = none;
|
|
initial = true;
|
|
|
|
// main layout
|
|
QVBoxLayout *mlayout = new QVBoxLayout(this);
|
|
mlayout->setSpacing(0);
|
|
mlayout->setContentsMargins(1,0,1,1);
|
|
|
|
QHBoxLayout *titleLayout = new QHBoxLayout;
|
|
titleLayout->setSpacing(0);
|
|
titleLayout->setContentsMargins(0,0,0,0);
|
|
mlayout->addLayout(titleLayout);
|
|
|
|
// scroller buttons
|
|
left = new QToolButton(this);
|
|
left->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
|
left->setAutoFillBackground(false);
|
|
left->setFixedSize(23,23);
|
|
left->setIcon(leftIcon);
|
|
left->setIconSize(QSize(23,23));
|
|
left->setFocusPolicy(Qt::NoFocus);
|
|
left->hide(); // don't show until we have >1 widgets
|
|
titleLayout->addWidget(left);
|
|
connect(left, SIGNAL(clicked()), this, SLOT(scrollLeft()));
|
|
|
|
titleLabel = new GcLabel("No Title Set");
|
|
titleLabel->setAutoFillBackground(false);
|
|
titleLabel->setFixedHeight(23);
|
|
|
|
// menu bar in the middle of the buttons
|
|
titleLayout->addStretch();
|
|
titleLayout->addWidget(titleLabel);
|
|
titleLayout->addStretch();
|
|
|
|
right = new QToolButton(this);
|
|
right->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
|
right->setAutoFillBackground(false);
|
|
right->setFixedSize(20,20);
|
|
right->setIcon(rightIcon);
|
|
right->setIconSize(QSize(20,20));
|
|
right->setFocusPolicy(Qt::NoFocus);
|
|
right->hide();
|
|
titleLayout->addWidget(right);
|
|
connect(right, SIGNAL(clicked()), this, SLOT(scrollRight()));
|
|
|
|
stack = new QStackedWidget(this);
|
|
stack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
mlayout->addWidget(stack);
|
|
|
|
// trap resize / mouse events
|
|
m_infocus = true;
|
|
m_showMenu = false;
|
|
m_isEditing = true;
|
|
installEventFilter(parent);
|
|
|
|
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
|
|
|
// setup colors
|
|
configChanged(CONFIG_APPEARANCE);
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::configChanged(qint32)
|
|
{
|
|
if (GCColor::isFlat()) {
|
|
titleLabel->setStyleSheet(QString("color: %1;").arg(GCColor::invertColor(GColor(CCHROME)).name()));
|
|
} else {
|
|
titleLabel->setStyleSheet("color: black;");
|
|
}
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::addWidget(QString title, QWidget *widget)
|
|
{
|
|
// we want this one
|
|
//widget->setParent(this);
|
|
//widget->releaseMouse();
|
|
//widget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
|
|
|
// add to list
|
|
items << GcOverlayWidgetItem(title, widget);
|
|
stack->addWidget(widget);
|
|
|
|
// but don't select it
|
|
// unless its the first one
|
|
if (items.count() == 1) setCurrentIndex(0);
|
|
|
|
// set cursors visible/hidden if needed
|
|
setCursors();
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::setCurrentIndex(int index)
|
|
{
|
|
if (initial || index != stack->currentIndex()) {
|
|
titleLabel->setText(items.at(index).name);
|
|
stack->setCurrentIndex(index);
|
|
|
|
// tell everyone we changed
|
|
emit currentIndexChanged(index);
|
|
|
|
initial = false;
|
|
}
|
|
}
|
|
|
|
int
|
|
GcOverlayWidget::currentIndex() const
|
|
{
|
|
return stack->currentIndex();
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::setCursors()
|
|
{
|
|
if (items.count() > 1) {
|
|
|
|
left->show();
|
|
right->show();
|
|
|
|
} else {
|
|
|
|
left->hide();
|
|
right->hide();
|
|
}
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::scrollRight()
|
|
{
|
|
int rightIndex = stack->currentIndex() + 1;
|
|
if (stack->count() > rightIndex) setCurrentIndex(rightIndex);
|
|
else setCurrentIndex(0);
|
|
}
|
|
|
|
void
|
|
GcOverlayWidget::scrollLeft()
|
|
{
|
|
if (stack->currentIndex() > 0) setCurrentIndex(stack->currentIndex() -1);
|
|
else setCurrentIndex(stack->count() -1);
|
|
}
|
|
|
|
GcOverlayWidget::~GcOverlayWidget() {}
|
|
|
|
void
|
|
GcOverlayWidget::paintEvent (QPaintEvent *event)
|
|
{
|
|
// paint the darn thing!
|
|
paintBackground(event);
|
|
QWidget::paintEvent(event);
|
|
}
|
|
|
|
// paint is the same as sidebar
|
|
void
|
|
GcOverlayWidget::paintBackground(QPaintEvent *)
|
|
{
|
|
// setup a painter and the area to paint
|
|
QPainter painter(this);
|
|
|
|
painter.save();
|
|
QRect all(0,0,width(),height());
|
|
QRect boundary(0,0,width()-1,height()-1);
|
|
|
|
painter.fillRect(all, GColor(CPLOTBACKGROUND));
|
|
painter.setPen(QPen(Qt::darkGray));
|
|
painter.drawRect(boundary);
|
|
|
|
// linear gradients
|
|
QLinearGradient active = GCColor::linearGradient(23, true);
|
|
QLinearGradient inactive = GCColor::linearGradient(23, false);
|
|
|
|
// title
|
|
QRect title(1,1,width()-2,22);
|
|
painter.fillRect(title, QColor(Qt::white));
|
|
painter.fillRect(title, isActiveWindow() ? active : inactive);
|
|
|
|
if (!GCColor::isFlat()) {
|
|
QPen black(QColor(100,100,100,200));
|
|
painter.setPen(black);
|
|
painter.drawLine(0,22, width()-1, 22);
|
|
|
|
//QPen gray(QColor(230,230,230));
|
|
//painter.setPen(gray);
|
|
//painter.drawLine(0,0, width()-1, 0);
|
|
}
|
|
|
|
painter.restore();
|
|
}
|
|
|
|
void GcOverlayWidget::focusInEvent(QFocusEvent *)
|
|
{
|
|
m_infocus = true;
|
|
parentWidget()->installEventFilter(this);
|
|
parentWidget()->repaint();
|
|
emit inFocus(true);
|
|
}
|
|
|
|
void GcOverlayWidget::focusOutEvent(QFocusEvent *)
|
|
{
|
|
if (!m_isEditing) return;
|
|
if (m_showMenu) return;
|
|
mode = none;
|
|
emit outFocus(false);
|
|
m_infocus = false;
|
|
}
|
|
|
|
bool GcOverlayWidget::eventFilter( QObject *obj, QEvent *evt )
|
|
{
|
|
//return QWidget::eventFilter(obj, evt);
|
|
if (m_infocus) {
|
|
QWidget *w = parentWidget();
|
|
|
|
if (w == obj && evt->type()==QEvent::Paint) {
|
|
#if 0
|
|
QPainter painter(w);
|
|
QPoint p = this->mapTo(w,QPoint(-3,-3));
|
|
QPoint LT = w->mapFrom(w,p);
|
|
QPoint LB = w->mapFrom(w,QPoint(p.x(),p.y()+this->height()));
|
|
QPoint RB = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()+this->height()));
|
|
QPoint RT = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()));
|
|
|
|
painter.fillRect(LT.x(),LT.y(),6,6,QColor("black"));
|
|
painter.fillRect(LB.x(),LB.y(),6,6,QColor("black"));
|
|
painter.fillRect(RB.x(),RB.y(),6,6,QColor("black"));
|
|
painter.fillRect(RT.x(),RT.y(),6,6,QColor("black"));
|
|
#endif
|
|
return QWidget::eventFilter(obj,evt);
|
|
}
|
|
}
|
|
return QWidget::eventFilter(obj, evt);
|
|
}
|
|
|
|
void GcOverlayWidget::mousePressEvent(QMouseEvent *e)
|
|
{
|
|
position = QPoint(e->globalX()-geometry().x(), e->globalY()-geometry().y());
|
|
if (!m_isEditing) return;
|
|
if (!m_infocus) return;
|
|
//QWidget::mouseMoveEvent(e);
|
|
if (!e->buttons() & Qt::LeftButton) {
|
|
setCursorShape(e->pos());
|
|
return;
|
|
}
|
|
|
|
if(e->button()==Qt::RightButton) {
|
|
//e->accept();
|
|
}
|
|
}
|
|
|
|
void GcOverlayWidget::keyPressEvent(QKeyEvent *e)
|
|
{
|
|
if (!m_isEditing) return;
|
|
if (e->key() == Qt::Key_Delete) {
|
|
//this->deleteLater();
|
|
}
|
|
|
|
if (QApplication::keyboardModifiers() == Qt::ControlModifier) {
|
|
QPoint newPos(x(),y());
|
|
if (e->key() == Qt::Key_Up) newPos.setY(newPos.y()-1);
|
|
if (e->key() == Qt::Key_Down) newPos.setY(newPos.y()+1);
|
|
if (e->key() == Qt::Key_Left) newPos.setX(newPos.x()-1);
|
|
if (e->key() == Qt::Key_Right) newPos.setX(newPos.x()+1);
|
|
move(newPos);
|
|
}
|
|
if (QApplication::keyboardModifiers() == Qt::ShiftModifier) {
|
|
if (e->key() == Qt::Key_Up) resize(width(),height()-1);
|
|
if (e->key() == Qt::Key_Down) resize(width(),height()+1);
|
|
if (e->key() == Qt::Key_Left) resize(width()-1,height());
|
|
if (e->key() == Qt::Key_Right) resize(width()+1,height());
|
|
}
|
|
emit newGeometry(geometry());
|
|
}
|
|
|
|
void GcOverlayWidget::setCursorShape(const QPoint &e_pos)
|
|
{
|
|
const int diff = 6;
|
|
if (
|
|
//Left-Bottom
|
|
((e_pos.y() > y() + height() - diff) && //Bottom
|
|
(e_pos.x() < x()+diff)) || //Left
|
|
//Right-Bottom
|
|
((e_pos.y() > y() + height() - diff) && //Bottom
|
|
(e_pos.x() > x() + width() - diff)) || //Right
|
|
//Left-Top
|
|
((e_pos.y() < y() + diff) && //Top
|
|
(e_pos.x() < x() + diff)) || //Left
|
|
//Right-Top
|
|
((e_pos.y() < y() + diff) && //Top
|
|
(e_pos.x() > x() + width() - diff)) //Right
|
|
)
|
|
{
|
|
//Left-Bottom
|
|
if ((e_pos.y() > y() + height() - diff) && //Bottom
|
|
(e_pos.x() < x() + diff)) { //Left
|
|
mode = resizebl;
|
|
setCursor(QCursor(Qt::SizeBDiagCursor));
|
|
}
|
|
//Right-Bottom
|
|
if ((e_pos.y() > y() + height() - diff) && //Bottom
|
|
(e_pos.x() > x() + width() - diff)) { //Right
|
|
mode = resizebr;
|
|
setCursor(QCursor(Qt::SizeFDiagCursor));
|
|
}
|
|
//Left-Top
|
|
if ((e_pos.y() < y() + diff) && //Top
|
|
(e_pos.x() < x() + diff)) { //Left
|
|
mode = resizetl;
|
|
setCursor(QCursor(Qt::SizeFDiagCursor));
|
|
}
|
|
//Right-Top
|
|
if ((e_pos.y() < y() + diff) && //Top
|
|
(e_pos.x() > x() + width() - diff)) { //Right
|
|
mode = resizetr;
|
|
setCursor(QCursor(Qt::SizeBDiagCursor));
|
|
}
|
|
}
|
|
// проверка положения курсора по горизонтали
|
|
else if ((e_pos.x() < x() + diff) || //Left
|
|
((e_pos.x() > x() + width() - diff))) { //Right
|
|
if (e_pos.x() < x() + diff) { //Left
|
|
setCursor(QCursor(Qt::SizeHorCursor));
|
|
mode = resizel;
|
|
} else { //Right
|
|
setCursor(QCursor(Qt::SizeHorCursor));
|
|
mode = resizer;
|
|
}
|
|
}
|
|
// проверка положения курсора по вертикали
|
|
else if (((e_pos.y() > y() + height() - diff)) || //Bottom
|
|
(e_pos.y() < y() + diff)) { //Top
|
|
if (e_pos.y() < y() + diff) { //Top
|
|
setCursor(QCursor(Qt::SizeVerCursor));
|
|
mode = resizet;
|
|
} else { //Bottom
|
|
setCursor(QCursor(Qt::SizeVerCursor));
|
|
mode = resizeb;
|
|
}
|
|
} else if (e_pos.y() <= y() + 23 ) {
|
|
setCursor(QCursor(Qt::ArrowCursor));
|
|
mode = moving;
|
|
}
|
|
}
|
|
|
|
void GcOverlayWidget::mouseReleaseEvent(QMouseEvent *e)
|
|
{
|
|
QWidget::mouseReleaseEvent(e);
|
|
}
|
|
|
|
void GcOverlayWidget::mouseMoveEvent(QMouseEvent *e)
|
|
{
|
|
QWidget::mouseMoveEvent(e);
|
|
if (!m_isEditing) return;
|
|
if (!m_infocus) return;
|
|
if (!e->buttons() & Qt::LeftButton) {
|
|
QPoint p = QPoint(e->x()+geometry().x(), e->y()+geometry().y());
|
|
setCursorShape(p);
|
|
return;
|
|
}
|
|
|
|
if (mode == moving && e->buttons() && Qt::LeftButton) {
|
|
QPoint toMove = e->globalPos() - position;
|
|
if (toMove.x() < 0) return;
|
|
if (toMove.y() < 0) return;
|
|
if (toMove.x() > parentWidget()->width()-width()) return;
|
|
move(toMove);
|
|
emit newGeometry(geometry());
|
|
parentWidget()->repaint();
|
|
return;
|
|
}
|
|
if ((mode != moving) && e->buttons() && Qt::LeftButton) {
|
|
switch (mode){
|
|
case resizetl: { //Left-Top
|
|
int newwidth = e->globalX() - position.x() - geometry().x();
|
|
int newheight = e->globalY() - position.y() - geometry().y();
|
|
QPoint toMove = e->globalPos() - position;
|
|
resize(geometry().width()-newwidth,geometry().height()-newheight);
|
|
move(toMove.x(),toMove.y());
|
|
break;
|
|
}
|
|
case resizetr: { //Right-Top
|
|
int newheight = e->globalY() - position.y() - geometry().y();
|
|
QPoint toMove = e->globalPos() - position;
|
|
resize(e->x(),geometry().height()-newheight);
|
|
move(x(),toMove.y());
|
|
break;
|
|
}
|
|
case resizebl: { //Left-Bottom
|
|
int newwidth = e->globalX() - position.x() - geometry().x();
|
|
QPoint toMove = e->globalPos() - position;
|
|
resize(geometry().width()-newwidth,e->y());
|
|
move(toMove.x(),y());
|
|
break;
|
|
}
|
|
case resizeb: { //Bottom
|
|
resize(width(),e->y()); break;}
|
|
case resizel: { //Left
|
|
int newwidth = e->globalX() - position.x() - geometry().x();
|
|
QPoint toMove = e->globalPos() - position;
|
|
resize(geometry().width()-newwidth,height());
|
|
move(toMove.x(),y());
|
|
break;
|
|
}
|
|
case resizet: { //Top
|
|
int newheight = e->globalY() - position.y() - geometry().y();
|
|
QPoint toMove = e->globalPos() - position;
|
|
resize(width(),geometry().height()-newheight);
|
|
move(x(),toMove.y());
|
|
break;
|
|
}
|
|
case resizer: { //Right
|
|
resize(e->x(),height()); break;}
|
|
case resizebr: { //Right-Bottom
|
|
resize(e->x(),e->y()); break;}
|
|
}
|
|
parentWidget()->repaint();
|
|
}
|
|
emit newGeometry(geometry());
|
|
//QWidget::mouseMoveEvent(e);
|
|
}
|