Commit 77ee9821 authored by Frederik Gladhorn's avatar Frederik Gladhorn

Make Primary Combo a regular QComboBox

Summary:
This will make it easier to re-design the UI.
Also it centralizes all updates, before a bunch of connections for the
individual outputs were not made when a new output appeared.

Reviewers: #plasma, mart

Reviewed By: #plasma, mart

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D14023
parent 615b0353
......@@ -11,7 +11,6 @@ set(kcm_kscreen_SRCS
collapsablebutton.cpp
controlpanel.cpp
outputconfig.cpp
primaryoutputcombo.cpp
unifiedoutputconfig.cpp
resolutionslider.cpp
utils.cpp
......
/*
* Copyright 2015 Daniel Vrátil <dvratil@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "primaryoutputcombo.h"
#include "utils.h"
#include <KLocalizedString>
#include <KScreen/Config>
#include <KScreen/Output>
PrimaryOutputCombo::PrimaryOutputCombo(QWidget* parent)
: QComboBox(parent)
{
connect(this, static_cast<void(QComboBox::*)(int)>(&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();
}
/*
* Copyright 2015 Daniel Vrátil <dvratil@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef PRIMARYOUTPUTCOMBO_H
#define PRIMARYOUTPUTCOMBO_H
#include <QComboBox>
#include <KScreen/Types>
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
......@@ -22,7 +22,6 @@
#ifdef WITH_PROFILES
#include "profilesmodel.h"
#endif
#include "primaryoutputcombo.h"
#include <QVBoxLayout>
#include <QSplitter>
......@@ -82,9 +81,11 @@ Widget::Widget(QWidget *parent)
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<int>::of(&QComboBox::currentIndexChanged),
this, &Widget::primaryOutputSelected);
mPrimaryLabel = new QLabel(i18n("Primary display:"));
hbox->addWidget(mPrimaryLabel);
hbox->addWidget(mPrimaryCombo);
......@@ -163,24 +164,26 @@ void Widget::setConfig(const KScreen::ConfigPtr &config)
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,6 +230,40 @@ void Widget::loadQml()
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());
......@@ -234,18 +271,23 @@ void Widget::slotFocusedOutputChanged(QMLOutput *output)
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 @@ void Widget::clearOutputIdentifiers()
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);
......
......@@ -64,6 +64,7 @@ class Widget : public QWidget
void slotFocusedOutputChanged(QMLOutput *output);
void slotOutputEnabledChanged();
void slotOutputConnectedChanged();
void slotUnifyOutputs();
void slotProfileChanged(int index);
......@@ -75,9 +76,15 @@ class Widget : public QWidget
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 @@ class Widget : public QWidget
ControlPanel *mControlPanel = nullptr;
ProfilesModel *mProfilesModel = nullptr;
PrimaryOutputCombo *mPrimaryCombo = nullptr;
QComboBox *mPrimaryCombo = nullptr;
QLabel *mPrimaryLabel = nullptr;
QComboBox *mProfilesCombo = nullptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment