aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/RootSubWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina/RootSubWindow.cpp')
-rw-r--r--src-qt5/core/libLumina/RootSubWindow.cpp351
1 files changed, 310 insertions, 41 deletions
diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp
index 7be89f48..ba682077 100644
--- a/src-qt5/core/libLumina/RootSubWindow.cpp
+++ b/src-qt5/core/libLumina/RootSubWindow.cpp
@@ -6,24 +6,24 @@
//===========================================
#include "RootSubWindow.h"
#include <QDebug>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QVBoxLayout>
+
+#define WIN_BORDER 3
// === 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);
- LoadProperties( QList< NativeWindow::Property>() << NativeWindow::WindowFlags << NativeWindow::Title << NativeWindow::Icon \
- << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Size );
+ initWindowFrame();
+ LoadProperties( NativeWindow::allProperties() );
//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));
+ connect(WIN, SIGNAL(PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)), this, SLOT(PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>)));
}
RootSubWindow::~RootSubWindow(){
@@ -35,10 +35,140 @@ 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) && !titleBar->geometry().contains(pt)){
+ //above the frame itself - need to figure out which quadrant it is in (8-directions)
+ if(pt.y() < WIN_BORDER){
+ //One of the top options
+ if(pt.x() < WIN_BORDER){
+ if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner
+ return ResizeTopLeft;
+ }else if(pt.x() > (this->width()-WIN_BORDER)){
+ 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()-WIN_BORDER) ){
+ //One of the bottom options
+ if(pt.x() < WIN_BORDER){
+ 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()-WIN_BORDER)){
+ 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() < WIN_BORDER){
+ 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()-WIN_BORDER) ){
+ 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){
+ if(currentCursor==state && !override){ return; } //nothing to change
+ 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{
+ currentCursor = state;
+ 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);
+ otherB = new QToolButton(this);
+ titleLabel = new QLabel(this);
+ titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ otherM = new QMenu(this); //menu of other actions
+ otherB->setMenu(otherM);
+ otherB->setPopupMode(QToolButton::InstantPopup);
+ otherB->setAutoRaise(true);
+ 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(otherB);
+ 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: darkblue;} QWidget#Label_Title{background-color: transparent; color: white; }");
+ //And adjust the margins
+ mainLayout->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER);
+ mainLayout->setSpacing(0);
+ titleBar->setSpacing(1);
+ titleBar->setContentsMargins(0,0,0,0);
+}
+
void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){
+ QList<QVariant> vals;
for(int i=0; i<list.length(); i++){
- propertyChanged( list[i], WIN->property(list[i]) );
+ vals << WIN->property(list[i]);
}
+ propertiesChanged(list, vals);
}
// === PUBLIC SLOTS ===
@@ -48,63 +178,202 @@ 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::clientShown(){
- qDebug() << "Client Shown";
- this->show();
+void RootSubWindow::toggleMaximize(){
+
}
-// === PRIVATE SLOTS ===
-void RootSubWindow::aboutToActivate(){
- WIN->emit RequestActivate(WIN->id());
+void RootSubWindow::triggerClose(){
+ WIN->requestClose();
+}
+
+void RootSubWindow::toggleSticky(){
+
+}
+
+void RootSubWindow::activate(){
+ WIN->requestProperty(NativeWindow::Active, true);
+}
+
+//Mouse Interactivity
+void RootSubWindow::startMoving(){
+ //If the cursor is not over this window, move it to the center of the titlebar
+ QPoint curpt = QCursor::pos(); //global coords
+ if(!this->geometry().contains(curpt)){
+ curpt = this->mapToGlobal(titleBar->geometry().center());
+ QCursor::setPos(curpt);
+ }
+ //Calculate the offset
+ activeState = Move;
+ offset = this->mapFromGlobal(curpt);
+ setMouseCursor(activeState, true); //this one is an override cursor
+ //Also need to capture the mouse
+ this->grabMouse();
+}
+
+void RootSubWindow::startResizing(){
+
}
-void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){
- if(val.isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet
- qDebug() << "Set Window Property:" << prop << val;
- switch(prop){
+
+
+// === PRIVATE SLOTS ===
+void RootSubWindow::propertiesChanged(QList<NativeWindow::Property> props, QList<QVariant> vals){
+ for(int i=0; i<props.length() && i<vals.length(); i++){
+ if(vals[i].isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet
+ //qDebug() << "Set Window Property:" << props[i] << vals[i];
+ switch(props[i]){
case NativeWindow::Visible:
- if(val.toBool()){ clientShown(); }
- else{ clientHidden(); }
+ if(vals[i].toBool()){ this->show(); }
+ else{ this->hide(); }
break;
case NativeWindow::Title:
- this->setWindowTitle(val.toString());
+ titleLabel->setText(vals[i].toString());
break;
case NativeWindow::Icon:
- this->setWindowIcon(val.value< QIcon>());
+ otherB->setIcon(vals[i].value< QIcon>());
break;
case NativeWindow::Size:
- this->resize(val.toSize());
+ WinWidget->resize(vals[i].toSize());
break;
case NativeWindow::MinSize:
- this->setMinimumSize(val.toSize());
+ WinWidget->setMinimumSize(vals[i].toSize());
break;
case NativeWindow::MaxSize:
- this->setMaximumSize(val.toSize());
+ WinWidget->setMaximumSize(vals[i].toSize());
break;
case NativeWindow::Active:
- if(val.toBool()){ this->mdiArea()->setActiveSubWindow(this); }
+ if(vals[i].toBool()){ WinWidget->setFocus(); }
break;
- case NativeWindow::WindowFlags:
+ /*case NativeWindow::WindowFlags:
this->setWindowFlags( val.value< Qt::WindowFlags >() );
- break;
+ break;*/
default:
- qDebug() << "Window Property Unused:" << prop << val;
+ qDebug() << "Window Property Unused:" << props[i] << vals[i];
+ }
}
}
// === 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();
+ QSize minsize(WinWidget->minimumSize().width() + (2*WIN_BORDER), WinWidget->minimumSize().height()+(2*WIN_BORDER)+titleBar->geometry().size().height());
+ switch(activeState){
+ case Move:
+ geom.moveTopLeft(ev->globalPos()-offset); //will not change size
+ break;
+ case ResizeTop:
+ geom.setTop(ev->globalPos().y()-offset.y());
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ break;
+ case ResizeTopRight:
+ geom.setTopRight(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeRight:
+ geom.setRight(ev->globalPos().x()-offset.x());
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeBottomRight:
+ geom.setBottomRight(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setRight(geom.x() + minsize.width()); //reset back to min width
+ }
+ break;
+ case ResizeBottom:
+ geom.setBottom(ev->globalPos().y()-offset.y());
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ break;
+ case ResizeBottomLeft:
+ geom.setBottomLeft(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setBottom(geom.y() + minsize.height()); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ break;
+ case ResizeLeft:
+ geom.setLeft(ev->globalPos().x()-offset.x());
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ break;
+ case ResizeTopLeft:
+ geom.setTopLeft(ev->globalPos()-offset);
+ if(geom.size().height() < minsize.height()){
+ geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height
+ }
+ if(geom.size().width() < minsize.width()){
+ geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width
+ }
+ 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()) );
+ if(QWidget::mouseGrabber() == this){ this->releaseMouse(); }
+}
+
+void RootSubWindow::leaveEvent(QEvent *ev){
+ QFrame::leaveEvent(ev);
+ if(activeState == Normal){
+ setMouseCursor(Normal);
+ }
+}
bgstack15