/* * 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); }