aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/RootSubWindow.cpp
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-03-02 19:28:05 -0500
committerKen Moore <ken@ixsystems.com>2017-03-02 19:28:05 -0500
commit00d95d8a1323a4c0603a7a6f622c1b5cc981d2ce (patch)
tree6b49932d76a45009855acceaae687e153bed0f8f /src-qt5/core/libLumina/RootSubWindow.cpp
parentMerge branch 'master' of github.com:trueos/lumina (diff)
downloadlumina-00d95d8a1323a4c0603a7a6f622c1b5cc981d2ce.tar.gz
lumina-00d95d8a1323a4c0603a7a6f622c1b5cc981d2ce.tar.bz2
lumina-00d95d8a1323a4c0603a7a6f622c1b5cc981d2ce.zip
Write up a new window frame for Lumina2 (not using the QMdi[Sub]Window classes). This seems to be working much better so far - still need to finish filling out the various interaction functions and themeing (stylesheet object names done).
Diffstat (limited to 'src-qt5/core/libLumina/RootSubWindow.cpp')
-rw-r--r--src-qt5/core/libLumina/RootSubWindow.cpp258
1 files changed, 233 insertions, 25 deletions
diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp
index e4c3c4ee..9769c922 100644
--- a/src-qt5/core/libLumina/RootSubWindow.cpp
+++ b/src-qt5/core/libLumina/RootSubWindow.cpp
@@ -6,22 +6,24 @@
//===========================================
#include "RootSubWindow.h"
#include <QDebug>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QVBoxLayout>
// === PUBLIC ===
-RootSubWindow::RootSubWindow(QMdiArea *root, NativeWindow *win) : QMdiSubWindow(0){
+RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){
this->setAttribute(Qt::WA_DeleteOnClose);
+ this->setMouseTracking(true);
//Create the QWindow and QWidget containers for the window
WIN = win;
closing = false;
WinWidget = QWidget::createWindowContainer( WIN->window(), this);
- this->setWidget(WinWidget);
+ initWindowFrame();
LoadProperties( QList< NativeWindow::Property>() << NativeWindow::Title << NativeWindow::Icon \
<< NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Size );
//Hookup the signals/slots
connect(this, SIGNAL(aboutToActivate()), this, SLOT(aboutToActivate()) );
connect(WIN, SIGNAL(PropertyChanged(NativeWindow::Property, QVariant)), this, SLOT(propertyChanged(NativeWindow::Property, QVariant)));
- //Now add this window to the root QMdiArea
- root->addSubWindow(this);
//Make sure the visibily property only gets loaded after it is added to the root area
propertyChanged(NativeWindow::Visible, WIN->property(NativeWindow::Visible));
}
@@ -35,6 +37,127 @@ WId RootSubWindow::id(){
}
// === PRIVATE ===
+RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset){
+ //Note: pt should be in widget-relative coordinates, not global
+ if(!WinWidget->geometry().contains(pt)){
+ //above the frame itself - need to figure out which quadrant it is in (8-directions)
+ if(pt.y() < 3){
+ //One of the top options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
+ return ResizeTopLeft;
+ }else if(pt.x() > (this->width()-3)){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(pt.y()); } //difference from top-right corner
+ return ResizeTopRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter)
+ return ResizeTop;
+ }
+ }else if(pt.y() > (this->height()-3) ){
+ //One of the bottom options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-left corner
+ return ResizeBottomLeft;
+ }else if(pt.x() > (this->width()-3)){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(this->height()-pt.y()); } //difference from bottom-right corner
+ return ResizeBottomRight;
+ }else{
+ if(setoffset){ offset.setX(0); offset.setY(this->height() - pt.y()); } //difference from bottom edge (X does not matter)
+ return ResizeBottom;
+ }
+ }else{
+ //One of the side options
+ if(pt.x() < 3){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter)
+ return ResizeLeft;
+ }else if(pt.x() > (this->width()-3) ){
+ if(setoffset){ offset.setX(this->width()-pt.x()); offset.setY(0); } //difference from right edge (Y does not matter)
+ return ResizeRight;
+ }else{
+ return Normal;
+ }
+ }
+ }
+ return Normal;
+}
+
+void RootSubWindow::setMouseCursor(ModState state, bool override){
+ Qt::CursorShape shape;
+ switch(state){
+ case Normal:
+ shape = Qt::ArrowCursor;
+ break;
+ case Move:
+ shape = Qt::SizeAllCursor;
+ break;
+ case ResizeTop:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeTopRight:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeRight:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeBottomRight:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ case ResizeBottom:
+ shape = Qt::SizeVerCursor;
+ break;
+ case ResizeBottomLeft:
+ shape = Qt::SizeBDiagCursor;
+ break;
+ case ResizeLeft:
+ shape = Qt::SizeHorCursor;
+ break;
+ case ResizeTopLeft:
+ shape = Qt::SizeFDiagCursor;
+ break;
+ }
+ if(override){
+ QApplication::setOverrideCursor(QCursor(shape));
+ }else{
+ this->setCursor(shape);
+ }
+}
+
+void RootSubWindow::initWindowFrame(){
+ mainLayout = new QVBoxLayout(this);
+ titleBar = new QHBoxLayout(this);
+ closeB = new QToolButton(this);
+ maxB = new QToolButton(this);
+ minB = new QToolButton(this);
+ titleLabel = new QLabel(this);
+ titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ otherM = new QMenu(this); //menu of other actions
+ connect(closeB, SIGNAL(clicked()), this, SLOT(triggerClose()) );
+ connect(maxB, SIGNAL(clicked()), this, SLOT(toggleMaximize()) );
+ connect(minB, SIGNAL(clicked()), this, SLOT(toggleMinimize()) );
+ //Now assemble the frame layout based on the current settings
+ this->setLayout(mainLayout);
+ titleBar->addWidget(titleLabel);
+ titleBar->addWidget(minB);
+ titleBar->addWidget(maxB);
+ titleBar->addWidget(closeB);
+ WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ mainLayout->addLayout(titleBar);
+ mainLayout->addWidget(WinWidget);
+ //Now all the stylesheet options
+ this->setObjectName("WindowFrame");
+ closeB->setObjectName("Button_Close");
+ minB->setObjectName("Button_Minimize");
+ maxB->setObjectName("Button_Maximize");
+ otherM->setObjectName("Menu_Actions");
+ titleLabel->setObjectName("Label_Title");
+ this->setStyleSheet("QWidget#WindowFrame{background-color: black;} QWidget#Label_Title{background-color: darkgrey; color: white; }");
+ //And adjust the margins
+ mainLayout->setContentsMargins(4,4,4,4);
+ mainLayout->setSpacing(0);
+ titleBar->setSpacing(1);
+ titleBar->setContentsMargins(0,0,0,0);
+}
+
void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
for(int i=0; i<list.length(); i++){
propertyChanged( list[i], WIN->property(list[i]) );
@@ -48,19 +171,41 @@ void RootSubWindow::clientClosed(){
this->close();
}
-void RootSubWindow::clientHidden(){
- qDebug() << "Client Hidden";
- this->hide();
+//Button Actions - public so they can be tied to key shortcuts and stuff as well
+void RootSubWindow::toggleMinimize(){
+
+}
+
+void RootSubWindow::toggleMaximize(){
+
+}
+
+void RootSubWindow::triggerClose(){
+ WIN->emit RequestClose(WIN->id());
+}
+
+void RootSubWindow::toggleSticky(){
+
+}
+
+void RootSubWindow::activate(){
+ WIN->emit RequestActivate(WIN->id());
+}
+
+//Mouse Interactivity
+void RootSubWindow::startMoving(){
+
}
-void RootSubWindow::clientShown(){
- qDebug() << "Client Shown";
- this->show();
+void RootSubWindow::startResizing(){
+
}
+
+
// === PRIVATE SLOTS ===
void RootSubWindow::aboutToActivate(){
- WIN->emit RequestActivate(WIN->id());
+
}
void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){
@@ -68,26 +213,26 @@ void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){
qDebug() << "Set Window Property:" << prop << val;
switch(prop){
case NativeWindow::Visible:
- if(val.toBool()){ clientShown(); }
- else{ clientHidden(); }
+ if(val.toBool()){ this->show(); }
+ else{ this->hide(); }
break;
case NativeWindow::Title:
- this->setWindowTitle(val.toString());
+ titleLabel->setText(val.toString());
break;
case NativeWindow::Icon:
- this->setWindowIcon(val.value< QIcon>());
+ //this->setWindowIcon(val.value< QIcon>());
break;
case NativeWindow::Size:
- this->resize(val.toSize());
+ WinWidget->resize(val.toSize());
break;
case NativeWindow::MinSize:
- this->setMinimumSize(val.toSize());
+ WinWidget->setMinimumSize(val.toSize());
break;
case NativeWindow::MaxSize:
- this->setMaximumSize(val.toSize());
+ WinWidget->setMaximumSize(val.toSize());
break;
case NativeWindow::Active:
- if(val.toBool()){ this->mdiArea()->setActiveSubWindow(this); }
+ WinWidget->setFocus();
break;
/*case NativeWindow::WindowFlags:
this->setWindowFlags( val.value< Qt::WindowFlags >() );
@@ -98,13 +243,76 @@ void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){
}
// === PROTECTED ===
-void RootSubWindow::closeEvent(QCloseEvent *ev){
- if(!closing){
- //qDebug() << "Close Window By Button:" << WIN->id();
- ev->ignore();
- WIN->emit RequestClose(WIN->id());
+void RootSubWindow::mousePressEvent(QMouseEvent *ev){
+ qDebug() << "Frame Mouse Press Event";
+ offset.setX(0); offset.setY(0);
+ if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse
+ this->activate();
+ if(this->childAt(ev->pos())!=0){
+ //Check for any non-left-click event and skip it
+ if(ev->button()!=Qt::LeftButton){ return; }
+ activeState = Move;
+ offset.setX(ev->pos().x()); offset.setY(ev->pos().y());
}else{
- QMdiSubWindow::closeEvent(ev);
+ //Clicked on the frame somewhere
+ activeState = getStateAtPoint(ev->pos(), true); //also have it set the offset variable
}
+ setMouseCursor(activeState, true); //this one is an override cursor
}
+
+void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){
+ ev->accept();
+ if(activeState == Normal){
+ setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor
+
+ }else{
+ //Currently in a modification state
+ QRect geom = this->geometry();
+ switch(activeState){
+ case Move:
+ geom.moveTopLeft(ev->globalPos()-offset); //will not change size
+ break;
+ case ResizeTop:
+ geom.setTop(ev->globalPos().y()-offset.y());
+ break;
+ case ResizeTopRight:
+ geom.setTopRight(ev->globalPos()-offset);
+ break;
+ case ResizeRight:
+ geom.setRight(ev->globalPos().x()-offset.x());
+ break;
+ case ResizeBottomRight:
+ geom.setBottomRight(ev->globalPos()-offset);
+ break;
+ case ResizeBottom:
+ geom.setBottom(ev->globalPos().y()-offset.y());
+ break;
+ case ResizeBottomLeft:
+ geom.setBottomLeft(ev->globalPos()-offset);
+ break;
+ case ResizeLeft:
+ geom.setLeft(ev->globalPos().x()-offset.x());
+ break;
+ case ResizeTopLeft:
+ geom.setTopLeft(ev->globalPos()-offset);
+ break;
+ default:
+ break;
+ }
+ this->setGeometry(geom);
+ }
+}
+
+void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){
+ //Check for a right-click event
+ qDebug() << "Frame Mouse Release Event";
+ ev->accept();
+ if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){
+ otherM->popup(ev->globalPos());
+ return;
+ }
+ activeState = Normal;
+ QApplication::restoreOverrideCursor();
+ setMouseCursor( getStateAtPoint(ev->pos()) );
+}
bgstack15