From 8d1a0d190b40cc398d8e3a11f3f9aefddf590a84 Mon Sep 17 00:00:00 2001 From: Hane Date: Wed, 3 Apr 2024 21:53:07 +0200 Subject: [PATCH] width + screen position --- src/qt/qtclasses.cpp | 219 +++++++++++++++++++++++++++++++------------ src/qt/qtclasses.h | 42 ++++++++- src/qtestmain.cpp | 3 +- 3 files changed, 199 insertions(+), 65 deletions(-) diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index 125352b..3887cb0 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -25,19 +25,61 @@ void ExtendedCheckBox::customEvent(QEvent* ev) { QCheckBox::customEvent(ev); } +QRect MainWindow::setSizePosition() { + //setGeometry ignores decoration size xdddd + QRect trayIconPos = this->trayIcon->geometry(); + int tix1, tix2, tiy1, tiy2; + trayIconPos.getCoords(&tix1, &tiy1, &tix2, &tiy2); + + screen = QGuiApplication::primaryScreen(); + QRect screenRes = screen->geometry(); + int srx1, srx2, sry1, sry2; + screenRes.getCoords(&srx1, &sry1, &srx2, &sry2); + QRect availableRes = screen->availableGeometry(); + int arx1, arx2, ary1, ary2; + availableRes.getCoords(&arx1, &ary1, &arx2, &ary2); + + uint8_t pos = 0; + pos = tiy2 < (sry2 / 2) ? SpawnPos::UP : SpawnPos::DOWN; + pos = tix2 < (srx2 / 2) ? pos | SpawnPos::LEFT : pos | SpawnPos::RIGHT; + + switch (pos) { + case SpawnPos::UP | SpawnPos::RIGHT: + return QRect((arx2 - windowWidth), ary1, windowWidth, 440); + break; + case SpawnPos::DOWN | SpawnPos::LEFT: + return QRect(arx1, (ary2-440), windowWidth, 440); + break; + case SpawnPos::DOWN | SpawnPos::RIGHT: + return QRect((arx2 - windowWidth), (ary2-440), windowWidth, 440); + break; + default: + return QRect(500, 400, windowWidth, 440); + break; + } +} + SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) : QWidget(parent){ - //todo: based on qgridlayout, name+mute should be its own widget, same with channels + //todo: based on qgridlayout, name+mute should be its own widget, same with channels this->idx = idx; this->sh = sh; - layout = new QGridLayout(this); + layout = new QHBoxLayout(this); + //layout->setSizeConstraint(QLayout::SetFixedSize); + layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + //layout->setMaximumSize(minimumSize()); //this->setLayout( muteButton = new QCheckBox(this); mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); mainSlider = new QSlider(Qt::Horizontal, this); - mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + mainLabel->setMaximumWidth(150 /*1/16ish 1080p*/); + mainLabel->setMinimumWidth(150 /*1/16ish 1080p*/); + mainLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + mainSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + mainSlider->setMinimumWidth(120 /*1/16 1080p*/); mainSlider->setFocusPolicy(Qt::StrongFocus); mainSlider->setTickPosition(QSlider::TicksBothSides); mainSlider->setTickInterval(5); @@ -46,17 +88,27 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) muteButton->setCheckState((sh->getMute() == false ? Qt::Unchecked : Qt::Checked)); muteButton->setText(sh->getMute() ? STRING_UNMUTE : STRING_MUTE); + muteButton->setMaximumWidth(60 /*1/32th 1080p*/); + muteButton->setMinimumWidth(60 /*1/32th 1080p*/); float volume = sh->getVolume(AudioChannel::CHANNEL_MAIN) * 100; mainSlider->setValue((int)volume); log_debugcpp("SESSION SET WITH VOLUME " + std::to_string(volume)); //tip: would need to be new widget with layout in it //mainMuteLayout = new QGridLayout(); - layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom); - layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom); - layout->addWidget(mainSlider, 0, 2, 1, 2); + /* + * layout->addWidget(mainLabel, 0, 0, Qt::AlignLeft | Qt::AlignBottom); + * layout->addWidget(muteButton, 0, 1, Qt::AlignLeft | Qt::AlignBottom); + * layout->addWidget(mainSlider, 0, 2, 1, 2); + * + * layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + */ + layout->addItem(new QSpacerItem(200, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); + layout->addWidget(mainLabel, Qt::AlignLeft | Qt::AlignBottom); + layout->addWidget(muteButton, Qt::AlignRight | Qt::AlignBottom); + layout->addWidget(mainSlider, Qt::AlignRight | Qt::AlignBottom); - layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + //layout->setSizeConstraint(QLayout::SetMinAndMaxSize); //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? connect(mainSlider, &QSlider::valueChanged, this,&SessionWidget::updateMainVolume); @@ -102,6 +154,49 @@ SessionWidget::~SessionWidget() { delete volumePoller; } +ChannelWidget::ChannelWidget(uint32_t channelCount, EndpointHandler* eph, QWidget *parent) : QWidget(parent){ + this->eph = eph; + this->channelCount = channelCount; + layout = new QGridLayout(this); + float volume = 100; +/* + * Channel sliders setup + */ + //uint32_t epChannelCount = eph->getChannelCount(); + for(uint32_t i = 0; i < channelCount && channelCount > 1; i++){ + QSlider* tmp = new QSlider(Qt::Horizontal); + QLabel* tmpLb = new QLabel(""); + tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + tmp->setTickInterval(5); + tmp->setSingleStep(1); + tmp->setRange(0,100); + + volume = eph->getVolume(i) * 100; + tmp->setValue((int) volume); + tmpLb->setText(QString::number(volume)); + this->channelSliders.push_back(tmp); + this->channelLabels.push_back(tmpLb); + layout->addWidget(tmp, 0, i); + layout->addWidget(tmpLb, 1, i); + + //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func + //this causes channel bar desync when back -> front. blocksignals below fix it. huh. + connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ + this->eph->setVolume(osh->getGuid(), i, newValue); + this->channelLabels.at(i)->setText(QString::number(newValue)); + }); + } + this->setLayout(layout); + +} + +void ChannelWidget::updateChannel(int channel) { + this->channelSliders.at(channel)->blockSignals(true); + this->channelSliders.at(channel)->setValue((int)((eph->getCallbackInfo()->channelVolumes[channel] + roundingFactor) * 100)); + this->channelLabels.at(channel)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[channel] + roundingFactor) * 100))); + this->channelSliders.at(channel)->blockSignals(false); +} + EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *parent) : QWidget(parent){ //todo: based on qgridlayout, name+mute should be its own widget, same with channels row = 0; @@ -135,6 +230,10 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Minimum), 1, 0); return; } + + mainLabel->setMaximumWidth(240 /*1/8 1080p*/); + mainLabel->setMinimumWidth(240 /*1/8 1080p*/); + //mainLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); //muteButton->setStyleSheet("background-color: #A3C1DA; color: red"); mainSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -152,11 +251,11 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare //tip: would need to be new widget with layout in it //mainMuteLayout = new QGridLayout(); - layout->addWidget(mainLabel, row, 0, Qt::AlignLeft | Qt::AlignVCenter); - layout->addWidget(muteButton, row, 1, Qt::AlignLeft | Qt::AlignVCenter); + layout->addWidget(mainLabel, row, 0, Qt::AlignLeft | Qt::AlignVCenter); + layout->addWidget(muteButton, row, 1, Qt::AlignLeft | Qt::AlignVCenter); layout->addWidget(mainSlider, row, 2, 1, 2, Qt::AlignLeft | Qt::AlignVCenter); layout->setSizeConstraint(QLayout::SetMinAndMaxSize); - int debug2 = this->minimumWidth(); + //int debug2 = this->minimumWidth(); row++; //TODO:0 = mute and muted, change volume = unmuted are client side tricks = 2 callbacks, one for volume, one for mute state. Implement as an user selectable option? @@ -164,34 +263,15 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare connect(muteButton, &QCheckBox::stateChanged, this, (&EndpointWidget::updateMute)); -/* - * Channel sliders setup - */ + /* + * Channel sliders setup + */ + uint32_t epChannelCount = eph->getChannelCount(); - for(uint32_t i = 0; i < epChannelCount && epChannelCount > 1; i++){ - QSlider* tmp = new QSlider(Qt::Horizontal); - QLabel* tmpLb = new QLabel(""); - tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - tmp->setTickInterval(5); - tmp->setSingleStep(1); - tmp->setRange(0,100); - - volume = eph->getVolume(i) * 100; - tmp->setValue((int) volume); - tmpLb->setText(QString::number(volume)); - this->channelSliders.push_back(tmp); - this->channelLabels.push_back(tmpLb); - layout->addWidget(tmp, row + 1, i); - layout->addWidget(tmpLb, row + 2, i); - - //TODO: check if there's a need to prevent deadlocks; probably this will eventually turn into its own func - //this causes channel bar desync when back -> front. blocksignals below fix it. huh. - connect(tmp, &QSlider::valueChanged, [this, i](int newValue){ - this->eph->setVolume(osh->getGuid(), i, newValue); - this->channelLabels.at(i)->setText(QString::number(newValue)); - }); + if(epChannelCount) { + cw = new ChannelWidget(epChannelCount, eph, this); + layout->addWidget(cw, row++, 0, 1, 4 /*colmax*/); } - row += 3; /* * Role ExtendedCheckBoxes setup @@ -229,16 +309,18 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare this->eph->setRoles(Roles::ROLE_COMMUNICATIONS); }); - layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), row, 0); - layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), row, 1); - layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), row, 2); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_ALL), row, 0); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_CONSOLE), row, 1); + layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_MULTIMEDIA), row, 2); layout->addWidget(defaultRolesCheckBoxes.at(Roles::ROLE_COMMUNICATIONS), row, 3); row++; -/* ----------------------------------------------------------- */ + + /* ----------------------------------------------------------- */ /* * EndpointVolume Polling time */ + timer = new QTimer(); connect(timer, &QTimer::timeout, [this, eph](){ //if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW. @@ -250,10 +332,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare muteButton->setCheckState((eph->getCallbackInfo()->muted == false ? Qt::Unchecked : Qt::Checked)); muteButton->setText(eph->getCallbackInfo()->muted ? STRING_UNMUTE : STRING_MUTE); for(uint32_t i = 0; i < eph->getCallbackInfo()->channels && eph->getChannelCount() > 1; i++){ - this->channelSliders.at(i)->blockSignals(true); - this->channelSliders.at(i)->setValue((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100)); - this->channelLabels.at(i)->setText(QString::number((int)((eph->getCallbackInfo()->channelVolumes[i] + roundingFactor) * 100))); - this->channelSliders.at(i)->blockSignals(false); + cw->updateChannel(i); } //memcpy(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)); @@ -268,7 +347,7 @@ EndpointWidget::EndpointWidget(uint64_t idx, EndpointHandler* eph, QWidget *pare /* First SessionWidget batch */ for (size_t i = 0; i < eph->getSessionCount(); i++) { SessionWidget* sessionWidget = new SessionWidget(i, eph->getSessionHandlers().at(i), this); - layout->addWidget(sessionWidget, row, 1, 1, 4); + layout->addWidget(sessionWidget, row, 0, 1, 4); row++; sessionWidgets.push_back(sessionWidget); eph->getSessionHandlers().at(i)->setFrontIndex(i); @@ -295,7 +374,7 @@ void EndpointWidget::addSessionWidget(CustomWidgetEvent* ev){ uint64_t index = this->sessionWidgets.size(); SessionWidget* sw = new SessionWidget(index, ev->payload, this); ev->payload->setFrontIndex(index); - this->layout->addWidget(sw, row, 1, 1, 4); + this->layout->addWidget(sw, row, 0, 1, 4); row++; sessionWidgets.push_back(sw); return; @@ -455,14 +534,15 @@ std::map EndpointWidget::getDefaultRolesWidgets() { HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) { layout = new QGridLayout(this); + QString text = "&" STRING_ABOUT; - about = new QPushButton(text, this); + about = new QPushButton(text, this); #ifdef WIN32 text = "&" STRING_CP; - openCP = new QPushButton(text, this); - connect(openCP, &QPushButton::clicked, [this](){ osh->openControlPanel(); }); - text = "&" STRING_STARTUP; - startup = new QPushButton(text, this); + openCP = new QPushButton(text, this); + connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); }); + text = "&" STRING_STARTUP; + startup = new QPushButton(text, this); layout->addWidget(openCP , 0, 0); layout->addWidget(startup, 0, 1); @@ -474,10 +554,17 @@ HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) { MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { // setWindowState(Qt::WindowFullScreen); // setCentralWidget(centralWidget); - + //todo: ratio + resize(windowWidth, 440); + setWindowFlags(Qt::Window | Qt::MSWindowsFixedSizeDialogHint); + #ifdef DEBUG + setWindowTitle(STRING_TITLE); + setWindowFlags(Qt::FramelessWindowHint); + #endif /* * Registering needed custom events */ + //| Qt::FramelessWindowHint QEvent::registerEventType(CustomQEvent::EndpointWidgetObsolete); QEvent::registerEventType(CustomQEvent::EndpointWidgetCreated); QEvent::registerEventType(CustomQEvent::EndpointDefaultChange); @@ -487,13 +574,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { //setWindowFlags(Qt::FramelessWindowHint); //setParent(0); // Create TopLevel-Widget //setAttribute(Qt::WA_NoSystemBackground, true); - //setAttribute(Qt::WA_TranslucentBackground, true); + //setAttribute(Qt::WA_TranslucentBackground, true); ewsUpdateTimer = new QTimer(this); widget = new QWidget(); layout = new QGridLayout(); trayIcon = new QSystemTrayIcon(); trayIconMenu = new QMenu(); trayIconMenuQuit = new QAction(STRING_QUIT); + trayIconMenuOpenCP = new QAction(STRING_CP); ewsUpdateTimer->setSingleShot(true); ewsUpdateTimer->setInterval(ewsUpdateTimerFrequency); @@ -513,24 +601,27 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { /* * Menu bar code */ - QMenuBar* menuBar = (this->menuBar)(); + mainMenuBar = this->menuBar(); hw = new HeaderWidget(this); - menuBar->setCornerWidget(hw,Qt::TopLeftCorner); - menuBar->show(); - this->setMenuBar(menuBar); + mainMenuBar->setCornerWidget(hw,Qt::TopLeftCorner); + mainMenuBar->show(); + this->setMenuBar(mainMenuBar); //setCentralWidget(widget); //layout->addWidget(pintas, 0, 0); - setWindowTitle(STRING_TITLE); reloadEndpointWidgets(); scrollArea->setMinimumWidth(ews.at(0)->minimumWidth()); - int debug = scrollArea->minimumWidth(); + log_debugcpp(std::to_string(scrollArea->minimumWidth())); + /* * Tray Icon code */ + //trayIconMenu->addSeparator(); + trayIconMenu->addAction(trayIconMenuOpenCP); trayIconMenu->addSeparator(); - trayIconMenu->addAction(trayIconMenuQuit); + trayIconMenu->addAction(trayIconMenuQuit); + connect(trayIconMenuOpenCP, &QAction::triggered, ([]() {osh->openControlPanel();}) ); connect(trayIconMenuQuit, &QAction::triggered, qApp, &QCoreApplication::quit); trayIcon->setIcon(QIcon(":/assets/notificationAreaIcon.png")); setWindowIcon(QIcon(":/assets/notificationAreaIcon.png")); @@ -540,6 +631,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { trayIcon->setToolTip(STRING_TITLE); trayIcon->setContextMenu(trayIconMenu); connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivated); + + /* + * Establishing initial window size and position + */ + //TODO: test. hardcode. var. + setGeometry(setSizePosition()); /* * Set of function callback definitons for EndpointSituationCallback @@ -598,7 +695,6 @@ void MainWindow::closeEvent(QCloseEvent *event) { if (trayIcon->isVisible()) { //todo: would be nice to show this to 1st time users; ini-san will come... //this->trayIcon->showMessage("ini file calling","tratarte como un gilipollas la primera vez", QSystemTrayIcon::Information); - hide(); event->ignore(); } @@ -607,6 +703,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { switch (reason) { case QSystemTrayIcon::Trigger: + this->setGeometry(this->setSizePosition()); this->showNormal(); break; default: diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 7a89400..4521120 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -22,6 +22,7 @@ #include #include #include +#include //#include /* @@ -62,6 +63,14 @@ * ToggleButton(QWidget *parent = nullptr); * }; */ + +enum SpawnPos { + LEFT = (1 << 1), + RIGHT = (0 << 1), + UP = (1 << 0), + DOWN = (0 << 0) +}; + enum CustomQEvent { EndpointWidgetObsolete = 1001, EndpointWidgetCreated = 1002, @@ -108,12 +117,30 @@ private: QLabel *mainLabel = nullptr; QSlider *mainSlider = nullptr; uint64_t idx; - QGridLayout *layout = nullptr; + //QGridLayout *layout = nullptr; + QHBoxLayout *layout = nullptr; QCheckBox *muteButton = nullptr; SessionHandler* sh; QTimer* volumePoller = nullptr; }; +class ChannelWidget : public QWidget { +Q_OBJECT + +public: + ChannelWidget(uint32_t channelCount, EndpointHandler* eph, QWidget *parent = nullptr); + void updateChannel(int channel); + +private: + const double roundingFactor = 0.005; + EndpointHandler* eph; + uint32_t channelCount; + std::vector channelSliders; + std::vector channelLabels; + QGridLayout *layout; + +}; + class EndpointWidget : public QWidget { Q_OBJECT @@ -162,6 +189,7 @@ private: size_t defaultRolesVectorSize = 4; QTimer* timer = nullptr; uint64_t idx; + ChannelWidget* cw; std::vector sessionWidgets; //std::vector *ephs; //std::vector *sliders; @@ -177,7 +205,6 @@ Q_OBJECT public: HeaderWidget(QWidget *parent = nullptr); - //~HeaderWidget(); //void updateMainVolume(float newValue); //void updateVolume(uint32_t channel, float newValue); @@ -215,6 +242,7 @@ public: protected: void closeEvent(QCloseEvent *event) override; void customEvent(QEvent* ev) override; + QRect setSizePosition(); private slots: void trayIconActivated(QSystemTrayIcon::ActivationReason reason); @@ -233,12 +261,20 @@ private: QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; QAction *trayIconMenuQuit; + QAction *trayIconMenuOpenCP; QTimer *ewsUpdateTimer; static constexpr uint64_t ewsUpdateTimerFrequency = 500; + //TODO: Test + //TODO: Come back here and check all are parametrized + uint64_t windowWidth = 600; QScrollArea *scrollArea; HeaderWidget* hw; - //QMenuBar *menuBar; + QMenuBar *mainMenuBar; + QScreen *screen; + //Win10 1080p 120% + QSize mwSize; + //public slots: // void setEndpointHandlers(std::vector *ephs); diff --git a/src/qtestmain.cpp b/src/qtestmain.cpp index 14c1aa8..85e1928 100644 --- a/src/qtestmain.cpp +++ b/src/qtestmain.cpp @@ -55,8 +55,9 @@ int main (int argc, char* argv[]) { //INIT FRONT QScopedPointer app(createApplication(argc, argv)); + MainWindow window = MainWindow(); - + //window.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::QSizePolicy::MinimumExpanding) QApplication::setQuitOnLastWindowClosed(false); /* * QFile styleFile(":/assets/style.qss");