2
* Copyright 2013 Daniel Vrátil <dvratil@redhat.com>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of
7
* the License or (at your option) version 3 or any later version
8
* accepted by the membership of KDE e.V. (or its successor approved
9
* by the membership of KDE e.V.), which shall act as a proxy
10
* defined in Section 14 of version 3 of the license.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "unifiedoutputconfig.h"
23
#include "collapsablebutton.h"
24
#include "resolutionslider.h"
29
#include <KLocalizedString>
31
#include <QGridLayout>
32
#include <QSpacerItem>
36
#include <kscreen/output.h>
37
#include <kscreen/config.h>
40
bool operator<(const QSize &s1, const QSize &s2)
42
return s1.width() * s1.height() < s2.width() * s2.height();
46
bool qMapLessThanKey(const QSize &s1, const QSize &s2)
52
UnifiedOutputConfig::UnifiedOutputConfig(KScreen::Config *config, QWidget *parent)
53
: OutputConfig(parent)
58
UnifiedOutputConfig::~UnifiedOutputConfig()
62
void UnifiedOutputConfig::setOutput(KScreen::Output *output)
67
Q_FOREACH (int id, mOutput->clones()) {
68
mClones << mConfig->output(id);
72
OutputConfig::setOutput(output);
75
void UnifiedOutputConfig::initUi()
77
QVBoxLayout *vbox = new QVBoxLayout(this);
78
mTitle = new QLabel(this);
79
mTitle->setAlignment(Qt::AlignHCenter);
80
vbox->addWidget(mTitle);
82
setTitle(i18n("Unified Outputs"));
84
QGridLayout *formLayout = new QGridLayout();
85
vbox->addLayout(formLayout);
88
KScreen::Output *fakeOutput = createFakeOutput();
89
mResolution = new ResolutionSlider(fakeOutput, this);
90
connect(mResolution, SIGNAL(resolutionChanged(QSize)), SLOT(slotResolutionChanged(QSize)));
91
formLayout->addWidget(new QLabel(i18n("Resolution:"), this), 1, 0);
92
formLayout->addWidget(mResolution, 1, 1);
93
slotResolutionChanged(mResolution->currentResolution());
95
mRotation = new QComboBox(this);
96
connect(mRotation, SIGNAL(currentIndexChanged(int)), SLOT(slotRotationChanged(int)));
97
mRotation->addItem(QIcon::fromTheme(QLatin1String("arrow-up")), i18n("Normal"), KScreen::Output::None);
98
mRotation->addItem(QIcon::fromTheme(QLatin1String("arrow-left")), i18n("90° clockwise"), KScreen::Output::Left);
99
mRotation->addItem(QIcon::fromTheme(QLatin1String("arrow-down")), i18n("Upside down"), KScreen::Output::Inverted);
100
mRotation->addItem(QIcon::fromTheme(QLatin1String("arrow-right")), i18n("90° counterclockwise"), KScreen::Output::Right);
101
formLayout->addWidget(new QLabel(i18n("Orientation:"), this), 2, 0);
102
formLayout->addWidget(mRotation, 2, 1);
104
formLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 2, 3, 1);
107
KScreen::Output *UnifiedOutputConfig::createFakeOutput()
109
// Find set of common resolutions
110
QMap<QSize, int> commonSizes;
111
Q_FOREACH (KScreen::Output *clone, mClones) {
112
QList<QSize> processedSizes;
113
Q_FOREACH (KScreen::Mode *mode, clone->modes()) {
114
// Make sure we don't count some modes multiple times because of different
116
if (processedSizes.contains(mode->size())) {
120
processedSizes << mode->size();
122
if (commonSizes.contains(mode->size())) {
123
commonSizes[mode->size()]++;
125
commonSizes.insert(mode->size(), 1);
130
KScreen::Output *fakeOutput = new KScreen::Output(this);
132
// This will give us list of resolution that are shared by all outputs
133
QList<QSize> commonResults = commonSizes.keys(mClones.count());
134
// If there are no common resolution, fallback to smallest preferred mode
135
if (commonResults.isEmpty()) {
137
Q_FOREACH (KScreen::Output *clone, mClones) {
138
qDebug() << smallestMode << clone->preferredMode()->size();
139
if (!smallestMode.isValid() || clone->preferredMode()->size() < smallestMode) {
140
smallestMode = clone->preferredMode()->size();
143
commonResults << smallestMode;
145
qSort(commonResults);
147
KScreen::ModeList modes;
148
Q_FOREACH (const QSize &size, commonResults) {
149
KScreen::Mode *mode = new KScreen::Mode(fakeOutput);
151
mode->setId(Utils::sizeToString(size));
152
mode->setName(mode->id());
153
modes.insert(mode->id(), mode);
155
fakeOutput->setModes(modes);
156
fakeOutput->setCurrentModeId(Utils::sizeToString(commonResults.last()));
160
void UnifiedOutputConfig::slotResolutionChanged(const QSize &size)
162
// Ignore disconnected outputs
163
if (!size.isValid()) {
167
Q_FOREACH (KScreen::Output *clone, mClones) {
168
const QString &id = findBestMode(clone, size);
174
clone->setCurrentModeId(id);
180
QString UnifiedOutputConfig::findBestMode(const KScreen::Output *output, const QSize &size)
182
float refreshRate = 0;
184
Q_FOREACH (KScreen::Mode *mode, output->modes()) {
185
if (mode->size() == size && mode->refreshRate() > refreshRate) {
186
refreshRate = mode->refreshRate();