File indexing completed on 2024-04-28 16:45:07

0001 /*
0002     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #pragma once
0007 
0008 #include <kscreen/config.h>
0009 #include <kscreen/output.h>
0010 
0011 #include <QAbstractListModel>
0012 #include <QPoint>
0013 #include <optional>
0014 
0015 class ConfigHandler;
0016 
0017 class OutputModel : public QAbstractListModel
0018 {
0019     Q_OBJECT
0020 public:
0021     enum OutputRoles {
0022         EnabledRole = Qt::UserRole + 1,
0023         InternalRole,
0024         PriorityRole,
0025         SizeRole,
0026         /** Position in the graphical view relative to some arbitrary but fixed origin. */
0027         PositionRole,
0028         /** Position for backend relative to most northwest display corner. */
0029         NormalizedPositionRole,
0030         AutoRotateRole,
0031         AutoRotateOnlyInTabletModeRole,
0032         RotationRole,
0033         ScaleRole,
0034         ResolutionIndexRole,
0035         ResolutionsRole,
0036         ResolutionRole,
0037         RefreshRateIndexRole,
0038         RefreshRatesRole,
0039         ReplicationSourceModelRole,
0040         ReplicationSourceIndexRole,
0041         ReplicasModelRole,
0042         CapabilitiesRole,
0043         OverscanRole,
0044         VrrPolicyRole,
0045         RgbRangeRole,
0046         InteractiveMoveRole, // This output is currently repositioned interactively
0047     };
0048 
0049     explicit OutputModel(ConfigHandler *configHandler);
0050     ~OutputModel() override = default;
0051 
0052     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0053     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0054     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
0055 
0056     void add(const KScreen::OutputPtr &output);
0057     void remove(int outputId);
0058 
0059     /**
0060      * Resets the origin for calculation of positions to the most northwest display corner
0061      * while keeping the normalized positions untouched.
0062      *
0063      * @return true if some (unnormalized) output position changed on this call, otherwise false.
0064      */
0065     bool normalizePositions();
0066     bool positionsNormalized() const;
0067 
0068     bool isMoving() const;
0069 
0070 Q_SIGNALS:
0071     void positionChanged();
0072     void sizeChanged();
0073 
0074 protected:
0075     QHash<int, QByteArray> roleNames() const override;
0076 
0077 private:
0078     struct Output {
0079         Output()
0080         {
0081         }
0082         Output(const Output &output)
0083             : ptr(output.ptr)
0084             , pos(output.pos)
0085         {
0086         }
0087         Output(Output &&) noexcept = default;
0088         Output(KScreen::OutputPtr _ptr, const QPoint &_pos)
0089             : ptr(_ptr)
0090             , pos(_pos)
0091         {
0092         }
0093         Output &operator=(const Output &output)
0094         {
0095             ptr = output.ptr;
0096             pos = output.pos;
0097             posReset = std::nullopt;
0098             return *this;
0099         }
0100         Output &operator=(Output &&) noexcept = default;
0101 
0102         KScreen::OutputPtr ptr;
0103         QPoint pos;
0104         // Indicates how to restore position when enabling or un-mirroring a screen.
0105         // Negative value of x means that the output was the left-most, and restoring it would require shifting all the other ones to the right.
0106         // Same for the y and shifting down.
0107         std::optional<QPoint> posReset = std::nullopt;
0108         bool moving = false;
0109     };
0110 
0111     void rolesChanged(int outputId, const QVector<int> &roles);
0112     QModelIndex indexForOutputId(int outputId) const;
0113 
0114     void resetPosition(Output &output);
0115     void reposition();
0116     void updatePositions();
0117 
0118     /**
0119      * @brief Snaps moved output to others
0120      * @param output the moved output
0121      * @param dest the desired destination to be adjusted by snapping
0122      */
0123     void snap(const Output &output, QPoint &dest);
0124     void maintainSnapping(const Output &changedOutput, const QSize &oldSize, const QSize &newSize);
0125     QPoint mostTopLeftLocationOfPositionableOutputOptionallyIgnoringOneOfThem(std::optional<KScreen::OutputPtr> ignored = std::nullopt) const;
0126 
0127     bool setEnabled(int outputIndex, bool enable);
0128 
0129     bool setResolution(int outputIndex, int resIndex);
0130     bool setRefreshRate(int outputIndex, int refIndex);
0131     bool setRotation(int outputIndex, KScreen::Output::Rotation rotation);
0132     bool setAutoRotate(int outputIndex, bool value);
0133     bool setAutoRotateOnlyInTabletMode(int outputIndex, bool value);
0134 
0135     int resolutionIndex(const KScreen::OutputPtr &output) const;
0136     int refreshRateIndex(const KScreen::OutputPtr &output) const;
0137     QSize resolution(const KScreen::OutputPtr &output) const;
0138     QVariantList resolutionsStrings(const KScreen::OutputPtr &output) const;
0139     QVector<QSize> resolutions(const KScreen::OutputPtr &output) const;
0140     QVector<float> refreshRates(const KScreen::OutputPtr &output) const;
0141 
0142     bool positionable(const Output &output) const;
0143 
0144     QStringList replicationSourceModel(const KScreen::OutputPtr &output) const;
0145     bool setReplicationSourceIndex(int outputIndex, int sourceIndex);
0146     int replicationSourceIndex(int outputIndex) const;
0147     int replicationSourceId(const Output &output) const;
0148 
0149     QVariantList replicasModel(const KScreen::OutputPtr &output) const;
0150 
0151     QVector<Output> m_outputs;
0152 
0153     ConfigHandler *m_config;
0154 };