KMail2

Dec. 16th, 2011 05:56 pm
madf: (Default)
[personal profile] madf
До нього у мене, власне, дві претензії (якщо не рахувати купу питань щодо юзабіліті):

Сьогодні під час компіляції libreoffice (10 Gb tmpfs, 5 паралельних процесів) мені терміново треба була інформація із вчорашнього листа. Перемкнувшись на 6-й десктоп я побачив що? Правильно, сірий квадрат замість KMail. При цьому Akregator, Okular і навіть Firefox працювали без помітних тормозів. Wtf?
strace показав що KMail нічим не зайнятий, тупо висить на select. gdb показав цікаву картинку.

Почнемо знизу:
#52 0x00007f498ff9fabc in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib64/qt4/libQtGui.so.4
#53 0x00007f498ff9ed60 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib64/qt4/libQtGui.so.4
#54 0x00007f4990168ad8 in QWidgetBackingStore::sync() () from /usr/lib64/qt4/libQtGui.so.4
#55 0x00007f4990168daa in QWidgetBackingStore::sync(QWidget*, QRegion const&) () from /usr/lib64/qt4/libQtGui.so.4
#56 0x00007f498ffce8b0 in QETWidget::translatePaintEvent(_XEvent const*) () from /usr/lib64/qt4/libQtGui.so.4
#57 0x00007f498ffcf64c in QApplication::x11ProcessEvent(_XEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#58 0x00007f498fff68a2 in x11EventSourceDispatch(_GSource*, int (*)(void*), void*) () from /usr/lib64/qt4/libQtGui.so.4
#59 0x00007f4987ad311a in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#60 0x00007f4987ad3928 in g_main_context_iterate.clone.6 () from /usr/lib64/libglib-2.0.so.0
#61 0x00007f4987ad3abf in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0
#62 0x00007f498fa71f5a in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#63 0x00007f498fff6566 in QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtGui.so.4
#64 0x00007f498fa46112 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#65 0x00007f498fa46394 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#66 0x00007f498fa4a87b in QCoreApplication::exec() () from /usr/lib64/qt4/libQtCore.so.4
#67 0x00000000004031f2 in main ()

Нічого цікавого. Прилетів pain event і він почав малювати. Далі йдуть з десяток викликів QWidgetPrivate::paintSiblingsRecursive, я не буду їх наводити. Йдемо вище:
#18 0x00007f499048568a in QTreeView::drawRow(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib64/qt4/libQtGui.so.4
#19 0x00007f49904885a5 in QTreeView::drawTree(QPainter*, QRegion const&) const () from /usr/lib64/qt4/libQtGui.so.4
#20 0x00007f4990488f9f in QTreeView::paintEvent(QPaintEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#21 0x00007f498ffa2135 in QWidget::event(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#22 0x00007f49903391de in QFrame::event(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#23 0x00007f499044572b in QAbstractItemView::viewportEvent(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#24 0x00007f499048a244 in QTreeView::viewportEvent(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#25 0x00007f498fa46f66 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4
#26 0x00007f498ff50093 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#27 0x00007f498ff54c1a in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#28 0x00007f49917f1948 in KApplication::notify(QObject*, QEvent*) () from /usr/lib64/libkdeui.so.5
#29 0x00007f498fa46dcb in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4

Теж нічого підозрілого, стандартний QTreeView малює себе. Йдемо далі:
#14 0x00007f498aecb2b1 in MessageList::Core::MessageItemPrivate::getTagList() const () from /usr/lib64/libmessagelist.so.4
#15 0x00007f498aecb4da in MessageList::Core::MessageItemPrivate::bestTag() const () from /usr/lib64/libmessagelist.so.4
#16 0x00007f498aecb7ad in MessageList::Core::MessageItem::backgroundColor() const () from /usr/lib64/libmessagelist.so.4
#17 0x00007f498aeef525 in MessageList::Core::ThemeDelegate::paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib64/libmessagelist.so.4

Естафетна паличка художника перейшла до делегату. Питаємо, який фоновий колір ставити для мессиджа. Проблема уже тут, але її все ще не видно. Йдемо далі:
#9  0x00007f49880ecb8f in Nepomuk::ResourceData::load() () from /usr/lib64/libnepomuk.so.4
#10 0x00007f49880ece9c in Nepomuk::ResourceData::property(QUrl const&) () from /usr/lib64/libnepomuk.so.4
#11 0x00007f498810054a in Nepomuk::Resource::property(QUrl const&) const () from /usr/lib64/libnepomuk.so.4
#12 0x00007f4988100e99 in Nepomuk::Resource::tags() const () from /usr/lib64/libnepomuk.so.4
#13 0x00007f498aeca9ad in MessageList::Core::MessageItemPrivate::fillTagList() const () from /usr/lib64/libmessagelist.so.4

