Changeset 191


Ignore:
Timestamp:
03/28/09 04:25:07 (3 years ago)
Author:
antonbatenev.ya.ru
Message:

перенос оптимизированного виджета дерева сообщений в транк

Files:
1 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/dev/doxygen.sh

    r119 r191  
    1313 
    1414doxygen doxygen/doxygen.conf 
     15 
     16kfmclient exec file:$(pwd)/doxygen/html/index.html 
  • trunk/form_message.cpp

    r172 r191  
    1010//---------------------------------------------------------------------------------------------- 
    1111 
    12 FormMessage::FormMessage (QWidget* parent, bool is_reply, const ATopicInfo& info, int edit_id) :  FormMessageUI (parent) 
     12FormMessage::FormMessage (QWidget* parent, bool is_reply, const AMessageInfoGUI& info, int edit_id) :  FormMessageUI (parent) 
    1313{ 
    1414        if (edit_id != 0) 
     
    264264                AMessageInfo info; 
    265265 
     266                // TODO: убрать заполнение лишних полей 
    266267                info.ID             = 0; 
    267268                info.IDTopic        = 0; 
  • trunk/form_message.h

    r147 r191  
    3232                 * \param edit_id ID редактирования существующего сообщения к отправке 
    3333                 */ 
    34                 FormMessage  (QWidget* parent, bool is_reply, const ATopicInfo& info, int edit_id = 0); 
     34                FormMessage  (QWidget* parent, bool is_reply, const AMessageInfoGUI& info, int edit_id = 0); 
    3535                ~FormMessage (); 
    3636 
     
    5555                 * \brief Текущее редактируемое сообщение. 
    5656                 */ 
    57                 ATopicInfo m_info; 
     57                AMessageInfoGUI m_info; 
    5858 
    5959                /*! 
  • trunk/forum_tree.cpp

    r152 r191  
    814814                return; 
    815815 
    816         ATopicInfo info; 
    817  
     816        AMessageInfoGUI info; 
     817 
     818        // TODO: убрать заполнение лишних полей 
    818819        info.ID             = 0; 
    819820        info.IDTopic        = 0; 
     
    832833        info.UserTitleColor = 0; 
    833834        info.LastModerated  = QDateTime(); 
    834         info.IsRead         = false; 
     835        /*info.IsRead         = false; 
    835836        info.HasChild       = false; 
    836         info.HasUnreadChild = false; 
     837        info.HasUnreadChild = false;*/ // TODO: 
    837838 
    838839        FormMessage* form = new FormMessage(NULL, false, info); 
  • trunk/global.cpp

    r162 r191  
    2424 
    2525        reload(); 
     26 
     27        AnonymousName = QString::fromUtf8("Аноним"); 
     28        DateFormat    = "dd.MM.yyyy hh:mm:ss"; 
    2629} 
    2730//---------------------------------------------------------------------------------------------- 
  • trunk/global.h

    r159 r191  
    4242                int      SynchronizeInterval; /*!< \brief Интервал синхронизации (минут)                   */ 
    4343                AColorer Colorer;             /*!< \brief Движок подсветки синтаксиса                      */ 
     44 
     45                // 
     46                // Константы 
     47                // 
     48 
     49                QString AnonymousName; /*!< \brief Отображаемое имя анонима */ 
     50                QString DateFormat;    /*!< \brief Формат даты/времени      */ 
    4451}; 
    4552 
  • trunk/message_tree.cpp

    r175 r191  
    55// $URL$ 
    66//---------------------------------------------------------------------------------------------- 
    7 #include "parser.h" 
     7#include "message_tree.h" 
     8//---------------------------------------------------------------------------------------------- 
    89#include "global.h" 
    9 #include "model/all.h" 
     10#include "form_source.h" 
    1011#include "icon_effect.h" 
    11 #include "form_source.h" 
    1212#include "form_message.h" 
    1313#include "form_moderate.h" 
    14 #include "message_tree.h" 
    1514#include "tree_widget_item.h" 
    1615#include "storage/storage_factory.h" 
    1716//---------------------------------------------------------------------------------------------- 
    1817/*! 
    19  * \brief Элемент, который хранится в каждой ноде дерева 
    20  */ 
    21 typedef struct AMessageInfoGUI 
    22 { 
    23         ATopicInfo Info;             /*!< \brief Дескриптор сообщения */ 
    24         bool       IsInfoLoaded;     /*!< \brief Флаг наличия загрузки информации (актуально только для топиков) */ 
    25         bool       IsChildLoaded;    /*!< \brief Флаг того, что загружены дочерние сообщения (актуально только для топиков) */ 
    26         int        UnreadChildCount; /*!< \brief Количество непрочитанных дочерних сообщений */ 
    27         bool       IsBodyLoaded;     /*!< \brief Загружено ли тело сообщения */ 
    28         int        Special;          /*!< \brief Спец-данные */ 
    29 } AMessageInfoGUI; 
    30 //---------------------------------------------------------------------------------------------- 
    31 /*! 
    32  * \brief Элемент для дерева группы форумов с информацией о группе 
     18 * \brief Элемент для дерева сообщений 
    3319 */ 
    3420typedef ATreeWidgetItemT<AMessageInfoGUI> MessageTreeWidgetItem; 
     
    3723AMessageTree::AMessageTree (QWidget* parent, QWidget* form) : QTreeWidget (parent), IMessageTree () 
    3824{ 
     25        // 
     26        // инициализация полей 
     27        // 
     28 
    3929        m_parent       = form; 
    4030        m_forum_tree   = 0; 
    4131        m_message_view = 0; 
    4232        m_main_form    = 0; 
    43         m_id_group     = 0; 
    44         m_id_forum     = 0; 
    45         m_me.ID        = -1; 
     33 
     34        m_me.ID = 0; 
     35 
     36        m_current_forum.ID        = 0; 
     37        m_current_forum.IDGroup   = 0; 
     38        m_current_forum.Rated     = false; 
     39        m_current_forum.InTop     = false; 
     40        m_current_forum.RateLimit = 0; 
     41 
     42        // 
     43        // инициализация GUI виджета 
     44        // 
    4645 
    4746        setFrameShadow(QFrame::Plain); 
     
    5958        headerItem()->setTextAlignment(1, Qt::AlignCenter); 
    6059        headerItem()->setTextAlignment(2, Qt::AlignCenter); 
     60 
     61        // 
     62        // иконки 
     63        // 
    6164 
    6265        m_message_read   = QIcon(":/icons/messageread.png"); 
     
    7881        m_moderate      = QIcon(":/icons/moderate.png"); 
    7982 
    80         // меню 
     83        // 
     84        // контекстное меню (для основного дерева сообщений) 
     85        // 
     86 
    8187        m_menu = new QMenu(this); 
    8288 
     
    100106        m_menu_mark_thread_as_unread->setIcon(QIcon(":/icons/markpatrialasunread16.png")); 
    101107 
    102         // спец-меню 
     108        // 
     109        // контекстное спец-меню (для оценок, модерилок и исходящих сообщений) 
     110        // 
     111 
    103112        m_menu_special = new QMenu(this); 
    104113 
     
    132141        m_menu_special_delete->setIcon(QIcon(":/icons/delete16.png")); 
    133142 
     143        // 
    134144        // события меню 
     145        // 
     146 
    135147        connect(m_menu_reply,                  SIGNAL(triggered()), this, SLOT(menu_reply_triggered())); 
    136148        connect(m_menu_mark_message_as_read,   SIGNAL(triggered()), this, SLOT(menu_mark_message_as_read_triggered())); 
     
    139151        connect(m_menu_mark_thread_as_unread,  SIGNAL(triggered()), this, SLOT(menu_mark_thread_as_unread_triggered())); 
    140152 
     153        // 
    141154        // события спец-меню 
     155        // 
     156 
    142157        connect(m_menu_special_delete, SIGNAL(triggered()), this, SLOT(menu_special_delete_triggered())); 
    143158        connect(m_menu_special_edit,   SIGNAL(triggered()), this, SLOT(menu_special_edit_triggered())); 
     
    151166        connect(m_menu_special_minus,  SIGNAL(triggered()), this, SLOT(menu_special_minus_triggered())); 
    152167 
    153         // события дерева 
     168        // 
     169        // события виджета 
     170        // 
     171 
    154172        connect(this, SIGNAL(itemSelectionChanged()),                    this, SLOT(selection_changed())); 
    155173        connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)),            this, SLOT(expand_item(QTreeWidgetItem*))); 
     
    159177        connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(vertical_scroll(int))); 
    160178 
     179        // событие таймера отметки как прочитанное 
    161180        connect(&m_timer, SIGNAL(timeout()), this, SLOT(timer_on_timer())); 
    162181} 
     
    170189void AMessageTree::resizeEvent (QResizeEvent* event) 
    171190{ 
     191        QTreeWidget::resizeEvent(event); 
     192 
     193        // при ресайзе по высоте могут внизу появиться незагруженные топики 
    172194        scrollTopics(); 
    173  
    174         QTreeWidget::resizeEvent(event); 
    175195} 
    176196//---------------------------------------------------------------------------------------------- 
     
    218238        if (currentItem() != NULL) 
    219239        { 
    220                 if (m_id_group != SPECIAL_ID_GROUP) 
     240                if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 
    221241                        m_menu->exec(viewport()->mapToGlobal(pos)); 
    222242                else 
    223243                { 
    224                         if (m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || 
    225                             m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND) 
     244                        if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     245                            m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 
    226246                        { 
    227247                                m_menu_special_edit->setVisible(true); 
     
    270290        else 
    271291        { 
    272                 setCurrentItem(topLevelItem(topLevelItemCount() - 1)); 
    273  
    274                 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
     292                // последний топик в списке 
     293                MessageTreeWidgetItem* topic_item = static_cast<MessageTreeWidgetItem*>(topLevelItem(topLevelItemCount() - 1)); 
    275294 
    276295                // если элемент еще не загружен, то загружаем 
    277                 if (item->pag()->IsInfoLoaded == false) 
    278                         setCurrentItem(item); 
    279  
    280                 while (true) 
    281                 { 
    282                         item->setExpanded(true); 
    283  
    284                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastChild(item)); 
    285  
    286                         if (item != NULL) 
    287                                 setCurrentItem(item); 
    288                         else 
    289                                 break; 
    290                 } 
     296                if (topic_item->pag()->IsInfoLoaded == false) 
     297                        setCurrentItem(topic_item); 
     298 
     299                // если дочерние элементы еще не загружены, то загружаем 
     300                if (topic_item->pag()->IsChildLoaded == false) 
     301                        topic_item->setExpanded(true); 
     302 
     303                // выделяем последний лист в топике 
     304                MessageTreeWidgetItem* last_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastLeaf(topic_item)); 
     305 
     306                setCurrentItem(last_item); 
    291307        } 
    292308 
     
    297313void AMessageTree::changeForum (const AForumInfo* forum_info) 
    298314{ 
    299         m_id_group    = 0; 
    300         m_id_forum    = 0; 
    301         m_me.ID       = -1; 
    302         m_forum_rated = false; 
     315        // 
     316        // базовая очистка 
     317        // 
     318 
     319        m_current_forum.ID        = 0; 
     320        m_current_forum.IDGroup   = 0; 
     321        m_current_forum.ShortName = ""; 
     322        m_current_forum.Name      = ""; 
     323        m_current_forum.Rated     = false; 
     324        m_current_forum.InTop     = false; 
     325        m_current_forum.RateLimit = 0; 
     326 
     327        m_me.ID             = 0; 
     328        m_me.Name           = ""; 
     329        m_me.Nick           = ""; 
     330        m_me.RealName       = ""; 
     331        m_me.Email          = ""; 
     332        m_me.Homepage       = ""; 
     333        m_me.Specialization = ""; 
     334        m_me.WhereFrom      = ""; 
     335        m_me.Origin         = ""; 
    303336 
    304337        if (m_main_form != NULL) 
     
    323356        } 
    324357 
     358        // 
     359        // есть форум для отображения 
     360        // 
     361 
     362        m_current_forum.ID        = forum_info->ID; 
     363        m_current_forum.IDGroup   = forum_info->IDGroup; 
     364        m_current_forum.ShortName = forum_info->ShortName; 
     365        m_current_forum.Name      = forum_info->Name; 
     366        m_current_forum.Rated     = forum_info->Rated; 
     367        m_current_forum.InTop     = forum_info->InTop; 
     368        m_current_forum.RateLimit = forum_info->RateLimit; 
     369 
    325370        // вывод наименования форума в хедер 
    326         headerItem()->setText(0, forum_info->Name); 
     371        headerItem()->setText(0, m_current_forum.Name); 
     372 
     373        // 
     374        // загрузка топиков в зависимости от типа форума 
     375        // 
    327376 
    328377        // получение хранилища 
     
    336385 
    337386        // получение информации о себе 
     387        // TODO: вынести в AGlobal 
    338388        QSettings settings; 
    339389 
    340390        m_me.Name = settings.value("rsdn/login", "").toString(); 
    341391 
    342         storage->whoAmI(m_me, NULL); 
     392        if (storage->whoAmI(m_me, NULL) == false) 
     393                m_me.Name = ""; 
    343394 
    344395        // если группа форумов обыкновенная 
    345         if (forum_info->IDGroup != SPECIAL_ID_GROUP) 
     396        if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 
    346397        { 
    347398                // получение топиков 
     399                // ориентировочное время выполнения 68 ms (для форума NET, 28199 топиков) 
     400                // основное время занимает запрос данных из хранилища 
    348401                QList<int> topic_list; 
    349402 
    350                 if (storage->getForumTopicList(forum_info->ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false) 
     403                if (storage->getForumTopicList(m_current_forum.ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false) 
    351404                { 
    352405                        storage->showError(m_parent); 
     
    355408 
    356409                // установка топиков 
     410                // ориентировочное время выполнения 50 ms (для форума NET, 28199 топиков) 
     411                // основное время занимает создание объекта MessageTreeWidgetItem 
    357412                QList<QTreeWidgetItem*> items; 
    358413 
    359414                for (int i = 0; i < topic_list.count(); i++) 
    360415                { 
    361                         MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    362  
    363                         AMessageInfoGUI* info = item->pag(); 
    364  
    365                         info->Info.ID          = topic_list[i]; 
    366                         info->IsInfoLoaded     = false; 
    367                         info->IsChildLoaded    = false; 
    368                         info->UnreadChildCount = 0; 
    369                         info->IsBodyLoaded     = false; 
    370                         info->Special          = 0; 
    371  
    372                         items.append(item); 
    373                 } 
    374  
    375                 // сохраняем для скролла 
    376                 m_id_group    = forum_info->IDGroup; 
    377                 m_id_forum    = forum_info->ID; 
    378                 m_forum_rated = forum_info->Rated; 
    379  
    380                 // отображение 
     416                        // начальное заполнение дескриптора топика 
     417                        AMessageInfoGUI* info = createItem(); 
     418 
     419                        info->ID = topic_list[i]; 
     420 
     421                        items.append(info->Item); 
     422                } 
     423 
     424                // отображение на виджет 
    381425                addTopLevelItems(items); 
    382426 
    383                 // загрузка видимых топиков 
     427                // дозагрузка информации о топиках, находящихся в видимой области отображения 
    384428                scrollTopics(); 
    385429        } 
     430        else   // if (forum_info->IDGroup != SPECIAL_ID_GROUP) 
     431        { 
     432                // специальная группа форумов 
     433                if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND) 
     434                        loadMessage2Send(); 
     435                else if (m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND) 
     436                        loadRating2Send(); 
     437                else if (m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 
     438                        loadModerate2Send(); 
     439        } 
     440} 
     441//---------------------------------------------------------------------------------------------- 
     442 
     443void AMessageTree::vertical_scroll (int /*value*/) 
     444{ 
     445        scrollTopics(); 
     446} 
     447//---------------------------------------------------------------------------------------------- 
     448 
     449void AMessageTree::scrollTopics () 
     450{ 
     451        // Среднее время выполнения для дозагрузки одного элемента 5 ms 
     452        // Среднее время выполнения для дозагрузки страницы из 56 топиков (полный экран 1280х1024) 32 ms 
     453 
     454        // пустой форум или спец-группа 
     455        if (m_current_forum.ID == 0 || m_current_forum.IDGroup == SPECIAL_ID_GROUP) 
     456                return; 
     457 
     458        // 
     459        // Определение диапазона возможной подгрузки данных 
     460        // 
     461 
     462        // поиск корня верхнего видимого элемента в отображении 
     463        QTreeWidgetItem* top_item = itemAt(1, 1); 
     464 
     465        if (top_item == NULL) 
     466                return; // нет элементов в дереве(?) 
     467 
     468        top_item = ATreeWidgetItem::rootItem(top_item); 
     469 
     470        int top_index = indexOfTopLevelItem(top_item); 
     471 
     472        // поиск корня нижнего видимого элемента в отображении 
     473        QTreeWidgetItem* bottom_item = itemAt(1, height() - 1); 
     474 
     475        int bottom_index; 
     476 
     477        if (bottom_item == NULL) 
     478                bottom_index = topLevelItemCount(); 
    386479        else 
    387480        { 
    388                 m_id_group    = forum_info->IDGroup; 
    389                 m_id_forum    = forum_info->ID; 
    390                 m_forum_rated = forum_info->Rated; 
    391  
    392                 // специальная группа форумов 
    393                 if (m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND) 
    394                         loadMessage2Send(); 
    395                 else if (m_id_forum == SPECIAL_ID_FORUM_RATING2SEND) 
    396                         loadRating2Send(); 
    397                 else if (m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND) 
    398                         loadModerate2Send(); 
    399         } 
    400 } 
    401 //---------------------------------------------------------------------------------------------- 
    402  
    403 void AMessageTree::vertical_scroll (int /*value*/) 
    404 { 
    405         scrollTopics(); 
    406 } 
    407 //---------------------------------------------------------------------------------------------- 
    408  
    409 void AMessageTree::scrollTopics () 
    410 { 
    411         // пустой форум или спец-группа 
    412         if (m_id_forum == 0 || m_id_group == SPECIAL_ID_GROUP) 
    413                 return; 
    414  
    415         // верхний видимый элемент 
    416         QTreeWidgetItem* top_item = itemAt(1, 5); 
    417  
    418         if (top_item == NULL) 
    419                 return; 
    420  
    421         while (top_item->parent() != NULL) 
    422                 top_item = top_item->parent(); 
    423  
    424         int from_index = indexOfTopLevelItem(top_item); 
    425  
    426         // нижний видимый элемент 
    427         QTreeWidgetItem* bottom_item = itemAt(1, height() - 5); 
    428  
    429         int to_index = topLevelItemCount(); 
    430  
    431         if (bottom_item != NULL) 
    432         { 
    433                 while (bottom_item->parent() != NULL) 
    434                         bottom_item = bottom_item->parent(); 
    435  
    436                 to_index = indexOfTopLevelItem(bottom_item) + 1; 
    437  
    438                 if (to_index < from_index) 
    439                         to_index = from_index + 100; // ~56 элементов влезет по высоте на стандартный экран 1280x1024 
    440  
    441                 if (to_index > topLevelItemCount()) 
    442                         to_index = topLevelItemCount(); 
    443         } 
    444  
    445         // поиск еще не агруженных элементов 
    446         ATopicInfoList                list; 
    447         QList<MessageTreeWidgetItem*> items; 
    448  
    449         while (from_index < to_index) 
    450         { 
    451                 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(from_index)); 
    452  
    453                 if (item->pag()->IsInfoLoaded == false) 
    454                 { 
    455                         ATopicInfo info; 
    456  
    457                         info.ID = item->pag()->Info.ID; 
    458  
     481                bottom_item = ATreeWidgetItem::rootItem(bottom_item); 
     482 
     483                bottom_index = indexOfTopLevelItem(bottom_item) + 1; 
     484        } 
     485 
     486        // 
     487        // Поиск еще не загруженных топиков в диапазоне 
     488        // 
     489 
     490        AMessageInfoGUIPtrList list; 
     491 
     492        while (top_index < bottom_index) 
     493        { 
     494                MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(top_index)); 
     495 
     496                AMessageInfoGUI* info = item->pag(); 
     497 
     498                if (info->IsInfoLoaded == false) 
    459499                        list.append(info); 
    460                         items.append(item); 
    461                 } 
    462  
    463                 from_index++; 
    464         } 
    465  
     500 
     501                top_index++; 
     502        } 
     503 
     504        // 
    466505        // загрузка топиков, которые не загружены 
    467         if (list.count() > 0) 
     506        // 
     507 
     508        if (list.count() == 0) 
     509                return; 
     510 
     511        // получение хранилища 
     512        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     513 
     514        if (storage.get() == NULL) 
     515        { 
     516                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     517                return; 
     518        } 
     519 
     520        if (storage->getTopicInfoList(m_current_forum.ID, list, m_me.ID, NULL) == false) 
     521        { 
     522                storage->showError(m_parent); 
     523                return; 
     524        } 
     525 
     526        AGlobal* global = AGlobal::getInstance(); 
     527 
     528        // 
     529        // Установка загруженой информации 
     530        // 
     531 
     532        for (int i = 0; i < list.count(); i++) 
     533        { 
     534                AMessageInfoGUI* info = list[i]; 
     535 
     536                info->IsInfoLoaded       = true; 
     537                info->UnreadChildCount   = 0; 
     538                info->UnreadChildCountMy = 0; 
     539 
     540                info->Item->setText(0, info->Subject); 
     541 
     542                // TODO: сделать общую функцию формирования имени/ника 
     543                if (info->IDUser == 0) 
     544                        info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 
     545                else 
     546                        info->Item->setText(1, info->UserNick); 
     547 
     548                info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     549 
     550                if (info->HasChild == true) 
     551                        info->Item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 
     552 
     553                if (info->IsRead == true) 
     554                { 
     555                        if (info->HasUnreadChildMy) 
     556                                info->Item->setIcon(0, m_child_unread_my); 
     557                        else if (info->HasUnreadChild) 
     558                                info->Item->setIcon(0, m_child_unread); 
     559                        else 
     560                                info->Item->setIcon(0, m_message_read); 
     561                } 
     562                else 
     563                { 
     564                        if (info->HasUnreadChildMy) 
     565                                info->Item->setIcon(0, m_message_unread_my); 
     566                        else 
     567                                info->Item->setIcon(0, m_message_unread); 
     568                } 
     569        } 
     570} 
     571//---------------------------------------------------------------------------------------------- 
     572 
     573void AMessageTree::expand_item (QTreeWidgetItem* item_expanded) 
     574{ 
     575        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(item_expanded); 
     576 
     577        AMessageInfoGUI* info = item->pag(); 
     578 
     579        // если дочерние сообщения не загружены (а это может быть только для топика в текущей реализации) 
     580        if (info->HasChild == true && info->IsChildLoaded == false) 
    468581        { 
    469582                // получение хранилища 
     
    476589                } 
    477590 
    478                 if (storage->getTopicInfoList(list, m_me.ID, NULL) == false) 
     591                // заполнение списка сообщений 
     592                // ориентировочное время выполнения 111 ms (для топика 279396 - 5149 сообщений) 
     593                // основное время занимает присвоение данных полям (преобразование из QVariant в QSqlQuery) 
     594                AMessageInfoGUIPtrList list; 
     595 
     596                if (storage->getTopicMessageList(m_current_forum.ID, info->ID, list, this, NULL) == false) 
    479597                { 
    480598                        storage->showError(m_parent); 
     
    482600                } 
    483601 
    484                 // заполнение вновь загруженных топиков 
    485                 for (int i = 0; i < list.count(); i++) 
    486                 { 
    487                         ATopicInfo info             = list[i]; 
    488                         MessageTreeWidgetItem* item = items[i]; 
    489  
    490                         AMessageInfoGUI* item_info  = item->pag(); 
    491  
    492                         item_info->Info             = info; 
    493                         item_info->IsInfoLoaded     = true; 
    494                         item_info->IsChildLoaded    = false; 
    495                         item_info->UnreadChildCount = 0; 
    496                         item_info->IsBodyLoaded     = false; 
    497                         item_info->Special          = 0; 
    498  
    499                         item->setText(0, info.Subject); 
    500  
    501                         if (info.IDUser == 0) 
    502                                 item->setText(1, QString::fromUtf8("Аноним")); 
    503                         else 
    504                                 item->setText(1, info.UserNick); 
    505  
    506                         item->setText(2, info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 
    507  
    508                         if (info.IsRead == true) 
    509                         { 
    510                                 if (info.HasUnreadChild != 0) 
    511                                 { 
    512                                         if (info.HasUnreadChild == 2) 
    513                                                 item->setIcon(0, m_child_unread_my); 
    514                                         else 
    515                                                 item->setIcon(0, m_child_unread); 
    516                                 } 
    517                                 else 
    518                                         item->setIcon(0, m_message_read); 
    519                         } 
    520                         else 
    521                         { 
    522                                 if (info.HasUnreadChild == 2) 
    523                                         item->setIcon(0, m_message_unread_my); 
    524                                 else 
    525                                         item->setIcon(0, m_message_unread); 
    526                         } 
    527  
    528                         if (info.HasChild == true) 
    529                                 item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 
    530                 } 
    531         } 
    532 } 
    533 //---------------------------------------------------------------------------------------------- 
    534  
    535 void AMessageTree::expand_item (QTreeWidgetItem* item_expanded) 
    536 { 
    537         if (item_expanded == NULL) 
    538                 return; 
    539  
    540         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(item_expanded); 
    541  
    542         if (item->pag()->Info.HasChild == true && item->pag()->IsChildLoaded == false) 
    543         { 
    544                 // получение хранилища 
    545                 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    546  
    547                 if (storage.get() == NULL) 
    548                 { 
    549                         QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    550                         return; 
    551                 } 
    552  
    553                 // получение сообщений 
    554                 ATopicInfoList list; 
    555  
    556                 if (storage->getTopicMessageList(item->pag()->Info.ID, list, m_me.ID, NULL) == false) 
    557                 { 
    558                         storage->showError(m_parent); 
    559                         return; 
    560                 } 
    561  
    562                 // постройка дерева 
    563                 buildTree(item, &list); 
     602                // постройка дерева, обход в ширину быстрее чем в высоту 
     603                // ориентировочное время выполнения 900 ms (для топика 279396 - 5149 сообщений) 
     604                // наиболее высокое дерево составляет 1555 сообщений (для топика 1099540) 
     605                // наиболее широкое дерево (глубина рекурсии) пока неизвестно 
     606                buildTree(info, &list); 
    564607 
    565608                // для предотвращения повторной загрузки 
    566                 item->pag()->IsChildLoaded = true; 
     609                info->IsChildLoaded = true; 
    567610 
    568611                // раскрытие дерева до уровня непрочитаных топиков 
    569                 if (item->pag()->UnreadChildCount != 0) 
     612                if (info->UnreadChildCount != 0) 
    570613                        expandUnreadChild(item); 
    571614        } 
     
    588631//---------------------------------------------------------------------------------------------- 
    589632 
    590 void AMessageTree::buildTree (QTreeWidgetItem* parent, ATopicInfoList* list) 
    591 { 
    592  
    593         MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(parent); 
    594  
    595         QList<MessageTreeWidgetItem*> to_build; 
    596  
    597         int index     = 0; 
    598         int size      = list->size(); 
    599         int id_parent = parent_item->pag()->Info.ID; 
    600  
    601         while (index < size) 
    602         { 
    603                 ATopicInfo info = list->at(index); 
    604  
    605                 if (info.IDParent == id_parent) 
    606                 { 
    607                         MessageTreeWidgetItem* item = new MessageTreeWidgetItem(parent_item); 
    608  
    609                         AMessageInfoGUI* item_info = item->pag(); 
    610  
    611                         // AMessageInfo 
    612                         item_info->Info.ID               = info.ID; 
    613                         item_info->Info.IDTopic          = info.IDTopic; 
    614                         item_info->Info.IDParent         = info.IDParent; 
    615                         item_info->Info.IDUser           = info.IDUser; 
    616                         item_info->Info.IDForum          = info.IDForum; 
    617                         item_info->Info.Subject          = info.Subject; 
    618                         item_info->Info.MessageName      = info.MessageName; 
    619                         item_info->Info.UserNick         = info.UserNick; 
    620                         item_info->Info.IDArticle        = info.IDArticle; 
    621                         item_info->Info.MessageDate      = info.MessageDate; 
    622                         item_info->Info.UpdateDate       = info.UpdateDate; 
    623                         item_info->Info.UserRole         = info.UserRole; 
    624                         item_info->Info.UserTitle        = info.UserTitle; 
    625                         item_info->Info.UserTitleColor   = info.UserTitleColor; 
    626                         item_info->Info.LastModerated    = info.LastModerated; 
    627  
    628                         // AMessageInfoEx 
    629                         item_info->Info.IsRead           = info.IsRead; 
    630  
    631                         // ATopicInfo 
    632                         item_info->Info.HasChild         = info.HasChild; 
    633                         item_info->Info.HasUnreadChild   = 0; 
    634  
    635                         // AMessageInfoGUI 
    636                         item_info->IsInfoLoaded          = true; 
    637                         item_info->IsChildLoaded         = true; 
    638                         item_info->UnreadChildCount      = 0; 
    639                         item_info->IsBodyLoaded          = false; 
    640                         item_info->Special               = 0; 
    641  
    642                         item->setText(0, info.Subject); 
    643  
    644                         if (info.IDUser != 0) 
    645                                 item->setText(1, info.UserNick); 
     633void AMessageTree::buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list) 
     634{ 
     635        if (list->count() == 0) 
     636                return; 
     637 
     638        int list_index = 0; 
     639 
     640        AGlobal* global = AGlobal::getInstance(); 
     641 
     642        while (list_index < list->count()) 
     643        { 
     644                AMessageInfoGUI* info = list->at(list_index); 
     645 
     646                if (info->IDParent == root->ID) 
     647                { 
     648                        list->removeAt(list_index); 
     649 
     650                        info->IsInfoLoaded       = true; 
     651                        info->IsChildLoaded      = true; 
     652                        info->UnreadChildCount   = 0; 
     653                        info->UnreadChildCountMy = 0; 
     654 
     655                        info->Item->setText(0, info->Subject); 
     656 
     657                        // TODO: сделать общую функцию формирования имени/ника 
     658                        if (info->IDUser != 0) 
     659                                info->Item->setText(1, info->UserNick); 
    646660                        else 
    647                                 item->setText(1, QString::fromUtf8("Аноним ") + info.UserTitle); 
    648  
    649                         item->setText(2, info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 
    650  
    651                         to_build.append(item); 
    652  
    653                         list->removeAt(index); 
    654  
    655                         size--; 
    656  
    657                         if (info.IsRead == true) 
    658                                 item->setIcon(0, m_message_read); 
    659                         else 
     661                                info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 
     662 
     663                        info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     664 
     665                        root->Item->addChild(info->Item); 
     666 
     667                        // установка родителям свойств непрочитанных сообщений 
     668                        if (info->IsRead == false && root->IDUser == m_me.ID) 
    660669                        { 
    661                                 item->setIcon(0, m_message_unread); 
    662  
    663                                 MessageTreeWidgetItem* temp_item = parent_item; 
    664  
    665                                 while (temp_item != NULL) 
     670                                // сообщение не прочитано и это ответ не мне 
     671                                info->Item->setIcon(0, m_message_unread_my); 
     672 
     673                                MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 
     674 
     675                                while (item_parent != NULL) 
    666676                                { 
    667                                         AMessageInfoGUI* temp_info = temp_item->pag(); 
    668  
    669                                         if (info.HasUnreadChild == 2) 
    670                                                 temp_info->Info.HasUnreadChild = 2; 
    671  
    672                                         if (temp_info->Info.IsRead == true) 
     677                                        AMessageInfoGUI* info_parent = item_parent->pag(); 
     678 
     679                                        if (info_parent->HasUnreadChildMy != true) 
    673680                                        { 
    674                                                 if (temp_info->Info.HasUnreadChild == 2) 
    675                                                         temp_item->setIcon(0, m_child_unread_my); 
     681                                                info_parent->HasUnreadChild   = true; 
     682                                                info_parent->HasUnreadChildMy = true; 
     683 
     684                                                if (info_parent->IsRead == true) 
     685                                                        item_parent->setIcon(0, m_child_unread_my); 
    676686                                                else 
    677                                                         temp_item->setIcon(0, m_child_unread); 
     687                                                        item_parent->setIcon(0, m_message_unread_my); 
    678688                                        } 
    679                                         else if (temp_info->Info.HasUnreadChild == 2) 
    680                                                 temp_item->setIcon(0, m_message_unread_my); 
    681  
    682                                         temp_info->UnreadChildCount++; 
    683  
    684                                         temp_item = (MessageTreeWidgetItem*)temp_item->parent(); 
    685                                 } 
     689 
     690                                        info_parent->UnreadChildCount++; 
     691                                        info_parent->UnreadChildCountMy++; 
     692 
     693                                        item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
     694 
     695                                }   // while (item_parent != NULL) 
    686696                        } 
    687                 } 
    688                 else 
    689                         index++; 
    690         } 
    691  
    692         size = to_build.size(); 
    693  
    694         for (int i = 0; i < size; i++) 
    695                 buildTree(to_build.at(i), list); 
     697                        else if (info->IsRead == false) 
     698                        { 
     699                                // сообщение не прочитано, но это ответ не мне 
     700                                info->Item->setIcon(0, m_message_unread); 
     701 
     702                                MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 
     703 
     704                                while (item_parent != NULL) 
     705                                { 
     706                                        AMessageInfoGUI* info_parent = item_parent->pag(); 
     707 
     708                                        if (info_parent->HasUnreadChild != true) 
     709                                        { 
     710                                                info_parent->HasUnreadChild = true; 
     711 
     712                                                if (info_parent->IsRead == true) 
     713                                                        item_parent->setIcon(0, m_child_unread); 
     714                                        } 
     715 
     716                                        info_parent->UnreadChildCount++; 
     717 
     718                                        item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
     719 
     720                                }   // while (item_parent != NULL) 
     721                        } 
     722                        else   // else if (info->IsRead == false) 
     723                        { 
     724                                // сообщение прочитано 
     725                                info->Item->setIcon(0, m_message_read); 
     726                        } 
     727 
     728                        // достройка дочерних веток для текущей 
     729                        if (info->HasChild) 
     730                        { 
     731                                buildTree(info, list); 
     732                                list_index = 0; 
     733                        } 
     734                } 
     735                else   // if (info->ID == id_parent) 
     736                { 
     737                        list_index++; 
     738                } 
     739        } 
    696740} 
    697741//---------------------------------------------------------------------------------------------- 
     
    713757                return; 
    714758 
    715         std::auto_ptr<FormSource> form (new FormSource(m_parent, item->pag()->Info.Message)); 
     759        std::auto_ptr<FormSource> form(new FormSource(m_parent, item->pag()->Message)); 
     760 
    716761        form->exec(); 
    717762} 
     
    724769        if (item == NULL) 
    725770                return; 
     771 
     772        AMessageInfoGUI* info = item->pag(); 
    726773 
    727774        if (m_main_form != NULL) 
     
    729776 
    730777        // загрузка тела сообщения, если тело еще не загружено 
    731         if (item->pag()->IsBodyLoaded == false) 
     778        if (info->IsBodyLoaded == false) 
    732779        { 
    733780                // получение хранилища 
     
    743790                QString body; 
    744791 
    745                 if (storage->getMessageBody(item->pag()->Info.ID, body, NULL) == false) 
     792                if (storage->getMessageBody(info->ID, body, NULL) == false) 
    746793                { 
    747794                        storage->showError(m_parent); 
     
    749796                } 
    750797 
    751                 item->pag()->IsBodyLoaded = true; 
    752                 item->pag()->Info.Message = body; 
    753         } 
    754  
    755         AMessageInfoGUI message = item->tag(); 
    756  
    757         m_message_view->setMessage(message.Info, m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND, m_forum_rated); 
    758  
    759         if (item->pag()->Info.IsRead == false) 
     798                info->IsBodyLoaded = true; 
     799                info->Message      = body; 
     800        } 
     801 
     802        // отображение сообщения 
     803        m_message_view->setMessage(*info, m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND, m_current_forum.Rated); 
     804 
     805        // взвод таймера для пометки как прочитанного 
     806        if (info->IsRead == false) 
    760807        { 
    761808                int interval = AGlobal::getInstance()->MarkAsReadTimer; 
     
    768815        else 
    769816                m_timer.stop(); 
     817 
    770818} 
    771819//---------------------------------------------------------------------------------------------- 
     
    778826 
    779827        // если уже прочитан 
    780         if (info->Info.IsRead == is_read) 
    781                 return; 
    782  
    783         // пометить как прочитаное в хранилище 
     828        if (info->IsRead == is_read) 
     829                return; 
     830 
     831        // пометить как прочитанное в хранилище 
    784832        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    785833 
     
    790838        } 
    791839 
    792         if (storage->setIDsAsRead(QList<int>() << info->Info.ID, idsMessage, is_read, QDateTime(), NULL) == false) 
     840        if (storage->setIDsAsRead(QList<int>() << info->ID, idsMessage, is_read, QDateTime(), NULL) == false) 
    793841        { 
    794842                storage->showError(m_parent); 
     
    796844        } 
    797845 
    798         // пометка в дереве 
    799         info->Info.IsRead = is_read; 
     846        // установка флага как прочитанного и пометка в дереве 
     847        info->IsRead = is_read; 
    800848 
    801849        if (is_read == true) 
    802850        { 
    803                 if (info->UnreadChildCount != 0) 
    804                 { 
    805                         if (info->Info.HasUnreadChild == 2) 
    806                                 item->setIcon(0, m_child_unread_my); 
    807                         else 
    808                                 item->setIcon(0, m_child_unread); 
    809                 } 
     851                // установка иконки помечаемому сообщению 
     852                if (info->HasUnreadChildMy) 
     853                        item->setIcon(0, m_child_unread_my); 
     854                else if (info->HasUnreadChild) 
     855                        item->setIcon(0, m_child_unread); 
    810856                else 
    811                 { 
    812                         if (item->parent() == NULL && info->IsChildLoaded == false && info->Info.HasUnreadChild != 0) 
     857                        item->setIcon(0, m_message_read); 
     858 
     859                // флаг того, что это было сообщение для меня 
     860                bool message_to_me = false; 
     861 
     862                // установка флагов и иконок у родительских сообщений 
     863                MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(item->parent()); 
     864 
     865                if (item_parent != NULL && item_parent->pag()->IDUser == m_me.ID) 
     866                        message_to_me = true; 
     867 
     868                while (item_parent != NULL) 
     869                { 
     870                        AMessageInfoGUI* info_parent = item_parent->pag(); 
     871 
     872                        int old_unread_count    = info_parent->UnreadChildCount; 
     873                        int old_unread_count_my = info_parent->UnreadChildCountMy; 
     874 
     875                        // уменьшение количества непрочитанных дочерних 
     876                        // и установка соответствующих флагов 
     877                        if (info_parent->UnreadChildCount > 0) 
     878                                info_parent->UnreadChildCount--; 
     879 
     880                        if (message_to_me == true && info_parent->UnreadChildCountMy > 0) 
     881                                info_parent->UnreadChildCountMy--; 
     882 
     883                        if (info_parent->UnreadChildCountMy == 0) 
     884                                info_parent->HasUnreadChildMy = false; 
     885 
     886                        if (info_parent->UnreadChildCount == 0) 
     887                                info_parent->HasUnreadChild = false; 
     888 
     889                        // установка иконок 
     890                        if (info_parent->IsRead == false) 
    813891                        { 
    814                                 if (info->Info.HasUnreadChild == 2) 
    815                                         item->setIcon(0, m_child_unread_my); 
    816                                 else 
    817                                         item->setIcon(0, m_child_unread); 
     892                                // родитель непрочитан 
     893 
     894                                // если среди дочерних прочитали дочернее мне и больше непрочитанных дочерних мне нет 
     895                                // и должна произойти смена иконки 
     896                                if (old_unread_count_my != 0 && info_parent->UnreadChildCountMy == 0) 
     897                                        item_parent->setIcon(0, m_message_unread); 
    818898                        } 
    819899                        else 
    820900                        { 
    821                                 item->setIcon(0, m_message_read); 
    822                                 info->Info.HasUnreadChild = 0; 
     901                                // родитель прочитан 
     902 
     903                                // если среди дочерних есть непрочитанные мне 
     904                                // и должна произойти смена иконки 
     905                                if (old_unread_count_my != info_parent->UnreadChildCountMy && info_parent->UnreadChildCountMy > 0) 
     906                                        item_parent->setIcon(0, m_child_unread_my); 
     907 
     908                                // если среди дочерних есть непрочитанные 
     909                                // и должна произойти смена иконки 
     910                                else if (old_unread_count != info_parent->UnreadChildCount && info_parent->UnreadChildCount > 0) 
     911                                        item_parent->setIcon(0, m_child_unread); 
     912 
     913                                // нет дочерних непрочитанных 
     914                                else 
     915                                        item_parent->setIcon(0, m_message_read); 
    823916                        } 
    824                 } 
    825  
    826                 MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    827  
    828                 while (parent_item != NULL) 
    829                 { 
    830                         AMessageInfoGUI* parent_info = parent_item->pag(); 
    831  
    832                         parent_info->UnreadChildCount--; 
    833  
    834                         if (parent_info->Info.IsRead == true && parent_info->UnreadChildCount == 0) 
    835                         { 
    836                                 parent_info->Info.HasUnreadChild = 0; 
    837                                 parent_item->setIcon(0, m_message_read); 
    838                         } 
    839  
    840                         parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); 
     917 
     918                        item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
    841919                } 
    842920 
     
    844922                m_forum_tree->changeUnreadCount(-1); 
    845923        } 
    846         else 
    847         { 
    848                 if (info->Info.HasUnreadChild == 2) 
    849                         item->setIcon(0, m_message_unread_my); 
    850                 else 
    851                         item->setIcon(0, m_message_unread); 
    852  
     924        else   // if (is_read == true) 
     925        { 
     926                // TODO: Доделать пометку родителей, если отметилось сообщение, которое является ответом мне 
     927 
     928                // установка иконки помечаемому сообщению 
     929                item->setIcon(0, m_message_unread); 
     930 
     931                // установка флагов и иконок у родительских сообщений 
    853932                MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    854933 
     
    857936                        AMessageInfoGUI* parent_info = parent_item->pag(); 
    858937 
     938                        // смена иконки при необходимости 
     939                        if (parent_info->IsRead == true && parent_info->HasUnreadChild == false) 
     940                                parent_item->setIcon(0, m_child_unread); 
     941 
    859942                        parent_info->UnreadChildCount++; 
    860                         parent_info->Info.HasUnreadChild = 1; // TODO: обновить в соответствии с ответами мне 
    861  
    862                         if (parent_info->Info.IsRead == true) 
    863                         { 
    864                                 if (parent_info->Info.HasUnreadChild == 2) 
    865                                         parent_item->setIcon(0, m_child_unread_my); 
    866                                 else 
    867                                         parent_item->setIcon(0, m_child_unread); 
    868                         } 
     943                        parent_info->HasUnreadChild = true; 
    869944 
    870945                        parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); 
     
    873948                // увеличение количества непрочитанных в дереве форума 
    874949                m_forum_tree->changeUnreadCount(1); 
    875         } 
     950 
     951        }   // if (is_read == true) ... else 
    876952} 
    877953//---------------------------------------------------------------------------------------------- 
     
    899975//---------------------------------------------------------------------------------------------- 
    900976 
    901 void AMessageTree::markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count) 
    902 { 
    903         MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 
    904  
    905         if (item_parent->pag()->Info.IsRead != is_read) 
    906                 count++; 
    907  
    908         if (is_read == true) 
    909         { 
    910                 item_parent->setIcon(0, m_message_read); 
    911  
    912                 item_parent->pag()->Info.IsRead         = is_read; 
    913                 item_parent->pag()->UnreadChildCount    = 0; 
    914                 item_parent->pag()->Info.HasUnreadChild = (is_read == true ? 1 : 0); // TODO: обновить в соответствии с ответами мне 
    915  
    916                 for (int i = 0; i < item_parent->childCount(); i++) 
    917                         markThreadAsRead(item_parent->child(i), is_read, count); 
     977bool AMessageTree::markThreadAsRead (int id, bool is_read) 
     978{ 
     979        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     980 
     981        if (storage.get() == NULL) 
     982        { 
     983                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     984                return false; 
     985        } 
     986 
     987        if (storage->setIDsAsRead(QList<int>() << id, idsTopic, is_read, QDateTime(), NULL) == false) 
     988        { 
     989                storage->showError(m_parent); 
     990                return false; 
     991        } 
     992 
     993        return true; 
     994} 
     995//---------------------------------------------------------------------------------------------- 
     996 
     997void AMessageTree::menu_mark_thread_as_read_triggered () 
     998{ 
     999        QTreeWidgetItem* item = currentItem(); 
     1000 
     1001        if (item == NULL) 
     1002                return; 
     1003 
     1004        // поиск родителя 
     1005        MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
     1006 
     1007        AMessageInfoGUI* info = parent->pag(); 
     1008 
     1009        // пометка в хранилище 
     1010        if (markThreadAsRead(info->ID, true) != true) 
     1011                return; 
     1012 
     1013        // пометка в дереве 
     1014        if (info->IsChildLoaded == true) 
     1015        { 
     1016                int count = 0; 
     1017 
     1018                markThreadAsRead(parent, true, count); 
     1019 
     1020                m_forum_tree->changeUnreadCount(-count); 
    9181021        } 
    9191022        else 
    9201023        { 
    921                 item_parent->setIcon(0, m_message_unread); 
    922  
    923                 item_parent->pag()->Info.IsRead = is_read; 
    924  
    925                 MessageTreeWidgetItem* temp_parent = static_cast<MessageTreeWidgetItem*>(parent->parent()); 
    926  
    927                 while (temp_parent != NULL) 
    928                 { 
    929                         temp_parent->pag()->Info.HasUnreadChild = (is_read == true ? 1 : 0); // TODO: обновить в соответствии с ответами мне 
    930                         temp_parent->pag()->UnreadChildCount++; 
    931                         temp_parent = static_cast<MessageTreeWidgetItem*>(temp_parent->parent()); 
    932                 } 
    933  
    934                 for (int i = 0; i < item_parent->childCount(); i++) 
    935                         markThreadAsRead(item_parent->child(i), is_read, count); 
    936         } 
    937 } 
    938 //---------------------------------------------------------------------------------------------- 
    939  
    940 void AMessageTree::menu_mark_thread_as_read_triggered () 
     1024                parent->setIcon(0, m_message_read); 
     1025 
     1026                AMessageInfoGUI* info = parent->pag(); 
     1027 
     1028                info->HasUnreadChild     = false; 
     1029                info->HasUnreadChildMy   = false; 
     1030                info->UnreadChildCount   = 0; 
     1031                info->UnreadChildCountMy = 0; 
     1032 
     1033                // поскольку дочерние элементы еще не загружены, 
     1034                // обновление количества непрочитаных в дереве форума 
     1035                m_forum_tree->reloadUnread(false); 
     1036        } 
     1037} 
     1038//---------------------------------------------------------------------------------------------- 
     1039 
     1040void AMessageTree::menu_mark_thread_as_unread_triggered () 
    9411041{ 
    9421042        QTreeWidgetItem* item = currentItem(); 
     
    9461046 
    9471047        // поиск родителя 
    948         QTreeWidgetItem* parent = item; 
    949  
    950         while (parent->parent() != NULL) 
    951                 parent = parent->parent(); 
    952  
    953         MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 
    954  
    955         AMessageInfoGUI* info = item_parent->pag(); 
    956  
    957         // обновление данных в хранилище 
    958         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    959  
    960         if (storage.get() == NULL) 
    961         { 
    962                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    963                 return; 
    964         } 
    965  
    966         if (storage->setIDsAsRead(QList<int>() << info->Info.ID, idsTopic, true, QDateTime(), NULL) == false) 
    967         { 
    968                 storage->showError(m_parent); 
    969                 return; 
    970         } 
    971  
    972         // обновление данных в дереве 
     1048        MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
     1049 
     1050        AMessageInfoGUI* info = parent->pag(); 
     1051 
     1052        // пометка в хранилище 
     1053        if (markThreadAsRead(info->ID, false) != true) 
     1054                return; 
     1055 
     1056        // пометка в дереве 
    9731057        if (info->IsChildLoaded == true) 
    9741058        { 
    9751059                int count = 0; 
    9761060 
    977                 markThreadAsRead(parent, true, count); 
    978  
    979                 item_parent->pag()->Info.HasUnreadChild = 0; // TODO: обновить в соответствии с ответами мне 
    980  
    981                 m_forum_tree->changeUnreadCount(-count); 
     1061                markThreadAsRead(parent, false, count); 
     1062 
     1063                m_forum_tree->changeUnreadCount(count); 
    9821064        } 
    9831065        else 
    9841066        { 
    985                 item_parent->setIcon(0, m_message_read); 
    986  
    987                 item_parent->pag()->Info.HasUnreadChild = 0; // TODO: обновить в соответствии с ответами мне 
    988  
    989                 // поскольку дочерние элементы еще не загружены, 
    990                 // обновление количества непрочитаных в дереве форума 
    991                 m_forum_tree->reloadUnread(false); 
    992         } 
    993 } 
    994 //---------------------------------------------------------------------------------------------- 
    995  
    996 void AMessageTree::menu_mark_thread_as_unread_triggered () 
    997 { 
    998         QTreeWidgetItem* item = currentItem(); 
     1067                parent->setIcon(0, m_message_unread); 
     1068 
     1069                AMessageInfoGUI* info = parent->pag(); 
     1070 
     1071                if (info->HasChild == true) 
     1072                        info->HasUnreadChild = true; 
     1073                else 
     1074                        info->HasUnreadChild = false; 
     1075 
     1076                info->HasUnreadChildMy = false; 
     1077 
     1078                // поскольку дочерние элементы еще не загружены, 
     1079                // обновление количества непрочитаных в дереве форума 
     1080                m_forum_tree->reloadUnread(false); 
     1081        } 
     1082} 
     1083//---------------------------------------------------------------------------------------------- 
     1084 
     1085void AMessageTree::menu_reply_triggered () 
     1086{ 
     1087        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    9991088 
    10001089        if (item == NULL) 
    10011090                return; 
    10021091 
    1003         // поиск родителя 
    1004         QTreeWidgetItem* parent = item; 
    1005  
    1006         while (parent->parent() != NULL) 
    1007                 parent = parent->parent(); 
    1008  
    1009         MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 
    1010  
    1011         AMessageInfoGUI* info = item_parent->pag(); 
    1012  
    1013         // обновление данных в хранилище 
    1014         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1015  
    1016         if (storage.get() == NULL) 
    1017         { 
    1018                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1019                 return; 
    1020         } 
    1021  
    1022         if (storage->setIDsAsRead(QList<int>() << info->Info.ID, idsTopic, false, QDateTime(), NULL) == false) 
    1023         { 
    1024                 storage->showError(m_parent); 
    1025                 return; 
    1026         } 
    1027  
    1028         // обновление данных в дереве 
    1029         if (info->IsChildLoaded == true) 
    1030         { 
    1031                 int count = 0; 
    1032  
    1033                 markThreadAsRead(parent, false, count); 
    1034  
    1035                 item_parent->pag()->Info.HasUnreadChild = 1; // TODO: Обновить в соответствии с ответами мне 
    1036  
    1037                 m_forum_tree->changeUnreadCount(count); 
    1038         } 
    1039         else 
    1040         { 
    1041                 item_parent->setIcon(0, m_message_unread); 
    1042  
    1043                 item_parent->pag()->Info.HasUnreadChild = 1; // TODO: Обновить в соответствии с ответами мне 
    1044  
    1045                 // поскольку дочерние элементы еще не загружены, 
    1046                 // обновление количества непрочитаных в дереве форума 
    1047                 m_forum_tree->reloadUnread(false); 
    1048         } 
    1049 } 
    1050 //---------------------------------------------------------------------------------------------- 
    1051  
    1052 void AMessageTree::menu_reply_triggered () 
    1053 { 
    1054         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    1055  
    1056         if (item == NULL) 
    1057                 return; 
    1058  
    1059         FormMessage* form = new FormMessage(NULL, true, item->pag()->Info); 
     1092        FormMessage* form = new FormMessage(NULL, true, *(item->pag())); 
    10601093 
    10611094        form->setForumTree(m_forum_tree); 
     
    10861119        QList<QTreeWidgetItem*> items; 
    10871120 
     1121        AGlobal* global = AGlobal::getInstance(); 
     1122 
    10881123        for (int i = 0; i < list.count(); i++) 
    10891124        { 
    1090                 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    1091  
    1092                 AMessageInfoGUI* info = item->pag(); 
    1093  
    1094                 info->Info.ID             = list[i].ID; 
    1095                 info->Info.IDTopic        = list[i].IDTopic; 
    1096                 info->Info.IDParent       = list[i].IDParent; 
    1097                 info->Info.IDUser         = list[i].IDUser; 
    1098                 info->Info.IDForum        = list[i].IDForum; 
    1099                 info->Info.Subject        = list[i].Subject; 
    1100                 info->Info.MessageName    = list[i].MessageName; 
    1101                 info->Info.UserNick       = list[i].UserNick; 
    1102                 info->Info.Message        = list[i].Message; 
    1103                 info->Info.IDArticle      = list[i].IDArticle; 
    1104                 info->Info.MessageDate    = list[i].MessageDate; 
    1105                 info->Info.UpdateDate     = list[i].UpdateDate; 
    1106                 info->Info.UserRole       = list[i].UserRole; 
    1107                 info->Info.UserTitle      = list[i].UserTitle; 
    1108                 info->Info.UserTitleColor = list[i].UserTitleColor; 
    1109                 info->Info.LastModerated  = list[i].LastModerated; 
    1110  
    1111                 info->Info.IsRead         = true; 
    1112  
    1113                 info->Info.HasChild       = false; 
    1114                 info->Info.HasUnreadChild = 0; 
    1115  
    1116                 info->IsInfoLoaded        = true; 
    1117                 info->IsChildLoaded       = true; 
    1118                 info->UnreadChildCount    = 0; 
    1119                 info->IsBodyLoaded        = true; 
    1120                 info->Special             = list[i].ID; 
    1121  
    1122                 item->setText(0, info->Info.Subject); 
    1123  
    1124                 if (info->Info.IDUser == 0) 
    1125                 { 
    1126                         info->Info.UserNick = QString::fromUtf8("(локальный)"); 
    1127                         item->setText(1, info->Info.UserNick); 
     1125                AMessageInfoGUI* info = createItem(); 
     1126 
     1127                info->ID             = list[i].ID; 
     1128                info->IDTopic        = list[i].IDTopic; 
     1129                info->IDParent       = list[i].IDParent; 
     1130                info->IDUser         = list[i].IDUser; 
     1131                info->IDForum        = list[i].IDForum; 
     1132                info->Subject        = list[i].Subject; 
     1133                info->MessageName    = list[i].MessageName; 
     1134                info->UserNick       = list[i].UserNick; 
     1135                info->Message        = list[i].Message; 
     1136                info->IDArticle      = list[i].IDArticle; 
     1137                info->MessageDate    = list[i].MessageDate; 
     1138                info->UpdateDate     = list[i].UpdateDate; 
     1139                info->UserRole       = list[i].UserRole; 
     1140                info->UserTitle      = list[i].UserTitle; 
     1141                info->UserTitleColor = list[i].UserTitleColor; 
     1142                info->LastModerated  = list[i].LastModerated; 
     1143 
     1144                info->IsInfoLoaded     = true; 
     1145                info->IsRead           = true; 
     1146                info->IsBodyLoaded     = true; 
     1147                info->IsChildLoaded    = true; 
     1148                info->HasUnreadChild   = 0; 
     1149                info->HasUnreadChildMy = 0; 
     1150                info->Special          = list[i].ID; 
     1151 
     1152                info->Item->setText(0, info->Subject); 
     1153 
     1154                if (info->IDUser == 0) 
     1155                { 
     1156                        info->UserNick = QString::fromUtf8("(локальный)"); 
     1157                        info->Item->setText(1, info->UserNick); 
    11281158                } 
    11291159                else 
    1130                         item->setText(1, info->Info.UserNick); 
    1131  
    1132                 item->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 
    1133  
    1134                 items.append(item); 
     1160                        info->Item->setText(1, info->UserNick); 
     1161 
     1162                info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     1163 
     1164                items.append(info->Item); 
    11351165        } 
    11361166 
     
    12011231        else if (url == "avalon:moderate") 
    12021232        { 
    1203                 FormModerate* form = new FormModerate(m_parent, item->pag()->Info.ID); 
     1233                FormModerate* form = new FormModerate(m_parent, item->pag()->ID); 
    12041234 
    12051235                form->setForumTree(m_forum_tree); 
     
    12271257        ARating2Send info; 
    12281258 
    1229         info.IDMessage = item->pag()->Info.ID; 
     1259        info.IDMessage = item->pag()->ID; 
    12301260        info.Rate      = rate; 
    12311261        info.Date      = QDateTime::currentDateTime(); 
     
    12391269        } 
    12401270 
    1241         // обновление в дереве форумов количества непрочитаных сообщений 
     1271        // обновление в дереве форумов количества непрочитанных сообщений 
    12421272        if (m_forum_tree != NULL) 
    12431273                m_forum_tree->reloadUnread(false); 
     
    12451275//---------------------------------------------------------------------------------------------- 
    12461276 
    1247 void AMessageTree::gotoNextUnreadArticle () 
    1248 { 
    1249         if (checkCurrentItem() == false) 
    1250                 return; 
     1277void AMessageTree::gotoNextUnreadArticle (QTreeWidgetItem* current_item) 
     1278{ 
     1279        AMessageInfoGUI* info = NULL; 
     1280 
     1281        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(current_item); 
     1282 
     1283        // если не было выделения, то ищем первый непрочитанный топик или топик с непрочитанными сообщениями 
     1284        if (item == NULL) 
     1285        { 
     1286                for (int i = 0; i < topLevelItemCount(); i++) 
     1287                { 
     1288                        item = static_cast<MessageTreeWidgetItem*>(topLevelItem(i)); 
     1289 
     1290                        info = item->pag(); 
     1291 
     1292                        if (info->IsInfoLoaded == false) 
     1293                                return; 
     1294                        else if (info->IsRead == false) 
     1295                        { 
     1296                                setCurrentItem(item); 
     1297 
     1298                                scrollToItem(item, QAbstractItemView::PositionAtCenter); 
     1299 
     1300                                return; 
     1301                        } 
     1302                        else if (info->HasUnreadChild == true) 
     1303                                break; 
     1304                } 
     1305        } 
     1306        else 
     1307                info = item->pag(); 
     1308 
     1309        // флаг петли 
     1310        bool loopback = false; 
     1311 
     1312        // есть выделение или найден топик с непрочитанными сообщениями 
     1313        while (true) 
     1314        { 
     1315                if (info->HasUnreadChild == true && info->IsChildLoaded == false) 
     1316                        item->setExpanded(true); 
     1317 
     1318                // выбор следующего элемента 
     1319                if (info->HasUnreadChild == true) 
     1320                        // если есть дочерние непрочитанные, то выбираем первый дочерний 
     1321                        item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstChild(item)); 
     1322                else 
     1323                { 
     1324                        // если нет дочерних непрочитанных, то ... 
     1325 
     1326                        // смотрим, есть ли у элемента родитель и есть ли у родителя непрочитанные дочерние 
     1327                        MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
     1328 
     1329                        // если есть родитель и у него нет непрочитанных дочерних, то поднимаемся на уровень родителя 
     1330                        if (parent_item != NULL && parent_item->pag()->HasUnreadChild == false) 
     1331                                item = parent_item; 
     1332                        else 
     1333                        { 
     1334                                // у родителя есть непрочитанные дочерние или нет родителя - переходим к следующему брату 
     1335                                // несмотря на то, что непрочитанный брат может быть и выше 
     1336                                MessageTreeWidgetItem* sibling_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
     1337 
     1338                                // если следующего брата нет 
     1339                                if (sibling_item == NULL && parent_item != NULL) 
     1340                                { 
     1341                                        // движение вверх по дереву, пока не найдется следующий брат у родителя 
     1342                                        while (parent_item != NULL) 
     1343                                        { 
     1344                                                MessageTreeWidgetItem* last_child_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastChild(parent_item)); 
     1345 
     1346                                                if (last_child_item != item) 
     1347                                                        break; 
     1348 
     1349                                                item = parent_item; 
     1350 
     1351                                                parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
     1352                                        } 
     1353 
     1354                                        // сдвиг на следующего брата в соседней подветке 
     1355                                        item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
     1356                                } 
     1357                                else 
     1358                                        item = sibling_item; 
     1359                        } 
     1360                } 
     1361 
     1362                // если достигнут конец дерева, то переходим в корень 
     1363                if (item == NULL) 
     1364                        item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
     1365 
     1366                info = item->pag(); 
     1367 
     1368                // если найденый топик с незагруженной информацией 
     1369                if (info->IsInfoLoaded == false) 
     1370                { 
     1371                        if (loopback == true) 
     1372                                return; 
     1373 
     1374                        item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
     1375                        info = item->pag(); 
     1376 
     1377                        loopback = true; 
     1378                } 
     1379 
     1380                if (info->IsRead == false) 
     1381                        break; 
     1382        } 
     1383 
     1384        setCurrentItem(item); 
     1385 
     1386        scrollToItem(item, QAbstractItemView::PositionAtCenter); 
     1387} 
     1388//---------------------------------------------------------------------------------------------- 
     1389 
     1390void AMessageTree::loadRating2Send () 
     1391{ 
     1392        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     1393 
     1394        if (storage.get() == NULL) 
     1395        { 
     1396                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     1397                return; 
     1398        } 
     1399 
     1400        ARating2SendList rating_list; 
     1401        AMessageInfoList message_list; 
     1402 
     1403        if (storage->getRating2SendList(message_list, rating_list, NULL) == false) 
     1404        { 
     1405                storage->showError(m_parent); 
     1406                return; 
     1407        } 
     1408 
     1409        QList<QTreeWidgetItem*> items; 
     1410 
     1411        AGlobal* global = AGlobal::getInstance(); 
     1412 
     1413        for (int i = 0; i < message_list.count(); i++) 
     1414        { 
     1415                AMessageInfoGUI* info = createItem(); 
     1416 
     1417                info->ID             = message_list[i].ID; 
     1418                info->IDTopic        = message_list[i].IDTopic; 
     1419                info->IDParent       = message_list[i].IDParent; 
     1420                info->IDUser         = message_list[i].IDUser; 
     1421                info->IDForum        = message_list[i].IDForum; 
     1422                info->Subject        = message_list[i].Subject; 
     1423                info->MessageName    = message_list[i].MessageName; 
     1424                info->UserNick       = message_list[i].UserNick; 
     1425                info->Message        = message_list[i].Message; 
     1426                info->IDArticle      = message_list[i].IDArticle; 
     1427                info->MessageDate    = message_list[i].MessageDate; 
     1428                info->UpdateDate     = message_list[i].UpdateDate; 
     1429                info->UserRole       = message_list[i].UserRole; 
     1430                info->UserTitle      = message_list[i].UserTitle; 
     1431                info->UserTitleColor = message_list[i].UserTitleColor; 
     1432                info->LastModerated  = message_list[i].LastModerated; 
     1433 
     1434                info->IsInfoLoaded     = true; 
     1435                info->IsRead           = true; 
     1436                info->IsBodyLoaded     = true; 
     1437                info->IsChildLoaded    = true; 
     1438                info->HasUnreadChild   = 0; 
     1439                info->HasUnreadChildMy = 0; 
     1440                info->Special          = rating_list[i].ID; 
     1441 
     1442                info->Item->setText(0, info->Subject); 
     1443 
     1444                if (info->IDUser == 0) 
     1445                { 
     1446                        info->UserNick = QString::fromUtf8("(локальный)"); 
     1447                        info->Item->setText(1, info->UserNick); 
     1448                } 
     1449                else 
     1450                        info->Item->setText(1, info->UserNick); 
     1451 
     1452                info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     1453 
     1454                int rate = rating_list[i].Rate; 
     1455 
     1456                if (rate == -4) 
     1457                        info->Item->setIcon(0, m_rating_plus); 
     1458                else if (rate == -3) 
     1459                        info->Item->setIcon(0, m_rating_plus_1); 
     1460                else if (rate == -2) 
     1461                        info->Item->setIcon(0, m_rating_smile); 
     1462                else if (rate == -1) 
     1463                        info->Item->setIcon(0, m_rating_cross); 
     1464                else if (rate == 0) 
     1465                        info->Item->setIcon(0, m_rating_minus); 
     1466                else if (rate == 1) 
     1467                        info->Item->setIcon(0, m_rating_1); 
     1468                else if (rate == 2) 
     1469                        info->Item->setIcon(0, m_rating_2); 
     1470                else if (rate == 3) 
     1471                        info->Item->setIcon(0, m_rating_3); 
     1472 
     1473                items.append(info->Item); 
     1474        } 
     1475 
     1476        addTopLevelItems(items); 
     1477} 
     1478//---------------------------------------------------------------------------------------------- 
     1479 
     1480void AMessageTree::loadModerate2Send () 
     1481{ 
     1482        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     1483 
     1484        if (storage.get() == NULL) 
     1485        { 
     1486                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     1487                return; 
     1488        } 
     1489 
     1490        AMessageInfoList   message_list; 
     1491        AModerate2SendList moderate_list; 
     1492 
     1493        if (storage->getModerate2SendList(message_list, moderate_list, NULL) == false) 
     1494        { 
     1495                storage->showError(m_parent); 
     1496                return; 
     1497        } 
     1498 
     1499        QList<QTreeWidgetItem*> items; 
     1500 
     1501        AGlobal* global = AGlobal::getInstance(); 
     1502 
     1503        for (int i = 0; i < message_list.count(); i++) 
     1504        { 
     1505                AMessageInfoGUI* info = createItem(); 
     1506 
     1507                info->ID             = message_list[i].ID; 
     1508                info->IDTopic        = message_list[i].IDTopic; 
     1509                info->IDParent       = message_list[i].IDParent; 
     1510                info->IDUser         = message_list[i].IDUser; 
     1511                info->IDForum        = message_list[i].IDForum; 
     1512                info->Subject        = message_list[i].Subject; 
     1513                info->MessageName    = message_list[i].MessageName; 
     1514                info->UserNick       = message_list[i].UserNick; 
     1515                info->Message        = message_list[i].Message; 
     1516                info->IDArticle      = message_list[i].IDArticle; 
     1517                info->MessageDate    = message_list[i].MessageDate; 
     1518                info->UpdateDate     = message_list[i].UpdateDate; 
     1519                info->UserRole       = message_list[i].UserRole; 
     1520                info->UserTitle      = message_list[i].UserTitle; 
     1521                info->UserTitleColor = message_list[i].UserTitleColor; 
     1522                info->LastModerated  = message_list[i].LastModerated; 
     1523 
     1524                info->IsInfoLoaded     = true; 
     1525                info->IsRead           = true; 
     1526                info->IsBodyLoaded     = true; 
     1527                info->IsChildLoaded    = true; 
     1528                info->HasUnreadChild   = 0; 
     1529                info->HasUnreadChildMy = 0; 
     1530                info->Special          = message_list[i].ID; 
     1531 
     1532                info->Item->setText(0, info->Subject); 
     1533 
     1534                if (info->IDUser == 0) 
     1535                { 
     1536                        info->UserNick = QString::fromUtf8("(локальный)"); 
     1537                        info->Item->setText(1, info->UserNick); 
     1538                } 
     1539                else 
     1540                        info->Item->setText(1, info->UserNick); 
     1541 
     1542                info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     1543 
     1544                info->Item->setIcon(0, m_moderate); 
     1545 
     1546                items.append(info->Item); 
     1547        } 
     1548 
     1549        addTopLevelItems(items); 
     1550} 
     1551//---------------------------------------------------------------------------------------------- 
     1552 
     1553void AMessageTree::gotoNextUnreadThread () 
     1554{ 
     1555        AMessageInfoGUI* info = NULL; 
    12511556 
    12521557        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    12531558 
     1559        // если не было выделения, то ищем следующую непрочитанную статью (она будет первой) 
     1560        if (item == NULL) 
     1561        { 
     1562                gotoNextUnreadArticle(NULL); 
     1563                return; 
     1564        } 
     1565 
     1566        // item установлен на топик 
     1567        item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
     1568        info = item->pag(); 
     1569 
     1570        // флаг петли 
     1571        bool loopback = false; 
     1572 
     1573        // поиск следующего топика с непрочитанными сообщениями 
    12541574        while (true) 
    12551575        { 
    1256                 if (item->pag()->Info.IsRead == false) 
     1576                // следующий топик за текущим 
     1577                item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
     1578 
     1579                // если достигнут конец дерева, то переходим в корень 
     1580                if (item == NULL) 
     1581                        item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
     1582 
     1583                info = item->pag(); 
     1584 
     1585                // если найденый топик с незагруженной информацией 
     1586                if (info->IsInfoLoaded == false) 
     1587                { 
     1588                        if (loopback == true) 
     1589                                return; 
     1590 
     1591                        item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
     1592                        info = item->pag(); 
     1593 
     1594                        loopback = true; 
     1595                } 
     1596 
     1597                if (info->IsRead == false) 
    12571598                        break; 
    12581599 
    1259                 if (item->pag()->Info.HasUnreadChild != 0) 
    1260                         item->setExpanded(true); 
    1261  
    1262                 MessageTreeWidgetItem* next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextItem(item)); 
    1263  
    1264                 if (next_item == NULL) 
    1265                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 
    1266                 else 
    1267                         item = next_item; 
    1268  
    1269                 if (item->pag()->IsInfoLoaded == false) 
    1270                 { 
    1271                         // 
    1272                         // было 
    1273                         // 
    1274                         // setCurrentItem(item); 
    1275                         // 
    1276                         // Однако, если элемент не загружен, то ниже, скорее всего, больше нет непрочитанных сообщений 
    1277                         // иначе, начинают сканироваться все топики до конца, что занимает много времени (т.к. приходится их все грузить) 
    1278                         // по этому, переходим на корневой элемент 
    1279                         // 
    1280  
    1281                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 
     1600                if (info->HasUnreadChild == true) 
     1601                { 
     1602                        gotoNextUnreadArticle(item); 
     1603                        return; 
    12821604                } 
    12831605        } 
    12841606 
    12851607        setCurrentItem(item); 
    1286 } 
    1287 //---------------------------------------------------------------------------------------------- 
    1288  
    1289 void AMessageTree::gotoNextUnreadThread () 
    1290 { 
    1291         if (currentItem() == NULL) 
    1292         { 
    1293                 if (checkCurrentItem() == false) 
    1294                         return; 
    1295  
    1296                 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(currentItem())); 
    1297  
    1298                 if (item->pag()->Info.HasUnreadChild != 0 || item->pag()->Info.IsRead == false) 
    1299                         return; 
    1300         } 
    1301  
    1302         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(currentItem())); 
    1303  
    1304         while (true) 
    1305         { 
    1306                 MessageTreeWidgetItem* next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
    1307  
    1308                 if (next_item == NULL) 
    1309                         next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(item)); 
    1310  
    1311                 item = next_item; 
    1312  
    1313                 // 
    1314                 // было 
    1315                 // 
    1316                 // if (item->pag()->IsInfoLoaded == false || item->pag()->IsChildLoaded == false) 
    1317                 //      setCurrentItem(item); 
    1318                 // 
    1319                 // Однако, если элемент не загружен, то ниже, скорее всего, больше нет непрочитанных сообщений 
    1320                 // иначе, начинают сканироваться все топики до конца, что занимает много времени (т.к. приходится их все грузить) 
    1321                 // по этому, переходим на корневой топик 
    1322                 // 
    1323  
    1324                 if (item->pag()->IsInfoLoaded == false) 
    1325                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 
    1326  
    1327                 if (item->pag()->Info.HasUnreadChild != 0 || item->pag()->Info.IsRead == false) 
    1328                         break; 
    1329         } 
    1330  
    1331         setCurrentItem(item); 
    1332 } 
    1333 //---------------------------------------------------------------------------------------------- 
    1334  
    1335 void AMessageTree::loadRating2Send () 
    1336 { 
     1608 
     1609        scrollToItem(item, QAbstractItemView::PositionAtCenter); 
     1610} 
     1611//---------------------------------------------------------------------------------------------- 
     1612 
     1613void AMessageTree::menu_special_delete_triggered () 
     1614{ 
     1615        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
     1616 
     1617        if (item == NULL) 
     1618                return; 
     1619 
     1620        if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     1621              m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND  || 
     1622              m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 
     1623        )) 
     1624                return; 
     1625 
    13371626        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    13381627 
     
    13431632        } 
    13441633 
    1345         AMessageInfoList message_list; 
    1346         ARating2SendList rating_list; 
    1347  
    1348         if (storage->getRating2SendList(message_list, rating_list, NULL) == false) 
     1634        if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_current_forum.ID, NULL) == false) 
    13491635        { 
    13501636                storage->showError(m_parent); 
     
    13521638        } 
    13531639 
    1354         QList<QTreeWidgetItem*> items; 
    1355  
    1356         for (int i = 0; i < message_list.count(); i++) 
    1357         { 
    1358                 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    1359  
    1360                 AMessageInfoGUI* info = item->pag(); 
    1361  
    1362                 info->Info.ID             = message_list[i].ID; 
    1363                 info->Info.IDTopic        = message_list[i].IDTopic; 
    1364                 info->Info.IDParent       = message_list[i].IDParent; 
    1365                 info->Info.IDUser         = message_list[i].IDUser; 
    1366                 info->Info.IDForum        = message_list[i].IDForum; 
    1367                 info->Info.Subject        = message_list[i].Subject; 
    1368                 info->Info.MessageName    = message_list[i].MessageName; 
    1369                 info->Info.UserNick       = message_list[i].UserNick; 
    1370                 info->Info.Message        = message_list[i].Message; 
    1371                 info->Info.IDArticle      = message_list[i].IDArticle; 
    1372                 info->Info.MessageDate    = message_list[i].MessageDate; 
    1373                 info->Info.UpdateDate     = message_list[i].UpdateDate; 
    1374                 info->Info.UserRole       = message_list[i].UserRole; 
    1375                 info->Info.UserTitle      = message_list[i].UserTitle; 
    1376                 info->Info.UserTitleColor = message_list[i].UserTitleColor; 
    1377                 info->Info.LastModerated  = message_list[i].LastModerated; 
    1378  
    1379                 info->Info.IsRead         = true; 
    1380  
    1381                 info->Info.HasChild       = false; 
    1382                 info->Info.HasUnreadChild = 0; 
    1383  
    1384                 info->IsInfoLoaded        = true; 
    1385                 info->IsChildLoaded       = true; 
    1386                 info->UnreadChildCount    = 0; 
    1387                 info->IsBodyLoaded        = true; 
    1388                 info->Special             = rating_list[i].ID; 
    1389  
    1390                 item->setText(0, info->Info.Subject); 
    1391  
    1392                 if (info->Info.IDUser == 0) 
    1393                 { 
    1394                         info->Info.UserNick = QString::fromUtf8("(локальный)"); 
    1395                         item->setText(1, info->Info.UserNick); 
    1396                 } 
    1397                 else 
    1398                         item->setText(1, info->Info.UserNick); 
    1399  
    1400                 item->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 
    1401  
    1402                 int rate = rating_list[i].Rate; 
    1403  
    1404                 if (rate == -4) 
    1405                         item->setIcon(0, m_rating_plus); 
    1406                 else if (rate == -3) 
    1407                         item->setIcon(0, m_rating_plus_1); 
    1408                 else if (rate == -2) 
    1409                         item->setIcon(0, m_rating_smile); 
    1410                 else if (rate == -1) 
    1411                         item->setIcon(0, m_rating_cross); 
    1412                 else if (rate == 0) 
    1413                         item->setIcon(0, m_rating_minus); 
    1414                 else if (rate == 1) 
    1415                         item->setIcon(0, m_rating_1); 
    1416                 else if (rate == 2) 
    1417                         item->setIcon(0, m_rating_2); 
    1418                 else if (rate == 3) 
    1419                         item->setIcon(0, m_rating_3); 
    1420  
    1421                 items.append(item); 
    1422         } 
    1423  
    1424         addTopLevelItems(items); 
    1425 } 
    1426 //---------------------------------------------------------------------------------------------- 
    1427  
    1428 void AMessageTree::loadModerate2Send () 
    1429 { 
    1430         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1431  
    1432         if (storage.get() == NULL) 
    1433         { 
    1434                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1435                 return; 
    1436         } 
    1437  
    1438         AMessageInfoList message_list; 
    1439         AModerate2SendList moderate_list; 
    1440  
    1441         if (storage->getModerate2SendList(message_list, moderate_list, NULL) == false) 
    1442         { 
    1443                 storage->showError(m_parent); 
    1444                 return; 
    1445         } 
    1446  
    1447         QList<QTreeWidgetItem*> items; 
    1448  
    1449         for (int i = 0; i < message_list.count(); i++) 
    1450         { 
    1451                 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    1452  
    1453                 AMessageInfoGUI* info = item->pag(); 
    1454  
    1455                 info->Info.ID             = message_list[i].ID; 
    1456                 info->Info.IDTopic        = message_list[i].IDTopic; 
    1457                 info->Info.IDParent       = message_list[i].IDParent; 
    1458                 info->Info.IDUser         = message_list[i].IDUser; 
    1459                 info->Info.IDForum        = message_list[i].IDForum; 
    1460                 info->Info.Subject        = message_list[i].Subject; 
    1461                 info->Info.MessageName    = message_list[i].MessageName; 
    1462                 info->Info.UserNick       = message_list[i].UserNick; 
    1463                 info->Info.Message        = message_list[i].Message; 
    1464                 info->Info.IDArticle      = message_list[i].IDArticle; 
    1465                 info->Info.MessageDate    = message_list[i].MessageDate; 
    1466                 info->Info.UpdateDate     = message_list[i].UpdateDate; 
    1467                 info->Info.UserRole       = message_list[i].UserRole; 
    1468                 info->Info.UserTitle      = message_list[i].UserTitle; 
    1469                 info->Info.UserTitleColor = message_list[i].UserTitleColor; 
    1470                 info->Info.LastModerated  = message_list[i].LastModerated; 
    1471  
    1472                 info->Info.IsRead         = true; 
    1473  
    1474                 info->Info.HasChild       = false; 
    1475                 info->Info.HasUnreadChild = 0; 
    1476  
    1477                 info->IsInfoLoaded        = true; 
    1478                 info->IsChildLoaded       = true; 
    1479                 info->UnreadChildCount    = 0; 
    1480                 info->IsBodyLoaded        = true; 
    1481                 info->Special             = moderate_list[i].ID; 
    1482  
    1483                 item->setText(0, info->Info.Subject); 
    1484  
    1485                 if (info->Info.IDUser == 0) 
    1486                 { 
    1487                         info->Info.UserNick = QString::fromUtf8("(локальный)"); 
    1488                         item->setText(1, info->Info.UserNick); 
    1489                 } 
    1490                 else 
    1491                         item->setText(1, info->Info.UserNick); 
    1492  
    1493                 item->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 
    1494  
    1495                 item->setIcon(0, m_moderate); 
    1496  
    1497                 items.append(item); 
    1498         } 
    1499  
    1500         addTopLevelItems(items); 
    1501 } 
    1502 //---------------------------------------------------------------------------------------------- 
    1503  
    1504 void AMessageTree::menu_special_delete_triggered () 
    1505 { 
    1506         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    1507  
    1508         if (item == NULL) 
    1509                 return; 
    1510  
    1511         if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 
    1512                 return; 
    1513  
    1514         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1515  
    1516         if (storage.get() == NULL) 
    1517         { 
    1518                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1519                 return; 
    1520         } 
    1521  
    1522         if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_id_forum, NULL) == false) 
    1523         { 
    1524                 storage->showError(m_parent); 
    1525                 return; 
    1526         } 
    1527  
    1528         // обновление в дереве форумов количества непрочитаных сообщений 
     1640        // обновление в дереве форумов количества непрочитанных сообщений 
    15291641        if (m_forum_tree != NULL) 
    15301642                m_forum_tree->reloadUnread(true); 
     
    15391651        setCurrentItem(item); 
    15401652 
    1541         if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 
     1653        if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     1654              m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND  || 
     1655              m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 
     1656        )) 
    15421657                return; 
    15431658 
     
    15531668                return; 
    15541669 
    1555         if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 
    1556                 return; 
    1557  
    1558         if (m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND) 
    1559         { 
    1560                 FormMessage* form = new FormMessage(NULL, false, item->pag()->Info, item->pag()->Special); 
     1670        if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     1671              m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND  || 
     1672              m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 
     1673        )) 
     1674                return; 
     1675 
     1676        if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND) 
     1677        { 
     1678                FormMessage* form = new FormMessage(NULL, false, *(item->pag()), item->pag()->Special); 
    15611679 
    15621680                form->setForumTree(m_forum_tree); 
     
    15651683                form->show(); 
    15661684        } 
    1567         else if (m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND) 
    1568         { 
    1569                 FormModerate* form = new FormModerate(m_parent, item->pag()->Info.ID, item->pag()->Special); 
     1685        else if (m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 
     1686        { 
     1687                FormModerate* form = new FormModerate(m_parent, item->pag()->ID, item->pag()->Special); 
    15701688 
    15711689                form->setForumTree(m_forum_tree); 
     
    15851703                return; 
    15861704 
    1587         if (m_id_forum != SPECIAL_ID_FORUM_RATING2SEND) 
     1705        if (m_current_forum.ID != SPECIAL_ID_FORUM_RATING2SEND) 
    15881706                return; 
    15891707 
     
    16701788                return; 
    16711789 
    1672         path.insert(0, item->pag()->Info.ID); 
     1790        path.insert(0, item->pag()->ID); 
    16731791 
    16741792        while (true) 
     
    16771795 
    16781796                if (item != NULL) 
    1679                         path.insert(0, item->pag()->Info.ID); 
     1797                        path.insert(0, item->pag()->ID); 
    16801798                else 
    16811799                        break; 
     
    16981816                MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(i)); 
    16991817 
    1700                 if (item->pag()->IsInfoLoaded == false) 
    1701                         return false; 
    1702  
    1703                 if (item->pag()->Info.ID == root_id) 
     1818                AMessageInfoGUI* info = item->pag(); 
     1819 
     1820                if (item->pag()->ID == root_id) 
    17041821                { 
    17051822                        root_item = item; 
    17061823 
    1707                         // переход на корень 
    1708                         setCurrentItem(root_item); 
     1824                        // переход на корень (и его загрузка, при необходимости) 
     1825                        if (info->IsInfoLoaded == false) 
     1826                                setCurrentItem(root_item); 
    17091827 
    17101828                        // ... и разворот, если ищется некорневое сообщение 
     
    17161834        } 
    17171835 
     1836        if (root_item == NULL) 
     1837                return false; 
     1838 
    17181839        // поиск в дочерних 
    17191840        for (int i = 1; i < path->count(); i++) 
     
    17271848                        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(root_item->child(j)); 
    17281849 
    1729                         if (item->pag()->IsInfoLoaded == false) 
    1730                                 setCurrentItem(item); 
    1731  
    1732                         if (item->pag()->Info.ID == next_id) 
     1850                        if (item->pag()->ID == next_id) 
    17331851                        { 
    1734                                 found = true; 
     1852                                found     = true; 
    17351853                                root_item = item; 
    1736  
    1737                                 setCurrentItem(root_item); 
    17381854 
    17391855                                if (i + 1 != path->count() && root_item->isExpanded() == false) 
     
    17451861 
    17461862                if (found == false) 
     1863                { 
     1864                        setCurrentItem(root_item); 
     1865 
    17471866                        return false; 
    1748         } 
     1867                } 
     1868        } 
     1869 
     1870        setCurrentItem(root_item); 
     1871 
     1872        scrollToItem(root_item, QAbstractItemView::PositionAtCenter); 
    17491873 
    17501874        return true; 
    17511875} 
    17521876//---------------------------------------------------------------------------------------------- 
     1877 
     1878void AMessageTree::gotoNextUnreadArticle () 
     1879{ 
     1880        gotoNextUnreadArticle(currentItem()); 
     1881} 
     1882//---------------------------------------------------------------------------------------------- 
     1883 
     1884 
     1885AMessageInfoGUI* AMessageTree::createItem () 
     1886{ 
     1887        MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
     1888 
     1889        AMessageInfoGUI* info = item->pag(); 
     1890 
     1891        info->Item = item; 
     1892 
     1893        return info; 
     1894} 
     1895//---------------------------------------------------------------------------------------------- 
     1896 
     1897void AMessageTree::markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count) 
     1898{ 
     1899        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(parent); 
     1900 
     1901        AMessageInfoGUI* info = item->pag(); 
     1902 
     1903        if (info->IsRead != is_read) 
     1904                count++; 
     1905 
     1906        info->IsRead = is_read; 
     1907 
     1908        if (is_read == true) 
     1909        { 
     1910                item->setIcon(0, m_message_read); 
     1911 
     1912                info->HasUnreadChild     = false; 
     1913                info->HasUnreadChildMy   = false; 
     1914                info->UnreadChildCount   = 0; 
     1915                info->UnreadChildCountMy = 0; 
     1916 
     1917                for (int i = 0; i < item->childCount(); i++) 
     1918                        markThreadAsRead(item->child(i), is_read, count); 
     1919        } 
     1920        else   // if (is_read == true) 
     1921        { 
     1922                item->setIcon(0, m_message_unread); 
     1923 
     1924                info->HasUnreadChild     = false; 
     1925                info->HasUnreadChildMy   = false; 
     1926                info->UnreadChildCount   = 0; 
     1927                info->UnreadChildCountMy = 0; 
     1928 
     1929                MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(item->parent()); 
     1930 
     1931                while (parent != NULL) 
     1932                { 
     1933                        info = parent->pag(); 
     1934 
     1935                        info->HasUnreadChild = true; 
     1936                        info->UnreadChildCount++; 
     1937 
     1938                        parent = static_cast<MessageTreeWidgetItem*>(parent->parent()); 
     1939                } 
     1940 
     1941                for (int i = 0; i < item->childCount(); i++) 
     1942                        markThreadAsRead(item->child(i), is_read, count); 
     1943 
     1944        }   // if (is_read == true) ... else 
     1945} 
     1946//---------------------------------------------------------------------------------------------- 
  • trunk/message_tree.h

    r175 r191  
    1818 */ 
    1919class AMessageTree : 
    20         public QTreeWidget, // стандартное дерево Qt 
    21         public IMessageTree // интерфес для взаимодействия со списком форумов и отображением сообщения 
     20        public  QTreeWidget,           // стандартное дерево Qt 
     21        public  IMessageTree,          // интерфес для взаимодействия со списком форумов и отображением сообщения 
     22        private IMessageInfoGUIFactory // интерфейс фабрики создания элементов дерева 
    2223{ 
    2324        Q_OBJECT 
     
    7071        private: 
    7172 
    72                 /*! 
    73                  * \brief Главная форма приложения (для отображения сообщений об ошибках) 
    74                  */ 
    75                 QWidget* m_parent; 
     73                QWidget* m_parent; /*!< \brief Главная форма приложения (для отображения сообщений об ошибках) */ 
    7674 
    7775                IForumTree*   m_forum_tree;   /*!< \brief Интерфейс дерева форумов        */ 
     
    7977                IFormMain*    m_main_form;    /*!< \brief Интерфейс главной формы         */ 
    8078 
     79                // 
    8180                // иконки для отображения статусов сообщений 
     81                // 
     82 
    8283                QIcon m_message_read;      /*!< \brief Сообщение прочитано                     */ 
    8384                QIcon m_child_unread;      /*!< \brief Есть непрочитанные дочерние сообщения   */ 
     
    8687                QIcon m_message_unread_my; /*!< \brief В ветке есть сообщение для меня         */ 
    8788 
     89                // 
    8890                // иконки для отображения оценок 
     91                // 
     92 
    8993                QIcon m_rating_plus_1; /*!< \brief "+1"  */ 
    9094                QIcon m_rating_1;      /*!< \brief "1"   */ 
     
    103107 
    104108                /*! 
    105                  * \brief Высплывающее меню 
     109                 * \brief Основное контекстное меню (для основного дерева сообщений) 
    106110                 */ 
    107111                QMenu* m_menu; 
     
    114118 
    115119                /*! 
    116                  * \brief Высплывающее меню в спец-фоорумах 
     120                 * \brief Контекстное меню в спец-фоорумах (оценки, модерилки, исходящие сообщения) 
    117121                 */ 
    118122                QMenu* m_menu_special; 
     
    129133                QAction* m_menu_special_minus;  /*!< \brief - (несогласен) */ 
    130134 
    131                 /*! 
    132                  * \brief ID текущей группы 
    133                  */ 
    134                 int m_id_group; 
    135  
    136                 /*! 
    137                  * \brief ID текущего форума 
    138                  */ 
    139                 int m_id_forum; 
    140  
    141                 /*! 
    142                  * \brief Оценивается ли форум 
    143                  */ 
    144                 bool m_forum_rated; 
    145  
    146                 /*! 
    147                  * \brief ID текущего пользователя RSDN 
    148                  */ 
    149                 AUserInfo m_me; 
    150  
    151                 /*! 
    152                  * \brief Функция проверки установки выделения, в случае отсутствия выделения, выделяет элемент, согласно параметру select_first 
    153                  * \param select_first Флаг выделения, если имеет значение true, то выделяется первый элемент, иначе, последний (из корневых) 
    154                  * \return true, если есть выделение, false при отсутствии элементов 
    155                  */ 
    156                 bool checkCurrentItem (bool select_first = true); 
    157  
    158                 /*! 
    159                  * \brief Загружает незагруженные топики при скроллинге (см. алгоритм работы с деревом в trac) 
     135                // 
     136                // внутренние переменные 
     137                // 
     138 
     139                AForumInfo m_current_forum; /*!< \brief Текущий отображаемый форум  */ 
     140                AUserInfo  m_me;            /*!< \brief Текущий пользователь avalon */ 
     141 
     142                /*! 
     143                 * \brief Дозагрузка информации о топиках, находящихся в видимой области отображения 
    160144                 */ 
    161145                void scrollTopics (); 
    162146 
    163147                /*! 
    164                  * \brief Разворачивает ветку до непрочитанных сообщений 
    165                  * \param item Элемент для разворачивания 
    166                  */ 
    167                 void expandUnreadChild (QTreeWidgetItem* item); 
    168  
    169                 /*! 
    170                  * \brief Построение веток 
    171                  * \param parent Родительский элемент 
    172                  * \param list список _всех_ дочерних веток (все уровни вложенности) 
    173                  */ 
    174                 void buildTree (QTreeWidgetItem* parent, ATopicInfoList* list); 
    175  
    176                 /*! 
    177                  * \brief Пометка сообщения как прочитанного 
     148                 * \brief Построение дерева (топика) из списка элементов 
     149                 * \param root Родительский элемент 
     150                 * \param list Список дочерних элементов для построения 
     151                 */ 
     152                void buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list); 
     153 
     154                /*! 
     155                 * \brief Раскрытие дерева элементов до всех непрочитанных сообщений 
     156                 * \param root Родительский элемент дерева для раскрытия 
     157                 */ 
     158                void expandUnreadChild (QTreeWidgetItem* widget_item); 
     159 
     160                /*! 
     161                 * \brief Функция проверки установки выделения, в случае отсутствия выделения, выделяет элемент, согласно параметру select_first 
     162                 * \param select_first Флаг выделения, если имеет значение true, то выделяется первый элемент, иначе, последний (из корневых) 
     163                 * \return true, если есть выделение, false при отсутствии элементов 
     164                 */ 
     165                bool checkCurrentItem (bool select_first = true); 
     166 
     167                /*! 
     168                 * \brief Редактирование оценки к отправке 
     169                 * \param new_rate Новая оценка 
     170                 */ 
     171                void changeRating (int new_rate); 
     172 
     173                /* 
     174                 * \brief Расширенная реализация IMessageTree::gotoNextUnreadArticle 
     175                 * \param item Элемент дерева, относительно которого требуется вести поиск 
     176                 */ 
     177                void gotoNextUnreadArticle (QTreeWidgetItem* current_item); 
     178 
     179                /* 
     180                 * \brief Пометка сообщения как прочитанного/непрочитанного 
    178181                 * \param item Элемент дерева 
    179                  * \param is_read Флаг прочитанности/непрочитанности 
     182                 * \param is_read Флаг прочитанного 
    180183                 */ 
    181184                void markItemAsRead (QTreeWidgetItem* item, bool is_read); 
    182185 
    183                 /*! 
    184                  * \brief Пометка ветки как прочитаной 
    185                  * \param parent Родительский элемент ветки 
    186                  * \param is_read Флаг прочитанности/непрочитанности 
    187                  * \param count Количество отмеченных элементов 
     186                /* 
     187                 * \brief Пометка ветки как прочитанной/непрочитанной 
     188                 * \param item Элемент дерева 
     189                 * \param is_read Флаг прочитанного 
     190                 * \param count Количество элементов, которые были помечены 
    188191                 */ 
    189192                void markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count); 
    190193 
     194                /* 
     195                 * \brief Пометка ветки как прочитанной/непрочитанной в хранилище 
     196                 * \param id ID топика 
     197                 * \param is_read Флаг прочитанного 
     198                 * \return true, если ветка в хранилище помечена 
     199                 */ 
     200                bool markThreadAsRead (int id, bool is_read); 
     201 
    191202                /*! 
    192203                 * \brief Загрузить сообщения к отправке 
     
    203214                 */ 
    204215                void loadModerate2Send (); 
    205  
    206                 /*! 
    207                  * \brief Смена оценки 
    208                  * \param new_rate Новая оценка 
    209                  */ 
    210                 void changeRating (int new_rate); 
    211216 
    212217        // IMessageTree 
     
    225230                bool selectByPath (const QList<int>* path); 
    226231 
     232        // IMessageInfoGUIFactory 
     233        private: 
     234 
     235                AMessageInfoGUI* createItem (); 
     236 
    227237        private slots: 
    228238 
     
    243253 
    244254                /*! 
    245                  * \brief Двойной клик 
     255                 * \brief Двойной клик (редактирование) 
    246256                 */ 
    247257                void item_double_clicked (QTreeWidgetItem* item, int column); 
     
    257267                void context_menu_request (const QPoint& pos); 
    258268 
    259                 // меню 
     269                // 
     270                // Основное контекстное меню 
     271                // 
     272 
    260273                void menu_reply_triggered                  (); /*!< \brief Ответить                             */ 
    261274                void menu_mark_message_as_read_triggered   (); /*!< \brief Пометить сообщение как прочитанное   */ 
     
    265278 
    266279                // 
    267                 // Специальное меню 
     280                // Специальное контекстное меню 
    268281                // 
    269282 
  • trunk/model/message.h

    r118 r191  
    6767 * \brief Расширенная информация о сообщении для отображения в дереве в GUI 
    6868 */ 
    69 typedef struct AMessageInfoEx : AMessageInfo 
     69typedef struct AMessageInfoGUI : AMessageInfo 
    7070{ 
    71         bool IsRead; /*!< \brief Прочитано ли сообщение */ 
     71        bool IsInfoLoaded;       /*!< \brief Загружена ли какая-нибудь информация кроме ID */ 
     72        bool IsRead;             /*!< \brief Прочитано ли сообщение                        */ 
     73        bool HasChild;           /*!< \brief Имеются ли дочерние сообщения                 */ 
     74        bool IsBodyLoaded;       /*!< \brief Загружено ли тело сообщения                   */ 
     75        bool IsChildLoaded;      /*!< \brief Загружены ли дочерние сообщения               */ 
     76        bool HasUnreadChild;     /*!< \brief Наличие непрочитанных дочерних                */ 
     77        bool HasUnreadChildMy;   /*!< \brief Наличие непрочитанных дочерних мне            */ 
     78        int  UnreadChildCount;   /*!< \brief Количество непрочитанных дочерних             */ 
     79        int  UnreadChildCountMy; /*!< \brief Количество непрочитанных дочерних мне         */ 
     80        int  Special;            /*!< \brief Спец-данные                                   */ 
     81 
     82        QTreeWidgetItem* Item;   /*!< \brief Слинкованный элемент дерева                   */ 
     83 
     84        AMessageInfoGUI () 
     85        { 
     86                // AMessageInfo 
     87                ID             = -1; 
     88                IDTopic        = -1; 
     89                IDParent       = -1; 
     90                IDUser         = -1; 
     91                IDForum        = -1; 
     92                IDArticle      = -1; 
     93                UserTitleColor = -1; 
     94 
     95                // AMessageInfoGUI 
     96                IsInfoLoaded       = false; 
     97                IsRead             = true; 
     98                HasChild           = false; 
     99                IsBodyLoaded       = false; 
     100                IsChildLoaded      = false; 
     101                HasUnreadChild     = false; 
     102                HasUnreadChildMy   = false; 
     103                UnreadChildCount   = -1; 
     104                UnreadChildCountMy = -1; 
     105                Special            = -1; 
     106 
     107                Item = NULL; 
     108        } 
     109 
    72110} AMessageInfoEx; 
    73111 
     
    75113 * \brief Список сообщений для отображения в дереве в GUI 
    76114 */ 
    77 typedef QList<AMessageInfoEx> AMessageInfoExList; 
    78  
    79 /*! 
    80  * \brief Информация о топике для отображения дерева в GUI 
    81  */ 
    82 typedef struct ATopicInfo : AMessageInfoEx 
    83 { 
    84         bool HasChild;       /*!< \brief Есть ли дочерние сообщения */ 
    85         int  HasUnreadChild; /*!< \brief Есть ли дочерние непрочитанные сообщения 0 - нет, 1 - да, 2 - есть непрочитанные для текущего пользователя */ 
    86 } ATopicInfo; 
     115typedef QList<AMessageInfoGUI> AMessageInfoGUIList; 
    87116 
    88117/*! 
    89118 * \brief Список сообщений для отображения в дереве в GUI 
    90119 */ 
    91 typedef QList<ATopicInfo> ATopicInfoList; 
     120typedef QList<AMessageInfoGUI*> AMessageInfoGUIPtrList; 
     121 
     122/*! 
     123 * \brief Интерфейс для фабрики элементов дерева отображения сообщений (см. IAStorage::getTopicMessageList) 
     124 * Необходим для уменьшения расходов врмени на копирование информации при загрузке большого топика 
     125 */ 
     126class IMessageInfoGUIFactory 
     127{ 
     128        public: 
     129 
     130                /*! 
     131                 * \brief Метод для создания GUI-элемента дерева сообщений 
     132                 * \return Указатель на готовый к заполнению данными элемент (поле Item устанавливается в валидное при создании) 
     133                 */ 
     134                virtual AMessageInfoGUI* createItem () = 0; 
     135}; 
    92136 
    93137/*! 
  • trunk/storage/istorage.h

    r175 r191  
    1717 
    1818/*! 
    19  * \brief Типы множеств для групповой обработки (см. IAStorage::SetIDsAsRead и IAStorage::Unsubscribe). 
     19 * \brief Типы множеств для групповой обработки (см. IAStorage::setIDsAsRead и IAStorage::unsubscribe). 
    2020 */ 
    2121typedef enum AIDSet 
     
    136136 
    137137                /*! 
    138                  * \brief Заполняет полную информацию о топиках за исключением тела самого сообщения, 
    139                  * тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 
    140                  * \param list Список топиков. 
    141                  * \param id_me ID текущего пользователя 
    142                  * \param progress Прогресс выполнения операции. 
    143                  */ 
    144                 virtual bool getTopicInfoList (ATopicInfoList& list, int id_me, IProgress* progress = NULL) = 0; 
    145  
    146                 /*! 
    147                  * \brief Возвращает список _всех_ сообщений в топике (родительской ветке) за исключением тел самих сообщений, 
    148                  * тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 
     138                 * \brief Заполняет информацию о топиках в форуме 
     139                 * 
     140                 * Поля списка (кроме ID и Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) 
     141                 * и не меняются без необходимости. 
     142                 * 
     143                 * Функция ДОЛЖНА заполнить все поля AMessageInfo плюс установить флаги AMessageInfoGUI::IsRead, AMessageInfoGUI::HasUnreadChild, 
     144                 * AMessageInfoGUI::HasUnreadChildMy в актуальные значения. 
     145                 * 
     146                 * Функция НЕ должна устанавливать флаг AMessageInfoGUI::IsInfoLoaded (устанавливается вызвающим кодом). 
     147                 * 
     148                 * Функция МОЖЕТ оставить некоторые поля AMessageInfo, которые не используются в текущем GUI, незаполненными в целях оптимизации 
     149                 * скорости работы - в этом случае они должны иметь значения по умолчанию (к таким полям, например, может относиться поле 
     150                 * AMessageInfo::LastModerated и т.д.) 
     151                 * 
     152                 * \param id_forum ID форума, для которого запрашивается список топиков 
     153                 * (для ненулевого значения, будет произведено исключение одного лишнего преобразования из QVariant на каждый элемент, 
     154                 * что положительно влияет на скорость) 
     155                 * \param list Список топиков (с установленным полем ID, по которому будет производиться дальнейшее заполнение информацией). 
     156                 * \param id_me ID текущего пользователя avalon. 
     157                 * \param progress Прогресс выполнения операции. 
     158                 */ 
     159                virtual bool getTopicInfoList (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress = NULL) = 0; 
     160 
     161                /*! 
     162                 * \brief Заполняет информацию о всех сообщениях в топике (родительской ветке). 
     163                 * 
     164                 * Функция ДОЛЖНА заполнить все поля AMessageInfo плюс установить флаги AMessageInfoGUI::IsRead, AMessageInfo::HasChild в актуальные 
     165                 * значения. 
     166                 * 
     167                 * Функция НЕ должна устанавливать флаг AMessageInfoGUI::IsInfoLoaded (устанавливается вызвающим кодом). 
     168                 * 
     169                 * Функция МОЖЕТ оставить некоторые поля AMessageInfo, которые не используются в текущем GUI, незаполненными в целях оптимизации 
     170                 * скорости работы - в этом случае они должны иметь значения по умолчанию (к таким полям, например, может относиться поле 
     171                 * AMessageInfo::LastModerated и т.д.) 
     172                 * 
     173                 * \param id_forum ID форума, для которого запрашивается список топиков 
     174                 * (для ненулевого значения, будет произведено исключение одного лишнего преобразования из QVariant на каждый элемент, 
     175                 * что положительно влияет на скорость) 
    149176                 * \param id_topic ID топика (темы, родительской ветки). 
    150                  * \param list Список сообщений. 
    151                  * \param id_me ID текущего пользователя 
    152                  * \param progress Прогресс выполнения операции. 
    153                  */ 
    154                 virtual bool getTopicMessageList (int id_topic, ATopicInfoList& list, int id_me, IProgress* progress = NULL) = 0; 
     177                 * \param list Список сообщений (изначально пустой, на выходе заполненый _не_ включая сообщение id_topic). 
     178                 * \param factory Фабрика для создания элементов (каждый элемент списка создается вызовом IMessageInfoGUIFactory::createItem), 
     179                 * поля (кроме Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) 
     180                 * и не меняются без необходимости. 
     181                 * \param progress Прогресс выполнения операции. 
     182                 */ 
     183                virtual bool getTopicMessageList (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress = NULL) = 0; 
    155184 
    156185                /*! 
  • trunk/storage/mysql_storage.cpp

    r175 r191  
    3434        else 
    3535                IAStorage::setLastError(message); 
     36 
     37        close(); 
    3638 
    3739        return false; 
     
    18341836        sql += "        `id_forum` = " + QString::number(id_forum) + "\n"; 
    18351837        sql += "ORDER BY\n"; 
    1836         sql += "        `message_date` DESC"; 
     1838        // поскльку id_message автоинкремент и растет вместе с датой, то 
     1839        // можно условно положиться на то, что бОльшему id_message соответствует 
     1840        // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 
     1841        //sql += "      `message_date` DESC"; 
     1842        sql += "        `id_message` DESC"; 
    18371843 
    18381844        if (count > 0) 
     
    18461852        if (query_select.get() == NULL) 
    18471853                return returnError(AMySQLDatabase::getLastError()); 
     1854 
     1855        query_select->setForwardOnly(true); 
    18481856 
    18491857        if (query_select->exec() == false) 
     
    18751883                return returnError(AMySQLDatabase::getLastError()); 
    18761884 
     1885        query_select_unread_child->setForwardOnly(true); 
     1886 
    18771887        if (query_select_unread_child->exec() == false) 
    18781888                return returnError(query_select_unread_child->getLastError()); 
     
    19101920                return returnError(AMySQLDatabase::getLastError()); 
    19111921 
     1922        query_select_unread_topic->setForwardOnly(true); 
     1923 
    19121924        if (query_select_unread_topic->exec() == false) 
    19131925                return returnError(query_select_unread_topic->getLastError()); 
     
    19291941//---------------------------------------------------------------------------------------------- 
    19301942 
    1931 bool AMySQLStorage::getTopicInfoList (ATopicInfoList& list, int id_me, IProgress* progress) 
     1943bool AMySQLStorage::getTopicInfoList (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress) 
    19321944{ 
    19331945        if (progress != NULL) 
     
    19391951        for (int i = 0; i < list.count(); i++) 
    19401952        { 
    1941                 ids += QString::number(list[i].ID); 
     1953                ids += QString::number(list[i]->ID); 
    19421954 
    19431955                if (i < list.count() - 1) 
     
    19491961        // 
    19501962        // получение инфы топика 
     1963        // часть полей, не принимающих участия в GUI, пропущена 
    19511964        // 
    19521965 
    19531966        sql += "SELECT\n"; 
    19541967        sql += "        `id`,\n"; 
    1955         sql += "        `id_topic`,\n"; 
    1956         sql += "        `id_parent`,\n"; 
    19571968        sql += "        `id_user`,\n"; 
    19581969        sql += "        `id_forum`,\n"; 
    19591970        sql += "        `subject`,\n"; 
    1960         sql += "        `message_name`,\n"; 
    19611971        sql += "        `user_nick`,\n"; 
    1962         sql += "        `id_article`,\n"; 
    19631972        sql += "        `message_date`,\n"; 
    1964         sql += "        `update_date`,\n"; 
    1965         sql += "        `user_role`,\n"; 
    1966         sql += "        `user_title`,\n"; 
    1967         sql += "        `user_title_color`,\n"; 
    1968         sql += "        `last_moderated`,\n"; 
    19691973        sql += "        `has_child`\n"; 
    19701974        sql += "FROM\n"; 
     
    19781982                return returnError(AMySQLDatabase::getLastError()); 
    19791983 
     1984        query_select->setForwardOnly(true); 
     1985 
    19801986        if (query_select->exec() == false) 
    19811987                return returnError(query_select->getLastError()); 
     
    19861992 
    19871993                for (int i = 0; i < list.count(); i++) 
    1988                         if (id == list[i].ID) 
     1994                { 
     1995                        AMessageInfoGUI* info = list[i]; 
     1996 
     1997                        if (id == info->ID) 
    19891998                        { 
    1990                                 list[i].IDTopic        = query_select->value(1).toInt(); 
    1991                                 list[i].IDParent       = query_select->value(2).toInt(); 
    1992                                 list[i].IDUser         = query_select->value(3).toInt(); 
    1993                                 list[i].IDForum        = query_select->value(4).toInt(); 
    1994                                 list[i].Subject        = query_select->value(5).toString(); 
    1995                                 list[i].MessageName    = query_select->value(6).toString(); 
    1996                                 list[i].UserNick       = query_select->value(7).toString(); 
    1997                                 list[i].IDArticle      = query_select->value(8).toInt(); 
    1998                                 list[i].MessageDate    = query_select->value(9).toDateTime(); 
    1999                                 list[i].UpdateDate     = query_select->value(10).toDateTime(); 
    2000                                 list[i].UserRole       = query_select->value(11).toString(); 
    2001                                 list[i].UserTitle      = query_select->value(12).toString(); 
    2002                                 list[i].UserTitleColor = query_select->value(13).toInt(); 
    2003                                 list[i].LastModerated  = query_select->value(14).toDateTime(); 
    2004                                 list[i].HasChild       = query_select->value(15).toInt(); 
    2005  
    2006                                 list[i].IsRead         = true; 
    2007                                 list[i].HasUnreadChild = 0; 
     1999                                // часть полей, не принимающих участия в GUI, оставлена без изменений 
     2000                                info->IDTopic  = 0; // всегда 0 для топиков 
     2001                                info->IDParent = 0; // всегда 0 для топиков 
     2002                                info->IDUser   = query_select->value(1).toInt(); 
     2003 
     2004                                if (id_forum != 0) 
     2005                                        info->IDForum = id_forum; 
     2006                                else 
     2007                                        info->IDForum = query_select->value(2).toInt(); 
     2008 
     2009                                info->Subject     = query_select->value(3).toString(); 
     2010                                info->UserNick    = query_select->value(4).toString(); 
     2011                                info->MessageDate = query_select->value(5).toDateTime(); 
     2012                                info->HasChild    = query_select->value(6).toInt(); 
    20082013 
    20092014                                break; 
    20102015                        } 
    2011         } 
    2012  
    2013         // 
    2014         // получение списка непрочитаных 
     2016                } 
     2017        } 
     2018 
     2019        // 
     2020        // получение списка непрочитаных топиков 
    20152021        // 
    20162022 
     
    20282034                return returnError(AMySQLDatabase::getLastError()); 
    20292035 
     2036        query_select_unread->setForwardOnly(true); 
     2037 
    20302038        if (query_select_unread->exec() == false) 
    20312039                return returnError(query_select_unread->getLastError()); 
     
    20362044 
    20372045                for (int i = 0; i < list.count(); i++) 
    2038                         if (id == list[i].ID) 
     2046                { 
     2047                        AMessageInfoGUI* info = list[i]; 
     2048 
     2049                        if (id == info->ID) 
    20392050                        { 
    2040                                 list[i].IsRead = false; 
     2051                                info->IsRead = false; 
    20412052                                break; 
    20422053                        } 
     2054                } 
    20432055        } 
    20442056 
     
    20632075                return returnError(AMySQLDatabase::getLastError()); 
    20642076 
     2077        query_select_unread_child->setForwardOnly(true); 
     2078 
    20652079        if (query_select_unread_child->exec() == false) 
    20662080                return returnError(query_select_unread_child->getLastError()); 
     
    20722086 
    20732087                for (int i = 0; i < list.count(); i++) 
    2074                         if (id == list[i].ID) 
     2088                { 
     2089                        AMessageInfoGUI* info = list[i]; 
     2090 
     2091                        if (id == info->ID) 
    20752092                        { 
    20762093                                if (id_parent_user > 1) 
    2077                                         list[i].HasUnreadChild = 2; 
    2078                                 else 
    2079                                         list[i].HasUnreadChild = 1; 
     2094                                        info->HasUnreadChildMy = true; 
     2095 
     2096                                info->HasUnreadChild = true; 
    20802097 
    20812098                                break; 
    20822099                        } 
     2100                } 
    20832101        } 
    20842102 
     
    20872105//---------------------------------------------------------------------------------------------- 
    20882106 
    2089 bool AMySQLStorage::getTopicMessageList (int id_topic, ATopicInfoList& list, int id_me, IProgress* progress) 
     2107bool AMySQLStorage::getTopicMessageList (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress) 
    20902108{ 
     2109 
    20912110        if (progress != NULL) 
    20922111                progress->onProgress(0); 
     
    20962115        // 
    20972116        // получение сообщений топика 
     2117        // часть полей, не принимающих участия в GUI, пропущена 
    20982118        // 
    20992119 
    21002120        sql += "SELECT\n"; 
    21012121        sql += "        `id`,\n"; 
    2102         sql += "        `id_topic`,\n"; 
    21032122        sql += "        `id_parent`,\n"; 
    21042123        sql += "        `id_user`,\n"; 
    21052124        sql += "        `id_forum`,\n"; 
    21062125        sql += "        `subject`,\n"; 
    2107         sql += "        `message_name`,\n"; 
    21082126        sql += "        `user_nick`,\n"; 
    2109         sql += "        `id_article`,\n"; 
    21102127        sql += "        `message_date`,\n"; 
    2111         sql += "        `update_date`,\n"; 
    2112         sql += "        `user_role`,\n"; 
    2113         sql += "        `user_title`,\n"; 
    2114         sql += "        `user_title_color`,\n"; 
    2115         sql += "        `last_moderated`,\n"; 
    21162128        sql += "        `has_child`\n"; 
    21172129        sql += "FROM\n"; 
     
    21202132        sql += "        `id_topic` = " + QString::number(id_topic) + "\n"; 
    21212133        sql += "ORDER BY\n"; 
    2122         sql += "        `message_date` DESC"; 
     2134        // поскльку id автоинкремент и растет вместе с датой, то 
     2135        // можно условно положиться на то, что бОльшему id_message соответствует 
     2136        // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 
     2137        //sql += "      `message_date` DESC"; 
     2138        sql += "        `id` DESC"; 
    21232139 
    21242140        std::auto_ptr<AQuery> query_select(createQuery(sql, false)); 
     
    21262142        if (query_select.get() == NULL) 
    21272143                return returnError(AMySQLDatabase::getLastError()); 
     2144 
     2145        query_select->setForwardOnly(true); 
    21282146 
    21292147        if (query_select->exec() == false) 
     
    21322150        while (query_select->next()) 
    21332151        { 
    2134                 ATopicInfo info; 
    2135  
    2136                 info.ID             = query_select->value(0).toInt(); 
    2137                 info.IDTopic        = query_select->value(1).toInt(); 
    2138                 info.IDParent       = query_select->value(2).toInt(); 
    2139                 info.IDUser         = query_select->value(3).toInt(); 
    2140                 info.IDForum        = query_select->value(4).toInt(); 
    2141                 info.Subject        = query_select->value(5).toString(); 
    2142                 info.MessageName    = query_select->value(6).toString(); 
    2143                 info.UserNick       = query_select->value(7).toString(); 
    2144                 info.IDArticle      = query_select->value(8).toInt(); 
    2145                 info.MessageDate    = query_select->value(9).toDateTime(); 
    2146                 info.UpdateDate     = query_select->value(10).toDateTime(); 
    2147                 info.UserRole       = query_select->value(11).toString(); 
    2148                 info.UserTitle      = query_select->value(12).toString(); 
    2149                 info.UserTitleColor = query_select->value(13).toInt(); 
    2150                 info.LastModerated  = query_select->value(14).toDateTime(); 
    2151                 info.HasChild       = query_select->value(15).toInt(); 
    2152  
    2153                 info.IsRead         = true; 
    2154                 info.HasUnreadChild = 0; 
     2152                AMessageInfoGUI* info = factory->createItem(); 
     2153 
     2154                // часть полей, не принимающих участия в GUI, оставлена без изменений 
     2155                info->ID       = query_select->value(0).toInt(); 
     2156                info->IDTopic  = id_topic; 
     2157                info->IDParent = query_select->value(1).toInt(); 
     2158                info->IDUser   = query_select->value(2).toInt(); 
     2159 
     2160                if (id_forum != 0) 
     2161                        info->IDForum = id_forum; 
     2162                else 
     2163                        info->IDForum = query_select->value(3).toInt(); 
     2164 
     2165                info->Subject     = query_select->value(4).toString(); 
     2166                info->UserNick    = query_select->value(5).toString(); 
     2167                info->MessageDate = query_select->value(6).toDateTime(); 
     2168                info->HasChild    = query_select->value(7).toInt(); 
    21552169 
    21562170                list.append(info); 
     
    21632177        sql  = ""; 
    21642178        sql += "SELECT\n"; 
    2165         sql += "        `id_message`,\n"; 
    2166         sql += "        `id_parent_user`\n"; 
     2179        sql += "        `id_message`\n"; 
    21672180        sql += "FROM\n"; 
    21682181        sql += "        `unread`\n"; 
     
    21772190                return returnError(AMySQLDatabase::getLastError()); 
    21782191 
     2192        query_select_unread->setForwardOnly(true); 
     2193 
    21792194        if (query_select_unread->exec() == false) 
    21802195                return returnError(query_select_unread->getLastError()); 
     
    21832198        { 
    21842199                int id = query_select_unread->value(0).toInt(); 
    2185                 int id_parent_user = query_select_unread->value(1).toInt(); 
    21862200 
    21872201                for (int i = 0; i < list.count(); i++) 
    2188                         if (list[i].ID == id) 
     2202                        if (list[i]->ID == id) 
    21892203                        { 
    2190                                 if (id_parent_user == id_me) 
    2191                                         list[i].HasUnreadChild = 2; 
    2192  
    2193                                 list[i].IsRead = false; 
    2194                                 //list.move(i, 0); 
     2204                                list[i]->IsRead = false; 
     2205 
     2206                                list.move(i, 0); 
     2207 
    21952208                                break; 
    21962209                        } 
  • trunk/storage/mysql_storage.h

    r175 r191  
    5757                bool getUnreadCount         (AUnreadForumCountInfoList& list, IProgress* progress = NULL); 
    5858                bool getForumTopicList      (int id_forum, int count, QList<int>& list, IProgress* progress = NULL); 
    59                 bool getTopicInfoList       (ATopicInfoList& list, int id_me, IProgress* progress = NULL); 
    60                 bool getTopicMessageList    (int id_topic, ATopicInfoList& list, int id_me, IProgress* progress = NULL); 
     59                bool getTopicInfoList       (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress = NULL); 
     60                bool getTopicMessageList    (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress = NULL); 
    6161                bool getMessageBody         (int id_message, QString& body, IProgress* progress = NULL); 
    6262                bool setIDsAsRead           (const QList<int>& list, AIDSet type, bool read, QDateTime date, IProgress* progress = NULL); 
  • trunk/sysheaders.h

    r175 r191  
    8282#define DEBUG_MSG(x) QMessageBox::critical(0, QString::fromUtf8("Ошибка!"), x) 
    8383 
     84/*! 
     85 * \brief Макрос для отладки и легкого вывода алерта (числа), в релизе использоваться не должен. 
     86 * \param x число для вывода. 
     87 */ 
     88#define DEBUG_INT(x) DEBUG_MSG(QString::number(x)) 
     89 
    8490#ifndef Q_WS_WIN 
    8591 
     
    9197class AProfiler 
    9298{ 
    93         public: 
     99        public: 
    94100 
    95101                /*! 
    96102                 * \brief При создании экземпляра создается первая отсечка времени. 
    97103                 */ 
    98                 AProfiler () 
    99                 { 
    100                         Start(); 
    101                 } 
     104                AProfiler () 
     105                { 
     106                        start(); 
     107                } 
    102108 
    103109                /*! 
     
    105111                 * при повторном вызове заменяет старую отсечку времени текущей. 
    106112                 */ 
    107                 void Start () 
    108                 { 
    109                         gettimeofday(&m_start, 0); 
    110                 } 
     113                void start () 
     114                { 
     115                        gettimeofday(&m_start, 0); 
     116                } 
    111117 
    112118                /*! 
    113119                 * \brief Создание второй отсечки времени и вывод разницы между текущей отсечкой и стартовой в миллисекундах. 
     120                 * \param ittr Количество итераций 
    114121                 */ 
    115                 void Stop () 
    116                 { 
    117                         gettimeofday(&m_stop, 0); 
     122                void stop (int ittr = 1) 
     123                { 
     124                        gettimeofday(&m_stop, 0); 
    118125 
    119                         long long int delta = (m_stop.tv_sec - m_start.tv_sec) * 1000 + (m_stop.tv_usec - m_start.tv_usec) / 1000; 
     126                        long long int delta = (m_stop.tv_sec - m_start.tv_sec) * 1000 + (m_stop.tv_usec - m_start.tv_usec) / 1000; 
    120127 
    121                         QString msg = QString::number(delta) + "ms"; 
     128                        QString msg; 
    122129 
    123                         QMessageBox::information(0, QString::fromUtf8("Таймер!"), msg); 
    124                 } 
     130                        msg += QString::fromUtf8("Общее время : ") + QString::number(delta) + " ms\n"; 
     131                        msg += QString::fromUtf8("Среднее время : ") + QString::number(delta / ittr) + " ms"; 
    125132 
    126         private: 
     133                        QMessageBox::information(0, QString::fromUtf8("Таймер!"), msg); 
     134                } 
     135 
     136        private: 
    127137 
    128138                /*! 
    129139                 * \brief Время вызова функции Start(). 
    130140                 */ 
    131                 timeval m_start; 
     141                timeval m_start; 
     142 
    132143                /*! 
    133144                 * \brief Время вызова функции Stop(). 
    134145                 */ 
    135                 timeval m_stop; 
     146                timeval m_stop; 
    136147}; 
    137148 
  • trunk/version.h

    r180 r191  
    2020 * \brief Дата билда (заменяется автоматически при каждом билде в version.h, что и приводит к смене номера ревизии) 
    2121 */ 
    22 #define AVALON_DATE "Пнд Мар 23 16:10:17 MSK 2009" 
     22#define AVALON_DATE "Сбт Мар 28 03:20:28 MSK 2009" 
    2323 
    2424#endif 
  • trunk/webservice.cpp

    r152 r191  
    9797        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    9898        header += "Host: rsdn.ru\r\n"; 
     99        header += "Connection: close\r\n"; 
     100        header += "Accept-Encoding: gzip, deflate\r\n"; 
     101        header += "User-Agent: " + getVersionString() + "\r\n"; 
    99102        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    100103        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
     
    233236        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    234237        header += "Host: rsdn.ru\r\n"; 
     238        header += "Connection: close\r\n"; 
     239        header += "Accept-Encoding: gzip, deflate\r\n"; 
     240        header += "User-Agent: " + getVersionString() + "\r\n"; 
    235241        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    236242        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
     
    357363        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    358364        header += "Host: rsdn.ru\r\n"; 
     365        header += "Connection: close\r\n"; 
     366        header += "Accept-Encoding: gzip, deflate\r\n"; 
     367        header += "User-Agent: " + getVersionString() + "\r\n"; 
    359368        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    360369        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
     
    514523        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    515524        header += "Host: rsdn.ru\r\n"; 
     525        header += "Connection: close\r\n"; 
     526        header += "Accept-Encoding: gzip, deflate\r\n"; 
     527        header += "User-Agent: " + getVersionString() + "\r\n"; 
    516528        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    517529        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
     
    719731        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    720732        header += "Host: rsdn.ru\r\n"; 
     733        header += "Connection: close\r\n"; 
     734        header += "Accept-Encoding: gzip, deflate\r\n"; 
     735        header += "User-Agent: " + getVersionString() + "\r\n"; 
    721736        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    722737        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
     
    784799        header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 
    785800        header += "Host: rsdn.ru\r\n"; 
     801        header += "Connection: close\r\n"; 
     802        header += "Accept-Encoding: gzip, deflate\r\n"; 
     803        header += "User-Agent: " + getVersionString() + "\r\n"; 
    786804        header += "Content-Type: text/xml; charset=utf-8\r\n"; 
    787805        header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; 
Note: See TracChangeset for help on using the changeset viewer.