diff --git a/kcm/src/CMakeLists.txt b/kcm/src/CMakeLists.txt --- a/kcm/src/CMakeLists.txt +++ b/kcm/src/CMakeLists.txt @@ -11,7 +11,6 @@ collapsablebutton.cpp controlpanel.cpp outputconfig.cpp - primaryoutputcombo.cpp unifiedoutputconfig.cpp resolutionslider.cpp utils.cpp diff --git a/kcm/src/primaryoutputcombo.h b/kcm/src/primaryoutputcombo.h deleted file mode 100644 --- a/kcm/src/primaryoutputcombo.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015 Daniel Vrátil - * - * 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 2 of - * the License or (at your option) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * 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 . - * - */ - -#ifndef PRIMARYOUTPUTCOMBO_H -#define PRIMARYOUTPUTCOMBO_H - -#include - -#include - -class PrimaryOutputCombo : public QComboBox -{ - Q_OBJECT -public: - explicit PrimaryOutputCombo(QWidget *parent = nullptr); - ~PrimaryOutputCombo() override; - - void setConfig(const KScreen::ConfigPtr &config); - KScreen::OutputPtr primaryOutput() const; - -Q_SIGNALS: - void changed(); - -private Q_SLOTS: - void addOutput(const KScreen::OutputPtr &output); - void removeOutput(int outputId); - void setPrimaryOutput(const KScreen::OutputPtr &output); - void outputChanged(const KScreen::OutputPtr &output); - - void onCurrentIndexChanged(int currentIndex); - -private: - void addOutputItem(const KScreen::OutputPtr &output); - void removeOutputItem(int outputId); - -private: - KScreen::ConfigPtr mConfig; -}; - -#endif diff --git a/kcm/src/primaryoutputcombo.cpp b/kcm/src/primaryoutputcombo.cpp deleted file mode 100644 --- a/kcm/src/primaryoutputcombo.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2015 Daniel Vrátil - * - * 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 2 of - * the License or (at your option) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * 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 . - * - */ - -#include "primaryoutputcombo.h" -#include "utils.h" - -#include - -#include -#include - - -PrimaryOutputCombo::PrimaryOutputCombo(QWidget* parent) - : QComboBox(parent) -{ - connect(this, static_cast(&QComboBox::currentIndexChanged), - this, &PrimaryOutputCombo::onCurrentIndexChanged); - - setSizeAdjustPolicy(QComboBox::AdjustToContents); - addItem(i18n("No Primary Output")); -} - -PrimaryOutputCombo::~PrimaryOutputCombo() -{ -} - -void PrimaryOutputCombo::setConfig(const KScreen::ConfigPtr &config) -{ - if (mConfig) { - mConfig->disconnect(this); - for (const KScreen::OutputPtr &output : mConfig->outputs()) { - output->disconnect(this); - } - } - - clear(); - addItem(i18n("No Primary Output")); - - if (!config) { - return; - } - - mConfig = config; - connect(mConfig.data(), &KScreen::Config::outputAdded, - this, &PrimaryOutputCombo::addOutput); - connect(mConfig.data(), &KScreen::Config::outputRemoved, - this, &PrimaryOutputCombo::removeOutput); - connect(mConfig.data(), &KScreen::Config::primaryOutputChanged, - this, &PrimaryOutputCombo::setPrimaryOutput); - - // Don't emit currentIndexChanged - const bool blocked = blockSignals(true); - for (const KScreen::OutputPtr &output : config->outputs()) { - addOutput(output); - } - blockSignals(blocked); -} - -void PrimaryOutputCombo::addOutput(const KScreen::OutputPtr &output) -{ - connect(output.data(), &KScreen::Output::isConnectedChanged, - [output, this]() { - outputChanged(output); - }); - connect(output.data(), &KScreen::Output::isEnabledChanged, - [output, this]() { - outputChanged(output); - }); - - if (!output->isConnected() || !output->isEnabled()) { - return; - } - - addOutputItem(output); -} - -void PrimaryOutputCombo::removeOutput(int outputId) -{ - KScreen::OutputPtr output = mConfig->output(outputId); - if (output) { - output->disconnect(this); - } - - removeOutputItem(outputId); -} - -KScreen::OutputPtr PrimaryOutputCombo::primaryOutput() const -{ - if (!mConfig) { - return KScreen::OutputPtr(); - } - - const int index = currentIndex(); - // "No Primary Output" item - if (index == 0) { - return KScreen::OutputPtr(); - } - - return mConfig->output(itemData(index).toInt()); -} - -void PrimaryOutputCombo::setPrimaryOutput(const KScreen::OutputPtr &output) -{ - Q_ASSERT(mConfig); - - const int index = output ? findData(output->id()) : 0; - if (index == -1) { - return; - } - - if (index == currentIndex()) { - return; - } - - setCurrentIndex(index); -} - - -void PrimaryOutputCombo::outputChanged(const KScreen::OutputPtr &output) -{ - const int index = findData(output->id()); - if (index == -1 && output->isConnected() && output->isEnabled()) { - addOutputItem(output); - } else if (index > 0 && (!output->isConnected() || !output->isEnabled())) { - removeOutputItem(output->id()); - } -} - -void PrimaryOutputCombo::addOutputItem(const KScreen::OutputPtr& output) -{ - addItem(Utils::outputName(output), output->id()); - if (output->isPrimary()) { - setPrimaryOutput(output); - } -} - -void PrimaryOutputCombo::removeOutputItem(int outputId) -{ - const int index = findData(outputId); - if (index == -1) { - return; - } - - if (index == currentIndex()) { - // We'll get the actual primary update signal eventually - // Don't emit currentIndexChanged - const bool blocked = blockSignals(true); - setCurrentIndex(0); - blockSignals(blocked); - } - removeItem(index); -} - -void PrimaryOutputCombo::onCurrentIndexChanged(int currentIndex) -{ - if (!mConfig) { - return; - } - - const KScreen::OutputPtr newPrimary = currentIndex == 0 ? KScreen::OutputPtr() : mConfig->output(itemData(currentIndex).toInt()); - if (newPrimary == mConfig->primaryOutput()) { - return; - } - - mConfig->setPrimaryOutput(newPrimary); - Q_EMIT changed(); -} - diff --git a/kcm/src/widget.h b/kcm/src/widget.h --- a/kcm/src/widget.h +++ b/kcm/src/widget.h @@ -64,6 +64,7 @@ void slotFocusedOutputChanged(QMLOutput *output); void slotOutputEnabledChanged(); + void slotOutputConnectedChanged(); void slotUnifyOutputs(); void slotProfileChanged(int index); @@ -75,9 +76,15 @@ void slotIdentifyOutputs(KScreen::ConfigOperation *op); void clearOutputIdentifiers(); + void outputAdded(const KScreen::OutputPtr &output); + void outputRemoved(int outputId); + void primaryOutputSelected(int index); + void primaryOutputChanged(const KScreen::OutputPtr &output); + private: void loadQml(); - void initPrimaryCombo(); + void resetPrimaryCombo(); + void addOutputToPrimaryCombo(const KScreen::OutputPtr &output); KScreen::OutputPtr findOutput(const KScreen::ConfigPtr &config, const QVariantMap &info); @@ -90,7 +97,7 @@ ControlPanel *mControlPanel = nullptr; ProfilesModel *mProfilesModel = nullptr; - PrimaryOutputCombo *mPrimaryCombo = nullptr; + QComboBox *mPrimaryCombo = nullptr; QLabel *mPrimaryLabel = nullptr; QComboBox *mProfilesCombo = nullptr; diff --git a/kcm/src/widget.cpp b/kcm/src/widget.cpp --- a/kcm/src/widget.cpp +++ b/kcm/src/widget.cpp @@ -22,7 +22,6 @@ #ifdef WITH_PROFILES #include "profilesmodel.h" #endif -#include "primaryoutputcombo.h" #include #include @@ -82,9 +81,11 @@ QHBoxLayout *hbox = new QHBoxLayout; vbox->addLayout(hbox); - mPrimaryCombo = new PrimaryOutputCombo(this); - connect(mPrimaryCombo, &PrimaryOutputCombo::changed, - this, &Widget::changed); + mPrimaryCombo = new QComboBox(this); + mPrimaryCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); + mPrimaryCombo->addItem(i18n("No Primary Output")); + connect(mPrimaryCombo, QOverload::of(&QComboBox::currentIndexChanged), + this, &Widget::primaryOutputSelected); mPrimaryLabel = new QLabel(i18n("Primary display:")); hbox->addWidget(mPrimaryLabel); hbox->addWidget(mPrimaryCombo); @@ -163,24 +164,26 @@ for (const KScreen::OutputPtr &output : mConfig->outputs()) { output->disconnect(this); } + mConfig->disconnect(this); } mConfig = config; KScreen::ConfigMonitor::instance()->addConfig(mConfig); + resetPrimaryCombo(); + connect(mConfig.data(), &KScreen::Config::outputAdded, + this, &Widget::outputAdded); + connect(mConfig.data(), &KScreen::Config::outputRemoved, + this, &Widget::outputRemoved); + connect(mConfig.data(), &KScreen::Config::primaryOutputChanged, + this, &Widget::primaryOutputChanged); mScreen->setConfig(mConfig); mControlPanel->setConfig(mConfig); - mPrimaryCombo->setConfig(mConfig); mUnifyButton->setEnabled(mConfig->outputs().count() > 1); mScaleAllOutputsButton->setVisible(!mConfig->supportedFeatures().testFlag(KScreen::Config::Feature::PerOutputScaling)); - mPrimaryCombo->setVisible(mConfig->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay)); - mPrimaryLabel->setVisible(mConfig->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay)); for (const KScreen::OutputPtr &output : mConfig->outputs()) { - connect(output.data(), &KScreen::Output::isEnabledChanged, - this, &Widget::slotOutputEnabledChanged); - connect(output.data(), &KScreen::Output::posChanged, - this, &Widget::changed); + outputAdded(output); } // Select the primary (or only) output by default @@ -227,25 +230,64 @@ this, SLOT(slotIdentifyButtonClicked())); } +void Widget::resetPrimaryCombo() +{ + bool isPrimaryDisplaySupported = mConfig->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay); + mPrimaryLabel->setVisible(isPrimaryDisplaySupported); + mPrimaryCombo->setVisible(isPrimaryDisplaySupported); + + // Don't emit currentIndexChanged when resetting + bool blocked = mPrimaryCombo->blockSignals(true); + mPrimaryCombo->clear(); + mPrimaryCombo->addItem(i18n("No Primary Output")); + mPrimaryCombo->blockSignals(blocked); + + if (!mConfig) { + return; + } + + for (auto &output: mConfig->outputs()) { + addOutputToPrimaryCombo(output); + } +} + +void Widget::addOutputToPrimaryCombo(const KScreen::OutputPtr &output) +{ + if (!output->isConnected() || !output->isEnabled()) { + return; + } + mPrimaryCombo->addItem(Utils::outputName(output), output->id()); + if (output->isPrimary()) { + Q_ASSERT(mConfig); + int lastIndex = mPrimaryCombo->count() - 1; + mPrimaryCombo->setCurrentIndex(lastIndex); + } +} + void Widget::slotFocusedOutputChanged(QMLOutput *output) { mControlPanel->activateOutput(output->outputPtr()); } void Widget::slotOutputEnabledChanged() { - int enabledOutputsCnt = 0; + resetPrimaryCombo(); + + int enabledOutputsCount = 0; Q_FOREACH (const KScreen::OutputPtr &output, mConfig->outputs()) { if (output->isEnabled()) { - ++enabledOutputsCnt; + ++enabledOutputsCount; } - - if (enabledOutputsCnt > 1) { + if (enabledOutputsCount > 1) { break; } } + mUnifyButton->setEnabled(enabledOutputsCount > 1); +} - mUnifyButton->setEnabled(enabledOutputsCnt > 1); +void Widget::slotOutputConnectedChanged() +{ + resetPrimaryCombo(); } void Widget::slotUnifyOutputs() @@ -422,6 +464,65 @@ mOutputIdentifiers.clear(); } +void Widget::outputAdded(const KScreen::OutputPtr &output) +{ + connect(output.data(), &KScreen::Output::isConnectedChanged, + this, &Widget::slotOutputConnectedChanged); + connect(output.data(), &KScreen::Output::isEnabledChanged, + this, &Widget::slotOutputEnabledChanged); + connect(output.data(), &KScreen::Output::posChanged, + this, &Widget::changed); + + addOutputToPrimaryCombo(output); +} + +void Widget::outputRemoved(int outputId) +{ + KScreen::OutputPtr output = mConfig->output(outputId); + if (!output.isNull()) { + output->disconnect(this); + } + + const int index = mPrimaryCombo->findData(outputId); + if (index == -1) { + return; + } + + if (index == mPrimaryCombo->currentIndex()) { + // We'll get the actual primary update signal eventually + // Don't emit currentIndexChanged + const bool blocked = mPrimaryCombo->blockSignals(true); + mPrimaryCombo->setCurrentIndex(0); + mPrimaryCombo->blockSignals(blocked); + } + mPrimaryCombo->removeItem(index); +} + +void Widget::primaryOutputSelected(int index) +{ + if (!mConfig) { + return; + } + + const KScreen::OutputPtr newPrimary = index == 0 ? KScreen::OutputPtr() : mConfig->output(mPrimaryCombo->itemData(index).toInt()); + if (newPrimary == mConfig->primaryOutput()) { + return; + } + + mConfig->setPrimaryOutput(newPrimary); + Q_EMIT changed(); +} + +void Widget::primaryOutputChanged(const KScreen::OutputPtr &output) +{ + Q_ASSERT(mConfig); + int index = output.isNull() ? 0 : mPrimaryCombo->findData(output->id()); + if (index == -1 || index == mPrimaryCombo->currentIndex()) { + return; + } + mPrimaryCombo->setCurrentIndex(index); +} + void Widget::slotIdentifyButtonClicked(bool checked) { Q_UNUSED(checked);