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@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@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@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@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