Skip to content

Commit

Permalink
Custom Paint Suggestion Icon&Text Spacing
Browse files Browse the repository at this point in the history
Qt does not provide css style or API for modifying icon and text spacing in QTreeView. This is a long issue in buttons as well, as Qt draws icon and texts instead of having them as widgets that can be applied styles.
  • Loading branch information
ShaopengLin committed Oct 22, 2024
1 parent a63e63b commit 68a288b
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 1 deletion.
2 changes: 2 additions & 0 deletions kiwix-desktop.pro
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ SOURCES += \
src/rownode.cpp \
src/suggestionlistworker.cpp \
src/suggestionlistmodel.cpp \
src/suggestionlistdelegate.cpp \
src/thumbnaildownloader.cpp \
src/translation.cpp \
src/main.cpp \
Expand Down Expand Up @@ -111,6 +112,7 @@ HEADERS += \
src/rownode.h \
src/suggestionlistworker.h \
src/suggestionlistmodel.h \
src/suggestionlistdelegate.h \
src/thumbnaildownloader.h \
src/translation.h \
src/mainwindow.h \
Expand Down
1 change: 1 addition & 0 deletions src/css_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace section {
const int margin = 5;
const int lineHeight = 24;
const int paddingBottom = 5;
const int paddingLeft = 10;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/searchbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "kiwixapp.h"
#include "suggestionlistworker.h"
#include "css_constants.h"
#include "suggestionlistdelegate.h"

namespace HeaderSectionCSS = CSS::PopupCSS::QHeaderView::section;

Expand Down Expand Up @@ -81,7 +82,7 @@ SearchBarLineEdit::SearchBarLineEdit(QWidget *parent) :
m_completer.setPopup(m_suggestionView);

/* The Delegate was overwritten by setPopup(), which is not style-aware */
m_suggestionView->setItemDelegate(new QStyledItemDelegate(this));
m_suggestionView->setItemDelegate(new SuggestionListDelegate(this));
m_suggestionView->header()->setStretchLastSection(true);
m_suggestionView->setRootIsDecorated(false);
m_suggestionView->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/popup.css"));
Expand Down
72 changes: 72 additions & 0 deletions src/suggestionlistdelegate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "suggestionlistdelegate.h"
#include "kiwixapp.h"
#include "css_constants.h"

#include <QPainter>

namespace HeaderSectionCSS = CSS::PopupCSS::QHeaderView::section;

void SuggestionListDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
/* Paint without text and icon */
QStyleOptionViewItem opt(option);
QStyledItemDelegate::paint(painter, opt, QModelIndex());

paintIcon(painter, opt, index);
paintText(painter, opt, index);
}

void SuggestionListDelegate::paintIcon(QPainter *p,
const QStyleOptionViewItem &opt,
const QModelIndex &index) const
{
QRect pixmapRect = opt.rect;
const int lineHeight = HeaderSectionCSS::lineHeight;
const int paddingLeft = HeaderSectionCSS::paddingLeft;

const QSize mapSize = QSize(lineHeight, lineHeight);
auto pixmap = index.data(Qt::DecorationRole).value<QIcon>().pixmap(mapSize);

/* Align icon to Header text */
if (KiwixApp::isRightToLeft())
{
const int rightEnd = pixmapRect.width() - mapSize.width();
pixmapRect.setX(pixmapRect.x() + rightEnd - paddingLeft);
}
else
pixmapRect.setX(pixmapRect.x() + paddingLeft);

/* Align middle */
pixmapRect.setY(pixmapRect.y() + (pixmapRect.height() - mapSize.height()) / 2);
pixmapRect.setSize(mapSize);
p->drawPixmap(pixmapRect, pixmap);
}

void SuggestionListDelegate::paintText(QPainter *p,
const QStyleOptionViewItem &opt,
const QModelIndex &index) const
{
auto& searchBar = KiwixApp::instance()->getSearchBar();
const auto& lineEditGeo = searchBar.getLineEdit().geometry();

/* Remove border from left() since left is is with respect to border. Detail
reason on how this calculation comes about can be seen in
SearchBarLineEdit::getCompleterRect();
*/
const int left = lineEditGeo.left() - CSS::SearchBar::border;
QRect textRect = opt.rect;
if (KiwixApp::isRightToLeft())
{
const auto& searchGeo = searchBar.geometry();
const int right = searchGeo.width() - left - lineEditGeo.width();
textRect.setWidth(textRect.width() - right);
}
else
textRect.setX(textRect.x() + left);

const int flag = {Qt::AlignVCenter | Qt::AlignLeading};
const QString text = index.data(Qt::DisplayRole).toString();
p->drawText(textRect, flag, text);
}
17 changes: 17 additions & 0 deletions src/suggestionlistdelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef SUGGESTIONLISTDELEGATE_H
#define SUGGESTIONLISTDELEGATE_H

#include <QStyledItemDelegate>

class SuggestionListDelegate : public QStyledItemDelegate
{
public:
SuggestionListDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {};
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

private:
void paintIcon(QPainter *p, const QStyleOptionViewItem &opt, const QModelIndex &index) const;
void paintText(QPainter *p, const QStyleOptionViewItem &opt, const QModelIndex &index) const;
};

#endif // SUGGESTIONLISTDELEGATE_H

0 comments on commit 68a288b

Please sign in to comment.