Розміру проблеми ще не видно, але волосся починає шевелитися. Набираємось сміливості, робимо кілька глибоких вдихів і йдемо до кінця:
#0  0x00007f498f10bee3 in select () from /lib64/libc.so.6
#1  0x00007f498fa6f03a in qt_safe_select(int, fd_set*, fd_set*, fd_set*, timeval const*) () from /usr/lib64/qt4/libQtCore.so.4
#2  0x00007f498e17dfd9 in QNativeSocketEnginePrivate::nativeSelect(int, bool, bool, bool*, bool*) const () from /usr/lib64/qt4/libQtNetwork.so.4
#3  0x00007f498e166c04 in QNativeSocketEngine::waitForReadOrWrite(bool*, bool*, bool, bool, int, bool*) () from /usr/lib64/qt4/libQtNetwork.so.4
#4  0x00007f498e177fc9 in QAbstractSocket::waitForReadyRead(int) () from /usr/lib64/qt4/libQtNetwork.so.4
#5  0x00007f4981895fce in Soprano::Client::ClientConnection::executeQuery(int, QString const&, Soprano::Query::QueryLanguage, QString const&) () from /usr/lib64/libsopranoclient.so.1
#6  0x00007f49818977c5 in Soprano::Client::ClientModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libsopranoclient.so.1
#7  0x00007f49880f6bb5 in Nepomuk::MainModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libnepomuk.so.4
#8  0x00007f49883dde31 in Soprano::FilterModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libsoprano.so.4

Нагадаю: Nepomuk - система керування метаданими, Soprano - об’єктно-орієнтований інтерфейс до метаданих. Виходить що? Виходить що для того щоб визначити колір фону для ячейки треба залізти у СУБД! І так для кожної ячейки! Для кожного paint event!
Поліз у сорси.
ThemeDelegate::paint
  if ( !index.isValid() )                                                                                              
    return; // bleah                                                                                                   
                                                                                                                       
  Item * item = itemFromIndex( index );                                                                                
  if ( !item )                                                                                                         
    return; // hm...                                                                                                   
                                                                                                                       
  QStyleOptionViewItemV4 opt = option;                                                                                 
  initStyleOption( &opt, index );                                                                                      
                                                                                                                       
  opt.text.clear(); // draw no text for me, please.. I'll do it in a while                                             
                                                                                                                       
  // Set background color of control if necessary                                                                      
  if ( item->type() == Item::Message ) {                                                                               
    MessageItem * msgItem = static_cast< MessageItem * >( item );                                                      
    if ( msgItem->backgroundColor().isValid() )                                                                        
      opt.backgroundBrush = QBrush( msgItem->backgroundColor() );                                                      
  } 

Ось цей "дядя з великиму вухами"! Що ж він такого робить у backgroundColor()?
MessageItem::backgroundColor
QColor MessageItem::backgroundColor() const                                                                            
{                                                                                                                      
  Q_D( const MessageItem );                                                                                            
  const Tag *bestTag = d->bestTag();                                                                                   
  if ( bestTag != 0 ) {                                                                                                
    return bestTag->backgroundColor();                                                                                 
  } else {                                                                                                             
    return QColor();                                                                                                   
  }                                                                                                                    
}

MessageItemPrivate::bestTag
const MessageItem::Tag* MessageItemPrivate::bestTag() const                     
{                                                                               
  const MessageItem::Tag *best = 0;                                             
  foreach( const MessageItem::Tag* tag, getTagList() ) {                        
    if ( !best || tag->priority() < best->priority() )                          
      best = tag;                                                               
  }                                                                             
  return best;                                                                  
}

Ну логічно що йому потрібен список тегів.
MessageItemPrivate::getTagList
QList<MessageItem::Tag*> MessageItemPrivate::getTagList() const                 
{                                                                               
  if ( !mTagList )                                                              
    fillTagList();                                                              
                                                                                
  return *mTagList;                                                             
}

Ага! "Ліниве" створення списку. Ну а fillTagList уже лізе в Nepomuk і звідти цей список витягує. Виникає питання: чому список тегів пустий якщо це не перший пейнт?
Ех, мені б трохи зайвого часу, я б цей KMail розкрутив по гвинтикам і пофіксив ці довбані баги (благо, №277399 у мене проявляється регулярно).


PS: вони (LJ) таки полагодили попередній перегляд!

Profile

madf: (Default)
madf

April 2018

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 24th, 2025 06:39 pm
Powered by Dreamwidth Studios