2007-09-26 09:44:06 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 Ivan Cukic <ivan.cukic+kde@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
2007-10-12 10:44:02 +02:00
|
|
|
* it under the terms of the GNU Library/Lesser General Public License
|
|
|
|
* version 2, or (at your option) any later version, as published by the
|
|
|
|
* Free Software Foundation
|
2007-09-26 09:44:06 +02:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details
|
|
|
|
*
|
2007-10-12 10:44:02 +02:00
|
|
|
* You should have received a copy of the GNU Library/Lesser General Public
|
2007-09-26 09:44:06 +02:00
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2007-09-27 20:51:31 +02:00
|
|
|
#include "kcategorizeditemsviewdelegate_p.h"
|
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
#include <cmath>
|
|
|
|
|
2007-12-10 20:50:31 +01:00
|
|
|
#include <QtCore/QtCore>
|
2007-09-27 20:51:31 +02:00
|
|
|
|
|
|
|
#include <KIconLoader>
|
|
|
|
|
|
|
|
#include "kcategorizeditemsview_p.h"
|
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
#define FAV_ICON_SIZE 24
|
|
|
|
#define EMBLEM_ICON_SIZE 16
|
|
|
|
#define UNIVERSAL_PADDING 6
|
|
|
|
#define FADE_LENGTH 32
|
|
|
|
#define MAIN_ICON_SIZE 48
|
|
|
|
#define DROPDOWN_PADDING 2
|
|
|
|
#define DROPDOWN_SEPARATOR_HEIGHT 32
|
|
|
|
|
|
|
|
KCategorizedItemsViewDelegate::KCategorizedItemsViewDelegate(QObject * parent)
|
2008-01-04 00:54:18 +01:00
|
|
|
: QItemDelegate(parent), m_favoriteIcon("bookmarks"),
|
2007-12-28 22:26:03 +01:00
|
|
|
m_favoriteAddIcon("list-add"), m_removeIcon("list-remove"),
|
2007-09-26 09:44:06 +02:00
|
|
|
m_onFavoriteIconItem(NULL)
|
|
|
|
{
|
|
|
|
m_parent = (KCategorizedItemsView *) parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCategorizedItemsViewDelegate::paint(QPainter *painter,
|
|
|
|
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
|
|
{
|
2007-12-10 02:18:57 +01:00
|
|
|
KCategorizedItemsViewModels::AbstractItem * item =
|
|
|
|
getItemByProxyIndex(index);
|
|
|
|
if (!item) return;
|
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
// Preparing needed data for painting
|
|
|
|
int left = option.rect.left();
|
|
|
|
int top = option.rect.top();
|
|
|
|
int width = option.rect.width();
|
|
|
|
int height = option.rect.height();
|
|
|
|
|
|
|
|
QColor backgroundColor = (option.state.testFlag(QStyle::State_Selected))?
|
|
|
|
option.palette.color(QPalette::Highlight):option.palette.color(QPalette::Base);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
// Base Background
|
|
|
|
painter->fillRect(option.rect, QBrush(backgroundColor));
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
switch (index.column()) {
|
|
|
|
case 0:
|
|
|
|
paintColMain(painter, option, item);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
paintColFav(painter, option, item);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
paintColRemove(painter, option, item);
|
|
|
|
break;
|
|
|
|
default:
|
2008-01-08 02:25:09 +01:00
|
|
|
kDebug() << "unexpected column";
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
// Dividing line
|
|
|
|
backgroundColor = option.palette.color(QPalette::Highlight);
|
|
|
|
backgroundColor.setAlpha(100);
|
|
|
|
painter->setPen(backgroundColor);
|
|
|
|
painter->drawLine(left, top + height - 1, left + width, top + height - 1);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
void KCategorizedItemsViewDelegate::paintColMain(QPainter *painter,
|
|
|
|
const QStyleOptionViewItem &option, const KCategorizedItemsViewModels::AbstractItem * item) const
|
|
|
|
{
|
|
|
|
int left = option.rect.left();
|
|
|
|
int top = option.rect.top();
|
|
|
|
int width = option.rect.width();
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
bool leftToRight = (painter->layoutDirection() == Qt::LeftToRight);
|
|
|
|
QIcon::Mode iconMode = QIcon::Normal;
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
QColor backgroundColor = (option.state.testFlag(QStyle::State_Selected))?
|
|
|
|
option.palette.color(QPalette::Highlight):option.palette.color(QPalette::Base);
|
|
|
|
QColor foregroundColor = (option.state.testFlag(QStyle::State_Selected))?
|
|
|
|
option.palette.color(QPalette::HighlightedText):option.palette.color(QPalette::Text);
|
|
|
|
|
|
|
|
// Painting main column
|
|
|
|
QStyleOptionViewItem local_option_title(option);
|
|
|
|
QStyleOptionViewItem local_option_normal(option);
|
|
|
|
|
|
|
|
local_option_title.font.setBold(true);
|
|
|
|
local_option_title.font.setPointSize(local_option_title.font.pointSize() + 2);
|
|
|
|
|
|
|
|
QLinearGradient gradient;
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
QString title = item->name();
|
|
|
|
QString description = item->description();
|
|
|
|
|
|
|
|
// Painting
|
|
|
|
|
|
|
|
// Text
|
|
|
|
int textInner = 2 * UNIVERSAL_PADDING + MAIN_ICON_SIZE;
|
|
|
|
|
|
|
|
painter->setPen(foregroundColor);
|
|
|
|
painter->setFont(local_option_title.font);
|
|
|
|
painter->drawText(
|
2007-09-26 09:44:06 +02:00
|
|
|
left + (leftToRight ? textInner : 0),
|
|
|
|
top + UNIVERSAL_PADDING,
|
|
|
|
width - textInner, MAIN_ICON_SIZE / 2,
|
|
|
|
Qt::AlignBottom | Qt::AlignLeft, title);
|
2007-12-10 02:18:57 +01:00
|
|
|
painter->setFont(local_option_normal.font);
|
|
|
|
painter->drawText(
|
2007-09-26 09:44:06 +02:00
|
|
|
left + (leftToRight ? textInner : 0),
|
|
|
|
top + UNIVERSAL_PADDING + MAIN_ICON_SIZE / 2,
|
|
|
|
width - textInner, MAIN_ICON_SIZE / 2,
|
|
|
|
Qt::AlignTop | Qt::AlignLeft, description);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
// Main icon
|
|
|
|
item->icon().paint(painter,
|
|
|
|
leftToRight ? left + UNIVERSAL_PADDING : left + width - UNIVERSAL_PADDING - MAIN_ICON_SIZE,
|
2007-09-26 09:44:06 +02:00
|
|
|
top + UNIVERSAL_PADDING,
|
|
|
|
MAIN_ICON_SIZE, MAIN_ICON_SIZE, Qt::AlignCenter, iconMode);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
// Counting the number of emblems for this item
|
|
|
|
int emblemCount = 0;
|
|
|
|
QPair < Filter, QIcon * > emblem;
|
|
|
|
foreach (emblem, m_parent->m_emblems) {
|
|
|
|
if (item->passesFiltering(emblem.first)) ++emblemCount;
|
|
|
|
}
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
// Gradient part of the background - fading of the text at the end
|
|
|
|
if (leftToRight) {
|
|
|
|
gradient = QLinearGradient(left + width - UNIVERSAL_PADDING - FADE_LENGTH, 0,
|
2007-09-26 09:44:06 +02:00
|
|
|
left + width - UNIVERSAL_PADDING, 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
gradient.setColorAt(1, backgroundColor);
|
|
|
|
backgroundColor.setAlpha(0);
|
|
|
|
gradient.setColorAt(0, backgroundColor);
|
|
|
|
} else {
|
|
|
|
gradient = QLinearGradient(left + UNIVERSAL_PADDING, 0,
|
2007-09-26 09:44:06 +02:00
|
|
|
left + UNIVERSAL_PADDING + FADE_LENGTH, 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
gradient.setColorAt(0, backgroundColor);
|
|
|
|
backgroundColor.setAlpha(0);
|
|
|
|
gradient.setColorAt(1, backgroundColor);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
QRect paintRect = option.rect;
|
|
|
|
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
|
|
|
|
painter->fillRect(paintRect, gradient);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
if (leftToRight) {
|
|
|
|
gradient.setStart(left + width
|
2007-09-26 09:44:06 +02:00
|
|
|
- emblemCount * (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE) - FADE_LENGTH, 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
gradient.setFinalStop(left + width
|
2007-09-26 09:44:06 +02:00
|
|
|
- emblemCount * (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE), 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
} else {
|
|
|
|
gradient.setStart(left + UNIVERSAL_PADDING
|
2007-09-26 09:44:06 +02:00
|
|
|
+ emblemCount * (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE), 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
gradient.setFinalStop(left + UNIVERSAL_PADDING
|
2007-09-26 09:44:06 +02:00
|
|
|
+ emblemCount * (UNIVERSAL_PADDING + EMBLEM_ICON_SIZE) + FADE_LENGTH, 0);
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
|
|
|
paintRect.setHeight(UNIVERSAL_PADDING + MAIN_ICON_SIZE / 2);
|
|
|
|
painter->fillRect(paintRect, gradient);
|
|
|
|
|
|
|
|
// Emblems icons
|
|
|
|
int emblemLeft = leftToRight ? (left + width - EMBLEM_ICON_SIZE) : left; // - FAV_ICON_SIZE - 2 * UNIVERSAL_PADDING
|
|
|
|
foreach (emblem, m_parent->m_emblems) {
|
|
|
|
if (item->passesFiltering(emblem.first)) {
|
|
|
|
emblem.second->paint(painter,
|
2007-09-26 09:44:06 +02:00
|
|
|
emblemLeft, top + UNIVERSAL_PADDING,
|
|
|
|
EMBLEM_ICON_SIZE, EMBLEM_ICON_SIZE, Qt::AlignCenter, iconMode);
|
2007-12-10 02:18:57 +01:00
|
|
|
if (leftToRight) {
|
|
|
|
emblemLeft -= UNIVERSAL_PADDING + EMBLEM_ICON_SIZE;
|
|
|
|
} else {
|
|
|
|
emblemLeft += UNIVERSAL_PADDING + EMBLEM_ICON_SIZE;
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
}
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
|
|
|
}
|
2007-09-26 09:44:06 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
void KCategorizedItemsViewDelegate::paintColFav(QPainter *painter,
|
|
|
|
const QStyleOptionViewItem &option, const KCategorizedItemsViewModels::AbstractItem * item) const
|
|
|
|
{
|
|
|
|
int left = option.rect.left();
|
|
|
|
int top = option.rect.top();
|
|
|
|
int width = option.rect.width();
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
// Painting favorite icon column
|
2007-09-26 09:44:06 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
if (! (option.state & QStyle::State_MouseOver) && m_onFavoriteIconItem == item)
|
|
|
|
m_onFavoriteIconItem = NULL;
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
QIcon::Mode iconMode = QIcon::Normal;
|
|
|
|
if (!item->isFavorite()) {
|
|
|
|
iconMode = QIcon::Disabled;
|
|
|
|
} else if (option.state & QStyle::State_MouseOver) {
|
|
|
|
iconMode = QIcon::Active;
|
|
|
|
}
|
2007-09-26 09:44:06 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
m_favoriteIcon.paint(painter,
|
2007-09-26 09:44:06 +02:00
|
|
|
left + width - FAV_ICON_SIZE - UNIVERSAL_PADDING, top + UNIVERSAL_PADDING,
|
|
|
|
FAV_ICON_SIZE, FAV_ICON_SIZE, Qt::AlignCenter, iconMode);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
const KIcon * icon = (item->isFavorite())? & m_removeIcon : & m_favoriteAddIcon;
|
2007-09-26 09:44:06 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
if ((option.state & QStyle::State_MouseOver) && (m_onFavoriteIconItem != item))
|
|
|
|
icon->paint(painter,
|
2007-09-26 09:44:06 +02:00
|
|
|
left + width - EMBLEM_ICON_SIZE - UNIVERSAL_PADDING, top + UNIVERSAL_PADDING,
|
|
|
|
EMBLEM_ICON_SIZE, EMBLEM_ICON_SIZE, Qt::AlignCenter, iconMode);
|
2007-12-10 02:18:57 +01:00
|
|
|
}
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
void KCategorizedItemsViewDelegate::paintColRemove(QPainter *painter,
|
|
|
|
const QStyleOptionViewItem &option, const KCategorizedItemsViewModels::AbstractItem * item) const
|
|
|
|
{
|
|
|
|
// Painting remove icon column
|
|
|
|
int running = item->running();
|
|
|
|
if (!running) {
|
|
|
|
return;
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
int left = option.rect.left();
|
|
|
|
int top = option.rect.top();
|
|
|
|
int width = option.rect.width();
|
|
|
|
|
|
|
|
QIcon::Mode iconMode = QIcon::Normal;
|
|
|
|
if (option.state & QStyle::State_MouseOver) {
|
|
|
|
iconMode = QIcon::Active;
|
|
|
|
}
|
2007-09-26 09:44:06 +02:00
|
|
|
|
2007-12-10 02:18:57 +01:00
|
|
|
m_removeIcon.paint(painter,
|
|
|
|
left + width - FAV_ICON_SIZE - UNIVERSAL_PADDING, top + UNIVERSAL_PADDING,
|
|
|
|
FAV_ICON_SIZE, FAV_ICON_SIZE, Qt::AlignCenter, iconMode);
|
|
|
|
|
|
|
|
if (running == 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//paint number
|
|
|
|
QColor foregroundColor = (option.state.testFlag(QStyle::State_Selected))?
|
|
|
|
option.palette.color(QPalette::HighlightedText):option.palette.color(QPalette::Text);
|
|
|
|
painter->setPen(foregroundColor);
|
|
|
|
painter->setFont(option.font);
|
|
|
|
painter->drawText(
|
|
|
|
left + UNIVERSAL_PADDING, //FIXME might be wrong
|
|
|
|
top + UNIVERSAL_PADDING + MAIN_ICON_SIZE / 2,
|
|
|
|
width - 2 * UNIVERSAL_PADDING, MAIN_ICON_SIZE / 2,
|
|
|
|
Qt::AlignCenter, QString::number(running));
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool KCategorizedItemsViewDelegate::editorEvent(QEvent *event,
|
|
|
|
QAbstractItemModel *model,
|
|
|
|
const QStyleOptionViewItem &option,
|
|
|
|
const QModelIndex &index)
|
|
|
|
{
|
2007-12-10 02:18:57 +01:00
|
|
|
if (event->type() == QEvent::MouseButtonPress) {
|
|
|
|
KCategorizedItemsViewModels::AbstractItem * item = getItemByProxyIndex(index);
|
|
|
|
if (index.column() == 1) {
|
2008-02-11 07:07:14 +01:00
|
|
|
m_onFavoriteIconItem = item;
|
|
|
|
item->setFavorite(!item->isFavorite());
|
2007-12-10 02:18:57 +01:00
|
|
|
return true;
|
|
|
|
} else if (index.column() == 2 && item->running()) {
|
|
|
|
item->setRunning(0);
|
|
|
|
emit destroyApplets(item->name());
|
|
|
|
return true;
|
|
|
|
}
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QItemDelegate::editorEvent(event, model, option, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize KCategorizedItemsViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|
|
|
const QModelIndex &index ) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(option);
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
//Q_UNUSED(index);
|
|
|
|
int width = (index.column() == 0) ? 0 : FAV_ICON_SIZE;
|
|
|
|
return QSize(width, MAIN_ICON_SIZE + 2 * UNIVERSAL_PADDING);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KCategorizedItemsViewDelegate::columnWidth (int column, int viewWidth) const {
|
2007-12-10 02:18:57 +01:00
|
|
|
if (column != 0) {
|
2007-09-26 09:44:06 +02:00
|
|
|
return FAV_ICON_SIZE + 2 * UNIVERSAL_PADDING;
|
2007-12-10 02:18:57 +01:00
|
|
|
} else return viewWidth - 2 * columnWidth(1, viewWidth);
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-18 21:55:50 +01:00
|
|
|
KCategorizedItemsViewModels::AbstractItem * KCategorizedItemsViewDelegate::getItemByProxyIndex(const QModelIndex & index) const {
|
2007-09-26 09:44:06 +02:00
|
|
|
return (AbstractItem *) m_parent->m_modelItems->itemFromIndex(
|
|
|
|
m_parent->m_modelFilterItems->mapToSource(index)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// KCategorizedItemsViewFilterDelegate
|
|
|
|
|
|
|
|
|
|
|
|
KCategorizedItemsViewFilterDelegate::KCategorizedItemsViewFilterDelegate(QObject *parent)
|
|
|
|
: QItemDelegate(parent) {
|
2008-01-08 02:25:09 +01:00
|
|
|
kDebug() << "KCategorizedItemsViewFilterDelegate(QObject *parent)\n";
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void KCategorizedItemsViewFilterDelegate::paint(QPainter *painter,
|
|
|
|
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
|
|
{
|
|
|
|
if (index.flags() & Qt::ItemIsEnabled) {
|
|
|
|
QItemDelegate::paint(painter, option, index);
|
|
|
|
} else {
|
|
|
|
QStyleOptionViewItem separatorOption(option);
|
|
|
|
int height = QItemDelegate::sizeHint(option, index).height() + 2 * DROPDOWN_PADDING;
|
2007-09-29 21:11:27 +02:00
|
|
|
|
2007-09-26 09:44:06 +02:00
|
|
|
separatorOption.state &= ~(QStyle::State_Selected
|
|
|
|
| QStyle::State_MouseOver | QStyle::State_HasFocus);
|
|
|
|
separatorOption.rect.setTop(separatorOption.rect.top() + separatorOption.rect.height() - height);
|
|
|
|
separatorOption.rect.setHeight(height);
|
|
|
|
QItemDelegate::paint(painter, separatorOption, index);
|
|
|
|
/*painter->drawLine(
|
|
|
|
option.rect.left(),
|
|
|
|
option.rect.top() + 1,
|
|
|
|
option.rect.left() + option.rect.width(),
|
|
|
|
option.rect.top() + 1);*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize KCategorizedItemsViewFilterDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|
|
|
const QModelIndex &index ) const
|
|
|
|
{
|
|
|
|
QSize size = QItemDelegate::sizeHint(option, index);
|
|
|
|
if (index.flags() & Qt::ItemIsEnabled) {
|
|
|
|
size.setHeight(size.height() + 2 * DROPDOWN_PADDING);
|
|
|
|
} else {
|
|
|
|
size.setHeight(DROPDOWN_SEPARATOR_HEIGHT);
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2007-09-27 20:51:31 +02:00
|
|
|
#include "kcategorizeditemsviewdelegate_p.moc"
|
2007-09-26 09:44:06 +02:00
|
|
|
|