Changeset 190


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

Доделано дерево сообщений в бранче. Перед переносом в транк.

Location:
branches/message_tree
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/message_tree/message_tree.cpp

    r189 r190  
    278278//---------------------------------------------------------------------------------------------- 
    279279 
     280bool AMessageTree::checkCurrentItem (bool select_first) 
     281{ 
     282        if (currentItem() != NULL) 
     283                return true; 
     284 
     285        if (topLevelItemCount() == 0) 
     286                return false; 
     287 
     288        if (select_first == true) 
     289                setCurrentItem(topLevelItem(0)); 
     290        else 
     291        { 
     292                // последний топик в списке 
     293                MessageTreeWidgetItem* topic_item = static_cast<MessageTreeWidgetItem*>(topLevelItem(topLevelItemCount() - 1)); 
     294 
     295                // если элемент еще не загружен, то загружаем 
     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); 
     307        } 
     308 
     309        return true; 
     310} 
     311//---------------------------------------------------------------------------------------------- 
     312 
     313void AMessageTree::changeForum (const AForumInfo* forum_info) 
     314{ 
     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         = ""; 
     336 
     337        if (m_main_form != NULL) 
     338                m_main_form->setEnabledAction(aaViewSource, false); 
     339 
     340        clear(); 
     341 
     342        m_message_view->clear(); 
     343 
     344        scrollToTop(); 
     345 
     346        // если выделена группа, то просто очистка 
     347        if (forum_info == NULL) 
     348        { 
     349                headerItem()->setText(0, QString::fromUtf8("тема")); 
     350 
     351                QFont font = headerItem()->font(0); 
     352                font.setBold(false); 
     353                headerItem()->setFont(0, font); 
     354 
     355                return; 
     356        } 
     357 
     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 
     370        // вывод наименования форума в хедер 
     371        headerItem()->setText(0, m_current_forum.Name); 
     372 
     373        // 
     374        // загрузка топиков в зависимости от типа форума 
     375        // 
     376 
     377        // получение хранилища 
     378        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     379 
     380        if (storage.get() == NULL) 
     381        { 
     382                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     383                return; 
     384        } 
     385 
     386        // получение информации о себе 
     387        // TODO: вынести в AGlobal 
     388        QSettings settings; 
     389 
     390        m_me.Name = settings.value("rsdn/login", "").toString(); 
     391 
     392        if (storage->whoAmI(m_me, NULL) == false) 
     393                m_me.Name = ""; 
     394 
     395        // если группа форумов обыкновенная 
     396        if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 
     397        { 
     398                // получение топиков 
     399                // ориентировочное время выполнения 68 ms (для форума NET, 28199 топиков) 
     400                // основное время занимает запрос данных из хранилища 
     401                QList<int> topic_list; 
     402 
     403                if (storage->getForumTopicList(m_current_forum.ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false) 
     404                { 
     405                        storage->showError(m_parent); 
     406                        return; 
     407                } 
     408 
     409                // установка топиков 
     410                // ориентировочное время выполнения 50 ms (для форума NET, 28199 топиков) 
     411                // основное время занимает создание объекта MessageTreeWidgetItem 
     412                QList<QTreeWidgetItem*> items; 
     413 
     414                for (int i = 0; i < topic_list.count(); i++) 
     415                { 
     416                        // начальное заполнение дескриптора топика 
     417                        AMessageInfoGUI* info = createItem(); 
     418 
     419                        info->ID = topic_list[i]; 
     420 
     421                        items.append(info->Item); 
     422                } 
     423 
     424                // отображение на виджет 
     425                addTopLevelItems(items); 
     426 
     427                // дозагрузка информации о топиках, находящихся в видимой области отображения 
     428                scrollTopics(); 
     429        } 
     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 
    280443void AMessageTree::vertical_scroll (int /*value*/) 
    281444{ 
    282445        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(); 
     479        else 
     480        { 
     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) 
     499                        list.append(info); 
     500 
     501                top_index++; 
     502        } 
     503 
     504        // 
     505        // загрузка топиков, которые не загружены 
     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) 
     581        { 
     582                // получение хранилища 
     583                std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     584 
     585                if (storage.get() == NULL) 
     586                { 
     587                        QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     588                        return; 
     589                } 
     590 
     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) 
     597                { 
     598                        storage->showError(m_parent); 
     599                        return; 
     600                } 
     601 
     602                // постройка дерева, обход в ширину быстрее чем в высоту 
     603                // ориентировочное время выполнения 900 ms (для топика 279396 - 5149 сообщений) 
     604                // наиболее высокое дерево составляет 1555 сообщений (для топика 1099540) 
     605                // наиболее широкое дерево (глубина рекурсии) пока неизвестно 
     606                buildTree(info, &list); 
     607 
     608                // для предотвращения повторной загрузки 
     609                info->IsChildLoaded = true; 
     610 
     611                // раскрытие дерева до уровня непрочитаных топиков 
     612                if (info->UnreadChildCount != 0) 
     613                        expandUnreadChild(item); 
     614        } 
     615} 
     616//---------------------------------------------------------------------------------------------- 
     617 
     618void AMessageTree::expandUnreadChild (QTreeWidgetItem* widget_item) 
     619{ 
     620        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(widget_item); 
     621 
     622        if (item->pag()->UnreadChildCount != 0) 
     623        { 
     624                for (int i = 0; i < item->childCount(); i++) 
     625                        if (((MessageTreeWidgetItem*)item->child(i))->pag()->UnreadChildCount != 0) 
     626                                expandUnreadChild(item->child(i)); 
     627 
     628                expandItem(item); 
     629        } 
     630} 
     631//---------------------------------------------------------------------------------------------- 
     632 
     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); 
     660                        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) 
     669                        { 
     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) 
     676                                { 
     677                                        AMessageInfoGUI* info_parent = item_parent->pag(); 
     678 
     679                                        if (info_parent->HasUnreadChildMy != true) 
     680                                        { 
     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); 
     686                                                else 
     687                                                        item_parent->setIcon(0, m_message_unread_my); 
     688                                        } 
     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) 
     696                        } 
     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        } 
     740} 
     741//---------------------------------------------------------------------------------------------- 
     742 
     743void AMessageTree::timer_on_timer () 
     744{ 
     745        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
     746 
     747        if (item != NULL) 
     748                markItemAsRead(item, true); 
    283749} 
    284750//---------------------------------------------------------------------------------------------- 
     
    353819//---------------------------------------------------------------------------------------------- 
    354820 
     821void AMessageTree::markItemAsRead (QTreeWidgetItem* widget_item, bool is_read) 
     822{ 
     823        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(widget_item); 
     824 
     825        AMessageInfoGUI* info = item->pag(); 
     826 
     827        // если уже прочитан 
     828        if (info->IsRead == is_read) 
     829                return; 
     830 
     831        // пометить как прочитанное в хранилище 
     832        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     833 
     834        if (storage.get() == NULL) 
     835        { 
     836                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     837                return; 
     838        } 
     839 
     840        if (storage->setIDsAsRead(QList<int>() << info->ID, idsMessage, is_read, QDateTime(), NULL) == false) 
     841        { 
     842                storage->showError(m_parent); 
     843                return; 
     844        } 
     845 
     846        // установка флага как прочитанного и пометка в дереве 
     847        info->IsRead = is_read; 
     848 
     849        if (is_read == true) 
     850        { 
     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); 
     856                else 
     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) 
     891                        { 
     892                                // родитель непрочитан 
     893 
     894                                // если среди дочерних прочитали дочернее мне и больше непрочитанных дочерних мне нет 
     895                                // и должна произойти смена иконки 
     896                                if (old_unread_count_my != 0 && info_parent->UnreadChildCountMy == 0) 
     897                                        item_parent->setIcon(0, m_message_unread); 
     898                        } 
     899                        else 
     900                        { 
     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); 
     916                        } 
     917 
     918                        item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
     919                } 
     920 
     921                // уменьшение количества непрочитанных в дереве форума 
     922                m_forum_tree->changeUnreadCount(-1); 
     923        } 
     924        else   // if (is_read == true) 
     925        { 
     926                // TODO: Доделать пометку родителей, если отметилось сообщение, которое является ответом мне 
     927 
     928                // установка иконки помечаемому сообщению 
     929                item->setIcon(0, m_message_unread); 
     930 
     931                // установка флагов и иконок у родительских сообщений 
     932                MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
     933 
     934                while (parent_item != NULL) 
     935                { 
     936                        AMessageInfoGUI* parent_info = parent_item->pag(); 
     937 
     938                        // смена иконки при необходимости 
     939                        if (parent_info->IsRead == true && parent_info->HasUnreadChild == false) 
     940                                parent_item->setIcon(0, m_child_unread); 
     941 
     942                        parent_info->UnreadChildCount++; 
     943                        parent_info->HasUnreadChild = true; 
     944 
     945                        parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); 
     946                } 
     947 
     948                // увеличение количества непрочитанных в дереве форума 
     949                m_forum_tree->changeUnreadCount(1); 
     950 
     951        }   // if (is_read == true) ... else 
     952} 
     953//---------------------------------------------------------------------------------------------- 
     954 
     955void AMessageTree::menu_mark_message_as_read_triggered () 
     956{ 
     957        QTreeWidgetItem* item = currentItem(); 
     958 
     959        if (item == NULL) 
     960                return; 
     961 
     962        markItemAsRead(item, true); 
     963} 
     964//---------------------------------------------------------------------------------------------- 
     965 
     966void AMessageTree::menu_mark_message_as_unread_triggered () 
     967{ 
     968        QTreeWidgetItem* item = currentItem(); 
     969 
     970        if (item == NULL) 
     971                return; 
     972 
     973        markItemAsRead(item, false); 
     974} 
     975//---------------------------------------------------------------------------------------------- 
     976 
     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); 
     1021        } 
     1022        else 
     1023        { 
     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 () 
     1041{ 
     1042        QTreeWidgetItem* item = currentItem(); 
     1043 
     1044        if (item == NULL) 
     1045                return; 
     1046 
     1047        // поиск родителя 
     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        // пометка в дереве 
     1057        if (info->IsChildLoaded == true) 
     1058        { 
     1059                int count = 0; 
     1060 
     1061                markThreadAsRead(parent, false, count); 
     1062 
     1063                m_forum_tree->changeUnreadCount(count); 
     1064        } 
     1065        else 
     1066        { 
     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()); 
     1088 
     1089        if (item == NULL) 
     1090                return; 
     1091 
     1092        FormMessage* form = new FormMessage(NULL, true, *(item->pag())); 
     1093 
     1094        form->setForumTree(m_forum_tree); 
     1095        form->setMainForm(m_main_form); 
     1096 
     1097        form->show(); 
     1098} 
     1099//---------------------------------------------------------------------------------------------- 
     1100 
     1101void AMessageTree::loadMessage2Send () 
     1102{ 
     1103        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     1104 
     1105        if (storage.get() == NULL) 
     1106        { 
     1107                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     1108                return; 
     1109        } 
     1110 
     1111        AMessageInfoList list; 
     1112 
     1113        if (storage->getMessage2SendList(list, NULL) == false) 
     1114        { 
     1115                storage->showError(m_parent); 
     1116                return; 
     1117        } 
     1118 
     1119        QList<QTreeWidgetItem*> items; 
     1120 
     1121        AGlobal* global = AGlobal::getInstance(); 
     1122 
     1123        for (int i = 0; i < list.count(); i++) 
     1124        { 
     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); 
     1158                } 
     1159                else 
     1160                        info->Item->setText(1, info->UserNick); 
     1161 
     1162                info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
     1163 
     1164                items.append(info->Item); 
     1165        } 
     1166 
     1167        addTopLevelItems(items); 
     1168} 
     1169//---------------------------------------------------------------------------------------------- 
     1170 
    3551171void AMessageTree::processUrl (const QString& url) 
    3561172{ 
     
    4591275//---------------------------------------------------------------------------------------------- 
    4601276 
    461 void AMessageTree::menu_reply_triggered () 
    462 { 
     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; 
     1556 
    4631557        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    4641558 
     1559        // если не было выделения, то ищем следующую непрочитанную статью (она будет первой) 
    4651560        if (item == NULL) 
    466                 return; 
    467  
    468         FormMessage* form = new FormMessage(NULL, true, *(item->pag())); 
    469  
    470         form->setForumTree(m_forum_tree); 
    471         form->setMainForm(m_main_form); 
    472  
    473         form->show(); 
    474 } 
    475 //---------------------------------------------------------------------------------------------- 
    476  
    477 void AMessageTree::item_double_clicked (QTreeWidgetItem* item, int /*column*/) 
    478 { 
     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        // поиск следующего топика с непрочитанными сообщениями 
     1574        while (true) 
     1575        { 
     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) 
     1598                        break; 
     1599 
     1600                if (info->HasUnreadChild == true) 
     1601                { 
     1602                        gotoNextUnreadArticle(item); 
     1603                        return; 
     1604                } 
     1605        } 
     1606 
     1607        setCurrentItem(item); 
     1608 
     1609        scrollToItem(item, QAbstractItemView::PositionAtCenter); 
     1610} 
     1611//---------------------------------------------------------------------------------------------- 
     1612 
     1613void AMessageTree::menu_special_delete_triggered () 
     1614{ 
     1615        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
     1616 
    4791617        if (item == NULL) 
    4801618                return; 
    481  
    482         setCurrentItem(item); 
    4831619 
    4841620        if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     
    4881624                return; 
    4891625 
    490         menu_special_edit_triggered(); 
    491 } 
    492 //---------------------------------------------------------------------------------------------- 
    493  
    494 void AMessageTree::menu_special_edit_triggered () 
    495 { 
    496         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    497  
     1626        std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
     1627 
     1628        if (storage.get() == NULL) 
     1629        { 
     1630                QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
     1631                return; 
     1632        } 
     1633 
     1634        if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_current_forum.ID, NULL) == false) 
     1635        { 
     1636                storage->showError(m_parent); 
     1637                return; 
     1638        } 
     1639 
     1640        // обновление в дереве форумов количества непрочитанных сообщений 
     1641        if (m_forum_tree != NULL) 
     1642                m_forum_tree->reloadUnread(true); 
     1643} 
     1644//---------------------------------------------------------------------------------------------- 
     1645 
     1646void AMessageTree::item_double_clicked (QTreeWidgetItem* item, int /*column*/) 
     1647{ 
    4981648        if (item == NULL) 
    4991649                return; 
     1650 
     1651        setCurrentItem(item); 
    5001652 
    5011653        if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 
     
    5051657                return; 
    5061658 
    507         if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND) 
    508         { 
    509                 FormMessage* form = new FormMessage(NULL, false, *(item->pag()), item->pag()->Special); 
    510  
    511                 form->setForumTree(m_forum_tree); 
    512                 form->setMainForm(m_main_form); 
    513  
    514                 form->show(); 
    515         } 
    516         else if (m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 
    517         { 
    518                 FormModerate* form = new FormModerate(m_parent, item->pag()->ID, item->pag()->Special); 
    519  
    520                 form->setForumTree(m_forum_tree); 
    521  
    522                 form->exec(); 
    523  
    524                 return; 
    525         } 
    526 } 
    527 //---------------------------------------------------------------------------------------------- 
    528  
    529 void AMessageTree::menu_special_delete_triggered () 
     1659        menu_special_edit_triggered(); 
     1660} 
     1661//---------------------------------------------------------------------------------------------- 
     1662 
     1663void AMessageTree::menu_special_edit_triggered () 
    5301664{ 
    5311665        MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
     
    5401674                return; 
    5411675 
    542         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    543  
    544         if (storage.get() == NULL) 
    545         { 
    546                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    547                 return; 
    548         } 
    549  
    550         if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_current_forum.ID, NULL) == false) 
    551         { 
    552                 storage->showError(m_parent); 
    553                 return; 
    554         } 
    555  
    556         // обновление в дереве форумов количества непрочитанных сообщений 
    557         if (m_forum_tree != NULL) 
    558                 m_forum_tree->reloadUnread(true); 
     1676        if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND) 
     1677        { 
     1678                FormMessage* form = new FormMessage(NULL, false, *(item->pag()), item->pag()->Special); 
     1679 
     1680                form->setForumTree(m_forum_tree); 
     1681                form->setMainForm(m_main_form); 
     1682 
     1683                form->show(); 
     1684        } 
     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); 
     1688 
     1689                form->setForumTree(m_forum_tree); 
     1690 
     1691                form->exec(); 
     1692 
     1693                return; 
     1694        } 
    5591695} 
    5601696//---------------------------------------------------------------------------------------------- 
     
    7401876//---------------------------------------------------------------------------------------------- 
    7411877 
    742 bool AMessageTree::checkCurrentItem (bool select_first) 
    743 { 
    744         if (currentItem() != NULL) 
    745                 return true; 
    746  
    747         if (topLevelItemCount() == 0) 
    748                 return false; 
    749  
    750         if (select_first == true) 
    751                 setCurrentItem(topLevelItem(0)); 
    752         else 
    753         { 
    754                 // последний топик в списке 
    755                 MessageTreeWidgetItem* topic_item = static_cast<MessageTreeWidgetItem*>(topLevelItem(topLevelItemCount() - 1)); 
    756  
    757                 // если элемент еще не загружен, то загружаем 
    758                 if (topic_item->pag()->IsInfoLoaded == false) 
    759                         setCurrentItem(topic_item); 
    760  
    761                 // если дочерние элементы еще не загружены, то загружаем 
    762                 if (topic_item->pag()->IsChildLoaded == false) 
    763                         topic_item->setExpanded(true); 
    764  
    765                 // выделяем последний лист в топике 
    766                 MessageTreeWidgetItem* last_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastLeaf(topic_item)); 
    767  
    768                 setCurrentItem(last_item); 
    769         } 
    770  
    771         return true; 
    772 } 
    773 //---------------------------------------------------------------------------------------------- 
    774  
    775 void AMessageTree::gotoNextUnreadArticle (QTreeWidgetItem* current_item) 
    776 { 
    777         AMessageInfoGUI* info = NULL; 
    778  
    779         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(current_item); 
    780  
    781         // если не было выделения, то ищем первый непрочитанный топик или топик с непрочитанными сообщениями 
    782         if (item == NULL) 
    783         { 
    784                 for (int i = 0; i < topLevelItemCount(); i++) 
    785                 { 
    786                         item = static_cast<MessageTreeWidgetItem*>(topLevelItem(i)); 
    787  
    788                         info = item->pag(); 
    789  
    790                         if (info->IsInfoLoaded == false) 
    791                                 return; 
    792                         else if (info->IsRead == false) 
    793                         { 
    794                                 setCurrentItem(item); 
    795  
    796                                 scrollToItem(item, QAbstractItemView::PositionAtCenter); 
    797  
    798                                 return; 
    799                         } 
    800                         else if (info->HasUnreadChild == true) 
    801                                 break; 
    802                 } 
    803         } 
    804         else 
    805                 info = item->pag(); 
    806  
    807         // флаг петли 
    808         bool loopback = false; 
    809  
    810         // есть выделение или найден топик с непрочитанными сообщениями 
    811         while (true) 
    812         { 
    813                 if (info->HasUnreadChild == true && info->IsChildLoaded == false) 
    814                         item->setExpanded(true); 
    815  
    816                 // выбор следующего элемента 
    817                 if (info->HasUnreadChild == true) 
    818                         // если есть дочерние непрочитанные, то выбираем первый дочерний 
    819                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstChild(item)); 
    820                 else 
    821                 { 
    822                         // если нет дочерних непрочитанных, то ... 
    823  
    824                         // смотрим, есть ли у элемента родитель и есть ли у родителя непрочитанные дочерние 
    825                         MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    826  
    827                         // если есть родитель и у него нет непрочитанных дочерних, то поднимаемся на уровень родителя 
    828                         if (parent_item != NULL && parent_item->pag()->HasUnreadChild == false) 
    829                                 item = parent_item; 
    830                         else 
    831                         { 
    832                                 // у родителя есть непрочитанные дочерние или нет родителя - переходим к следующему брату 
    833                                 // несмотря на то, что непрочитанный брат может быть и выше 
    834                                 MessageTreeWidgetItem* sibling_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
    835  
    836                                 // если следующего брата нет 
    837                                 if (sibling_item == NULL && parent_item != NULL) 
    838                                 { 
    839                                         // движение вверх по дереву, пока не найдется следующий брат у родителя 
    840                                         while (parent_item != NULL) 
    841                                         { 
    842                                                 MessageTreeWidgetItem* last_child_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastChild(parent_item)); 
    843  
    844                                                 if (last_child_item != item) 
    845                                                         break; 
    846  
    847                                                 item = parent_item; 
    848  
    849                                                 parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    850                                         } 
    851  
    852                                         // сдвиг на следующего брата в соседней подветке 
    853                                         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
    854                                 } 
    855                                 else 
    856                                         item = sibling_item; 
    857                         } 
    858                 } 
    859  
    860                 // если достигнут конец дерева, то переходим в корень 
    861                 if (item == NULL) 
    862                         item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
    863  
    864                 info = item->pag(); 
    865  
    866                 // если найденый топик с незагруженной информацией 
    867                 if (info->IsInfoLoaded == false) 
    868                 { 
    869                         if (loopback == true) 
    870                                 return; 
    871  
    872                         item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
    873                         info = item->pag(); 
    874  
    875                         loopback = true; 
    876                 } 
    877  
    878                 if (info->IsRead == false) 
    879                         break; 
    880         } 
    881  
    882         setCurrentItem(item); 
    883  
    884         scrollToItem(item, QAbstractItemView::PositionAtCenter); 
    885 } 
    886 //---------------------------------------------------------------------------------------------- 
    887  
    8881878void AMessageTree::gotoNextUnreadArticle () 
    8891879{ 
     
    8921882//---------------------------------------------------------------------------------------------- 
    8931883 
    894 void AMessageTree::gotoNextUnreadThread () 
    895 { 
    896         AMessageInfoGUI* info = NULL; 
    897  
    898         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    899  
    900         // если не было выделения, то ищем следующую непрочитанную статью (она будет первой) 
    901         if (item == NULL) 
    902         { 
    903                 gotoNextUnreadArticle(NULL); 
    904                 return; 
    905         } 
    906  
    907         // item установлен на топик 
    908         item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
    909         info = item->pag(); 
    910  
    911         // флаг петли 
    912         bool loopback = false; 
    913  
    914         // поиск следующего топика с непрочитанными сообщениями 
    915         while (true) 
    916         { 
    917                 // следующий топик за текущим 
    918                 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 
    919  
    920                 // если достигнут конец дерева, то переходим в корень 
    921                 if (item == NULL) 
    922                         item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
    923  
    924                 info = item->pag(); 
    925  
    926                 // если найденый топик с незагруженной информацией 
    927                 if (info->IsInfoLoaded == false) 
    928                 { 
    929                         if (loopback == true) 
    930                                 return; 
    931  
    932                         item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 
    933                         info = item->pag(); 
    934  
    935                         loopback = true; 
    936                 } 
    937  
    938                 if (info->IsRead == false) 
    939                         break; 
    940  
    941                 if (info->HasUnreadChild == true) 
    942                 { 
    943                         gotoNextUnreadArticle(item); 
    944                         return; 
    945                 } 
    946         } 
    947  
    948         setCurrentItem(item); 
    949  
    950         scrollToItem(item, QAbstractItemView::PositionAtCenter); 
    951 } 
    952 //---------------------------------------------------------------------------------------------- 
    953  
    954 void AMessageTree::menu_mark_message_as_read_triggered () 
    955 { 
    956         QTreeWidgetItem* item = currentItem(); 
    957  
    958         if (item == NULL) 
    959                 return; 
    960  
    961         markItemAsRead(item, true); 
    962 } 
    963 //---------------------------------------------------------------------------------------------- 
    964  
    965 void AMessageTree::menu_mark_message_as_unread_triggered () 
    966 { 
    967         QTreeWidgetItem* item = currentItem(); 
    968  
    969         if (item == NULL) 
    970                 return; 
    971  
    972         markItemAsRead(item, false); 
    973 } 
    974 //---------------------------------------------------------------------------------------------- 
    975  
    976 void AMessageTree::timer_on_timer () 
    977 { 
    978         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 
    979  
    980         if (item != NULL) 
    981                 markItemAsRead(item, true); 
    982 } 
    983 //---------------------------------------------------------------------------------------------- 
    984  
    985 void AMessageTree::markItemAsRead (QTreeWidgetItem* widget_item, bool is_read) 
    986 { 
    987         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(widget_item); 
     1884 
     1885AMessageInfoGUI* AMessageTree::createItem () 
     1886{ 
     1887        MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    9881888 
    9891889        AMessageInfoGUI* info = item->pag(); 
    9901890 
    991         // если уже прочитан 
    992         if (info->IsRead == is_read) 
    993                 return; 
    994  
    995         // пометить как прочитанное в хранилище 
    996         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    997  
    998         if (storage.get() == NULL) 
    999         { 
    1000                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1001                 return; 
    1002         } 
    1003  
    1004         if (storage->setIDsAsRead(QList<int>() << info->ID, idsMessage, is_read, QDateTime(), NULL) == false) 
    1005         { 
    1006                 storage->showError(m_parent); 
    1007                 return; 
    1008         } 
    1009  
    1010         // установка флага как прочитанного и пометка в дереве 
     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 
    10111906        info->IsRead = is_read; 
    10121907 
    10131908        if (is_read == true) 
    10141909        { 
    1015                 // установка иконки помечаемому сообщению 
    1016                 if (info->HasUnreadChildMy) 
    1017                         item->setIcon(0, m_child_unread_my); 
    1018                 else if (info->HasUnreadChild) 
    1019                         item->setIcon(0, m_child_unread); 
    1020                 else 
    1021                         item->setIcon(0, m_message_read); 
    1022  
    1023                 // флаг того, что это было сообщение для меня 
    1024                 bool message_to_me = false; 
    1025  
    1026                 // установка флагов и иконок у родительских сообщений 
    1027                 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    1028  
    1029                 if (item_parent != NULL && item_parent->pag()->IDUser == m_me.ID) 
    1030                         message_to_me = true; 
    1031  
    1032                 while (item_parent != NULL) 
    1033                 { 
    1034                         AMessageInfoGUI* info_parent = item_parent->pag(); 
    1035  
    1036                         int old_unread_count    = info_parent->UnreadChildCount; 
    1037                         int old_unread_count_my = info_parent->UnreadChildCountMy; 
    1038  
    1039                         // уменьшение количества непрочитанных дочерних 
    1040                         // и установка соответствующих флагов 
    1041                         if (info_parent->UnreadChildCount > 0) 
    1042                                 info_parent->UnreadChildCount--; 
    1043  
    1044                         if (message_to_me == true && info_parent->UnreadChildCountMy > 0) 
    1045                                 info_parent->UnreadChildCountMy--; 
    1046  
    1047                         if (info_parent->UnreadChildCountMy == 0) 
    1048                                 info_parent->HasUnreadChildMy = false; 
    1049  
    1050                         if (info_parent->UnreadChildCount == 0) 
    1051                                 info_parent->HasUnreadChild = false; 
    1052  
    1053                         // установка иконок 
    1054                         if (info_parent->IsRead == false) 
    1055                         { 
    1056                                 // родитель непрочитан 
    1057  
    1058                                 // если среди дочерних прочитали дочернее мне и больше непрочитанных дочерних мне нет 
    1059                                 // и должна произойти смена иконки 
    1060                                 if (old_unread_count_my != 0 && info_parent->UnreadChildCountMy == 0) 
    1061                                         item_parent->setIcon(0, m_message_unread); 
    1062                         } 
    1063                         else 
    1064                         { 
    1065                                 // родитель прочитан 
    1066  
    1067                                 // если среди дочерних есть непрочитанные мне 
    1068                                 // и должна произойти смена иконки 
    1069                                 if (old_unread_count_my != info_parent->UnreadChildCountMy && info_parent->UnreadChildCountMy > 0) 
    1070                                         item_parent->setIcon(0, m_child_unread_my); 
    1071  
    1072                                 // если среди дочерних есть непрочитанные 
    1073                                 // и должна произойти смена иконки 
    1074                                 else if (old_unread_count != info_parent->UnreadChildCount && info_parent->UnreadChildCount > 0) 
    1075                                         item_parent->setIcon(0, m_child_unread); 
    1076  
    1077                                 // нет дочерних непрочитанных 
    1078                                 else 
    1079                                         item_parent->setIcon(0, m_message_read); 
    1080                         } 
    1081  
    1082                         item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
    1083                 } 
    1084  
    1085                 // уменьшение количества непрочитанных в дереве форума 
    1086                 m_forum_tree->changeUnreadCount(-1); 
    1087         } 
    1088         else   // if (is_read == true) 
    1089         { 
    1090                 // TODO: Доделать пометку родителей, если отметилось сообщение, которое является ответом мне 
    1091  
    1092                 // установка иконки помечаемому сообщению 
    1093                 item->setIcon(0, m_message_unread); 
    1094  
    1095                 // установка флагов и иконок у родительских сообщений 
    1096                 MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 
    1097  
    1098                 while (parent_item != NULL) 
    1099                 { 
    1100                         AMessageInfoGUI* parent_info = parent_item->pag(); 
    1101  
    1102                         // смена иконки при необходимости 
    1103                         if (parent_info->IsRead == true && parent_info->HasUnreadChild == false) 
    1104                                 parent_item->setIcon(0, m_child_unread); 
    1105  
    1106                         parent_info->UnreadChildCount++; 
    1107                         parent_info->HasUnreadChild = true; 
    1108  
    1109                         parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); 
    1110                 } 
    1111  
    1112                 // увеличение количества непрочитанных в дереве форума 
    1113                 m_forum_tree->changeUnreadCount(1); 
    1114  
    1115         }   // if (is_read == true) ... else 
    1116 } 
    1117 //---------------------------------------------------------------------------------------------- 
    1118  
    1119 AMessageInfoGUI* AMessageTree::createItem () 
    1120 { 
    1121         MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 
    1122  
    1123         AMessageInfoGUI* info = item->pag(); 
    1124  
    1125         info->Item = item; 
    1126  
    1127         return info; 
    1128 } 
    1129 //---------------------------------------------------------------------------------------------- 
    1130  
    1131 void AMessageTree::changeForum (const AForumInfo* forum_info) 
    1132 { 
    1133         // 
    1134         // базовая очистка 
    1135         // 
    1136  
    1137         m_current_forum.ID        = 0; 
    1138         m_current_forum.IDGroup   = 0; 
    1139         m_current_forum.ShortName = ""; 
    1140         m_current_forum.Name      = ""; 
    1141         m_current_forum.Rated     = false; 
    1142         m_current_forum.InTop     = false; 
    1143         m_current_forum.RateLimit = 0; 
    1144  
    1145         m_me.ID             = 0; 
    1146         m_me.Name           = ""; 
    1147         m_me.Nick           = ""; 
    1148         m_me.RealName       = ""; 
    1149         m_me.Email          = ""; 
    1150         m_me.Homepage       = ""; 
    1151         m_me.Specialization = ""; 
    1152         m_me.WhereFrom      = ""; 
    1153         m_me.Origin         = ""; 
    1154  
    1155         if (m_main_form != NULL) 
    1156                 m_main_form->setEnabledAction(aaViewSource, false); 
    1157  
    1158         clear(); 
    1159  
    1160         m_message_view->clear(); 
    1161  
    1162         scrollToTop(); 
    1163  
    1164         // если выделена группа, то просто очистка 
    1165         if (forum_info == NULL) 
    1166         { 
    1167                 headerItem()->setText(0, QString::fromUtf8("тема")); 
    1168  
    1169                 QFont font = headerItem()->font(0); 
    1170                 font.setBold(false); 
    1171                 headerItem()->setFont(0, font); 
    1172  
    1173                 return; 
    1174         } 
    1175  
    1176         // 
    1177         // есть форум для отображения 
    1178         // 
    1179  
    1180         m_current_forum.ID        = forum_info->ID; 
    1181         m_current_forum.IDGroup   = forum_info->IDGroup; 
    1182         m_current_forum.ShortName = forum_info->ShortName; 
    1183         m_current_forum.Name      = forum_info->Name; 
    1184         m_current_forum.Rated     = forum_info->Rated; 
    1185         m_current_forum.InTop     = forum_info->InTop; 
    1186         m_current_forum.RateLimit = forum_info->RateLimit; 
    1187  
    1188         // вывод наименования форума в хедер 
    1189         headerItem()->setText(0, m_current_forum.Name); 
    1190  
    1191         // 
    1192         // загрузка топиков в зависимости от типа форума 
    1193         // 
    1194  
    1195         // получение хранилища 
    1196         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1197  
    1198         if (storage.get() == NULL) 
    1199         { 
    1200                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1201                 return; 
    1202         } 
    1203  
    1204         // получение информации о себе 
    1205         // TODO: вынести в AGlobal 
    1206         QSettings settings; 
    1207  
    1208         m_me.Name = settings.value("rsdn/login", "").toString(); 
    1209  
    1210         if (storage->whoAmI(m_me, NULL) == false) 
    1211                 m_me.Name = ""; 
    1212  
    1213         // если группа форумов обыкновенная 
    1214         if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 
    1215         { 
    1216                 // получение топиков 
    1217                 // ориентировочное время выполнения 68 ms (для форума NET, 28199 топиков) 
    1218                 // основное время занимает запрос данных из хранилища 
    1219                 QList<int> topic_list; 
    1220  
    1221                 if (storage->getForumTopicList(m_current_forum.ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false) 
    1222                 { 
    1223                         storage->showError(m_parent); 
    1224                         return; 
    1225                 } 
    1226  
    1227                 // установка топиков 
    1228                 // ориентировочное время выполнения 50 ms (для форума NET, 28199 топиков) 
    1229                 // основное время занимает создание объекта MessageTreeWidgetItem 
    1230                 QList<QTreeWidgetItem*> items; 
    1231  
    1232                 for (int i = 0; i < topic_list.count(); i++) 
    1233                 { 
    1234                         // начальное заполнение дескриптора топика 
    1235                         AMessageInfoGUI* info = createItem(); 
    1236  
    1237                         info->ID = topic_list[i]; 
    1238  
    1239                         items.append(info->Item); 
    1240                 } 
    1241  
    1242                 // отображение на виджет 
    1243                 addTopLevelItems(items); 
    1244  
    1245                 // дозагрузка информации о топиках, находящихся в видимой области отображения 
    1246                 scrollTopics(); 
    1247         } 
    1248         else   // if (forum_info->IDGroup != SPECIAL_ID_GROUP) 
    1249         { 
    1250         } 
    1251 } 
    1252 //---------------------------------------------------------------------------------------------- 
    1253  
    1254 void AMessageTree::scrollTopics () 
    1255 { 
    1256         // Среднее время выполнения для дозагрузки одного элемента 5 ms 
    1257         // Среднее время выполнения для дозагрузки страницы из 56 топиков (полный экран 1280х1024) 32 ms 
    1258  
    1259         // пустой форум или спец-группа 
    1260         if (m_current_forum.ID == 0 || m_current_forum.IDGroup == SPECIAL_ID_GROUP) 
    1261                 return; 
    1262  
    1263         // 
    1264         // Определение диапазона возможной подгрузки данных 
    1265         // 
    1266  
    1267         // поиск корня верхнего видимого элемента в отображении 
    1268         QTreeWidgetItem* top_item = itemAt(1, 1); 
    1269  
    1270         if (top_item == NULL) 
    1271                 return; // нет элементов в дереве(?) 
    1272  
    1273         top_item = ATreeWidgetItem::rootItem(top_item); 
    1274  
    1275         int top_index = indexOfTopLevelItem(top_item); 
    1276  
    1277         // поиск корня нижнего видимого элемента в отображении 
    1278         QTreeWidgetItem* bottom_item = itemAt(1, height() - 1); 
    1279  
    1280         int bottom_index; 
    1281  
    1282         if (bottom_item == NULL) 
    1283                 bottom_index = topLevelItemCount(); 
    1284         else 
    1285         { 
    1286                 bottom_item = ATreeWidgetItem::rootItem(bottom_item); 
    1287  
    1288                 bottom_index = indexOfTopLevelItem(bottom_item) + 1; 
    1289         } 
    1290  
    1291         // 
    1292         // Поиск еще не загруженных топиков в диапазоне 
    1293         // 
    1294  
    1295         AMessageInfoGUIPtrList list; 
    1296  
    1297         while (top_index < bottom_index) 
    1298         { 
    1299                 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(top_index)); 
    1300  
    1301                 AMessageInfoGUI* info = item->pag(); 
    1302  
    1303                 if (info->IsInfoLoaded == false) 
    1304                         list.append(info); 
    1305  
    1306                 top_index++; 
    1307         } 
    1308  
    1309         // 
    1310         // загрузка топиков, которые не загружены 
    1311         // 
    1312  
    1313         if (list.count() == 0) 
    1314                 return; 
    1315  
    1316         // получение хранилища 
    1317         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1318  
    1319         if (storage.get() == NULL) 
    1320         { 
    1321                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1322                 return; 
    1323         } 
    1324  
    1325         if (storage->getTopicInfoList(m_current_forum.ID, list, m_me.ID, NULL) == false) 
    1326         { 
    1327                 storage->showError(m_parent); 
    1328                 return; 
    1329         } 
    1330  
    1331         AGlobal* global = AGlobal::getInstance(); 
    1332  
    1333         // 
    1334         // Установка загруженой информации 
    1335         // 
    1336  
    1337         for (int i = 0; i < list.count(); i++) 
    1338         { 
    1339                 AMessageInfoGUI* info = list[i]; 
    1340  
    1341                 info->IsInfoLoaded       = true; 
    1342                 info->UnreadChildCount   = 0; 
    1343                 info->UnreadChildCountMy = 0; 
    1344  
    1345                 info->Item->setText(0, info->Subject); 
    1346  
    1347                 // TODO: сделать общую функцию формирования имени/ника 
    1348                 if (info->IDUser == 0) 
    1349                         info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 
    1350                 else 
    1351                         info->Item->setText(1, info->UserNick); 
    1352  
    1353                 info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
    1354  
    1355                 if (info->HasChild == true) 
    1356                         info->Item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 
    1357  
    1358                 if (info->IsRead == true) 
    1359                 { 
    1360                         if (info->HasUnreadChildMy) 
    1361                                 info->Item->setIcon(0, m_child_unread_my); 
    1362                         else if (info->HasUnreadChild) 
    1363                                 info->Item->setIcon(0, m_child_unread); 
    1364                         else 
    1365                                 info->Item->setIcon(0, m_message_read); 
    1366                 } 
    1367                 else 
    1368                 { 
    1369                         if (info->HasUnreadChildMy) 
    1370                                 info->Item->setIcon(0, m_message_unread_my); 
    1371                         else 
    1372                                 info->Item->setIcon(0, m_message_unread); 
    1373                 } 
    1374         } 
    1375 } 
    1376 //---------------------------------------------------------------------------------------------- 
    1377  
    1378 void AMessageTree::expand_item (QTreeWidgetItem* item_expanded) 
    1379 { 
    1380         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(item_expanded); 
    1381  
    1382         AMessageInfoGUI* info = item->pag(); 
    1383  
    1384         // если дочерние сообщения не загружены (а это может быть только для топика в текущей реализации) 
    1385         if (info->HasChild == true && info->IsChildLoaded == false) 
    1386         { 
    1387                 // получение хранилища 
    1388                 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1389  
    1390                 if (storage.get() == NULL) 
    1391                 { 
    1392                         QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1393                         return; 
    1394                 } 
    1395  
    1396                 // заполнение списка сообщений 
    1397                 // ориентировочное время выполнения 111 ms (для топика 279396 - 5149 сообщений) 
    1398                 // основное время занимает присвоение данных полям (преобразование из QVariant в QSqlQuery) 
    1399                 AMessageInfoGUIPtrList list; 
    1400  
    1401                 if (storage->getTopicMessageList(m_current_forum.ID, info->ID, list, this, NULL) == false) 
    1402                 { 
    1403                         storage->showError(m_parent); 
    1404                         return; 
    1405                 } 
    1406  
    1407                 // постройка дерева, обход в ширину быстрее чем в высоту 
    1408                 // ориентировочное время выполнения 900 ms (для топика 279396 - 5149 сообщений) 
    1409                 // наиболее высокое дерево составляет 1555 сообщений (для топика 1099540) 
    1410                 // наиболее широкое дерево (глубина рекурсии) пока неизвестно 
    1411                 buildTree(info, &list); 
    1412  
    1413                 // для предотвращения повторной загрузки 
    1414                 info->IsChildLoaded = true; 
    1415  
    1416                 // раскрытие дерева до уровня непрочитаных топиков 
    1417                 if (info->UnreadChildCount != 0) 
    1418                         expandUnreadChild(item); 
    1419         } 
    1420 } 
    1421 //---------------------------------------------------------------------------------------------- 
    1422  
    1423 void AMessageTree::buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list) 
    1424 { 
    1425         if (list->count() == 0) 
    1426                 return; 
    1427  
    1428         int list_index = 0; 
    1429  
    1430         AGlobal* global = AGlobal::getInstance(); 
    1431  
    1432         while (list_index < list->count()) 
    1433         { 
    1434                 AMessageInfoGUI* info = list->at(list_index); 
    1435  
    1436                 if (info->IDParent == root->ID) 
    1437                 { 
    1438                         list->removeAt(list_index); 
    1439  
    1440                         info->IsInfoLoaded       = true; 
    1441                         info->IsChildLoaded      = true; 
    1442                         info->UnreadChildCount   = 0; 
    1443                         info->UnreadChildCountMy = 0; 
    1444  
    1445                         info->Item->setText(0, info->Subject); 
    1446  
    1447                         // TODO: сделать общую функцию формирования имени/ника 
    1448                         if (info->IDUser != 0) 
    1449                                 info->Item->setText(1, info->UserNick); 
    1450                         else 
    1451                                 info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 
    1452  
    1453                         info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 
    1454  
    1455                         root->Item->addChild(info->Item); 
    1456  
    1457                         // установка родителям свойств непрочитанных сообщений 
    1458                         if (info->IsRead == false && root->IDUser == m_me.ID) 
    1459                         { 
    1460                                 // сообщение не прочитано и это ответ не мне 
    1461                                 info->Item->setIcon(0, m_message_unread_my); 
    1462  
    1463                                 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 
    1464  
    1465                                 while (item_parent != NULL) 
    1466                                 { 
    1467                                         AMessageInfoGUI* info_parent = item_parent->pag(); 
    1468  
    1469                                         if (info_parent->HasUnreadChildMy != true) 
    1470                                         { 
    1471                                                 info_parent->HasUnreadChild   = true; 
    1472                                                 info_parent->HasUnreadChildMy = true; 
    1473  
    1474                                                 if (info_parent->IsRead == true) 
    1475                                                         item_parent->setIcon(0, m_child_unread_my); 
    1476                                                 else 
    1477                                                         item_parent->setIcon(0, m_message_unread_my); 
    1478                                         } 
    1479  
    1480                                         info_parent->UnreadChildCount++; 
    1481                                         info_parent->UnreadChildCountMy++; 
    1482  
    1483                                         item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
    1484  
    1485                                 }   // while (item_parent != NULL) 
    1486                         } 
    1487                         else if (info->IsRead == false) 
    1488                         { 
    1489                                 // сообщение не прочитано, но это ответ не мне 
    1490                                 info->Item->setIcon(0, m_message_unread); 
    1491  
    1492                                 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 
    1493  
    1494                                 while (item_parent != NULL) 
    1495                                 { 
    1496                                         AMessageInfoGUI* info_parent = item_parent->pag(); 
    1497  
    1498                                         if (info_parent->HasUnreadChild != true) 
    1499                                         { 
    1500                                                 info_parent->HasUnreadChild = true; 
    1501  
    1502                                                 if (info_parent->IsRead == true) 
    1503                                                         item_parent->setIcon(0, m_child_unread); 
    1504                                         } 
    1505  
    1506                                         info_parent->UnreadChildCount++; 
    1507  
    1508                                         item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 
    1509  
    1510                                 }   // while (item_parent != NULL) 
    1511                         } 
    1512                         else   // else if (info->IsRead == false) 
    1513                         { 
    1514                                 // сообщение прочитано 
    1515                                 info->Item->setIcon(0, m_message_read); 
    1516                         } 
    1517  
    1518                         // достройка дочерних веток для текущей 
    1519                         if (info->HasChild) 
    1520                         { 
    1521                                 buildTree(info, list); 
    1522                                 list_index = 0; 
    1523                         } 
    1524                 } 
    1525                 else   // if (info->ID == id_parent) 
    1526                 { 
    1527                         list_index++; 
    1528                 } 
    1529         } 
    1530 } 
    1531 //---------------------------------------------------------------------------------------------- 
    1532  
    1533 void AMessageTree::expandUnreadChild (QTreeWidgetItem* widget_item) 
    1534 { 
    1535         MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(widget_item); 
    1536  
    1537         if (item->pag()->UnreadChildCount != 0) 
    1538         { 
    1539                 for (int i = 0; i < item->childCount(); i++) 
    1540                         if (((MessageTreeWidgetItem*)item->child(i))->pag()->UnreadChildCount != 0) 
    1541                                 expandUnreadChild(item->child(i)); 
    1542  
    1543                 expandItem(item); 
    1544         } 
    1545 } 
    1546 //---------------------------------------------------------------------------------------------- 
    1547  
    1548 bool AMessageTree::markThreadAsRead (int id, bool is_read) 
    1549 { 
    1550         std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 
    1551  
    1552         if (storage.get() == NULL) 
    1553         { 
    1554                 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 
    1555                 return false; 
    1556         } 
    1557  
    1558         if (storage->setIDsAsRead(QList<int>() << id, idsTopic, is_read, QDateTime(), NULL) == false) 
    1559         { 
    1560                 storage->showError(m_parent); 
    1561                 return false; 
    1562         } 
    1563  
    1564         return true; 
    1565 } 
    1566 //---------------------------------------------------------------------------------------------- 
    1567  
    1568 void AMessageTree::menu_mark_thread_as_read_triggered () 
    1569 { 
    1570         QTreeWidgetItem* item = currentItem(); 
    1571  
    1572         if (item == NULL) 
    1573                 return; 
    1574  
    1575         // поиск родителя 
    1576         MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
    1577  
    1578         AMessageInfoGUI* info = parent->pag(); 
    1579  
    1580         // пометка в хранилище 
    1581         if (markThreadAsRead(info->ID, true) != true) 
    1582                 return; 
    1583  
    1584         // пометка в дереве 
    1585         if (info->IsChildLoaded == true) 
    1586         { 
    1587                 int count = 0; 
    1588  
    1589                 markThreadAsRead(parent, true, count); 
    1590  
    1591                 m_forum_tree->changeUnreadCount(-count); 
    1592         } 
    1593         else 
    1594         { 
    1595                 parent->setIcon(0, m_message_read); 
    1596  
    1597                 AMessageInfoGUI* info = parent->pag(); 
     1910                item->setIcon(0, m_message_read); 
    15981911 
    15991912                info->HasUnreadChild     = false; 
     
    16021915                info->UnreadChildCountMy = 0; 
    16031916 
    1604                 // поскольку дочерние элементы еще не загружены, 
    1605                 // обновление количества непрочитаных в дереве форума 
    1606                 m_forum_tree->reloadUnread(false); 
    1607         } 
    1608 } 
    1609 //---------------------------------------------------------------------------------------------- 
    1610  
    1611 void AMessageTree::menu_mark_thread_as_unread_triggered () 
    1612 { 
    1613         QTreeWidgetItem* item = currentItem(); 
    1614  
    1615         if (item == NULL) 
    1616                 return; 
    1617  
    1618         // поиск родителя 
    1619         MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 
    1620  
    1621         AMessageInfoGUI* info = parent->pag(); 
    1622  
    1623         // пометка в хранилище 
    1624         if (markThreadAsRead(info->ID, false) != true) 
    1625                 return; 
    1626  
    1627         // пометка в дереве 
    1628         if (info->IsChildLoaded == true) 
    1629         { 
    1630                 int count = 0; 
    1631  
    1632                 markThreadAsRead(parent, false, count); 
    1633  
    1634                 m_forum_tree->changeUnreadCount(count); 
    1635         } 
    1636         else 
    1637         { 
    1638                 parent->setIcon(0, m_message_unread); 
    1639  
    1640                 AMessageInfoGUI* info = parent->pag(); 
    1641  
    1642                 if (info->HasChild == true) 
     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 
    16431935                        info->HasUnreadChild = true; 
    1644                 else 
    1645                         info->HasUnreadChild = false; 
    1646  
    1647                 info->HasUnreadChildMy = false; 
    1648  
    1649                 // поскольку дочерние элементы еще не загружены, 
    1650                 // обновление количества непрочитаных в дереве форума 
    1651                 m_forum_tree->reloadUnread(false); 
    1652         } 
    1653 } 
    1654 //---------------------------------------------------------------------------------------------- 
    1655  
    1656 void AMessageTree::markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count) 
    1657 { 
    1658 } 
    1659 //---------------------------------------------------------------------------------------------- 
     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//---------------------------------------------------------------------------------------------- 
  • branches/message_tree/message_tree.h

    r189 r190  
    200200                bool markThreadAsRead (int id, bool is_read); 
    201201 
     202                /*! 
     203                 * \brief Загрузить сообщения к отправке 
     204                 */ 
     205                void loadMessage2Send (); 
     206 
     207                /*! 
     208                 * \brief Загрузить рейтинги к отправке 
     209                 */ 
     210                void loadRating2Send (); 
     211 
     212                /*! 
     213                 * \brief Загрузить модерилки к отправке 
     214                 */ 
     215                void loadModerate2Send (); 
     216 
    202217        // IMessageTree 
    203218        public: 
  • branches/message_tree/version.h

    r189 r190  
    2020 * \brief Дата билда (заменяется автоматически при каждом билде в version.h, что и приводит к смене номера ревизии) 
    2121 */ 
    22 #define AVALON_DATE "Птн Мар 27 20:01:36 MSK 2009" 
     22#define AVALON_DATE "Сбт Мар 28 03:12:39 MSK 2009" 
    2323 
    2424#endif 
Note: See TracChangeset for help on using the changeset viewer.