Changeset 182
- Timestamp:
- 03/24/09 21:51:11 (3 years ago)
- Location:
- branches/message_tree
- Files:
-
- 7 edited
-
message_tree.cpp (modified) (19 diffs)
-
message_tree.h (modified) (10 diffs)
-
model/message.h (modified) (1 diff)
-
storage/istorage.h (modified) (3 diffs)
-
storage/mysql_storage.cpp (modified) (8 diffs)
-
storage/mysql_storage.h (modified) (1 diff)
-
version.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/message_tree/message_tree.cpp
r181 r182 20 20 AMessageTree::AMessageTree (QWidget* parent, QWidget* form) : QTreeWidget (parent), IMessageTree () 21 21 { 22 // 23 // инициализация полей 24 // 25 22 26 m_parent = form; 23 27 m_forum_tree = 0; … … 33 37 m_current_forum.RateLimit = 0; 34 38 39 // 40 // инициализация GUI виджета 41 // 42 35 43 setFrameShadow(QFrame::Plain); 36 44 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); … … 47 55 headerItem()->setTextAlignment(1, Qt::AlignCenter); 48 56 headerItem()->setTextAlignment(2, Qt::AlignCenter); 57 58 // 59 // иконки 60 // 49 61 50 62 m_message_read = QIcon(":/icons/messageread.png"); … … 66 78 m_moderate = QIcon(":/icons/moderate.png"); 67 79 68 // меню 80 // 81 // контекстное меню (для основного дерева сообщений) 82 // 83 69 84 m_menu = new QMenu(this); 70 85 … … 88 103 m_menu_mark_thread_as_unread->setIcon(QIcon(":/icons/markpatrialasunread16.png")); 89 104 90 // спец-меню 105 // 106 // контекстное спец-меню (для оценок, модерилок и исходящих сообщений) 107 // 108 91 109 m_menu_special = new QMenu(this); 92 110 … … 120 138 m_menu_special_delete->setIcon(QIcon(":/icons/delete16.png")); 121 139 140 // 122 141 // события меню 142 // 143 123 144 connect(m_menu_reply, SIGNAL(triggered()), this, SLOT(menu_reply_triggered())); 124 145 connect(m_menu_mark_message_as_read, SIGNAL(triggered()), this, SLOT(menu_mark_message_as_read_triggered())); … … 127 148 connect(m_menu_mark_thread_as_unread, SIGNAL(triggered()), this, SLOT(menu_mark_thread_as_unread_triggered())); 128 149 150 // 129 151 // события спец-меню 152 // 153 130 154 connect(m_menu_special_delete, SIGNAL(triggered()), this, SLOT(menu_special_delete_triggered())); 131 155 connect(m_menu_special_edit, SIGNAL(triggered()), this, SLOT(menu_special_edit_triggered())); … … 139 163 connect(m_menu_special_minus, SIGNAL(triggered()), this, SLOT(menu_special_minus_triggered())); 140 164 141 // события дерева 165 // 166 // события виджета 167 // 168 142 169 connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(selection_changed())); 143 170 connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(expand_item(QTreeWidgetItem*))); … … 147 174 connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(vertical_scroll(int))); 148 175 176 // событие таймера отметки как прочитанное 149 177 connect(&m_timer, SIGNAL(timeout()), this, SLOT(timer_on_timer())); 150 178 } … … 159 187 { 160 188 QTreeWidget::resizeEvent(event); 189 190 // при ресайзе по высоте могут внизу появиться незагруженные топики 191 scrollTopics(); 161 192 } 162 193 //---------------------------------------------------------------------------------------------- … … 211 242 //---------------------------------------------------------------------------------------------- 212 243 213 void AMessageTree::expand_item (QTreeWidgetItem* item_expanded)214 {215 }216 //----------------------------------------------------------------------------------------------217 218 244 void AMessageTree::timer_on_timer () 219 245 { … … 328 354 bool AMessageTree::selectByPath (const QList<int>* path) 329 355 { 356 } 357 //---------------------------------------------------------------------------------------------- 358 359 AMessageInfoGUI* AMessageTree::createItem () 360 { 361 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 362 363 AMessageInfoGUI* info = item->pag(); 364 365 info->Item = item; 366 367 return info; 330 368 } 331 369 //---------------------------------------------------------------------------------------------- … … 405 443 406 444 // получение информации о себе 445 // TODO: вынести в AGlobal 407 446 QSettings settings; 408 447 … … 433 472 for (int i = 0; i < topic_list.count(); i++) 434 473 { 435 MessageTreeWidgetItem* item = new MessageTreeWidgetItem();436 437 474 // начальное заполнение дескриптора топика 438 AMessageInfoGUI* info = item->pag(); 439 440 info->ID = topic_list[i]; 441 info->Item = item; 442 443 items.append(item); 475 AMessageInfoGUI* info = createItem(); 476 477 info->ID = topic_list[i]; 478 479 items.append(info->Item); 444 480 } 445 481 … … 458 494 void AMessageTree::scrollTopics () 459 495 { 496 // Среднее время выполнения для дозагрузки одного элемента 10 ms 497 // Среднее время выполнения для дозагрузки страницы из 56 топиков (полный экран 1280х1024) 61 ms 498 460 499 // пустой форум или спец-группа 461 500 if (m_current_forum.ID == 0 || m_current_forum.IDGroup == SPECIAL_ID_GROUP) … … 470 509 471 510 if (top_item == NULL) 472 { 473 DEBUG_MSG("top_item == NULL"); 474 return; 475 } 511 return; // нет элементов в дереве(?) 476 512 477 513 top_item = ATreeWidgetItem::rootItem(top_item); 478 514 479 int from_index = indexOfTopLevelItem(top_item);515 int top_index = indexOfTopLevelItem(top_item); 480 516 481 517 // поиск корня нижнего видимого элемента в отображении 482 518 QTreeWidgetItem* bottom_item = itemAt(1, height() - 1); 483 519 484 int to_index;520 int bottom_index; 485 521 486 522 if (bottom_item == NULL) 487 to_index = topLevelItemCount();523 bottom_index = topLevelItemCount(); 488 524 else 489 525 { 490 526 bottom_item = ATreeWidgetItem::rootItem(bottom_item); 491 527 492 to_index = indexOfTopLevelItem(bottom_item) + 1;528 bottom_index = indexOfTopLevelItem(bottom_item) + 1; 493 529 } 494 530 … … 499 535 AMessageInfoGUIPtrList list; 500 536 501 while ( from_index < to_index)502 { 503 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem( from_index));537 while (top_index < bottom_index) 538 { 539 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(top_index)); 504 540 505 541 AMessageInfoGUI* info = item->pag(); … … 508 544 list.append(info); 509 545 510 from_index++;546 top_index++; 511 547 } 512 548 … … 578 614 } 579 615 //---------------------------------------------------------------------------------------------- 616 617 void AMessageTree::expand_item (QTreeWidgetItem* item_expanded) 618 { 619 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(item_expanded); 620 621 AMessageInfoGUI* info = item->pag(); 622 623 if (info->HasChild == true && info->IsChildLoaded == false) 624 { 625 // получение хранилища 626 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 627 628 if (storage.get() == NULL) 629 { 630 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 631 return; 632 } 633 634 // заполнение списка сообщений 635 AMessageInfoGUIPtrList list; 636 637 if (storage->getTopicMessageList(info->ID, list, this, m_me.ID, NULL) == false) 638 { 639 storage->showError(m_parent); 640 return; 641 } 642 643 // постройка дерева 644 buildTree(info, &list); 645 646 // для предотвращения повторной загрузки TODO 647 //info->IsChildLoaded = true; 648 649 /* 650 // раскрытие дерева до уровня непрочитаных топиков 651 if (item->pag()->UnreadChildCount != 0) 652 expandUnreadChild(item); 653 */ 654 } 655 } 656 //---------------------------------------------------------------------------------------------- 657 658 void AMessageTree::buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list) 659 { 660 } 661 //---------------------------------------------------------------------------------------------- -
branches/message_tree/message_tree.h
r181 r182 18 18 */ 19 19 class AMessageTree : 20 public QTreeWidget, // стандартное дерево Qt 21 public IMessageTree // интерфес для взаимодействия со списком форумов и отображением сообщения 20 public QTreeWidget, // стандартное дерево Qt 21 public IMessageTree, // интерфес для взаимодействия со списком форумов и отображением сообщения 22 private IMessageInfoGUIFactory // интерфейс фабрики создания элементов дерева 22 23 { 23 24 Q_OBJECT … … 76 77 IFormMain* m_main_form; /*!< \brief Интерфейс главной формы */ 77 78 79 // 78 80 // иконки для отображения статусов сообщений 81 // 82 79 83 QIcon m_message_read; /*!< \brief Сообщение прочитано */ 80 84 QIcon m_child_unread; /*!< \brief Есть непрочитанные дочерние сообщения */ … … 83 87 QIcon m_message_unread_my; /*!< \brief В ветке есть сообщение для меня */ 84 88 89 // 85 90 // иконки для отображения оценок 91 // 92 86 93 QIcon m_rating_plus_1; /*!< \brief "+1" */ 87 94 QIcon m_rating_1; /*!< \brief "1" */ … … 100 107 101 108 /*! 102 * \brief Высплывающее меню109 * \brief Основное контекстное меню (для основного дерева сообщений) 103 110 */ 104 111 QMenu* m_menu; … … 111 118 112 119 /*! 113 * \brief Высплывающее меню в спец-фоорумах120 * \brief Контекстное меню в спец-фоорумах (оценки, модерилки, исходящие сообщения) 114 121 */ 115 122 QMenu* m_menu_special; … … 138 145 void scrollTopics (); 139 146 147 /*! 148 * \brief Построение дерева (топика) из списка элементов 149 * \param root Родительский элемент 150 * \param list Список дочерних элементов для построения 151 */ 152 void buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list); 153 140 154 // IMessageTree 141 155 public: … … 153 167 bool selectByPath (const QList<int>* path); 154 168 169 // IMessageInfoGUIFactory 170 private: 171 172 AMessageInfoGUI* createItem (); 173 155 174 private slots: 156 175 … … 171 190 172 191 /*! 173 * \brief Двойной клик 192 * \brief Двойной клик (редактирование) 174 193 */ 175 194 void item_double_clicked (QTreeWidgetItem* item, int column); … … 185 204 void context_menu_request (const QPoint& pos); 186 205 187 // меню 206 // 207 // Основное контекстное меню 208 // 209 188 210 void menu_reply_triggered (); /*!< \brief Ответить */ 189 211 void menu_mark_message_as_read_triggered (); /*!< \brief Пометить сообщение как прочитанное */ … … 193 215 194 216 // 195 // Специальное меню217 // Специальное контекстное меню 196 218 // 197 219 -
branches/message_tree/model/message.h
r181 r182 121 121 122 122 /*! 123 * \brief Интерфейс для фабрики элементов дерева отображения сообщений (см. IAStorage::getTopicMessageList) 124 * Необходим для уменьшения расходов врмени на копирование информации при загрузке большого топика 125 */ 126 class IMessageInfoGUIFactory 127 { 128 public: 129 130 /*! 131 * \brief Метод для создания GUI-элемента дерева сообщений 132 * \return Указатель на готовый к заполнению данными элемент (поле Item устанавливается в валидное при создании) 133 */ 134 virtual AMessageInfoGUI* createItem () = 0; 135 }; 136 137 /*! 123 138 * \brief Сообщение к отправке 124 139 */ -
branches/message_tree/storage/istorage.h
r181 r182 17 17 18 18 /*! 19 * \brief Типы множеств для групповой обработки (см. IAStorage:: SetIDsAsRead и IAStorage::Unsubscribe).19 * \brief Типы множеств для групповой обработки (см. IAStorage::setIDsAsRead и IAStorage::unsubscribe). 20 20 */ 21 21 typedef enum AIDSet … … 137 137 /*! 138 138 * \brief Заполняет информацию о топиках 139 * Поля списка (кроме ID и Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI ()) и не меняются без необходимости.139 * Поля списка (кроме ID и Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) и не меняются без необходимости. 140 140 * Функция должна заполнить все поля AMessageInfo плюс установить флаги IsRead, HasUnreadChild, HasUnreadChildMy в актуальные значения. 141 * Функция НЕ должна устанавливать флаг IsInfoLoaded (устанавливается вызвающим кодом) 141 * Функция НЕ должна устанавливать флаг IsInfoLoaded (устанавливается вызвающим кодом). 142 142 * \param list Список топиков (с установленным полем ID, по которому будет производиться дальнейшее заполнение информацией). 143 * \param id_me ID текущего пользователя 143 * \param id_me ID текущего пользователя avalon. 144 144 * \param progress Прогресс выполнения операции. 145 145 */ … … 147 147 148 148 /*! 149 * \brief Возвращает список _всех_ сообщений в топике (родительской ветке) за исключением тел самих сообщений, 150 * тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 149 * \brief Заполняет информацию о всех сообщениях в топике (родительской ветке). 150 * Функция должна заполнить все поля AMessageInfoGUI кроме (TODO) (которые устанавливаются вызвающим кодом), 151 * body - тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 151 152 * \param id_topic ID топика (темы, родительской ветки). 152 * \param list Список сообщений. 153 * \param id_me ID текущего пользователя 154 * \param progress Прогресс выполнения операции. 155 */ 156 virtual bool getTopicMessageList (int id_topic, AMessageInfoGUIList& list, int id_me, IProgress* progress = NULL) = 0; 153 * \param list Список сообщений (изначально пустой, на выходе заполненый). 154 * \param factory Фабрика для создания элементов (каждый элемент списка создается вызовом IMessageInfoGUIFactory::createItem), 155 * поля (кроме Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) и не меняются без необходимости. 156 * \param id_me ID текущего пользователя avalon. 157 * \param progress Прогресс выполнения операции. 158 */ 159 virtual bool getTopicMessageList (int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, int id_me, IProgress* progress = NULL) = 0; 157 160 158 161 /*! -
branches/message_tree/storage/mysql_storage.cpp
r181 r182 1836 1836 sql += " `id_forum` = " + QString::number(id_forum) + "\n"; 1837 1837 sql += "ORDER BY\n"; 1838 1839 1838 // поскльку id_message автоинкремент и растет вместе с датой, то 1840 1839 // можно условно положиться на то, что бОльшему id_message соответствует 1841 1840 // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 1842 1841 //sql += " `message_date` DESC"; 1843 1844 1842 sql += " `id_message` DESC"; 1845 1843 … … 2120 2118 //---------------------------------------------------------------------------------------------- 2121 2119 2122 bool AMySQLStorage::getTopicMessageList (int id_topic, AMessageInfoGUI List& list, int id_me, IProgress* progress)2120 bool AMySQLStorage::getTopicMessageList (int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, int id_me, IProgress* progress) 2123 2121 { 2124 /* 2122 2125 2123 if (progress != NULL) 2126 2124 progress->onProgress(0); … … 2154 2152 sql += " `id_topic` = " + QString::number(id_topic) + "\n"; 2155 2153 sql += "ORDER BY\n"; 2156 sql += " `message_date` DESC"; 2154 // поскльку id автоинкремент и растет вместе с датой, то 2155 // можно условно положиться на то, что бОльшему id_message соответствует 2156 // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 2157 //sql += " `message_date` DESC"; 2158 sql += " `id` DESC"; 2157 2159 2158 2160 std::auto_ptr<AQuery> query_select(createQuery(sql, false)); … … 2160 2162 if (query_select.get() == NULL) 2161 2163 return returnError(AMySQLDatabase::getLastError()); 2164 2165 query_select->setForwardOnly(true); 2162 2166 2163 2167 if (query_select->exec() == false) … … 2166 2170 while (query_select->next()) 2167 2171 { 2168 ATopicInfo info; 2169 2170 info.ID = query_select->value(0).toInt(); 2171 info.IDTopic = query_select->value(1).toInt(); 2172 info.IDParent = query_select->value(2).toInt(); 2173 info.IDUser = query_select->value(3).toInt(); 2174 info.IDForum = query_select->value(4).toInt(); 2175 info.Subject = query_select->value(5).toString(); 2176 info.MessageName = query_select->value(6).toString(); 2177 info.UserNick = query_select->value(7).toString(); 2178 info.IDArticle = query_select->value(8).toInt(); 2179 info.MessageDate = query_select->value(9).toDateTime(); 2180 info.UpdateDate = query_select->value(10).toDateTime(); 2181 info.UserRole = query_select->value(11).toString(); 2182 info.UserTitle = query_select->value(12).toString(); 2183 info.UserTitleColor = query_select->value(13).toInt(); 2184 info.LastModerated = query_select->value(14).toDateTime(); 2185 info.HasChild = query_select->value(15).toInt(); 2186 2187 info.IsRead = true; 2188 info.HasUnreadChild = 0; 2172 AMessageInfoGUI* info = factory->createItem(); 2173 2174 info->ID = query_select->value(0).toInt(); 2175 info->IDTopic = query_select->value(1).toInt(); 2176 info->IDParent = query_select->value(2).toInt(); 2177 info->IDUser = query_select->value(3).toInt(); 2178 info->IDForum = query_select->value(4).toInt(); 2179 info->Subject = query_select->value(5).toString(); 2180 info->MessageName = query_select->value(6).toString(); 2181 info->UserNick = query_select->value(7).toString(); 2182 info->IDArticle = query_select->value(8).toInt(); 2183 info->MessageDate = query_select->value(9).toDateTime(); 2184 info->UpdateDate = query_select->value(10).toDateTime(); 2185 info->UserRole = query_select->value(11).toString(); 2186 info->UserTitle = query_select->value(12).toString(); 2187 info->UserTitleColor = query_select->value(13).toInt(); 2188 info->LastModerated = query_select->value(14).toDateTime(); 2189 info->HasChild = query_select->value(15).toInt(); 2189 2190 2190 2191 list.append(info); … … 2211 2212 return returnError(AMySQLDatabase::getLastError()); 2212 2213 2214 query_select_unread->setForwardOnly(true); 2215 2213 2216 if (query_select_unread->exec() == false) 2214 2217 return returnError(query_select_unread->getLastError()); … … 2223 2226 { 2224 2227 if (id_parent_user == id_me) 2225 list[i].HasUnreadChild = 2; 2226 2227 list[i].IsRead = false; 2228 //list.move(i, 0); 2228 list[i]->HasUnreadChild = 2; 2229 2230 list[i]->IsRead = false; 2231 2232 list.move(i, 0); 2233 2229 2234 break; 2230 2235 } … … 2232 2237 2233 2238 return returnSuccess(); 2234 */2235 returnError(QString::fromUtf8("AMySQLStorage::getTopicMessageList"));2236 2239 } 2237 2240 //---------------------------------------------------------------------------------------------- -
branches/message_tree/storage/mysql_storage.h
r181 r182 58 58 bool getForumTopicList (int id_forum, int count, QList<int>& list, IProgress* progress = NULL); 59 59 bool getTopicInfoList (AMessageInfoGUIPtrList& list, int id_me, IProgress* progress = NULL); 60 bool getTopicMessageList (int id_topic, AMessageInfoGUI List& list, int id_me, IProgress* progress = NULL);60 bool getTopicMessageList (int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, int id_me, IProgress* progress = NULL); 61 61 bool getMessageBody (int id_message, QString& body, IProgress* progress = NULL); 62 62 bool setIDsAsRead (const QList<int>& list, AIDSet type, bool read, QDateTime date, IProgress* progress = NULL); -
branches/message_tree/version.h
r181 r182 20 20 * \brief Дата билда (заменяется автоматически при каждом билде в version.h, что и приводит к смене номера ревизии) 21 21 */ 22 #define AVALON_DATE " Пнд Мар 23 20:37:20MSK 2009"22 #define AVALON_DATE "Втр Мар 24 20:28:25 MSK 2009" 23 23 24 24 #endif
Note: See TracChangeset
for help on using the changeset viewer.
