[X2Go-Commits] [x2gokdriveclient] 01/01: Add floating tool bar.
git-admin at x2go.org
git-admin at x2go.org
Wed Jan 22 13:24:59 CET 2020
This is an automated email from the git hooks/post-receive script.
x2go pushed a commit to branch master
in repository x2gokdriveclient.
commit 44e288fea482d84f3c5063fde4a4c978f405bf94
Author: Oleksandr Shneyder <o.shneyder at phoca-gmbh.de>
Date: Wed Jan 22 13:18:16 2020 +0100
Add floating tool bar.
---
client.cpp | 112 +++++++----
client.h | 10 +-
debian/changelog | 3 +
displayarea.cpp | 20 +-
menuframe.cpp | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++
menuframe.h | 92 +++++++++
res/minimize.svg | 13 ++
res/pin.svg | 13 ++
res/view.svg | 13 ++
resources.qrc | 3 +
x2gokdriveclient.pro | 4 +-
11 files changed, 740 insertions(+), 58 deletions(-)
diff --git a/client.cpp b/client.cpp
index 73b6994..44977aa 100644
--- a/client.cpp
+++ b/client.cpp
@@ -32,6 +32,14 @@
#include <QDesktopWidget>
#include <QMimeData>
#include <QBuffer>
+#include <QMenuBar>
+#include <QToolBar>
+#include "menuframe.h"
+
+#include <QHBoxLayout>
+
+#include <QLabel>
+#include <QInputDialog>
#include <QResizeEvent>
@@ -40,12 +48,13 @@
#include <QGuiApplication>
#include <QScreen>
#include <QPushButton>
+#include <QToolButton>
#include <QMenu>
-
#include <QClipboard>
+
X2GoCursor::X2GoCursor(uint16_t width, uint16_t height, uint16_t xhot, uint16_t yhot, uint32_t serialNumber, uint32_t dataSize)
{
this->width=width;
@@ -101,14 +110,13 @@ Frame::~Frame()
Client::Client()
{
- resize(799,600);
- move(-0,0);
+ displayArea=new DisplayArea(this);
+
+ displayArea->setObjectName("DisplayArea");
+ displayArea->setStyleSheet("QFrame#DisplayArea{background-color:black;border-image:url(:res/x2gobg.svg) 0 0 0 0 stretch stretch;}");
- displayArea=new DisplayArea(this);
- displayArea->setStyleSheet("background-color:black;");
- displayArea->setStyleSheet("border-image:url(:res/x2gobg.svg) 0 0 0 0 stretch stretch;");
displayArea->show();
setCentralWidget(displayArea);
setWindowIcon(QIcon(":res/x2goclient.png"));
@@ -123,7 +131,6 @@ Client::Client()
connect(QGuiApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(slotSelectionChanged(QClipboard::Mode)));
- QTimer::singleShot(10,this,SLOT(connectToServer()));
geometryDelay=new QTimer(this);
geometryDelay->setSingleShot(true);
@@ -143,28 +150,39 @@ Client::Client()
slotScreenAdded(screen);
}
- menuButton=new QPushButton("",this);
- menuButton->resize(24,24);
- menuButton->move(0,0);
- menuButton->setStyleSheet("border-image:none;");
- menuButton->setFocusPolicy(Qt::NoFocus);
- menu=new QMenu(menuButton);
+ QMenu* menuCon=menuBar()->addMenu(tr("&Connection"));
+ menu=menuBar()->addMenu(tr("&View"));
+ FSMenuBar=new MenuFrame(this, menu);
+// FSMenuBar->hide();
+ menuBar()->hide();
+
+ connect(FSMenuBar, SIGNAL(editCaption()), this, SLOT(editWindowTitle()));
+ connect(this, SIGNAL(windowTitleChanged(const QString &)), FSMenuBar, SLOT(setCaption(const QString &)));
+
- actRandr=menu->addAction(QIcon(":res/randr.svg"), tr("Enable RandR extension"),this, SLOT(slotEnableRandr()));
+ actRandr=menu->addAction(QIcon(":res/randr.svg"), tr("Multiple monitors"),this, SLOT(slotEnableRandr()));
+ actRandr->setCheckable(true);
+ menu->addSeparator();
for(int i=0;i<4;++i)
- actDisp[i]=menu->addAction(QIcon(":res/view-fullscreen.svg"), tr("Display ")+QString::number(i+1) ,this, SLOT(slotDisplayFS()));
- actFS=menu->addAction(QIcon(":res/view-fullscreen.svg"), tr("All displays"),this, SLOT(slotFS()));
- actRestore=menu->addAction(QIcon(":res/view-restore.svg"), tr("Restore") ,this, SLOT(slotRestore()));
+ actDisp[i]=menu->addAction(QIcon(":res/view-fullscreen.svg"), tr("Monitor ")+QString::number(i+1) ,this, SLOT(slotDisplayFS()));
+
+ actFS=menu->addAction(QIcon(":res/view-fullscreen.svg"), tr("All monitors"),this, SLOT(slotFS()));
menu->addSeparator();
- actDisconnect=menu->addAction(QIcon(":res/network-disconnect.svg"), tr("Disconnect"),this, SLOT(slotDisconnect()));
+ actRestore=menu->addAction(QIcon(":res/view-restore.svg"), tr("Restore") ,this, SLOT(slotRestore()));
+ menuBar()->addSeparator();
+
+
+ actDisconnect=menuCon->addAction( tr("Disconnect"),this, SLOT(slotDisconnect()));
+ actDisconnect->setIcon(QIcon(":res/network-disconnect.svg"));
+ actDisconnect->setToolTip(tr("Disconnect"));
+
+ QTimer::singleShot(10,this,SLOT(connectToServer()));
+
- menuButton->setMenu(menu);
- menuButton->hide();
- menuButton->setCursor(Qt::ArrowCursor);
- connect(menu,SIGNAL(aboutToHide()), menuButton, SLOT(hide()));
connect(menu,SIGNAL(aboutToShow()), this, SLOT(slotSetupMenu()));
+ setWindowTitle(tr("X2GoKDrive Client"));
}
@@ -180,6 +198,23 @@ Client::~Client()
delete currentCursor;
}
+
+void Client::editWindowTitle()
+{
+ bool ok;
+ QString title=QInputDialog::getText(this,tr("Enter new window title"),tr("New window title:"),QLineEdit::Normal, windowTitle(),&ok);
+ if(ok)
+ {
+ if(title.length()==0)
+ {
+ setWindowTitle(tr("X2GoKDrive Client"));
+ return;
+ }
+ setWindowTitle(title);
+ }
+}
+
+
void Client::slotEnableRandr()
{
setUseRandr(!useRandr);
@@ -289,7 +324,6 @@ void Client::slotRealFs()
#endif
}
-
void Client::setFS(int screenNumber)
{
if(!isFs)
@@ -331,16 +365,16 @@ void Client::slotSetupMenu()
menu->setEnabled(clientSocket->isOpen());
if(useRandr)
{
- actRandr->setText(tr("Disable RandR extension"));
+ actRandr->setChecked(true);
}
else
{
- actRandr->setText(tr("Enable RandR extension"));
+ actRandr->setChecked(false);
}
actRestore->setVisible(isFs);
actFS->setVisible((!isFs));
- actDisp[0]->setText(tr("Display 1"));
+ actDisp[0]->setText(tr("Monitor 1"));
if(((QGuiApplication*)QGuiApplication::instance())->screens().count()==1)
{
@@ -366,22 +400,22 @@ void Client::slotSetupMenu()
displayArea->slotGrabDisplay();
}
-
-void Client::hideMenuButton()
-{
- menuButton->hide();
-}
-
-void Client::showMenuButton()
+bool Client::isDisplayPointer(QMouseEvent* event)
{
- if(!menuButton->isVisible())
+ if(event->x() > FSMenuBar->x() && event->x() < FSMenuBar->x() + FSMenuBar->width() &&
+ event->y() > FSMenuBar->y() && event->y() < FSMenuBar->y() + FSMenuBar->height() &&
+ event->button()== Qt::NoButton && event->buttons() == 0)
{
- displayArea->slotGrabDisplay();
+ FSMenuBar->setHasPointer(true);
+ return false;
+ }
+ else
+ {
+ FSMenuBar->setHasPointer(false);
+ return true;
}
- menuButton->show();
}
-
void Client::freeMessageBuffer()
{
if(messageBuffer)
@@ -556,7 +590,7 @@ void Client::renderFrame()
}
else
{
- qDebug()<<"got Screen update:"<<currentFrame->width<< currentFrame->height<<currentFrame->regions[0]->pix.size();
+// qDebug()<<"got Screen update:"<<currentFrame->width<< currentFrame->height<<currentFrame->regions[0]->pix.size();
displayArea->setDisplayPix(currentFrame->regions[0]->pix, currentFrame->x, currentFrame->y);
}
}
@@ -1009,6 +1043,7 @@ void Client::dataArrived()
void Client::socketConnected()
{
+ displayArea->setStyleSheet("QFrame#DisplayArea{background-color:black;}");
fprintf(stderr,"Connected to server\n");
fprintf(stderr,"Established X server connection\n");
@@ -1099,6 +1134,7 @@ void Client::resizeEvent(QResizeEvent* )
if(geometryDelay->isActive())
geometryDelay->stop();
geometryDelay->start();
+ FSMenuBar->adjustPosition();
}
void Client::resizeToOldSize()
diff --git a/client.h b/client.h
index 4163e37..04a1b3b 100644
--- a/client.h
+++ b/client.h
@@ -108,7 +108,7 @@ public:
class QTcpSocket;
class DisplayArea;
class QTimer;
-class QPushButton;
+class MenuFrame;
class QMenu;
class QAction;
@@ -120,13 +120,12 @@ public:
Client();
~Client();
void sendEvent(char *event);
- void showMenuButton();
- void hideMenuButton();
Frame* getCurrentFrame(){return currentFrame;}
bool needUpdate(){return wantRepaint;}
void setUptodate();
QPixmap getPixmapFromCache(uint32_t crc);
QPixmap addPixmapToCache();
+ bool isDisplayPointer(QMouseEvent* event);
private slots:
@@ -152,6 +151,8 @@ private slots:
void slotEnableRandr();
void slotResizeFSFinal();
void slotSelectionChanged(QClipboard::Mode mode);
+public slots:
+ void editWindowTitle();
private:
@@ -192,8 +193,9 @@ private:
int dispNumber=1;
QString cookie;
- QPushButton *menuButton;
+ MenuFrame *FSMenuBar;
QMenu* menu;
+
QAction* actRandr;
QAction* actFS;
QAction* actDisp[4];
diff --git a/debian/changelog b/debian/changelog
index 6e5fed2..a3b1ab2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,4 +13,7 @@ x2gokdriveclient (0.0.0.1-0x2go1) UNRELEASED; urgency=medium
* Let qmake add general Qt {C{,XX},L}FLAGS instead of overriding them.
Especially needed for C++11 support.
+ [ Oleksandr Shneyder ]
+ * Add floating tool bar.
+
-- Mike Gabriel <mike.gabriel at das-netzwerkteam.de> Tue, 04 Jun 2019 11:10:43 +0200
diff --git a/displayarea.cpp b/displayarea.cpp
index ad14953..855922a 100644
--- a/displayarea.cpp
+++ b/displayarea.cpp
@@ -182,10 +182,10 @@ void DisplayArea::paintEvent(QPaintEvent* ev)
int32_t etype, x, y, width, height;
etype=UPDATE;
- width=ev->rect().width();
- height=ev->rect().height();
- x=ev->rect().x();
- y=ev->rect().y();
+ width=ev->rect().width()+ev->rect().x();
+ height=ev->rect().height()+ev->rect().y();
+ x=0;
+ y=0;
memcpy(evmsg,(char*)&etype,4);
@@ -238,6 +238,8 @@ uint32_t DisplayArea::X11MouseButton(Qt::MouseButton qtMouseButton)
void DisplayArea::mouseMoveEvent(QMouseEvent* event)
{
+ if(!parent->isDisplayPointer(event))
+ return;
char evmsg[EVLENGTH]={};
uint32_t etype, x, y;
etype=MOUSEMOTION;
@@ -247,16 +249,6 @@ void DisplayArea::mouseMoveEvent(QMouseEvent* event)
x=event->x();
y=event->y();
- if(x<25 && y<25 &&event->button()== Qt::NoButton && event->buttons() == 0)
- {
- parent->showMenuButton();
- return;
- }
- else
- {
- parent->hideMenuButton();
- }
-
memcpy(evmsg,(char*)&etype,4);
memcpy(evmsg+4,(char*)&x,4);
memcpy(evmsg+8,(char*)&y,4);
diff --git a/menuframe.cpp b/menuframe.cpp
new file mode 100644
index 0000000..7605d96
--- /dev/null
+++ b/menuframe.cpp
@@ -0,0 +1,515 @@
+/*
+ * QT Client for X2GoKDrive
+ * Copyright (C) 2018 Oleksandr Shneyder <o.shneyder at phoca-gmbh.de>
+ * Copyright (C) 2018 phoca-GmbH
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <menuframe.h>
+#include <QDebug>
+#include <QMouseEvent>
+#include <QCursor>
+#include <QToolButton>
+#include <QLabel>
+#include <QMenu>
+#include <QHBoxLayout>
+#include <QSettings>
+#include <QTimer>
+
+#include "client.h"
+
+
+
+
+
+#include <QPainter>
+
+RotatedLabel::RotatedLabel(QWidget *parent): QLabel(parent)
+{
+}
+
+RotatedLabel::RotatedLabel(const QString &text, QWidget *parent): QLabel(text, parent)
+{
+}
+
+void RotatedLabel::setOrientation(RotatedLabel::orient ort)
+{
+ orientation=ort;
+}
+
+void RotatedLabel::mouseDoubleClickEvent(QMouseEvent*)
+{
+ emit doubleClick();
+}
+
+
+void RotatedLabel::paintEvent(QPaintEvent* ev)
+{
+ switch (orientation)
+ {
+ case NORMAL:
+ QLabel::paintEvent(ev);
+ return;
+ case LEFT:
+ {
+ QPainter painter(this);
+ painter.translate(8,2);
+ painter.rotate(90);
+ painter.drawText(0,0,text());
+ break;
+ }
+ case RIGHT:
+ {
+ QPainter painter(this);
+ painter.translate( sizeHint().height()-4,sizeHint().width()+1);
+ painter.rotate(270);
+ painter.drawText(0,0,text());
+ break;
+ }
+ }
+}
+
+MenuFrame::MenuFrame(QWidget* parent, QMenu* menu):QFrame(parent)
+{
+ setMouseTracking(true);
+ setObjectName("FSMenuBar");
+
+ bPin=new QToolButton(this);
+ bPin->setIcon(QIcon(":res/pin.svg"));
+ bPin->setCheckable(true);
+ bPin->setToolTip(tr("Pin menu bar"));
+
+
+ connect(bPin, SIGNAL(toggled(bool)), this, SLOT(setPinned(bool)));
+
+
+ QHBoxLayout* ml=new QHBoxLayout(this);
+
+ hLayout=new QHBoxLayout();
+ vLayout=new QVBoxLayout();
+
+ ml->addLayout(hLayout);
+ ml->addLayout(vLayout);
+
+ defaultMargin=ml->margin();
+ defaultSpacing=ml->spacing();
+
+ ml->setSpacing(0);
+ ml->setMargin(0);
+
+
+ viewMenu=new QToolButton(this);
+
+ viewMenu->setMenu(menu);
+ viewMenu->setPopupMode(QToolButton::InstantPopup);
+ viewMenu->setToolTip(tr("View"));
+ viewMenu->setIcon(QIcon(":res/view.svg"));
+
+ capt=new RotatedLabel("", this);
+ capt->setToolTip(tr("Double click to change window title\nDrag to change position"));
+
+ connect(capt, SIGNAL(doubleClick()), this,SIGNAL(editCaption()));
+
+ bDisc=new QToolButton(this);
+ bDisc->setToolTip(tr("Disconnect"));
+ bDisc->setIcon(QIcon(":res/network-disconnect.svg"));
+ Client* client=(Client*)parent;
+ connect(bDisc, SIGNAL(clicked(bool)),client, SLOT(slotDisconnect()));
+
+ bMin=new QToolButton(this);
+ bMin->setToolTip(tr("Minimize"));
+ bMin->setIcon(QIcon(":res/minimize.svg"));
+ connect(bMin, SIGNAL(clicked(bool)),client, SLOT(showMinimized()));
+
+ QSettings s( "Obviously Nice","x2gokdriveclient");
+ isPinned=s.value("pinned",false).toBool();
+
+ position=s.value("position",0.5).toDouble();
+
+ QString orstr=s.value("orientation", "top").toString();
+
+ if(orstr=="bottom")
+ orientation=BOTTOM;
+ if(orstr=="left")
+ orientation=LEFT;
+ if(orstr=="right")
+ orientation=RIGHT;
+
+
+ setupFrame();
+ adjustPosition();
+ bPin->setChecked(isPinned);
+ hovered=true;
+ setHasPointer(false);
+ applyStyle();
+
+}
+
+void MenuFrame::setupFrame()
+{
+ if(hLayout->count())
+ {
+ hLayout->removeWidget(bPin);
+ hLayout->removeWidget(viewMenu);
+ hLayout->removeWidget(capt);
+ hLayout->removeWidget(bMin);
+ hLayout->removeWidget(bDisc);
+ }
+ if(vLayout->count())
+ {
+ vLayout->removeWidget(bPin);
+ vLayout->removeWidget(viewMenu);
+ vLayout->removeWidget(capt);
+ vLayout->removeWidget(bMin);
+ vLayout->removeWidget(bDisc);
+ }
+
+ switch(orientation)
+ {
+ case TOP:
+ case BOTTOM:
+ vLayout->setSpacing(0);
+ vLayout->setMargin(0);
+ hLayout->setSpacing(defaultSpacing);
+ hLayout->setMargin(defaultMargin);
+ hLayout->addWidget(bPin);
+ hLayout->addWidget(viewMenu);
+ hLayout->addWidget(capt);
+ hLayout->addWidget(bMin);
+ hLayout->addWidget(bDisc);
+ capt->setOrientation(RotatedLabel::NORMAL);
+ setMinimumHeight(bDisc->sizeHint().height()+defaultMargin*2);
+ setMaximumHeight(bDisc->sizeHint().height()+defaultMargin*2);
+ setMinimumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ setMaximumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ break;
+ case LEFT:
+ capt->setOrientation(RotatedLabel::LEFT);
+ // fall through
+ case RIGHT:
+ if(orientation!=LEFT)
+ capt->setOrientation(RotatedLabel::RIGHT);
+ hLayout->setSpacing(0);
+ hLayout->setMargin(0);
+ vLayout->setSpacing(defaultSpacing);
+ vLayout->setMargin(defaultMargin);
+ vLayout->addWidget(bPin);
+ vLayout->addWidget(viewMenu);
+ vLayout->addWidget(capt);
+ vLayout->addWidget(bMin);
+ vLayout->addWidget(bDisc);
+ setMinimumWidth(bDisc->sizeHint().height()+defaultMargin*2);
+ setMaximumWidth(bDisc->sizeHint().height()+defaultMargin*2);
+ setMinimumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ setMaximumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ break;
+ }
+
+}
+
+
+void MenuFrame::adjustPosition()
+{
+ int y=0;
+ int x=0;
+
+ qDebug()<<"Widget width"<<width();
+ switch(orientation)
+ {
+ case BOTTOM:
+ y=parentWidget()->height()-height();
+ // fall through
+ case TOP:
+ {
+ if(position==0)
+ {
+ x=0;
+ }
+ else if(position==1)
+ {
+ x=parentWidget()->width()-width()-1;
+ }
+ else
+ {
+ x=parentWidget()->width()*position-width()/2;
+ if(x<11)
+ {
+ x=11;
+ }
+ if(x+11>parentWidget()->width()-width())
+ {
+ x=parentWidget()->width()-width()-11;
+ }
+ }
+ break;
+ }
+ case RIGHT:
+ x=parentWidget()->width()-width();
+ // fall through
+ case LEFT:
+ {
+ if(position==0)
+ {
+ y=0;
+ }
+ else if(position==1)
+ {
+ y=parentWidget()->height()-height()-1;
+ }
+ else
+ {
+ y=parentWidget()->height()*position-height()/2;
+ if(y<11)
+ {
+ y=11;
+ }
+ if(y+11>parentWidget()->height()-height())
+ {
+ y=parentWidget()->height()-height()-11;
+ }
+ }
+ break;
+ }
+ }
+ move(x,y);
+
+ hovered=true;
+ setHasPointer(false);
+}
+
+
+void MenuFrame::setCaption(const QString& text)
+{
+ capt->setText(text);
+ switch(orientation)
+ {
+ case TOP:
+ case BOTTOM:
+ setMinimumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ setMaximumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ break;
+ case LEFT:
+ case RIGHT:
+ setMinimumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ setMaximumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
+ break;
+ }
+
+ QTimer::singleShot(20,this, SLOT(adjustPosition()));
+}
+
+void MenuFrame::applyStyle()
+{
+ QPalette pal=bPin->palette();
+ QString bgCol;
+ QColor col=pal.color(QPalette::Window);
+
+ bgCol.sprintf("rgba(%d,%d,%d,%d)",col.red(), col.green(), col.blue() ,col.alpha()) ;
+
+ switch(orientation)
+ {
+ case TOP:
+ setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-bottom-right-radius:5px;border-bottom-left-radius:5px;border-left-style:solid;border-right-style:solid;border-bottom-style:solid;border-width:1px;border-color:grey;}");
+ break;
+ case BOTTOM:
+ setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-right-radius:5px;border-top-left-radius:5px;border-left-style:solid;border-right-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
+ break;
+ case LEFT:
+ setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-right-radius:5px;border-bottom-right-radius:5px;border-right-style:solid;border-bottom-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
+ break;
+ case RIGHT:
+ setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-left-radius:5px;border-bottom-left-radius:5px;border-left-style:solid;border-bottom-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
+ break;
+ }
+}
+
+
+void MenuFrame::mouseMoveEvent(QMouseEvent* event)
+{
+ setHasPointer(true);
+ if(!drag)
+ return;
+ int deltaX=event->screenPos().x()-startPosX;
+ startPosX=event->screenPos().x();
+
+ int deltaY=event->screenPos().y()-startPosY;
+ startPosY=event->screenPos().y();
+
+
+ int localY=event->screenPos().y() - parentWidget()->geometry().y();
+ int localX=event->screenPos().x() - parentWidget()->geometry().x();
+
+ int rDist=parentWidget()->width()-localX;
+ int bDist=parentWidget()->height()-localY;
+
+ if(rDist<localX && rDist<localY && rDist<bDist)
+ {
+ if(orientation!=RIGHT)
+ {
+ orientation=RIGHT;
+ applyStyle();
+ setupFrame();
+ }
+ }else if(localY<rDist && localY<localX && localY<bDist)
+ {
+ if(orientation!=TOP)
+ {
+ orientation=TOP;
+ applyStyle();
+ setupFrame();
+ }
+ }
+ else if(bDist<localY && bDist<localX && bDist<rDist)
+ {
+ if(orientation!=BOTTOM)
+ {
+ orientation=BOTTOM;
+ applyStyle();
+ setupFrame();
+ }
+ }
+ else
+ {
+ if(orientation!=LEFT)
+ {
+ orientation=LEFT;
+ applyStyle();
+ setupFrame();
+ }
+ }
+
+ int newX=0;
+ int newY=0;
+
+ switch(orientation)
+ {
+ case BOTTOM:
+ newY=parentWidget()->height()-height();
+ // fall through
+ case TOP:
+ {
+ newX=x()+deltaX;
+ if(newX<0)
+ newX=0;
+ if(newX+width() > parentWidget()->width())
+ newX=parentWidget()->width() - width();
+
+ move(newX,newY);
+ position=(newX+width()/2.)/parentWidget()->width();
+ if(newX<=10)
+ position=0;
+ if(newX+width()>=parentWidget()->width()-10)
+ position=1;
+ }
+ break;
+ case RIGHT:
+ newX=parentWidget()->width()-width();
+ // fall through
+ case LEFT:
+ {
+ newY=y()+deltaY;
+ if(newY<0)
+ newY=0;
+ if(newY+height() > parentWidget()->height())
+ newY=parentWidget()->height()-height();
+ move(newX, newY);
+ position=(newY+height()/2.)/parentWidget()->height();
+ if(newY<=10)
+ position=0;
+ if(newY+height()>=parentWidget()->height()-10)
+ position=1;
+ }
+ break;
+ }
+
+ QSettings s( "Obviously Nice","x2gokdriveclient");
+ s.setValue("position",position);
+ switch(orientation)
+ {
+ case TOP:
+ s.setValue("orientation","top");
+ break;
+ case BOTTOM:
+ s.setValue("orientation","bottom");
+ break;
+ case LEFT:
+ s.setValue("orientation","left");
+ break;
+ case RIGHT:
+ s.setValue("orientation","right");
+ break;
+
+ }
+
+}
+
+
+void MenuFrame::setHasPointer(bool hasPointer)
+{
+ if(hasPointer==hovered)
+ return;
+ hovered=hasPointer;
+// qDebug()<<"hovered:"<<hovered;
+ int newY=y();
+ int newX=x();
+
+ if(hovered || isPinned)
+ {
+ switch(orientation)
+ {
+ case TOP: newY=0; break;
+ case BOTTOM: newY=parentWidget()->height()-height(); break;
+ case LEFT: newX=0;break;
+ case RIGHT:newX=parentWidget()->width()-width();break;
+ }
+ }
+ else
+ {
+ switch(orientation)
+ {
+ case TOP: newY=0-height()+5; break;
+ case BOTTOM: newY=parentWidget()->height()-5; break;
+ case LEFT: newX=0-width()+5;break;
+ case RIGHT: newX=parentWidget()->width()-5; break;
+ }
+ }
+ move(newX, newY);
+}
+
+
+void MenuFrame::mousePressEvent(QMouseEvent* event)
+{
+ drag=true;
+ startPosX=event->screenPos().x();
+ startPosY=event->screenPos().y();
+ setCursor(Qt::SizeAllCursor);
+}
+
+void MenuFrame::mouseReleaseEvent(QMouseEvent* )
+{
+ drag=false;
+ setCursor(Qt::ArrowCursor);
+}
+
+void MenuFrame::setPinned(bool toggled)
+{
+ qDebug()<<"pinned: "<<toggled;
+ isPinned=toggled;
+ QSettings s( "Obviously Nice","x2gokdriveclient");
+ s.setValue("pinned",isPinned);
+}
+
+
diff --git a/menuframe.h b/menuframe.h
new file mode 100644
index 0000000..a15c991
--- /dev/null
+++ b/menuframe.h
@@ -0,0 +1,92 @@
+/*
+ * QT Client for X2GoKDrive
+ * Copyright (C) 2018 Oleksandr Shneyder <o.shneyder at phoca-gmbh.de>
+ * Copyright (C) 2018 phoca-GmbH
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MENUFRAME_H
+#define MENUFRAME_H
+#include <QFrame>
+#include <QLabel>
+
+class RotatedLabel: public QLabel
+{
+ Q_OBJECT
+public:
+ typedef enum{NORMAL,LEFT, RIGHT} orient;
+ explicit RotatedLabel(QWidget *parent=0);
+ explicit RotatedLabel(const QString &text, QWidget *parent=0);
+ void setOrientation(orient ort);
+
+private:
+ orient orientation=NORMAL;
+
+protected:
+ void paintEvent(QPaintEvent* ev);
+ void mouseDoubleClickEvent(QMouseEvent*);
+signals:
+ void doubleClick();
+};
+
+class QMenu;
+class QLabel;
+class QHBoxLayout;
+class QVBoxLayout;
+class QToolButton;
+class MenuFrame : public QFrame
+{
+ Q_OBJECT
+public:
+ MenuFrame(QWidget* parent, QMenu* menu);
+ void setHasPointer(bool hasPointer);
+
+private:
+ void applyStyle();
+ void setupFrame();
+ bool isPinned=false;
+ int startPosX=0;
+ int startPosY=0;
+ double position;
+ bool drag=false;
+ bool hovered=false;
+ int defaultMargin=0;
+ int defaultSpacing=0;
+ RotatedLabel *capt;
+ QHBoxLayout* hLayout;
+ QVBoxLayout* vLayout;
+ QToolButton* bPin;
+ QToolButton* viewMenu;
+ QToolButton* bDisc;
+ QToolButton* bMin;
+
+ enum{TOP,BOTTOM, LEFT, RIGHT} orientation=TOP;
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+
+public slots:
+ void setPinned(bool toggled);
+ void setCaption(const QString& text);
+ void adjustPosition();
+
+signals:
+ void editCaption();
+};
+
+#endif // MENUFRAME_H
diff --git a/res/minimize.svg b/res/minimize.svg
new file mode 100644
index 0000000..937de0f
--- /dev/null
+++ b/res/minimize.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="m8 11.5l-6-6.251.719-.749 4.125 4.298 1.156 1.237 1.156-1.237 4.125-4.298.719.749-4.125 4.298z"
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/res/pin.svg b/res/pin.svg
new file mode 100644
index 0000000..0275514
--- /dev/null
+++ b/res/pin.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 8.5 2 C 7.119294 2 6.0000083 3.1192857 6 4.5 L 6 10.535156 L 6.0019531 10.535156 C 6.0210368 11.349063 6.6858693 11.999164 7.5 12 C 8.3284271 12 9 11.328427 9 10.5 L 9 5 L 8 5 L 8 10.5 C 8 10.776142 7.7761424 11 7.5 11 C 7.2238576 11 7 10.776142 7 10.5 L 7 4.5 C 7 3.6715729 7.6715729 3 8.5 3 C 9.3284271 3 10 3.6715729 10 4.5 L 10 10.5 C 10 11.880712 8.8807119 13 7.5 13 C 6.1192881 13 5 11.880712 5 10.5 L 5 4 L 4 4 L 4 10.5 C 4 12.433 5.567 14.000008 7.5 14 C 9.433 14.000008 11. [...]
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/res/view.svg b/res/view.svg
new file mode 100644
index 0000000..ce99a6a
--- /dev/null
+++ b/res/view.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 2 2 L 2 11 L 6 11 L 6 13 L 5 13 L 5 14 L 11 14 L 11 13 L 10 13 L 10 11 L 14 11 L 14 2 L 2 2 z M 3 3 L 13 3 L 13 10 L 3 10 L 3 3 z M 7 4 L 7 9 L 10 6.5 L 7 4 z M 7 11 L 9 11 L 9 13 L 7 13 L 7 11 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/resources.qrc b/resources.qrc
index 4b3e91b..8bcf0d1 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -5,6 +5,9 @@
<file>res/application-menu.svg</file>
<file>res/network-disconnect.svg</file>
<file>res/randr.svg</file>
+ <file>res/minimize.svg</file>
+ <file>res/view.svg</file>
+ <file>res/pin.svg</file>
<file>res/view-fullscreen.svg</file>
<file>res/view-restore.svg</file>
</qresource>
diff --git a/x2gokdriveclient.pro b/x2gokdriveclient.pro
index f3df708..fab1ed2 100644
--- a/x2gokdriveclient.pro
+++ b/x2gokdriveclient.pro
@@ -20,5 +20,5 @@ RESOURCES += resources.qrc
# Input
-SOURCES += main.cpp client.cpp displayarea.cpp
-HEADERS += client.h displayarea.h
+SOURCES += main.cpp client.cpp displayarea.cpp menuframe.cpp
+HEADERS += client.h displayarea.h menuframe.h
--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2gokdriveclient.git
More information about the x2go-commits
mailing list