0

What I want is to create a sidebar with qt with QTreeView that branches are put at right side of items. Like AdminLTE sidebar: https://adminlte.io/themes/AdminLTE/index2.html#.

I have Tried several solutions each failing my desired design:

  1. Using delegates
  2. Deriving TreeView class and reimplement DrawBranches
  3. Create a custom ProxyStyle

The whole point is I am from a web development background and doing such things is super easy with it!

Edit:

Supposing we have a stupid ProxyStyle-derived class, what I should do for the situations below:

void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    if (element == PE_IndicatorBranch) {
        // put this damn thing at right
    }
    else if(element == PE_PanelItemViewItem) {
        // put this at left
    }
    // else
    QProxyStyle::drawPrimitive(element, option, painter, widget);
}

or maybe using a delegate:

void TreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    // for example translate branch!? what to do????
    QStyledItemDelegate::paint(painter, option, index);

}

or maybe reimplementing TreeView::DrawBranches. Either way, no idea what to do to fully accomplish my requirements.

Edit2:

This is it for now, but still not what I want, for example hovering makes off behavior:

sidebar.cpp

#include "sidebar.h"

#include <QMouseEvent>
#include <QPainter>
#include "sidebarstyle.h"
#include "sidebardelegate.h"

SideBar::SideBar(QWidget *parent)
    : QTreeView(parent)
{
    setStyle(new SideBarStyle);
    setItemDelegate(new SideBarDelegate(this));
    setHeaderHidden(true);
    setEditTriggers(QAbstractItemView::NoEditTriggers);
    //    setIndentation(40);
    resize(230, parent->height());
    setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));

    //    QPalette palette;
    //    palette.setBrush(QPalette::Base, QColor(34, 45, 50));
    //    palette.setBrush(QPalette::Highlight, Qt::transparent);
    //    setPalette(palette);
    setStyleSheet("QTreeView::item {height: 50px;} QTreeView {background-color: #222d32; color: #b8c7ce; font-size: 14px; font-weight: 400;} QTreeView::branch:selected, QTreeView::item:selected, QTreeView::branch:hover, QTreeView::item:hover {background-color: #1e282c; color: #fff}");
    //    setStyleSheet("QTreeView {background-color: #222d32; color: #b8c7ce}");


}

void SideBar::mousePressEvent(QMouseEvent *event)
{
    QModelIndex index = indexAt(event->pos());
    bool lastState = isExpanded(index);
    QTreeView::mousePressEvent(event);
    setExpanded(index, !lastState);
}

void SideBar::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const
{
    QTreeView::drawBranches(painter, rect, index);
}

sidebardelegate.cpp

#include "sidebardelegate.h"
#include <QPainter>
#include "state.h"

SideBarDelegate::SideBarDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
    font.setFamily("FontAwesome");
    font.setPixelSize(28);

}

void SideBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
    QStyledItemDelegate::paint(painter, option, index);
    if(index.column() == 0){
        QRect _branch = QRect(option.widget->width() - option.decorationSize.width() -25, option.rect.y() + option.rect.height() / 4, option.decorationSize.width() + 15, option.rect.height() / 2);
        //        QRect icon = QRect(5, option.rect.y() + option.rect.height() / 4, option.decorationSize.width(), option.rect.height() / 2);
        QModelIndex _index = index;
        int depth = 0;
        while ( _index.parent().isValid() )
        {
            _index = _index.parent();
            depth++;
        }
        //        if(index.parent().isValid()) {
        QRect icon = QRect(5 + option.decorationSize.width() * depth, option.rect.y() + option.rect.height() / 4, option.decorationSize.width() + 10, option.rect.height() / 2);
        //        }
        painter->setFont(font);
        if(option.state & QStyle::State_Children)
        {
            if(option.state & QStyle::State_Open)
            {
                //                painter->drawImage(_branch, QImage("/home/fisher/Pictures/Download.png"));
                painter->drawText(_branch, "\uf107");
            }
            else
            {
                //painter->drawImage(_branch, QImage("/home/fisher/Pictures/135210286.png"));
                painter->drawText(_branch, "\uf104");
            }
            switch (index.row()) {
            case 0:
                //                painter->drawImage(icon, QImage("/home/fisher/Pictures/135210286.png"));
                painter->drawText(icon, "\uf080");
                break;
            case 1:
                //                painter->drawImage(icon, QImage("/home/fisher/Pictures/images.png"));
                painter->drawText(icon, "\uf14a");
                break;
            case 2:
                //                painter->drawImage(icon, QImage("/home/fisher/Pictures/iamges.jpeg"));
                painter->drawText(icon, "\uf0c3");
                break;
            default:
                //                painter->drawImage(icon, QImage("/home/fisher/Pictures/images (1).png"));
                painter->drawText(icon, "\uf085");
            }
            if(option.state & QStyle::State_Selected) {
                QRect bar = QRect(0, option.rect.y(), 2, option.rect.height());
                painter->setBrush(QColor(60, 141, 188));
                painter->setPen(QColor(60, 141, 188));
                painter->drawRect(bar);
            }
        } else {
                        adjustDefaultTextColors(option, *painter);
            painter->drawText(icon, "\uf111");
            //painter->drawImage(icon, QImage("/home/fisher/Pictures/images (1).jpeg"));
        }
    }
}

