[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