From 54518a5896efc9c9c4477a0e6ae4724d6e9e20fc Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 24 Mar 2019 22:34:34 +1100 Subject: [PATCH] custom style delegate for icon view --- global/config.h | 5 +- global/math.cpp | 67 ++- global/math.h | 4 + icons/icons.qrc | 1 + icons/listview.svg | 829 +++++++++++++++++++++++++++++++++++ panels/project.cpp | 52 ++- panels/project.h | 2 + project/footage.cpp | 14 - project/footage.h | 2 - project/media.cpp | 39 +- project/media.h | 2 + project/previewgenerator.cpp | 4 - project/sourcescommon.h | 3 +- ui/sourceiconview.cpp | 125 ++++++ ui/sourceiconview.h | 10 + 15 files changed, 1085 insertions(+), 74 deletions(-) create mode 100644 icons/listview.svg diff --git a/global/config.h b/global/config.h index 968e4a8c3..c72b52077 100644 --- a/global/config.h +++ b/global/config.h @@ -120,7 +120,10 @@ namespace olive { PROJECT_VIEW_TREE, /** Display project media in icon browser */ - PROJECT_VIEW_ICON + PROJECT_VIEW_ICON, + + /** Display project media in list browser */ + PROJECT_VIEW_LIST }; /** diff --git a/global/math.cpp b/global/math.cpp index 31c630d01..fe19b229b 100644 --- a/global/math.cpp +++ b/global/math.cpp @@ -26,57 +26,76 @@ #include "debug.h" int lerp(int a, int b, double t) { - return qRound(((1.0 - t) * a) + (t * b)); + return qRound(((1.0 - t) * a) + (t * b)); } float float_lerp(float a, float b, float t) { - return ((1.0F - t) * a) + (t * b); + return ((1.0F - t) * a) + (t * b); } double double_lerp(double a, double b, double t) { - return ((1.0 - t) * a) + (t * b); + return ((1.0 - t) * a) + (t * b); } double quad_from_t(double a, double b, double c, double t) { - return qPow(1.0 - t, 2)*a + 2*(1.0 - t)*t*b + qPow(t, 2)*c; + return qPow(1.0 - t, 2)*a + 2*(1.0 - t)*t*b + qPow(t, 2)*c; } double quad_t_from_x(double x, double a, double b, double c) { - return (a - b + qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); - // alt: return (a - b - qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); + return (a - b + qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); + // alt: return (a - b - qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); } double cubic_from_t(double a, double b, double c, double d, double t) { - return qPow(1.0 - t, 3)*a + 3*qPow(1.0 - t, 2)*t*b + 3*(1.0 - t)*qPow(t, 2)*c + qPow(t, 3)*d; + return qPow(1.0 - t, 3)*a + 3*qPow(1.0 - t, 2)*t*b + 3*(1.0 - t)*qPow(t, 2)*c + qPow(t, 3)*d; } double cubic_t_from_x(double x_target, double a, double b, double c, double d) { - double tolerance = 0.0001; + double tolerance = 0.0001; - double lower = 0.0; - double upper = 1.0; + double lower = 0.0; + double upper = 1.0; - double percent = 0.5; - double x = cubic_from_t(a, b, c, d, percent); + double percent = 0.5; + double x = cubic_from_t(a, b, c, d, percent); - while (qAbs(x_target - x) > tolerance) { - if (x_target > x) { - lower = percent; - } else { - upper = percent; - } + while (qAbs(x_target - x) > tolerance) { + if (x_target > x) { + lower = percent; + } else { + upper = percent; + } - percent = (upper + lower) / 2.0; - x = cubic_from_t(a, b, c, d, percent); - } + percent = (upper + lower) / 2.0; + x = cubic_from_t(a, b, c, d, percent); + } - return percent; + return percent; } double amplitude_to_db(double amplitude) { - return (20.0*(qLn(amplitude)/qLn(10.0))); + return (20.0*(qLn(amplitude)/qLn(10.0))); } double db_to_amplitude(double db) { - return qPow(M_E, (db*qLn(10.0))/20.0); + return qPow(M_E, (db*qLn(10.0))/20.0); +} + +QRect fit_size_into_rect(const QRect &r, int width, int height) +{ + // Get aspect ratio of object we're fitting + double inner_ar = double(width) / double(height); + + // Get aspect ratio of rectangle + double rect_ar = double(r.width()) / double(r.height()); + + if (rect_ar > inner_ar) { + // The rect is wider than the object, so we'll be limiting by height and scaling by width + int new_width = qRound(r.height() * inner_ar); + return QRect(r.x() + (r.width() / 2 - new_width / 2), r.y(), new_width, r.height()); + } else { + // The rect is taller than the object, so we'll be limiting by width and scaling by height + int new_height = qRound(r.width() / inner_ar); + return QRect(r.x(), r.y() + (r.height() / 2 - new_height / 2), r.width(), new_height); + } } diff --git a/global/math.h b/global/math.h index 9e6a7a45a..ed71f3981 100644 --- a/global/math.h +++ b/global/math.h @@ -21,6 +21,8 @@ #ifndef MATH_H #define MATH_H +#include + int lerp(int a, int b, double t); float float_lerp(float a, float b, float t); double double_lerp(double a, double b, double t); @@ -30,6 +32,8 @@ double cubic_from_t(double a, double b, double c, double d, double t); double cubic_t_from_x(double x_target, double a, double b, double c, double d); double solveCubicBezier(double p0, double p1, double p2, double p3, double x); +QRect fit_size_into_rect(const QRect& r, int width, int height); + // decibel conversion functions double amplitude_to_db(double amplitude); double db_to_amplitude(double db); diff --git a/icons/icons.qrc b/icons/icons.qrc index 8d00cf945..341bbf1b1 100644 --- a/icons/icons.qrc +++ b/icons/icons.qrc @@ -52,5 +52,6 @@ align-right.svg justify-center.svg bold.svg + listview.svg diff --git a/icons/listview.svg b/icons/listview.svg new file mode 100644 index 000000000..062cebc39 --- /dev/null +++ b/icons/listview.svg @@ -0,0 +1,829 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Martin Ruskov + + + http://commons.wikimedia.org/wiki/Tango_icon + + + + + + + + + + + + + + + + + + diff --git a/panels/project.cpp b/panels/project.cpp index 93e5005b3..fb609a114 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -103,31 +103,31 @@ Project::Project(QWidget *parent) : QPushButton* toolbar_new = new QPushButton(); toolbar_new->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/add-button.svg"))); - toolbar_new->setToolTip("New"); + toolbar_new->setToolTip(tr("New")); connect(toolbar_new, SIGNAL(clicked(bool)), this, SLOT(make_new_menu())); toolbar->addWidget(toolbar_new); QPushButton* toolbar_open = new QPushButton(); toolbar_open->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/open.svg"))); - toolbar_open->setToolTip("Open Project"); + toolbar_open->setToolTip(tr("Open Project")); connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(OpenProject())); toolbar->addWidget(toolbar_open); QPushButton* toolbar_save = new QPushButton(); toolbar_save->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/save.svg"))); - toolbar_save->setToolTip("Save Project"); + toolbar_save->setToolTip(tr("Save Project")); connect(toolbar_save, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(save_project())); toolbar->addWidget(toolbar_save); QPushButton* toolbar_undo = new QPushButton(); toolbar_undo->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/undo.svg"))); - toolbar_undo->setToolTip("Undo"); + toolbar_undo->setToolTip(tr("Undo")); connect(toolbar_undo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(undo())); toolbar->addWidget(toolbar_undo); QPushButton* toolbar_redo = new QPushButton(); toolbar_redo->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/redo.svg"))); - toolbar_redo->setToolTip("Redo"); + toolbar_redo->setToolTip(tr("Redo")); connect(toolbar_redo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(redo())); toolbar->addWidget(toolbar_redo); @@ -138,16 +138,22 @@ Project::Project(QWidget *parent) : QPushButton* toolbar_tree_view = new QPushButton(); toolbar_tree_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/treeview.svg"))); - toolbar_tree_view->setToolTip("Tree View"); + toolbar_tree_view->setToolTip(tr("Tree View")); connect(toolbar_tree_view, SIGNAL(clicked(bool)), this, SLOT(set_tree_view())); toolbar->addWidget(toolbar_tree_view); QPushButton* toolbar_icon_view = new QPushButton(); toolbar_icon_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/iconview.svg"))); - toolbar_icon_view->setToolTip("Icon View"); + toolbar_icon_view->setToolTip(tr("Icon View")); connect(toolbar_icon_view, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); toolbar->addWidget(toolbar_icon_view); + QPushButton* toolbar_list_view = new QPushButton(); + toolbar_list_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/listview.svg"))); + toolbar_list_view->setToolTip(tr("List View")); + connect(toolbar_list_view, SIGNAL(clicked(bool)), this, SLOT(set_list_view())); + toolbar->addWidget(toolbar_list_view); + verticalLayout->addWidget(toolbar_widget); // tree view @@ -180,9 +186,9 @@ Project::Project(QWidget *parent) : icon_view_controls->addStretch(); - QSlider* icon_size_slider = new QSlider(Qt::Horizontal); + icon_size_slider = new QSlider(Qt::Horizontal); icon_size_slider->setMinimum(16); - icon_size_slider->setMaximum(120); + icon_size_slider->setMaximum(256); icon_view_controls->addWidget(icon_size_slider); connect(icon_size_slider, SIGNAL(valueChanged(int)), this, SLOT(set_icon_view_size(int))); @@ -191,12 +197,12 @@ Project::Project(QWidget *parent) : icon_view = new SourceIconView(sources_common); icon_view->project_parent = this; icon_view->setModel(&sorter); - icon_view->setIconSize(QSize(100, 100)); + icon_view->setGridSize(QSize(100, 100)); icon_view->setViewMode(QListView::IconMode); icon_view->setUniformItemSizes(true); icon_view_container_layout->addWidget(icon_view); - icon_size_slider->setValue(icon_view->iconSize().height()); + icon_size_slider->setValue(icon_view->gridSize().height()); verticalLayout->addWidget(icon_view_container); @@ -1322,13 +1328,22 @@ void Project::save_project(bool autorecovery) { void Project::update_view_type() { tree_view->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_TREE); - icon_view_container->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON); + icon_view_container->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON + || olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_LIST); + switch (olive::CurrentConfig.project_view_type) { case olive::PROJECT_VIEW_TREE: sources_common.view = tree_view; break; case olive::PROJECT_VIEW_ICON: + case olive::PROJECT_VIEW_LIST: + icon_view->setViewMode(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON ? + QListView::IconMode : QListView::ListMode); + + // update list/grid size since they use this value slightly differently + set_icon_view_size(icon_size_slider->value()); + sources_common.view = icon_view; break; } @@ -1339,6 +1354,12 @@ void Project::set_icon_view() { update_view_type(); } +void Project::set_list_view() +{ + olive::CurrentConfig.project_view_type = olive::PROJECT_VIEW_LIST; + update_view_type(); +} + void Project::set_tree_view() { olive::CurrentConfig.project_view_type = olive::PROJECT_VIEW_TREE; update_view_type(); @@ -1367,7 +1388,12 @@ void Project::clear_recent_projects() { } void Project::set_icon_view_size(int s) { - icon_view->setIconSize(QSize(s, s)); + if (icon_view->viewMode() == QListView::IconMode) { + icon_view->setGridSize(QSize(s, s)); + } else { + icon_view->setGridSize(QSize()); + icon_view->setIconSize(QSize(s, s)); + } } void Project::set_up_dir_enabled() { diff --git a/panels/project.h b/panels/project.h index 4cf77fe95..e3dfbf3bf 100644 --- a/panels/project.h +++ b/panels/project.h @@ -112,6 +112,7 @@ private: QString get_file_name_from_path(const QString &path); QDir proj_dir; QWidget* icon_view_container; + QSlider* icon_size_slider; QPushButton* directory_up; QLineEdit* toolbar_search; @@ -124,6 +125,7 @@ private: private slots: void update_view_type(); void set_icon_view(); + void set_list_view(); void set_tree_view(); void clear_recent_projects(); void set_icon_view_size(int); diff --git a/project/footage.cpp b/project/footage.cpp index bde8c4c20..7ac98617a 100644 --- a/project/footage.cpp +++ b/project/footage.cpp @@ -77,17 +77,3 @@ FootageStream* Footage::get_stream_from_file_index(bool video, int index) { } return nullptr; } - -void FootageStream::make_square_thumb() { - // generate square version for QListView? - int square_size = qMax(video_preview.width(), video_preview.height()); - QPixmap pixmap(square_size, square_size); - pixmap.fill(Qt::transparent); - QPainter p(&pixmap); - int diff = (video_preview.width() - video_preview.height())>>1; - int sqx = (diff < 0) ? -diff : 0; - int sqy = (diff > 0) ? diff : 0; - p.drawImage(sqx, sqy, video_preview); - p.end(); - video_preview_square = QIcon(pixmap); -} diff --git a/project/footage.h b/project/footage.h index 04ff51706..a6f45d8ac 100644 --- a/project/footage.h +++ b/project/footage.h @@ -62,9 +62,7 @@ struct FootageStream { // preview thumbnail/waveform bool preview_done; QImage video_preview; - QIcon video_preview_square; QVector audio_preview; - void make_square_thumb(); }; struct Footage { diff --git a/project/media.cpp b/project/media.cpp index 70d0cb35c..cde487055 100644 --- a/project/media.cpp +++ b/project/media.cpp @@ -284,6 +284,24 @@ int Media::columnCount() const { return 3; } +QString Media::GetStringDuration() { + if (get_type() == MEDIA_TYPE_SEQUENCE) { + Sequence* s = to_sequence().get(); + return frame_to_timecode(s->getEndFrame(), olive::CurrentConfig.timecode_view, s->frame_rate); + } + if (get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); + double r = 30; + + if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate)) + r = f->video_tracks.at(0).video_frame_rate * f->speed; + + long len = f->get_length_in_frames(r); + if (len > 0) return frame_to_timecode(len, olive::CurrentConfig.timecode_view, r); + } + return QString(); +} + QVariant Media::data(int column, int role) { switch (role) { case Qt::DecorationRole: @@ -292,7 +310,7 @@ QVariant Media::data(int column, int role) { Footage* f = to_footage(); if (f->video_tracks.size() > 0 && f->video_tracks.at(0).preview_done) { - return f->video_tracks.at(0).video_preview_square; + return QIcon(QPixmap::fromImage(f->video_tracks.at(0).video_preview)); } } @@ -304,20 +322,7 @@ QVariant Media::data(int column, int role) { case 0: return (root) ? QCoreApplication::translate("Media", "Name") : get_name(); case 1: if (root) return QCoreApplication::translate("Media", "Duration"); - if (get_type() == MEDIA_TYPE_SEQUENCE) { - Sequence* s = to_sequence().get(); - return frame_to_timecode(s->getEndFrame(), olive::CurrentConfig.timecode_view, s->frame_rate); - } - if (get_type() == MEDIA_TYPE_FOOTAGE) { - Footage* f = to_footage(); - double r = 30; - - if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate)) - r = f->video_tracks.at(0).video_frame_rate * f->speed; - - long len = f->get_length_in_frames(r); - if (len > 0) return frame_to_timecode(len, olive::CurrentConfig.timecode_view, r); - } + return GetStringDuration(); break; case 2: if (root) return QCoreApplication::translate("Media", "Rate"); @@ -336,6 +341,10 @@ QVariant Media::data(int column, int role) { break; case Qt::ToolTipRole: return tooltip; + + case Qt::UserRole: + // User role returns the duration + return GetStringDuration(); } return QVariant(); } diff --git a/project/media.h b/project/media.h index 05d60bfe4..2daff6aaf 100644 --- a/project/media.h +++ b/project/media.h @@ -87,6 +87,8 @@ private: int type; VoidPtr object; + QString GetStringDuration(); + // item functions QList children; Media* parent; diff --git a/project/previewgenerator.cpp b/project/previewgenerator.cpp index 3597e744b..f14fe8ddf 100644 --- a/project/previewgenerator.cpp +++ b/project/previewgenerator.cpp @@ -153,8 +153,6 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) { QString thumb_path = get_thumbnail_path(hash, ms); QFile f(thumb_path); if (f.exists() && ms.video_preview.load(thumb_path)) { - //dout << "loaded thumb" << ms->file_index << "from" << thumb_path; - ms.make_square_thumb(); ms.preview_done = true; } else { found = false; @@ -364,8 +362,6 @@ void PreviewGenerator::generate_waveform() { &data, linesize); - s->make_square_thumb(); - // is video interlaced? s->video_auto_interlacing = (temp_frame->interlaced_frame) ? ((temp_frame->top_field_first) ? VIDEO_TOP_FIELD_FIRST : VIDEO_BOTTOM_FIELD_FIRST) : VIDEO_PROGRESSIVE; s->video_interlacing = s->video_auto_interlacing; diff --git a/project/sourcescommon.h b/project/sourcescommon.h index 506610ebc..b710f552a 100644 --- a/project/sourcescommon.h +++ b/project/sourcescommon.h @@ -46,6 +46,8 @@ public: void dropEvent(QWidget *parent, QDropEvent* e, const QModelIndex& drop_item, const QModelIndexList &items); void item_click(Media* m, const QModelIndex &index); +public slots: + void stop_rename_timer(); private slots: void create_seq_from_selected(); void reveal_in_browser(); @@ -62,7 +64,6 @@ private: QModelIndex editing_index; QModelIndexList selected_items; Project* project_parent; - void stop_rename_timer(); QTimer rename_timer; // we cache the selected footage items for open_create_proxy_dialog() diff --git a/ui/sourceiconview.cpp b/ui/sourceiconview.cpp index 3ed554c4c..e8fbf0fbd 100644 --- a/ui/sourceiconview.cpp +++ b/ui/sourceiconview.cpp @@ -21,18 +21,22 @@ #include "sourceiconview.h" #include +#include #include "panels/project.h" #include "project/media.h" #include "project/sourcescommon.h" #include "global/debug.h" +#include "global/math.h" SourceIconView::SourceIconView(SourcesCommon &commons) : commons_(commons) { + setMovement(QListView::Free); setSelectionMode(QAbstractItemView::ExtendedSelection); setResizeMode(QListView::Adjust); setContextMenuPolicy(Qt::CustomContextMenu); + setItemDelegate(&delegate_); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&))); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu())); } @@ -88,3 +92,124 @@ void SourceIconView::mouseDoubleClickEvent(QMouseEvent *) { // Double click was not a folder, so we perform the default behavior (sending the double click to SourcesCommon) commons_.mouseDoubleClickEvent(selectedIndexes()); } + +SourceIconDelegate::SourceIconDelegate(QObject *parent) : + QStyledItemDelegate (parent) +{ +} + +QSize SourceIconDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (option.decorationPosition == QStyleOptionViewItem::Top) { // Icon Mode + + return QSize(256, 256); + + } else { + + return QSize(option.decorationSize.height(), option.decorationSize.height()); + + } +} + +void SourceIconDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QFontMetrics fm = painter->fontMetrics(); + QRect img_rect = option.rect; + + if (option.decorationPosition == QStyleOptionViewItem::Top) { // Icon Mode + + // Draw Text + if (fm.height() < option.rect.height() / 2) { + img_rect.setHeight(img_rect.height()-fm.height()); + + QRect text_rect = option.rect; + text_rect.setTop(text_rect.top() + option.rect.height() - fm.height()); + + QColor text_bgcolor; + QColor text_fgcolor; + + if (option.state & QStyle::State_Selected) { + text_bgcolor = option.palette.highlight().color(); + text_fgcolor = option.palette.highlightedText().color(); + } else { + text_bgcolor = Qt::white; + text_fgcolor = Qt::black; + } + + painter->fillRect(text_rect, text_bgcolor); + painter->setPen(text_fgcolor); + + QString duration_str = index.data(Qt::UserRole).toString(); + int timecode_width = fm.width(duration_str); + int max_name_width = option.rect.width(); + + if (timecode_width < option.rect.width() / 2) { + painter->drawText(text_rect, Qt::AlignBottom | Qt::AlignRight, index.data(Qt::UserRole).toString()); + max_name_width -= timecode_width; + } + + painter->drawText(text_rect, + Qt::AlignBottom | Qt::AlignLeft, + fm.elidedText(index.data(Qt::DisplayRole).toString(), Qt::ElideRight, max_name_width)); + + } + + // Draw image + QIcon ico = index.data(Qt::DecorationRole).value(); + QSize icon_size = ico.actualSize(img_rect.size()); + img_rect = QRect(img_rect.x() + (img_rect.width() / 2 - icon_size.width() / 2), + img_rect.y() + (img_rect.height() / 2 - icon_size.height() / 2), + icon_size.width(), + icon_size.height()); + painter->drawPixmap(img_rect, ico.pixmap(icon_size)); + + if (option.state & QStyle::State_Selected) { + QColor highlight_color = option.palette.highlight().color(); + highlight_color.setAlphaF(0.5); + + painter->setCompositionMode(QPainter::CompositionMode_SourceAtop); + painter->fillRect(img_rect, highlight_color); + } + } else if (option.decorationPosition == QStyleOptionViewItem::Left) { // List Mode + + if (option.state & QStyle::State_Selected) { + painter->fillRect(option.rect, option.palette.highlight()); + } + + img_rect.setWidth(qMin(img_rect.width(), img_rect.height())); + + QIcon ico = index.data(Qt::DecorationRole).value(); + QSize icon_size = ico.actualSize(img_rect.size()); + img_rect = QRect(img_rect.x() + (img_rect.width() / 2 - icon_size.width() / 2), + img_rect.y() + (img_rect.height() / 2 - icon_size.height() / 2), + icon_size.width(), + icon_size.height()); + painter->drawPixmap(img_rect, ico.pixmap(icon_size)); + + QRect text_rect = option.rect; + text_rect.setLeft(text_rect.left() + option.rect.height()); + + int maximum_line_count = qMax(1, option.rect.height() / fm.height() - 1); + QString text; + if (maximum_line_count == 1) { + text = index.data(Qt::DisplayRole).toString(); + } else { + text = index.data(Qt::ToolTipRole).toString(); + if (text.isEmpty()) { + text = index.data(Qt::DisplayRole).toString(); + } else { + QStringList strings = text.split("\n"); + while (strings.size() > maximum_line_count) { + strings.removeLast(); + } + text = strings.join("\n"); + } + } + + painter->setPen(option.state & QStyle::State_Selected ? + option.palette.highlightedText().color() : option.palette.text().color()); + + painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter, text); + + } +} diff --git a/ui/sourceiconview.h b/ui/sourceiconview.h index df872d01c..e615068f0 100644 --- a/ui/sourceiconview.h +++ b/ui/sourceiconview.h @@ -23,10 +23,19 @@ #include #include +#include #include "project/sourcescommon.h" class Project; +class SourceIconDelegate; + +class SourceIconDelegate : public QStyledItemDelegate { +public: + SourceIconDelegate(QObject *parent = nullptr); + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; class SourceIconView : public QListView { Q_OBJECT @@ -46,6 +55,7 @@ private slots: void item_click(const QModelIndex& index); private: SourcesCommon& commons_; + SourceIconDelegate delegate_; }; #endif // SOURCEICONVIEW_H