Review Request for KDecoration

Milian Wolff mail at milianw.de
Mon Nov 3 22:33:15 GMT 2014


On Friday 31 October 2014 08:22:53 Martin Gräßlin wrote:
> Hi KDE core developers,
> 
> today I want to start the review process for the new KDecoration library[1].
> This library is intended to replace the window decoration library used by
> KWin and addresses some of the shortcomings we hit with the existing
> library.

Hey Martin,

I'll list a few things that I spotted, in no special order. Is there maybe a 
possibility to get some tooling help in the review phase here? Copy'n'pasting 
code and filenames is cumbersome to say the least ;-) Maybe we could create a 
(git read-only) kdereview repository to reviewboard. Then one can add the 
whole repo as a huge diff to that repository and review stuff there? Admins, 
is this feasible?

DecorationShadow::Private
	int paddingTop;
    int paddingRight;
    int paddingBottom;
    int paddingLeft;
-> QMargins? Might also simplify DecorationShadow then, though I don't know 
whether QMargins is transparently useable from within QML.

DecorationButton::Private and other places
    QPointer<Decoration>
-> is the lifetime really undefined? I.e. can a button outlive a decoration? 
Or put differently, why do you need a QPointer here? Also, if you really want 
to use it, pass it by const& like Albert mentioned.

Decoration::Private
-> unrelated question: why do you add getters and setters for private data? 
just because or do you see a value in that? Personally, I'd get rid of all 
that code and use plain structs where possible. This is private API after all. 
With Q_D or similar you'll also get a const/non-const d_ptr which gives you 
const-correctness as well. But this is certainly not something you must 
change. I'm genuinely interested why you decided to go that route.

DecorationSettings
    onAllDesktopsAvailableChanged
-> remove the "on" prefix

DecorationButtonGroup::Private
    buttons() const
-> returning a const& is usually a bad idea. And due to NRVO it won't be 
faster than returning a non-const. Rather, you should bind to a const& on the 
callee side if you want to optimize, see also 
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Note how this "issue" would not exist, if you'd let the public class access 
the data members of the ::Private classes directly.

DecorationButton .cpp
    auto updateSlot = [this]() { update(); };
    connect(this, &DecorationButton::hoveredChanged, this, updateSlot);
    connect(this, &DecorationButton::pressedChanged, this, updateSlot);
    connect(this, &DecorationButton::checkedChanged, this, updateSlot);
    connect(this, &DecorationButton::enabledChanged, this, updateSlot);
-> remove the named lambda and replace it with &DecorationButton::update
-> also further down in ::addButton

DecoarationButton
    #define DELEGATE
    #undef
    #define
-> why not have one macro, called DEFINE_GETTER_SETTER?

DecorationButtonGroup.cpp
    for (auto it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) {
-> for (auto button : m_buttons)
also in other places

while (!d->buttons().isEmpty()) {
                delete d->buttons().takeFirst();
            }
-> qDeleteAll + clear. Also note how this loop has very bad performance as you 
takeFirst. A QList<T*> is - more or less - a QVector<T*>. 

DecorationButtonGroup::hasButton
-> you iterate over a list of QPointer<...> but do not check for the validity 
of the buttons. Why do you use QPointer then?

DecorationButtonGroup::removeButton
-> I'd suggest you use std::remove_if + std::erase.

Generally: Ceterum censeo QList esse delendam
-> I suggest you remove QList and use QVector by default everywhere.

DecoratedClient::DC
    , d(std::move(bridge->createClient(this, parent)))
-> is the move here really required? I don't think so.

DecoratedClient::decoration
-> why wrap it in a QPointer? If the caller wants a QPointer, he can wrap it 
manually, no?

Decoration.cpp
    ::findBridge
-> this should go into an anonymous namespace or made static
-> the check for isValid is not really required, .toMap will give you an empty 
map in such cases
-> the find etc. below can be replaced by this code:
    b = map.value(QStringLiteral("bridge"));
.value() of a QMap/QHash will return a default-constructed value of T. And a 
T*() == Q_NULLPTR.
So overall this can be written as:

namespace {
DecorarationBridge* findBridge(const QVariantList &args)
{
    for (const auto &arg : args) {
        if (auto bridge = arg.toMap().value(QStringLiteral("bridge"))) {
            return bridge;
        }
    }
    Q_UNREACHABLE();
}
}

Decoration::Private::set(Extended)Borders
-> QMargins?

DecoarationBridge::DB
    qRegisterMetaType<Qt::MouseButton>();
-> upstream that to Qt? Or why is this required here?

Overall I can say very clean code. Nice work Martin! Hope the above nitpicks 
help you a bit.

Cheers!
-- 
Milian Wolff
mail at milianw.de
http://milianw.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20141103/464c72e5/attachment.sig>


More information about the kde-core-devel mailing list