mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 19:02:51 +00:00
996 lines
35 KiB
C++
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"
|