kde-workspace/plasma/shells/plasma-desktop/panelcontroller.cpp
Ivailo Monev be2411566c plasma: remove unused qx11info_x11 header inclusion
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-06-18 19:54:17 +03:00

996 lines
35 KiB
C++

/*
* Copyright 2008 Marco Martin <notmart@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "panelcontroller.h"
#include <QAction>
#include <QApplication>
#include <QBoxLayout>
#include <QVBoxLayout>
#include <QFrame>
#include <QLabel>
#include <QtGui/qevent.h>
#include <QPainter>
#include <QToolButton>
#include <KColorUtils>
#include <KIconLoader>
#include <KIcon>
#include <kwindowsystem.h>
#include <netwm.h>
#include <Plasma/Containment>
#include <Plasma/Corona>
#include <Plasma/PaintUtils>
#include <Plasma/Theme>
#include <Plasma/FrameSvg>
#include <Plasma/Dialog>
#include "desktopcorona.h"
#include "plasmaapp.h"
#include "positioningruler.h"
#include "toolbutton.h"
#include "widgetsexplorer/widgetexplorer.h"
class PanelController::ButtonGroup: public QFrame
{
public:
ButtonGroup(QWidget *parent)
: QFrame(parent)
{
background = new Plasma::FrameSvg(this);
background->setImagePath("widgets/frame");
background->setElementPrefix("plain");
}
void paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
background->resizeFrame(size());
background->paintFrame(&painter);
}
Plasma::FrameSvg *background;
};
static const int MINIMUM_HEIGHT = 10;
PanelController::PanelController(QWidget* parent)
: ControllerWindow(parent),
m_extLayout(0),
m_layout(0),
m_dragging(NoElement),
m_startDragControllerPos(0,0),
m_startDragMousePos(0,0),
m_optionsDialog(0),
m_leftAlignTool(0),
m_centerAlignTool(0),
m_rightAlignTool(0),
m_drawMoveHint(false)
{
Q_UNUSED(parent)
setAttribute(Qt::WA_TranslucentBackground);
QPalette pal = palette();
pal.setBrush(backgroundRole(), Qt::transparent);
setPalette(pal);
m_iconSvg = new Plasma::Svg(this);
m_iconSvg->setImagePath("widgets/configuration-icons");
m_iconSvg->setContainsMultipleImages(true);
m_iconSvg->resize(IconSize(KIconLoader::Small), IconSize(KIconLoader::Small));
//setWindowFlags(Qt::Popup);
//setWindowFlags(Qt::FramelessWindowHint);
KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
setAttribute(Qt::WA_DeleteOnClose);
setFocus(Qt::ActiveWindowFocusReason);
//layout setup
m_configWidget = new QWidget(this);
layout()->addWidget(m_configWidget);
m_extLayout = new QBoxLayout(QBoxLayout::TopToBottom, m_configWidget);
m_extLayout->setContentsMargins(0, background()->marginSize(Plasma::TopMargin), 0, 0);
m_layout = new QBoxLayout(QBoxLayout::LeftToRight);
m_layout->setContentsMargins(0, 0, 0, 0);
if (QApplication::layoutDirection() == Qt::RightToLeft) {
m_layout->setDirection(QBoxLayout::RightToLeft);
} else {
m_layout->setDirection(QBoxLayout::LeftToRight);
}
m_layout->addStretch();
m_extLayout->addLayout(m_layout);
//Add buttons
//alignment
//first the container
QFrame *alignFrame = new ButtonGroup(m_configWidget);
QVBoxLayout *alignLayout = new QVBoxLayout(alignFrame);
m_alignLabel = new QLabel(i18n("Panel Alignment"), m_configWidget);
alignLayout->addWidget(m_alignLabel);
m_leftAlignTool = addTool("format-justify-left", i18n("Left"), alignFrame, Qt::ToolButtonTextBesideIcon, true);
m_leftAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
alignLayout->addWidget(m_leftAlignTool);
m_leftAlignTool->setChecked(true);
connect(m_leftAlignTool, SIGNAL(toggled(bool)), this, SLOT(alignToggled(bool)));
m_centerAlignTool = addTool("format-justify-center", i18n("Center"), alignFrame, Qt::ToolButtonTextBesideIcon, true);
m_centerAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
alignLayout->addWidget(m_centerAlignTool);
connect(m_centerAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
m_rightAlignTool = addTool("format-justify-right", i18n("Right"), alignFrame, Qt::ToolButtonTextBesideIcon, true);
m_rightAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
alignLayout->addWidget(m_rightAlignTool);
connect(m_rightAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
//Panel mode
//first the container
QFrame *modeFrame = new ButtonGroup(m_configWidget);
QVBoxLayout *modeLayout = new QVBoxLayout(modeFrame);
m_modeLabel = new QLabel(i18n("Visibility"), m_configWidget);
modeLayout->addWidget(m_modeLabel);
m_normalPanelTool = addTool("layer-visible-on", i18n("Always visible"), modeFrame, Qt::ToolButtonTextBesideIcon, true);
m_normalPanelTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
modeLayout->addWidget(m_normalPanelTool);
connect(m_normalPanelTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
m_autoHideTool = addTool("video-display", i18n("Auto-hide"), modeFrame, Qt::ToolButtonTextBesideIcon, true);
m_autoHideTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
modeLayout->addWidget(m_autoHideTool);
connect(m_autoHideTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
m_underWindowsTool = addTool("view-fullscreen", i18n("Windows can cover"), modeFrame, Qt::ToolButtonTextBesideIcon, true);
m_underWindowsTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
modeLayout->addWidget(m_underWindowsTool);
connect(m_underWindowsTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
m_overWindowsTool = addTool("view-restore", i18n("Windows go below"), modeFrame, Qt::ToolButtonTextBesideIcon, true);
m_overWindowsTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
modeLayout->addWidget(m_overWindowsTool);
connect(m_overWindowsTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
m_layout->addStretch();
m_moveTool = addTool(QString(), i18n("Screen Edge"), m_configWidget);
m_moveTool->setIcon(m_iconSvg->pixmap("move"));
m_moveTool->installEventFilter(this);
m_moveTool->setCursor(Qt::SizeAllCursor);
m_moveTool->setToolTip(i18n("Press left mouse button and drag to a screen edge to change panel edge"));
m_layout->addWidget(m_moveTool);
m_sizeTool = addTool(QString(), i18n("Height"), m_configWidget);
m_sizeTool->installEventFilter(this);
m_sizeTool->setCursor(Qt::SizeVerCursor);
m_sizeTool->setToolTip(i18n("Press left mouse button and drag vertically to change panel height"));
m_layout->addWidget(m_sizeTool);
m_layout->addStretch();
//other buttons
m_layout->addSpacing(20);
//Settings popup menu
m_settingsTool = addTool("configure", i18n("More Settings"), m_configWidget);
m_settingsTool->setToolTip(i18n("Show more options about panel alignment, visibility and other settings"));
m_layout->addWidget(m_settingsTool);
connect(m_settingsTool, SIGNAL(pressed()), this, SLOT(settingsPopup()));
m_optionsDialog = new Plasma::Dialog(0); // don't pass in a parent; breaks with some lesser WMs
m_optionsDialog->installEventFilter(this);
KWindowSystem::setState(m_optionsDialog->winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
m_optDialogLayout = new QVBoxLayout(m_optionsDialog);
m_optDialogLayout->setMargin(0);
m_optDialogLayout->addWidget(alignFrame);
m_optDialogLayout->addWidget(modeFrame);
m_expandTool = addTool(QString(), i18n("Maximize Panel"), m_configWidget);
m_expandTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
m_expandTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_optDialogLayout->addWidget(m_expandTool);
connect(m_expandTool, SIGNAL(clicked()), this, SLOT(maximizePanel()));
m_closeControllerTool = addTool("window-close", i18n("Close this configuration window"), m_configWidget, Qt::ToolButtonIconOnly, false);
m_layout->addWidget(m_closeControllerTool);
connect(m_closeControllerTool, SIGNAL(clicked()), this, SLOT(close()));
m_ruler = new PositioningRuler(m_configWidget);
connect(m_ruler, SIGNAL(rulersMoved(int,int,int)), this, SLOT(rulersMoved(int,int,int)));
m_extLayout->addWidget(m_ruler);
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(themeChanged()));
themeChanged();
}
PanelController::~PanelController()
{
//TODO: should we try and only call this when something has actually been
// altered that we care about?
PlasmaApp::self()->corona()->requestConfigSync();
delete m_optionsDialog;
}
void PanelController::setContainment(Plasma::Containment *c)
{
if (!c) {
return;
}
ControllerWindow::setContainment(c);
PlasmaApp::self()->hideController(containment()->screen());
QWidget *child;
while (!m_actionWidgets.isEmpty()) {
child = m_actionWidgets.first();
//try to remove from both layouts
m_layout->removeWidget(child);
m_optDialogLayout->removeWidget(child);
m_actionWidgets.removeFirst();
child->deleteLater();
}
int insertIndex = m_layout->count() - 3;
QAction *action = containment()->action("add widgets");
if (action && action->isEnabled()) {
ToolButton *addWidgetTool = addTool(action, this);
m_layout->insertWidget(insertIndex, addWidgetTool);
++insertIndex;
connect(containment(), SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(switchToWidgetExplorer()));
}
action = new QAction(i18n("Add Spacer"), this);
action->setIcon(KIcon("distribute-horizontal-x"));
ToolButton *addSpaceTool = addTool(action, this);
addSpaceTool->setToolTip(i18n("Add a spacer to the panel useful to add some space between two widgets"));
m_layout->insertWidget(insertIndex, addSpaceTool);
++insertIndex;
connect(action, SIGNAL(triggered()), this, SLOT(addSpace()));
action = containment()->action("lock widgets");
if (action && action->isEnabled()) {
ToolButton *lockWidgetsTool = addTool(action, this);
lockWidgetsTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_optDialogLayout->addWidget(lockWidgetsTool, m_optDialogLayout->count() - 2);
connect(lockWidgetsTool, SIGNAL(clicked()), m_optionsDialog, SLOT(hide()));
connect(lockWidgetsTool, SIGNAL(clicked()), this, SLOT(hide()));
}
action = containment()->action("remove");
if (action && action->isEnabled()) {
ToolButton *removePanelTool = addTool(action, this);
removePanelTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_optDialogLayout->insertWidget(insertIndex, removePanelTool);
connect(removePanelTool, SIGNAL(clicked()), this, SLOT(hide()));
}
syncRuler();
}
void PanelController::moveEvent(QMoveEvent *event)
{
//FIXME: this is a glorious hack: it causes the window to be positioned correctly after kwin positions it incorrectly.
//TODO: the proper way to do is to give a window type specific to the panel controller, that gets positioned correctly
if (((location() == Plasma::BottomEdge || location() == Plasma::TopEdge) &&
event->oldPos().x() != event->pos().x()) ||
((location() == Plasma::LeftEdge || location() == Plasma::RightEdge) &&
event->oldPos().y() != event->pos().y())) {
emit offsetChanged(m_ruler->offset());
}
ControllerWindow::moveEvent(event);
}
void PanelController::showEvent(QShowEvent *event)
{
if (containment()) {
setMaximumSize(PlasmaApp::self()->corona()->screenGeometry(containment()->screen()).size());
syncToLocation();
}
ControllerWindow::showEvent(event);
}
void PanelController::setLocation(const Plasma::Location &loc)
{
if (location() == loc) {
return;
}
ControllerWindow::setLocation(loc);
syncToLocation();
}
void PanelController::syncToLocation()
{
const Plasma::Location loc = location();
m_ruler->setLocation(loc);
//The external layout gwts auto flipped when QApplication::layoutDirection() changes
//and it shouldn't, the internal one no and it should, so i must manually invert both
switch (loc) {
case Plasma::LeftEdge:
if (QApplication::layoutDirection() == Qt::RightToLeft) {
m_extLayout->setDirection(QBoxLayout::LeftToRight);
m_extLayout->setContentsMargins(background()->marginSize(Plasma::LeftMargin), 0, 0, 0);
} else {
m_extLayout->setDirection(QBoxLayout::RightToLeft);
m_extLayout->setContentsMargins(0, 0, background()->marginSize(Plasma::RightMargin), 0);
}
m_layout->setDirection(QBoxLayout::TopToBottom);
break;
case Plasma::RightEdge:
if (QApplication::layoutDirection() == Qt::RightToLeft) {
m_extLayout->setDirection(QBoxLayout::RightToLeft);
m_extLayout->setContentsMargins(0, 0, background()->marginSize(Plasma::RightMargin), 0);
} else {
m_extLayout->setDirection(QBoxLayout::LeftToRight);
m_extLayout->setContentsMargins(background()->marginSize(Plasma::LeftMargin), 0, 0, 0);
}
m_layout->setDirection(QBoxLayout::TopToBottom);
break;
case Plasma::TopEdge:
if (QApplication::layoutDirection() == Qt::RightToLeft) {
m_layout->setDirection(QBoxLayout::RightToLeft);
} else {
m_layout->setDirection(QBoxLayout::LeftToRight);
}
m_extLayout->setDirection(QBoxLayout::BottomToTop);
m_extLayout->setContentsMargins(0, 0, 0, background()->marginSize(Plasma::BottomMargin));
break;
case Plasma::BottomEdge:
default:
if (QApplication::layoutDirection() == Qt::RightToLeft) {
m_layout->setDirection(QBoxLayout::RightToLeft);
} else {
m_layout->setDirection(QBoxLayout::LeftToRight);
}
m_extLayout->setDirection(QBoxLayout::TopToBottom);
m_extLayout->setContentsMargins(0, background()->marginSize(Plasma::TopMargin), 0, 0);
break;
}
switch (loc) {
case Plasma::LeftEdge:
case Plasma::RightEdge:
m_sizeTool->setCursor(Qt::SizeHorCursor);
m_sizeTool->setText(i18n("Width"));
m_sizeTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
m_expandTool->setIcon(m_iconSvg->pixmap("size-vertical"));
m_leftAlignTool->setText(i18n("Top"));
m_rightAlignTool->setText(i18n("Bottom"));
break;
case Plasma::TopEdge:
case Plasma::BottomEdge:
default:
m_sizeTool->setCursor(Qt::SizeVerCursor);
m_sizeTool->setText(i18n("Height"));
m_sizeTool->setIcon(m_iconSvg->pixmap("size-vertical"));
m_expandTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
m_leftAlignTool->setText(i18n("Left"));
m_rightAlignTool->setText(i18n("Right"));
}
syncRuler();
QSize rulerSize = m_ruler->sizeHint();
m_ruler->hide();
m_ruler->setFixedSize(rulerSize);
m_ruler->show();
updateGeometry();
setMinimumSize(QSize(0, 0));
setMaximumSize(sizeHint());
resize(sizeHint());
}
void PanelController::setOffset(int newOffset)
{
if (newOffset != m_ruler->offset()) {
m_ruler->setOffset(newOffset);
}
}
int PanelController::offset() const
{
return m_ruler->offset();
}
void PanelController::setAlignment(const Qt::Alignment &newAlignment)
{
if (newAlignment != m_ruler->alignment()) {
if (newAlignment == Qt::AlignLeft) {
m_leftAlignTool->setChecked(true);
} else if (newAlignment == Qt::AlignCenter) {
m_centerAlignTool->setChecked(true);
} else if (newAlignment == Qt::AlignRight) {
m_rightAlignTool->setChecked(true);
}
m_ruler->setAlignment(newAlignment);
}
}
Qt::Alignment PanelController::alignment() const
{
return m_ruler->alignment();
}
void PanelController::setVisibilityMode(PanelView::VisibilityMode mode)
{
switch (mode) {
case PanelView::AutoHide:
m_autoHideTool->setChecked(true);
break;
case PanelView::LetWindowsCover:
m_underWindowsTool->setChecked(true);
break;
case PanelView::WindowsGoBelow:
m_overWindowsTool->setChecked(true);
break;
case PanelView::NormalPanel:
default:
m_normalPanelTool->setChecked(true);
break;
}
}
PanelView::VisibilityMode PanelController::panelVisibilityMode() const
{
if (m_underWindowsTool->isChecked()) {
return PanelView::LetWindowsCover;
} else if (m_overWindowsTool->isChecked()) {
return PanelView::WindowsGoBelow;
} else if (m_autoHideTool->isChecked()) {
return PanelView::AutoHide;
} else {
return PanelView::NormalPanel;
}
}
void PanelController::themeChanged()
{
QColor color = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
QPalette p = m_alignLabel->palette();
p.setColor(QPalette::Normal, QPalette::WindowText, color);
p.setColor(QPalette::Inactive, QPalette::WindowText, color);
m_alignLabel->setPalette(p);
m_modeLabel->setPalette(p);
m_sizeTool->setIcon(m_iconSvg->pixmap("move"));
if (orientation() == Qt::Horizontal) {
m_sizeTool->setIcon(m_iconSvg->pixmap("size-vertical"));
} else {
m_sizeTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
}
}
void PanelController::switchToWidgetExplorer()
{
m_configWidget->hide();
}
void PanelController::closeIfNotFocussed()
{
QWidget *widget = QApplication::activeWindow();
if (!widget || widget != m_optionsDialog) {
ControllerWindow::closeIfNotFocussed();
}
}
void PanelController::switchToController()
{
setGraphicsWidget(0);
m_configWidget->show();
syncToLocation();
}
bool PanelController::eventFilter(QObject *watched, QEvent *event)
{
ControllerWindow::eventFilter(watched, event);
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
m_lastPos = mouseEvent->globalPos();
}
if (watched == m_optionsDialog && event->type() == QEvent::WindowDeactivate && (!isControllerViewVisible())) {
if (!m_settingsTool->underMouse()) {
m_optionsDialog->hide();
}
if (!isActiveWindow()) {
close();
}
return true;
} else if (watched == m_moveTool) {
if (event->type() == QEvent::MouseButtonPress) {
m_dragging = MoveButtonElement;
m_moveTool->grabMouse();
} else if (event->type() == QEvent::MouseButtonRelease) {
m_dragging = NoElement;
m_moveTool->releaseMouse();
emit locationChanged(location());
} else if (event->type() == QEvent::MouseMove) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
mouseMoveFilter(mouseEvent);
}
} else if (watched == m_sizeTool) {
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
m_startDragMousePos = mouseEvent->globalPos();
m_startDragControllerPos = pos(); // the global position of the controller window
m_dragging = ResizeButtonElement;
} else if (event->type() == QEvent::MouseButtonRelease) {
//resets properties saved during the drag
m_startDragMousePos = QPoint(0, 0);
m_startDragControllerPos = QPoint(0, 0);
m_dragging = NoElement;
setCursor(Qt::ArrowCursor);
} else if (event->type() == QEvent::MouseMove) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
mouseMoveFilter(mouseEvent);
}
}
return false;
}
void PanelController::mouseMoveFilter(QMouseEvent *event)
{
if (m_dragging == NoElement || !containment()) {
return;
}
DesktopCorona *corona = PlasmaApp::self()->corona();
const QRect screenGeom = corona->screenGeometry(containment()->screen());
if (m_dragging == MoveButtonElement) {
if (!screenGeom.contains(event->globalPos())) {
//move panel to new screen if dragged there
int targetScreen = corona->screenId(event->globalPos());
//kDebug() << "Moving panel from screen" << containment()->screen() << "to screen" << targetScreen;
containment()->setScreen(targetScreen);
return;
}
if (location() == Plasma::BottomEdge || location() == Plasma::TopEdge) {
emit partialMove(QPoint(0, m_lastPos.y() - event->globalY()));
} else if (location() == Plasma::LeftEdge || location() == Plasma::RightEdge) {
emit partialMove(QPoint(m_lastPos.x() - event->globalX(), 0));
}
m_lastPos = event->globalPos();
//create a dead zone so you can go across the middle without having it hop to one side
float dzFactor = 0.35;
QPoint offset = QPoint(screenGeom.width()*dzFactor,screenGeom.height()*dzFactor);
QRect deadzone = QRect(screenGeom.topLeft()+offset, screenGeom.bottomRight()-offset);
if (deadzone.contains(event->globalPos())) {
//kDebug() << "In the deadzone:" << deadzone;
return;
}
const Plasma::Location oldLocation = containment()->location();
Plasma::Location newLocation = oldLocation;
float screenAspect = float(screenGeom.height())/screenGeom.width();
/* Use diagonal lines so we get predictable behavior when moving the panel
* y=topleft.y+(x-topleft.x)*aspectratio topright < bottomleft
* y=bottomleft.y-(x-topleft.x)*aspectratio topleft < bottomright
*/
if (event->globalY() < screenGeom.y()+(event->globalX()-screenGeom.x())*screenAspect) {
if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
if (containment()->location() == Plasma::TopEdge) {
return;
} else {
newLocation = Plasma::TopEdge;
}
} else if (containment()->location() == Plasma::RightEdge) {
return;
} else {
newLocation = Plasma::RightEdge;
}
} else {
if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
if (containment()->location() == Plasma::LeftEdge) {
return;
} else {
newLocation = Plasma::LeftEdge;
}
} else if(containment()->location() == Plasma::BottomEdge) {
return;
} else {
newLocation = Plasma::BottomEdge;
}
}
//If the orientation changed swap width and height
if (oldLocation != newLocation) {
emit locationChanged(newLocation);
}
return;
}
//Resize handle moved
switch (location()) {
case Plasma::LeftEdge: {
int newX = m_startDragControllerPos.x() + event->globalX() - m_startDragMousePos.x();
newX = qMax(newX, screenGeom.left() + MINIMUM_HEIGHT);
newX = qMin(newX, screenGeom.left() + screenGeom.width()/3);
move(newX, pos().y());
resizeFrameHeight(geometry().left() - screenGeom.left());
break;
}
case Plasma::RightEdge: {
int newX = m_startDragControllerPos.x() + event->globalX() - m_startDragMousePos.x();
newX = qMin(newX, screenGeom.right() - MINIMUM_HEIGHT - width());
newX = qMax(newX, screenGeom.left() + 2*(screenGeom.width()/3) - width());
move(newX, pos().y());
resizeFrameHeight(screenGeom.right() - geometry().right());
break;
}
case Plasma::TopEdge: {
int newY = m_startDragControllerPos.y() + event->globalY() - m_startDragMousePos.y();
newY = qMax(newY, screenGeom.top() + MINIMUM_HEIGHT);
newY = qMin(newY, screenGeom.top() + screenGeom.height()/3);
move(pos().x(), newY);
resizeFrameHeight(geometry().top() - screenGeom.top());
break;
}
case Plasma::BottomEdge:
default: {
int newY = m_startDragControllerPos.y() + event->globalY() - m_startDragMousePos.y();
newY = qMin(newY, screenGeom.bottom() - MINIMUM_HEIGHT - height());
newY = qMax(newY, screenGeom.top() + 2*(screenGeom.height()/3) - height());
move(pos().x(), newY);
resizeFrameHeight(screenGeom.bottom() - geometry().bottom());
break;
}
}
}
void PanelController::focusOutEvent(QFocusEvent * event)
{
Q_UNUSED(event)
if (!m_optionsDialog->isActiveWindow() && !isControllerViewVisible() && !isActiveWindow()) {
m_optionsDialog->hide();
close();
}
}
ToolButton *PanelController::addTool(QAction *action, QWidget *parent, Qt::ToolButtonStyle style)
{
ToolButton *tool = new ToolButton(parent);
tool->setToolButtonStyle(style);
tool->setAction(action);
m_actionWidgets.append(tool);
return tool;
}
ToolButton *PanelController::addTool(const QString iconName, const QString iconText, QWidget *parent, Qt::ToolButtonStyle style, bool checkButton)
{
//TODO take advantage of setDefaultAction using the containment's actions if possible
ToolButton *tool = new ToolButton(parent);
KIcon icon = KIcon(iconName);
if (!icon.isNull() && !iconName.isNull()) {
tool->setIcon(icon);
}
tool->setText(iconText);
tool->setToolButtonStyle(style);
if (style == Qt::ToolButtonIconOnly) {
tool->setToolTip(iconText);
}
tool->setCheckable(checkButton);
tool->setAutoExclusive(checkButton);
return tool;
}
void PanelController::resizeFrameHeight(const int newHeight)
{
if (!containment()) {
return;
}
switch (location()) {
case Plasma::LeftEdge:
case Plasma::RightEdge:
containment()->setMinimumSize(QSize(newHeight, (int)containment()->minimumSize().height()));
containment()->setMaximumSize(QSize(newHeight, (int)containment()->maximumSize().height()));
containment()->resize(QSize(newHeight, (int)containment()->size().height()));
break;
case Plasma::TopEdge:
case Plasma::BottomEdge:
default:
containment()->setMinimumSize(QSize((int)containment()->minimumSize().width(), newHeight));
containment()->setMaximumSize(QSize((int)containment()->maximumSize().width(), newHeight));
containment()->resize(QSize((int)containment()->size().width(), newHeight));
break;
}
}
void PanelController::rulersMoved(int offset, int minLength, int maxLength)
{
if (!containment()) {
return;
}
QSize preferredSize(containment()->preferredSize().toSize());
switch (location()) {
case Plasma::LeftEdge:
case Plasma::RightEdge:
containment()->resize(QSize((int)containment()->size().width(), qBound(minLength, preferredSize.height(), maxLength)));
containment()->setMinimumSize(QSize((int)containment()->minimumSize().width(), minLength));
containment()->setMaximumSize(QSize((int)containment()->maximumSize().width(), maxLength));
break;
case Plasma::TopEdge:
case Plasma::BottomEdge:
default:
containment()->resize(QSize(qBound(minLength, preferredSize.width(), maxLength), (int)containment()->size().height()));
containment()->setMinimumSize(QSize(minLength, (int)containment()->minimumSize().height()));
containment()->setMaximumSize(QSize(maxLength, (int)containment()->maximumSize().height()));
break;
}
emit offsetChanged(offset);
}
void PanelController::alignToggled(bool toggle)
{
if (!toggle) {
return;
}
if (sender() == m_leftAlignTool) {
emit alignmentChanged(Qt::AlignLeft);
m_ruler->setAlignment(Qt::AlignLeft);
} else if (sender() == m_centerAlignTool) {
emit alignmentChanged(Qt::AlignCenter);
m_ruler->setAlignment(Qt::AlignCenter);
} else if (sender() == m_rightAlignTool) {
emit alignmentChanged(Qt::AlignRight);
m_ruler->setAlignment(Qt::AlignRight);
}
emit offsetChanged(0);
m_ruler->setOffset(0);
}
void PanelController::panelVisibilityModeChanged(bool toggle)
{
if (!toggle) {
return;
}
if (sender() == m_normalPanelTool) {
emit panelVisibilityModeChanged(PanelView::NormalPanel);
} else if (sender() == m_autoHideTool) {
emit panelVisibilityModeChanged(PanelView::AutoHide);
} else if (sender() == m_underWindowsTool) {
emit panelVisibilityModeChanged(PanelView::LetWindowsCover);
} else if (sender() == m_overWindowsTool) {
emit panelVisibilityModeChanged(PanelView::WindowsGoBelow);
}
}
void PanelController::settingsPopup()
{
if (m_optionsDialog->isVisible()) {
m_optionsDialog->hide();
} else {
KWindowSystem::setState(m_optionsDialog->winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
QPoint pos = mapToGlobal(m_settingsTool->pos());
m_optionsDialog->layout()->activate();
m_optionsDialog->resize(m_optionsDialog->sizeHint());
QSize s = m_optionsDialog->size();
switch (location()) {
case Plasma::BottomEdge:
pos = QPoint(pos.x(), pos.y() - s.height());
break;
case Plasma::TopEdge:
pos = QPoint(pos.x(), pos.y() + m_settingsTool->size().height());
break;
case Plasma::LeftEdge:
pos = QPoint(pos.x() + m_settingsTool->size().width(), pos.y());
break;
case Plasma::RightEdge:
pos = QPoint(pos.x() - s.width(), pos.y());
break;
default:
if (pos.y() - s.height() > 0) {
pos = QPoint(pos.x(), pos.y() - s.height());
} else {
pos = QPoint(pos.x(), pos.y() + m_settingsTool->size().height());
}
}
const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
if (pos.rx() + s.width() > screenGeom.right()) {
pos.rx() -= ((pos.rx() + s.width()) - screenGeom.right());
}
if (pos.ry() + s.height() > screenGeom.bottom()) {
pos.ry() -= ((pos.ry() + s.height()) - screenGeom.bottom());
}
pos.rx() = qMax(0, pos.rx());
m_optionsDialog->move(pos);
m_optionsDialog->show();
}
}
void PanelController::syncRuler()
{
const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
switch (location()) {
case Plasma::LeftEdge:
case Plasma::RightEdge:
m_ruler->setAvailableLength(screenGeom.height());
m_ruler->setMaxLength(qMin((int)containment()->maximumSize().height(), screenGeom.height()));
m_ruler->setMinLength(containment()->minimumSize().height());
break;
case Plasma::TopEdge:
case Plasma::BottomEdge:
default:
m_ruler->setAvailableLength(screenGeom.width());
m_ruler->setMaxLength(qMin((int)containment()->maximumSize().width(), screenGeom.width()));
m_ruler->setMinLength(containment()->minimumSize().width());
break;
}
}
void PanelController::resizeEvent(QResizeEvent *event)
{
bool showText = true;
switch (location()) {
case Plasma::LeftEdge:
case Plasma::RightEdge:
showText = true;
break;
case Plasma::TopEdge:
case Plasma::BottomEdge:
default: {
const int screen = containment()->screen();
const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
QRegion availGeom(screenGeom);
QFontMetrics fm(QApplication::font());
QString wholeText;
//FIXME: better (and faster) way to do that?
for (int i=0; i < m_layout->count(); ++i) {
ToolButton *button = qobject_cast<ToolButton *>(m_layout->itemAt(i)->widget());
if (button) {
wholeText += button->text();
}
}
if ( fm.width(wholeText) > screenGeom.width()) {
showText = false;
}
break;
}
}
//FIXME: better (and faster) way to do that?
for (int i=0; i < m_layout->count(); ++i) {
ToolButton *button = qobject_cast<ToolButton *>(m_layout->itemAt(i)->widget());
if(button)
if (button) {
if (showText && button != m_closeControllerTool) {
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
} else {
button->setToolButtonStyle(Qt::ToolButtonIconOnly);
}
}
}
ControllerWindow::resizeEvent(event);
}
void PanelController::maximizePanel()
{
const int length = m_ruler->availableLength();
const int screen = containment()->screen();
const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
QRegion availGeom(screenGeom);
foreach (PanelView *view, PlasmaApp::self()->panelViews()) {
if (view->containment() != containment() &&
view->screen() == screen && view->visibilityMode() == PanelView::NormalPanel) {
availGeom = availGeom.subtracted(view->geometry());
}
}
int offset = 0;
const int w = containment()->size().width();
const int h = containment()->size().height();
switch (location()) {
case Plasma::LeftEdge: {
QRect r = availGeom.intersected(QRect(0, 0, w, length)).boundingRect();
offset = r.top();
break;
}
case Plasma::RightEdge: {
QRect r = availGeom.intersected(QRect(screenGeom.right() - w, 0, w, length)).boundingRect();
offset = r.top();
break;
}
case Plasma::TopEdge: {
QRect r = availGeom.intersected(QRect(0, 0, length, h)).boundingRect();
offset = r.left();
break;
}
case Plasma::BottomEdge:
default: {
QRect r = availGeom.intersected(QRect(0, screenGeom.bottom() - h, length, h)).boundingRect();
offset = r.left();
break;
}
}
rulersMoved(offset, length, length);
m_ruler->setMaxLength(length);
m_ruler->setMinLength(length);
}
void PanelController::addSpace()
{
Plasma::Applet *spacer = containment()->addApplet("panelspacer_internal");
if (spacer) {
QMetaObject::invokeMethod(spacer, "updateConfigurationMode", Q_ARG(bool, true));
}
}
#include "moc_panelcontroller.cpp"