void SideBarDelegate::adjustDefaultTextColors(const QStyleOptionViewItem &option, QPainter &painter)  const
{
    if(option.state & QStyle::State_MouseOver) {
        painter.setPen(QColor(255, 255, 255));
    } else {
        painter.setPen(QColor(138, 164, 175));
    }
}

sidebarstyle.cpp

#include "sidebarstyle.h"
#include <QStyleFactory>
#include <QStyleOption>
#include <QColor>

SideBarStyle::SideBarStyle()
    : QProxyStyle(QStyleFactory::create("linux"))
{
}

void SideBarStyle::drawPrimitive(PrimitiveElement element,
                                 const QStyleOption *option,
                                 QPainter *painter,
                                 const QWidget *widget) const
{
    if(element & PE_IndicatorBranch) {
        return;
    }
//    if(option->state & QStyle::State_HasFocus){
//        QStyleOptionViewItem myViewItemOption;
//        const QStyleOptionViewItem *viewItemOption =
//                qstyleoption_cast<const QStyleOptionViewItem *>(option);
//        if (viewItemOption) {
//            myViewItemOption = *viewItemOption;
//            myViewItemOption.palette.setBrush(QPalette::Highlight, QColor(30, 40, 44));
//            myViewItemOption.palette.setBrush(QPalette::HighlightedText, Qt::white);
//        }
//        QProxyStyle::drawPrimitive(element, &myViewItemOption, painter, widget);
//        return;
//    }
    QProxyStyle::drawPrimitive(element, option, painter, widget);

}

//void SideBarStyle::drawControl(ControlElement element,
//                               const QStyleOption *option,
//                               QPainter *painter,
//                               const QWidget *widget) const
//{
////    if(option->state & QStyle::State_HasFocus){
////        QStyleOptionViewItem myViewItemOption;
////        const QStyleOptionViewItem *viewItemOption =
////                qstyleoption_cast<const QStyleOptionViewItem *>(option);
////        if (viewItemOption) {
////            myViewItemOption = *viewItemOption;
////            myViewItemOption.palette.setBrush(QPalette::Highlight, QColor(30, 40, 44));
////            myViewItemOption.palette.setBrush(QPalette::HighlightedText, Qt::white);

////        }
////        QProxyStyle::drawControl(element, &myViewItemOption, painter, widget);
////        return;
////    }
//    QProxyStyle::drawControl(element, option, painter, widget);
//}

current picture

Also I borrowed some help from @eyllanesc answer to this question: How to remove QTreeView indentation

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Armin Fisher
  • 134
  • 5
  • Be advised, I have read Qt docs extensively, the point is I still don't know what to do, please help :( – Armin Fisher Dec 06 '19 at 11:28
  • Please provide [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) of your attempt to do that, what did you get as a result and what was wrong with it. – folibis Dec 07 '19 at 14:59
  • Sure, see edit above. – Armin Fisher Dec 09 '19 at 14:44
  • Just imagine doing this with angular or maybe qml! piece of cake – Armin Fisher Dec 09 '19 at 14:50
  • @ArminFisher you could show an image of what you want to obtain, a link to a website does not help since it has many elements and you cannot distinguish what you want to obtain. On the other hand your question should not be very wide, if you have a similar question but with different technologies ( 1) C++ - QTreeView, 2) QML-TreeView) then you must create several questions. – eyllanesc Dec 10 '19 at 15:49

1 Answers1

0

You can try QWidget::setLayoutDirection

auto view = new QTreeView();
view->setLayoutDirection(Qt::RightToLeft);
daru
  • 76
  • 2