/* Copyright (C) 2006 Oswald Buddenhagen 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 Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "positioner.h" #include #include #include #include #include #include #include #define TOTAL_WIDTH 200 #define TOTAL_HEIGHT 186 #define ACTIVE_X 23 #define ACTIVE_Y 14 #define ACTIVE_WIDTH 151 #define ACTIVE_HEIGHT 115 #define MARGIN 10 #define SNAP 10 #define STEP 5 static void fit(int &p) { if (p < SNAP) p = 0; else if (p > 100 - SNAP) p = 100; else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2) p = 50; } static void step(int &p, int d) { if (p < SNAP) p = 0 + (d + 1) * SNAP / 2; else if (p > 100 - SNAP) p = 100 + (d - 1) * SNAP / 2; else if (p > 50 - SNAP / 2 && p < 50 + SNAP / 2) p = 50 + d * SNAP / 2; else { p += d * STEP; fit(p); } } Positioner::Positioner(QWidget *parent) : ScreenPreviewWidget(parent) , m_x(50) , m_y(50) { QDesktopWidget *desktop = QApplication::desktop(); setRatio((qreal)desktop->width() / (qreal)desktop->height()); m_anchor = QPixmap(KStandardDirs::locate("data", "kcontrol/pics/anchor.png")); setFocusPolicy(Qt::StrongFocus); const int fw = MARGIN * 2; setMinimumSize(TOTAL_WIDTH + fw, TOTAL_HEIGHT + fw); setMaximumWidth(400); QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Expanding); sp.setHeightForWidth(true); setSizePolicy(sp); m_frame = new QFrame(this); m_screen = new QWidget(m_frame); m_screen->setAutoFillBackground(true); QPalette pal; pal.setColor(QPalette::Background, QColor(255, 255, 255, 128)); m_screen->setPalette(pal); m_dlg = new QFrame(m_screen); m_dlg->setFrameStyle(QFrame::Panel | QFrame::Raised); m_dlg->setAutoFillBackground(true); QPalette pal2; pal2.setBrush(QPalette::Background, pal2.brush(QPalette::Normal, QPalette::Background)); m_dlg->setPalette(pal2); m_ptr = new QLabel(m_screen); m_ptr->setPixmap(m_anchor); QString wts(i18n( "Drag the anchor to move the center of the dialog to the desired position. " "Keyboard control is possible as well: Use the arrow keys or Home to center. " "Note that the actual proportions of the dialog are probably different.")); m_frame->setWhatsThis(wts); m_screen->setWhatsThis(wts); m_ptr->setWhatsThis(wts); } void Positioner::setPosition(int x, int y) { m_x = x; m_y = y; updateHandle(); } int Positioner::heightForWidth(int w) const { const int fw = MARGIN * 2; return ((w - fw) * TOTAL_HEIGHT + (TOTAL_WIDTH / 2)) / TOTAL_WIDTH + fw; } void Positioner::updateHandle() { int px = m_screen->size().width() * m_x / 100; int py = m_screen->size().height() * m_y / 100; m_ptr->setGeometry(px - m_anchor.width() / 2, py - m_anchor.height() / 2, m_anchor.width(), m_anchor.height()); int sw = m_screen->width() * 2 / 5; int sh = m_screen->height() * 2 / 5; QRect grt(px - sw / 2, py - sh / 2, sw, sh); int di; if ((di = m_screen->size().width() - grt.right()) < 0) grt.translate(di, 0); if ((di = - grt.left()) > 0) grt.translate(di, 0); if ((di = m_screen->size().height() - grt.bottom()) < 0) grt.translate(0, di); if ((di = - grt.top()) > 0) grt.translate(0, di); m_dlg->setGeometry(grt); } void Positioner::resizeEvent(QResizeEvent *event) { ScreenPreviewWidget::resizeEvent(event); const int fw = MARGIN * 2; QSize rs(TOTAL_WIDTH, TOTAL_HEIGHT); rs.scale(size() - QSize(fw, fw), Qt::KeepAspectRatio); m_frame->setGeometry(0, 0, rs.width() + fw, rs.height() + fw); m_frame->resize(size()); m_screen->setGeometry(previewRect()); updateHandle(); } void Positioner::focusInEvent(QFocusEvent *) { m_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken); } void Positioner::focusOutEvent(QFocusEvent *) { m_frame->setFrameStyle(QFrame::NoFrame); } void Positioner::mousePressEvent(QMouseEvent *event) { QPoint cp = event->pos() - m_screen->pos(); if (m_ptr->geometry().contains(cp)) m_delta = m_ptr->geometry().center() - cp; else m_delta.setX(-1); } void Positioner::mouseMoveEvent(QMouseEvent *event) { if (m_delta.x() != -1) { QPoint cp = event->pos() - m_screen->pos() + m_delta; m_x = cp.x() * 100 / m_screen->size().width(); m_y = cp.y() * 100 / m_screen->size().height(); fit(m_x); fit(m_y); updateHandle(); emit positionChanged(); } } void Positioner::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Home: m_x = m_y = 50; break; case Qt::Key_Left: step(m_x, -1); break; case Qt::Key_Right: step(m_x, 1); break; case Qt::Key_Up: step(m_y, -1); break; case Qt::Key_Down: step(m_y, 1); break; default: event->ignore(); return; } updateHandle(); emit positionChanged(); event->accept(); } #include "positioner.moc"