Changeset 191
- Timestamp:
- 03/28/09 04:25:07 (3 years ago)
- Files:
-
- 1 deleted
- 15 edited
-
branches/message_tree (deleted)
-
trunk/dev/doxygen.sh (modified) (1 diff)
-
trunk/form_message.cpp (modified) (2 diffs)
-
trunk/form_message.h (modified) (2 diffs)
-
trunk/forum_tree.cpp (modified) (2 diffs)
-
trunk/global.cpp (modified) (1 diff)
-
trunk/global.h (modified) (1 diff)
-
trunk/message_tree.cpp (modified) (50 diffs)
-
trunk/message_tree.h (modified) (12 diffs)
-
trunk/model/message.h (modified) (2 diffs)
-
trunk/storage/istorage.h (modified) (2 diffs)
-
trunk/storage/mysql_storage.cpp (modified) (22 diffs)
-
trunk/storage/mysql_storage.h (modified) (1 diff)
-
trunk/sysheaders.h (modified) (3 diffs)
-
trunk/version.h (modified) (1 diff)
-
trunk/webservice.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/dev/doxygen.sh
r119 r191 13 13 14 14 doxygen doxygen/doxygen.conf 15 16 kfmclient exec file:$(pwd)/doxygen/html/index.html -
trunk/form_message.cpp
r172 r191 10 10 //---------------------------------------------------------------------------------------------- 11 11 12 FormMessage::FormMessage (QWidget* parent, bool is_reply, const A TopicInfo& info, int edit_id) : FormMessageUI (parent)12 FormMessage::FormMessage (QWidget* parent, bool is_reply, const AMessageInfoGUI& info, int edit_id) : FormMessageUI (parent) 13 13 { 14 14 if (edit_id != 0) … … 264 264 AMessageInfo info; 265 265 266 // TODO: убрать заполнение лишних полей 266 267 info.ID = 0; 267 268 info.IDTopic = 0; -
trunk/form_message.h
r147 r191 32 32 * \param edit_id ID редактирования существующего сообщения к отправке 33 33 */ 34 FormMessage (QWidget* parent, bool is_reply, const A TopicInfo& info, int edit_id = 0);34 FormMessage (QWidget* parent, bool is_reply, const AMessageInfoGUI& info, int edit_id = 0); 35 35 ~FormMessage (); 36 36 … … 55 55 * \brief Текущее редактируемое сообщение. 56 56 */ 57 A TopicInfom_info;57 AMessageInfoGUI m_info; 58 58 59 59 /*! -
trunk/forum_tree.cpp
r152 r191 814 814 return; 815 815 816 ATopicInfo info; 817 816 AMessageInfoGUI info; 817 818 // TODO: убрать заполнение лишних полей 818 819 info.ID = 0; 819 820 info.IDTopic = 0; … … 832 833 info.UserTitleColor = 0; 833 834 info.LastModerated = QDateTime(); 834 info.IsRead = false;835 /*info.IsRead = false; 835 836 info.HasChild = false; 836 info.HasUnreadChild = false; 837 info.HasUnreadChild = false;*/ // TODO: 837 838 838 839 FormMessage* form = new FormMessage(NULL, false, info); -
trunk/global.cpp
r162 r191 24 24 25 25 reload(); 26 27 AnonymousName = QString::fromUtf8("Аноним"); 28 DateFormat = "dd.MM.yyyy hh:mm:ss"; 26 29 } 27 30 //---------------------------------------------------------------------------------------------- -
trunk/global.h
r159 r191 42 42 int SynchronizeInterval; /*!< \brief Интервал синхронизации (минут) */ 43 43 AColorer Colorer; /*!< \brief Движок подсветки синтаксиса */ 44 45 // 46 // Константы 47 // 48 49 QString AnonymousName; /*!< \brief Отображаемое имя анонима */ 50 QString DateFormat; /*!< \brief Формат даты/времени */ 44 51 }; 45 52 -
trunk/message_tree.cpp
r175 r191 5 5 // $URL$ 6 6 //---------------------------------------------------------------------------------------------- 7 #include "parser.h" 7 #include "message_tree.h" 8 //---------------------------------------------------------------------------------------------- 8 9 #include "global.h" 9 #include " model/all.h"10 #include "form_source.h" 10 11 #include "icon_effect.h" 11 #include "form_source.h"12 12 #include "form_message.h" 13 13 #include "form_moderate.h" 14 #include "message_tree.h"15 14 #include "tree_widget_item.h" 16 15 #include "storage/storage_factory.h" 17 16 //---------------------------------------------------------------------------------------------- 18 17 /*! 19 * \brief Элемент, который хранится в каждой ноде дерева 20 */ 21 typedef struct AMessageInfoGUI 22 { 23 ATopicInfo Info; /*!< \brief Дескриптор сообщения */ 24 bool IsInfoLoaded; /*!< \brief Флаг наличия загрузки информации (актуально только для топиков) */ 25 bool IsChildLoaded; /*!< \brief Флаг того, что загружены дочерние сообщения (актуально только для топиков) */ 26 int UnreadChildCount; /*!< \brief Количество непрочитанных дочерних сообщений */ 27 bool IsBodyLoaded; /*!< \brief Загружено ли тело сообщения */ 28 int Special; /*!< \brief Спец-данные */ 29 } AMessageInfoGUI; 30 //---------------------------------------------------------------------------------------------- 31 /*! 32 * \brief Элемент для дерева группы форумов с информацией о группе 18 * \brief Элемент для дерева сообщений 33 19 */ 34 20 typedef ATreeWidgetItemT<AMessageInfoGUI> MessageTreeWidgetItem; … … 37 23 AMessageTree::AMessageTree (QWidget* parent, QWidget* form) : QTreeWidget (parent), IMessageTree () 38 24 { 25 // 26 // инициализация полей 27 // 28 39 29 m_parent = form; 40 30 m_forum_tree = 0; 41 31 m_message_view = 0; 42 32 m_main_form = 0; 43 m_id_group = 0; 44 m_id_forum = 0; 45 m_me.ID = -1; 33 34 m_me.ID = 0; 35 36 m_current_forum.ID = 0; 37 m_current_forum.IDGroup = 0; 38 m_current_forum.Rated = false; 39 m_current_forum.InTop = false; 40 m_current_forum.RateLimit = 0; 41 42 // 43 // инициализация GUI виджета 44 // 46 45 47 46 setFrameShadow(QFrame::Plain); … … 59 58 headerItem()->setTextAlignment(1, Qt::AlignCenter); 60 59 headerItem()->setTextAlignment(2, Qt::AlignCenter); 60 61 // 62 // иконки 63 // 61 64 62 65 m_message_read = QIcon(":/icons/messageread.png"); … … 78 81 m_moderate = QIcon(":/icons/moderate.png"); 79 82 80 // меню 83 // 84 // контекстное меню (для основного дерева сообщений) 85 // 86 81 87 m_menu = new QMenu(this); 82 88 … … 100 106 m_menu_mark_thread_as_unread->setIcon(QIcon(":/icons/markpatrialasunread16.png")); 101 107 102 // спец-меню 108 // 109 // контекстное спец-меню (для оценок, модерилок и исходящих сообщений) 110 // 111 103 112 m_menu_special = new QMenu(this); 104 113 … … 132 141 m_menu_special_delete->setIcon(QIcon(":/icons/delete16.png")); 133 142 143 // 134 144 // события меню 145 // 146 135 147 connect(m_menu_reply, SIGNAL(triggered()), this, SLOT(menu_reply_triggered())); 136 148 connect(m_menu_mark_message_as_read, SIGNAL(triggered()), this, SLOT(menu_mark_message_as_read_triggered())); … … 139 151 connect(m_menu_mark_thread_as_unread, SIGNAL(triggered()), this, SLOT(menu_mark_thread_as_unread_triggered())); 140 152 153 // 141 154 // события спец-меню 155 // 156 142 157 connect(m_menu_special_delete, SIGNAL(triggered()), this, SLOT(menu_special_delete_triggered())); 143 158 connect(m_menu_special_edit, SIGNAL(triggered()), this, SLOT(menu_special_edit_triggered())); … … 151 166 connect(m_menu_special_minus, SIGNAL(triggered()), this, SLOT(menu_special_minus_triggered())); 152 167 153 // события дерева 168 // 169 // события виджета 170 // 171 154 172 connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(selection_changed())); 155 173 connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(expand_item(QTreeWidgetItem*))); … … 159 177 connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(vertical_scroll(int))); 160 178 179 // событие таймера отметки как прочитанное 161 180 connect(&m_timer, SIGNAL(timeout()), this, SLOT(timer_on_timer())); 162 181 } … … 170 189 void AMessageTree::resizeEvent (QResizeEvent* event) 171 190 { 191 QTreeWidget::resizeEvent(event); 192 193 // при ресайзе по высоте могут внизу появиться незагруженные топики 172 194 scrollTopics(); 173 174 QTreeWidget::resizeEvent(event);175 195 } 176 196 //---------------------------------------------------------------------------------------------- … … 218 238 if (currentItem() != NULL) 219 239 { 220 if (m_ id_group != SPECIAL_ID_GROUP)240 if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 221 241 m_menu->exec(viewport()->mapToGlobal(pos)); 222 242 else 223 243 { 224 if (m_ id_forum== SPECIAL_ID_FORUM_MESSAGE2SEND ||225 m_ id_forum== SPECIAL_ID_FORUM_MODERATE2SEND)244 if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 245 m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 226 246 { 227 247 m_menu_special_edit->setVisible(true); … … 270 290 else 271 291 { 272 setCurrentItem(topLevelItem(topLevelItemCount() - 1)); 273 274 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 292 // последний топик в списке 293 MessageTreeWidgetItem* topic_item = static_cast<MessageTreeWidgetItem*>(topLevelItem(topLevelItemCount() - 1)); 275 294 276 295 // если элемент еще не загружен, то загружаем 277 if (item->pag()->IsInfoLoaded == false) 278 setCurrentItem(item); 279 280 while (true) 281 { 282 item->setExpanded(true); 283 284 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastChild(item)); 285 286 if (item != NULL) 287 setCurrentItem(item); 288 else 289 break; 290 } 296 if (topic_item->pag()->IsInfoLoaded == false) 297 setCurrentItem(topic_item); 298 299 // если дочерние элементы еще не загружены, то загружаем 300 if (topic_item->pag()->IsChildLoaded == false) 301 topic_item->setExpanded(true); 302 303 // выделяем последний лист в топике 304 MessageTreeWidgetItem* last_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::lastLeaf(topic_item)); 305 306 setCurrentItem(last_item); 291 307 } 292 308 … … 297 313 void AMessageTree::changeForum (const AForumInfo* forum_info) 298 314 { 299 m_id_group = 0; 300 m_id_forum = 0; 301 m_me.ID = -1; 302 m_forum_rated = false; 315 // 316 // базовая очистка 317 // 318 319 m_current_forum.ID = 0; 320 m_current_forum.IDGroup = 0; 321 m_current_forum.ShortName = ""; 322 m_current_forum.Name = ""; 323 m_current_forum.Rated = false; 324 m_current_forum.InTop = false; 325 m_current_forum.RateLimit = 0; 326 327 m_me.ID = 0; 328 m_me.Name = ""; 329 m_me.Nick = ""; 330 m_me.RealName = ""; 331 m_me.Email = ""; 332 m_me.Homepage = ""; 333 m_me.Specialization = ""; 334 m_me.WhereFrom = ""; 335 m_me.Origin = ""; 303 336 304 337 if (m_main_form != NULL) … … 323 356 } 324 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 325 370 // вывод наименования форума в хедер 326 headerItem()->setText(0, forum_info->Name); 371 headerItem()->setText(0, m_current_forum.Name); 372 373 // 374 // загрузка топиков в зависимости от типа форума 375 // 327 376 328 377 // получение хранилища … … 336 385 337 386 // получение информации о себе 387 // TODO: вынести в AGlobal 338 388 QSettings settings; 339 389 340 390 m_me.Name = settings.value("rsdn/login", "").toString(); 341 391 342 storage->whoAmI(m_me, NULL); 392 if (storage->whoAmI(m_me, NULL) == false) 393 m_me.Name = ""; 343 394 344 395 // если группа форумов обыкновенная 345 if ( forum_info->IDGroup != SPECIAL_ID_GROUP)396 if (m_current_forum.IDGroup != SPECIAL_ID_GROUP) 346 397 { 347 398 // получение топиков 399 // ориентировочное время выполнения 68 ms (для форума NET, 28199 топиков) 400 // основное время занимает запрос данных из хранилища 348 401 QList<int> topic_list; 349 402 350 if (storage->getForumTopicList( forum_info->ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false)403 if (storage->getForumTopicList(m_current_forum.ID, AGlobal::getInstance()->MaxTopicToShow, topic_list, NULL) == false) 351 404 { 352 405 storage->showError(m_parent); … … 355 408 356 409 // установка топиков 410 // ориентировочное время выполнения 50 ms (для форума NET, 28199 топиков) 411 // основное время занимает создание объекта MessageTreeWidgetItem 357 412 QList<QTreeWidgetItem*> items; 358 413 359 414 for (int i = 0; i < topic_list.count(); i++) 360 415 { 361 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 362 363 AMessageInfoGUI* info = item->pag(); 364 365 info->Info.ID = topic_list[i]; 366 info->IsInfoLoaded = false; 367 info->IsChildLoaded = false; 368 info->UnreadChildCount = 0; 369 info->IsBodyLoaded = false; 370 info->Special = 0; 371 372 items.append(item); 373 } 374 375 // сохраняем для скролла 376 m_id_group = forum_info->IDGroup; 377 m_id_forum = forum_info->ID; 378 m_forum_rated = forum_info->Rated; 379 380 // отображение 416 // начальное заполнение дескриптора топика 417 AMessageInfoGUI* info = createItem(); 418 419 info->ID = topic_list[i]; 420 421 items.append(info->Item); 422 } 423 424 // отображение на виджет 381 425 addTopLevelItems(items); 382 426 383 // загрузка видимых топиков427 // дозагрузка информации о топиках, находящихся в видимой области отображения 384 428 scrollTopics(); 385 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 443 void AMessageTree::vertical_scroll (int /*value*/) 444 { 445 scrollTopics(); 446 } 447 //---------------------------------------------------------------------------------------------- 448 449 void 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(); 386 479 else 387 480 { 388 m_id_group = forum_info->IDGroup; 389 m_id_forum = forum_info->ID; 390 m_forum_rated = forum_info->Rated; 391 392 // специальная группа форумов 393 if (m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND) 394 loadMessage2Send(); 395 else if (m_id_forum == SPECIAL_ID_FORUM_RATING2SEND) 396 loadRating2Send(); 397 else if (m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND) 398 loadModerate2Send(); 399 } 400 } 401 //---------------------------------------------------------------------------------------------- 402 403 void AMessageTree::vertical_scroll (int /*value*/) 404 { 405 scrollTopics(); 406 } 407 //---------------------------------------------------------------------------------------------- 408 409 void AMessageTree::scrollTopics () 410 { 411 // пустой форум или спец-группа 412 if (m_id_forum == 0 || m_id_group == SPECIAL_ID_GROUP) 413 return; 414 415 // верхний видимый элемент 416 QTreeWidgetItem* top_item = itemAt(1, 5); 417 418 if (top_item == NULL) 419 return; 420 421 while (top_item->parent() != NULL) 422 top_item = top_item->parent(); 423 424 int from_index = indexOfTopLevelItem(top_item); 425 426 // нижний видимый элемент 427 QTreeWidgetItem* bottom_item = itemAt(1, height() - 5); 428 429 int to_index = topLevelItemCount(); 430 431 if (bottom_item != NULL) 432 { 433 while (bottom_item->parent() != NULL) 434 bottom_item = bottom_item->parent(); 435 436 to_index = indexOfTopLevelItem(bottom_item) + 1; 437 438 if (to_index < from_index) 439 to_index = from_index + 100; // ~56 элементов влезет по высоте на стандартный экран 1280x1024 440 441 if (to_index > topLevelItemCount()) 442 to_index = topLevelItemCount(); 443 } 444 445 // поиск еще не агруженных элементов 446 ATopicInfoList list; 447 QList<MessageTreeWidgetItem*> items; 448 449 while (from_index < to_index) 450 { 451 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(from_index)); 452 453 if (item->pag()->IsInfoLoaded == false) 454 { 455 ATopicInfo info; 456 457 info.ID = item->pag()->Info.ID; 458 481 bottom_item = ATreeWidgetItem::rootItem(bottom_item); 482 483 bottom_index = indexOfTopLevelItem(bottom_item) + 1; 484 } 485 486 // 487 // Поиск еще не загруженных топиков в диапазоне 488 // 489 490 AMessageInfoGUIPtrList list; 491 492 while (top_index < bottom_index) 493 { 494 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(top_index)); 495 496 AMessageInfoGUI* info = item->pag(); 497 498 if (info->IsInfoLoaded == false) 459 499 list.append(info); 460 items.append(item); 461 } 462 463 from_index++; 464 } 465 500 501 top_index++; 502 } 503 504 // 466 505 // загрузка топиков, которые не загружены 467 if (list.count() > 0) 506 // 507 508 if (list.count() == 0) 509 return; 510 511 // получение хранилища 512 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 513 514 if (storage.get() == NULL) 515 { 516 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 517 return; 518 } 519 520 if (storage->getTopicInfoList(m_current_forum.ID, list, m_me.ID, NULL) == false) 521 { 522 storage->showError(m_parent); 523 return; 524 } 525 526 AGlobal* global = AGlobal::getInstance(); 527 528 // 529 // Установка загруженой информации 530 // 531 532 for (int i = 0; i < list.count(); i++) 533 { 534 AMessageInfoGUI* info = list[i]; 535 536 info->IsInfoLoaded = true; 537 info->UnreadChildCount = 0; 538 info->UnreadChildCountMy = 0; 539 540 info->Item->setText(0, info->Subject); 541 542 // TODO: сделать общую функцию формирования имени/ника 543 if (info->IDUser == 0) 544 info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 545 else 546 info->Item->setText(1, info->UserNick); 547 548 info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 549 550 if (info->HasChild == true) 551 info->Item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 552 553 if (info->IsRead == true) 554 { 555 if (info->HasUnreadChildMy) 556 info->Item->setIcon(0, m_child_unread_my); 557 else if (info->HasUnreadChild) 558 info->Item->setIcon(0, m_child_unread); 559 else 560 info->Item->setIcon(0, m_message_read); 561 } 562 else 563 { 564 if (info->HasUnreadChildMy) 565 info->Item->setIcon(0, m_message_unread_my); 566 else 567 info->Item->setIcon(0, m_message_unread); 568 } 569 } 570 } 571 //---------------------------------------------------------------------------------------------- 572 573 void 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) 468 581 { 469 582 // получение хранилища … … 476 589 } 477 590 478 if (storage->getTopicInfoList(list, m_me.ID, NULL) == false) 591 // заполнение списка сообщений 592 // ориентировочное время выполнения 111 ms (для топика 279396 - 5149 сообщений) 593 // основное время занимает присвоение данных полям (преобразование из QVariant в QSqlQuery) 594 AMessageInfoGUIPtrList list; 595 596 if (storage->getTopicMessageList(m_current_forum.ID, info->ID, list, this, NULL) == false) 479 597 { 480 598 storage->showError(m_parent); … … 482 600 } 483 601 484 // заполнение вновь загруженных топиков 485 for (int i = 0; i < list.count(); i++) 486 { 487 ATopicInfo info = list[i]; 488 MessageTreeWidgetItem* item = items[i]; 489 490 AMessageInfoGUI* item_info = item->pag(); 491 492 item_info->Info = info; 493 item_info->IsInfoLoaded = true; 494 item_info->IsChildLoaded = false; 495 item_info->UnreadChildCount = 0; 496 item_info->IsBodyLoaded = false; 497 item_info->Special = 0; 498 499 item->setText(0, info.Subject); 500 501 if (info.IDUser == 0) 502 item->setText(1, QString::fromUtf8("Аноним")); 503 else 504 item->setText(1, info.UserNick); 505 506 item->setText(2, info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 507 508 if (info.IsRead == true) 509 { 510 if (info.HasUnreadChild != 0) 511 { 512 if (info.HasUnreadChild == 2) 513 item->setIcon(0, m_child_unread_my); 514 else 515 item->setIcon(0, m_child_unread); 516 } 517 else 518 item->setIcon(0, m_message_read); 519 } 520 else 521 { 522 if (info.HasUnreadChild == 2) 523 item->setIcon(0, m_message_unread_my); 524 else 525 item->setIcon(0, m_message_unread); 526 } 527 528 if (info.HasChild == true) 529 item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); 530 } 531 } 532 } 533 //---------------------------------------------------------------------------------------------- 534 535 void AMessageTree::expand_item (QTreeWidgetItem* item_expanded) 536 { 537 if (item_expanded == NULL) 538 return; 539 540 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(item_expanded); 541 542 if (item->pag()->Info.HasChild == true && item->pag()->IsChildLoaded == false) 543 { 544 // получение хранилища 545 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 546 547 if (storage.get() == NULL) 548 { 549 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 550 return; 551 } 552 553 // получение сообщений 554 ATopicInfoList list; 555 556 if (storage->getTopicMessageList(item->pag()->Info.ID, list, m_me.ID, NULL) == false) 557 { 558 storage->showError(m_parent); 559 return; 560 } 561 562 // постройка дерева 563 buildTree(item, &list); 602 // постройка дерева, обход в ширину быстрее чем в высоту 603 // ориентировочное время выполнения 900 ms (для топика 279396 - 5149 сообщений) 604 // наиболее высокое дерево составляет 1555 сообщений (для топика 1099540) 605 // наиболее широкое дерево (глубина рекурсии) пока неизвестно 606 buildTree(info, &list); 564 607 565 608 // для предотвращения повторной загрузки 566 i tem->pag()->IsChildLoaded = true;609 info->IsChildLoaded = true; 567 610 568 611 // раскрытие дерева до уровня непрочитаных топиков 569 if (i tem->pag()->UnreadChildCount != 0)612 if (info->UnreadChildCount != 0) 570 613 expandUnreadChild(item); 571 614 } … … 588 631 //---------------------------------------------------------------------------------------------- 589 632 590 void AMessageTree::buildTree (QTreeWidgetItem* parent, ATopicInfoList* list) 591 { 592 593 MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(parent); 594 595 QList<MessageTreeWidgetItem*> to_build; 596 597 int index = 0; 598 int size = list->size(); 599 int id_parent = parent_item->pag()->Info.ID; 600 601 while (index < size) 602 { 603 ATopicInfo info = list->at(index); 604 605 if (info.IDParent == id_parent) 606 { 607 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(parent_item); 608 609 AMessageInfoGUI* item_info = item->pag(); 610 611 // AMessageInfo 612 item_info->Info.ID = info.ID; 613 item_info->Info.IDTopic = info.IDTopic; 614 item_info->Info.IDParent = info.IDParent; 615 item_info->Info.IDUser = info.IDUser; 616 item_info->Info.IDForum = info.IDForum; 617 item_info->Info.Subject = info.Subject; 618 item_info->Info.MessageName = info.MessageName; 619 item_info->Info.UserNick = info.UserNick; 620 item_info->Info.IDArticle = info.IDArticle; 621 item_info->Info.MessageDate = info.MessageDate; 622 item_info->Info.UpdateDate = info.UpdateDate; 623 item_info->Info.UserRole = info.UserRole; 624 item_info->Info.UserTitle = info.UserTitle; 625 item_info->Info.UserTitleColor = info.UserTitleColor; 626 item_info->Info.LastModerated = info.LastModerated; 627 628 // AMessageInfoEx 629 item_info->Info.IsRead = info.IsRead; 630 631 // ATopicInfo 632 item_info->Info.HasChild = info.HasChild; 633 item_info->Info.HasUnreadChild = 0; 634 635 // AMessageInfoGUI 636 item_info->IsInfoLoaded = true; 637 item_info->IsChildLoaded = true; 638 item_info->UnreadChildCount = 0; 639 item_info->IsBodyLoaded = false; 640 item_info->Special = 0; 641 642 item->setText(0, info.Subject); 643 644 if (info.IDUser != 0) 645 item->setText(1, info.UserNick); 633 void 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); 646 660 else 647 item->setText(1, QString::fromUtf8("Аноним ") + info.UserTitle); 648 649 item->setText(2, info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 650 651 to_build.append(item); 652 653 list->removeAt(index); 654 655 size--; 656 657 if (info.IsRead == true) 658 item->setIcon(0, m_message_read); 659 else 661 info->Item->setText(1, global->AnonymousName /*+ info->UserTitle*/); 662 663 info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 664 665 root->Item->addChild(info->Item); 666 667 // установка родителям свойств непрочитанных сообщений 668 if (info->IsRead == false && root->IDUser == m_me.ID) 660 669 { 661 item->setIcon(0, m_message_unread); 662 663 MessageTreeWidgetItem* temp_item = parent_item; 664 665 while (temp_item != NULL) 670 // сообщение не прочитано и это ответ не мне 671 info->Item->setIcon(0, m_message_unread_my); 672 673 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 674 675 while (item_parent != NULL) 666 676 { 667 AMessageInfoGUI* temp_info = temp_item->pag(); 668 669 if (info.HasUnreadChild == 2) 670 temp_info->Info.HasUnreadChild = 2; 671 672 if (temp_info->Info.IsRead == true) 677 AMessageInfoGUI* info_parent = item_parent->pag(); 678 679 if (info_parent->HasUnreadChildMy != true) 673 680 { 674 if (temp_info->Info.HasUnreadChild == 2) 675 temp_item->setIcon(0, m_child_unread_my); 681 info_parent->HasUnreadChild = true; 682 info_parent->HasUnreadChildMy = true; 683 684 if (info_parent->IsRead == true) 685 item_parent->setIcon(0, m_child_unread_my); 676 686 else 677 temp_item->setIcon(0, m_child_unread);687 item_parent->setIcon(0, m_message_unread_my); 678 688 } 679 else if (temp_info->Info.HasUnreadChild == 2) 680 temp_item->setIcon(0, m_message_unread_my);681 682 temp_info->UnreadChildCount++; 683 684 temp_item = (MessageTreeWidgetItem*)temp_item->parent(); 685 } 689 690 info_parent->UnreadChildCount++; 691 info_parent->UnreadChildCountMy++; 692 693 item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 694 695 } // while (item_parent != NULL) 686 696 } 687 } 688 else 689 index++; 690 } 691 692 size = to_build.size(); 693 694 for (int i = 0; i < size; i++) 695 buildTree(to_build.at(i), list); 697 else if (info->IsRead == false) 698 { 699 // сообщение не прочитано, но это ответ не мне 700 info->Item->setIcon(0, m_message_unread); 701 702 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(info->Item->parent()); 703 704 while (item_parent != NULL) 705 { 706 AMessageInfoGUI* info_parent = item_parent->pag(); 707 708 if (info_parent->HasUnreadChild != true) 709 { 710 info_parent->HasUnreadChild = true; 711 712 if (info_parent->IsRead == true) 713 item_parent->setIcon(0, m_child_unread); 714 } 715 716 info_parent->UnreadChildCount++; 717 718 item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 719 720 } // while (item_parent != NULL) 721 } 722 else // else if (info->IsRead == false) 723 { 724 // сообщение прочитано 725 info->Item->setIcon(0, m_message_read); 726 } 727 728 // достройка дочерних веток для текущей 729 if (info->HasChild) 730 { 731 buildTree(info, list); 732 list_index = 0; 733 } 734 } 735 else // if (info->ID == id_parent) 736 { 737 list_index++; 738 } 739 } 696 740 } 697 741 //---------------------------------------------------------------------------------------------- … … 713 757 return; 714 758 715 std::auto_ptr<FormSource> form (new FormSource(m_parent, item->pag()->Info.Message)); 759 std::auto_ptr<FormSource> form(new FormSource(m_parent, item->pag()->Message)); 760 716 761 form->exec(); 717 762 } … … 724 769 if (item == NULL) 725 770 return; 771 772 AMessageInfoGUI* info = item->pag(); 726 773 727 774 if (m_main_form != NULL) … … 729 776 730 777 // загрузка тела сообщения, если тело еще не загружено 731 if (i tem->pag()->IsBodyLoaded == false)778 if (info->IsBodyLoaded == false) 732 779 { 733 780 // получение хранилища … … 743 790 QString body; 744 791 745 if (storage->getMessageBody(i tem->pag()->Info.ID, body, NULL) == false)792 if (storage->getMessageBody(info->ID, body, NULL) == false) 746 793 { 747 794 storage->showError(m_parent); … … 749 796 } 750 797 751 i tem->pag()->IsBodyLoaded = true;752 i tem->pag()->Info.Message= body;753 } 754 755 AMessageInfoGUI message = item->tag();756 757 m_message_view->setMessage(message.Info, m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND, m_forum_rated); 758 759 if (i tem->pag()->Info.IsRead == false)798 info->IsBodyLoaded = true; 799 info->Message = body; 800 } 801 802 // отображение сообщения 803 m_message_view->setMessage(*info, m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND, m_current_forum.Rated); 804 805 // взвод таймера для пометки как прочитанного 806 if (info->IsRead == false) 760 807 { 761 808 int interval = AGlobal::getInstance()->MarkAsReadTimer; … … 768 815 else 769 816 m_timer.stop(); 817 770 818 } 771 819 //---------------------------------------------------------------------------------------------- … … 778 826 779 827 // если уже прочитан 780 if (info->I nfo.IsRead == is_read)781 return; 782 783 // пометить как прочитан ое в хранилище828 if (info->IsRead == is_read) 829 return; 830 831 // пометить как прочитанное в хранилище 784 832 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 785 833 … … 790 838 } 791 839 792 if (storage->setIDsAsRead(QList<int>() << info->I nfo.ID, idsMessage, is_read, QDateTime(), NULL) == false)840 if (storage->setIDsAsRead(QList<int>() << info->ID, idsMessage, is_read, QDateTime(), NULL) == false) 793 841 { 794 842 storage->showError(m_parent); … … 796 844 } 797 845 798 // пометка в дереве799 info->I nfo.IsRead = is_read;846 // установка флага как прочитанного и пометка в дереве 847 info->IsRead = is_read; 800 848 801 849 if (is_read == true) 802 850 { 803 if (info->UnreadChildCount != 0) 804 { 805 if (info->Info.HasUnreadChild == 2) 806 item->setIcon(0, m_child_unread_my); 807 else 808 item->setIcon(0, m_child_unread); 809 } 851 // установка иконки помечаемому сообщению 852 if (info->HasUnreadChildMy) 853 item->setIcon(0, m_child_unread_my); 854 else if (info->HasUnreadChild) 855 item->setIcon(0, m_child_unread); 810 856 else 811 { 812 if (item->parent() == NULL && info->IsChildLoaded == false && info->Info.HasUnreadChild != 0) 857 item->setIcon(0, m_message_read); 858 859 // флаг того, что это было сообщение для меня 860 bool message_to_me = false; 861 862 // установка флагов и иконок у родительских сообщений 863 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(item->parent()); 864 865 if (item_parent != NULL && item_parent->pag()->IDUser == m_me.ID) 866 message_to_me = true; 867 868 while (item_parent != NULL) 869 { 870 AMessageInfoGUI* info_parent = item_parent->pag(); 871 872 int old_unread_count = info_parent->UnreadChildCount; 873 int old_unread_count_my = info_parent->UnreadChildCountMy; 874 875 // уменьшение количества непрочитанных дочерних 876 // и установка соответствующих флагов 877 if (info_parent->UnreadChildCount > 0) 878 info_parent->UnreadChildCount--; 879 880 if (message_to_me == true && info_parent->UnreadChildCountMy > 0) 881 info_parent->UnreadChildCountMy--; 882 883 if (info_parent->UnreadChildCountMy == 0) 884 info_parent->HasUnreadChildMy = false; 885 886 if (info_parent->UnreadChildCount == 0) 887 info_parent->HasUnreadChild = false; 888 889 // установка иконок 890 if (info_parent->IsRead == false) 813 891 { 814 if (info->Info.HasUnreadChild == 2) 815 item->setIcon(0, m_child_unread_my); 816 else 817 item->setIcon(0, m_child_unread); 892 // родитель непрочитан 893 894 // если среди дочерних прочитали дочернее мне и больше непрочитанных дочерних мне нет 895 // и должна произойти смена иконки 896 if (old_unread_count_my != 0 && info_parent->UnreadChildCountMy == 0) 897 item_parent->setIcon(0, m_message_unread); 818 898 } 819 899 else 820 900 { 821 item->setIcon(0, m_message_read); 822 info->Info.HasUnreadChild = 0; 901 // родитель прочитан 902 903 // если среди дочерних есть непрочитанные мне 904 // и должна произойти смена иконки 905 if (old_unread_count_my != info_parent->UnreadChildCountMy && info_parent->UnreadChildCountMy > 0) 906 item_parent->setIcon(0, m_child_unread_my); 907 908 // если среди дочерних есть непрочитанные 909 // и должна произойти смена иконки 910 else if (old_unread_count != info_parent->UnreadChildCount && info_parent->UnreadChildCount > 0) 911 item_parent->setIcon(0, m_child_unread); 912 913 // нет дочерних непрочитанных 914 else 915 item_parent->setIcon(0, m_message_read); 823 916 } 824 } 825 826 MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 827 828 while (parent_item != NULL) 829 { 830 AMessageInfoGUI* parent_info = parent_item->pag(); 831 832 parent_info->UnreadChildCount--; 833 834 if (parent_info->Info.IsRead == true && parent_info->UnreadChildCount == 0) 835 { 836 parent_info->Info.HasUnreadChild = 0; 837 parent_item->setIcon(0, m_message_read); 838 } 839 840 parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); 917 918 item_parent = static_cast<MessageTreeWidgetItem*>(item_parent->parent()); 841 919 } 842 920 … … 844 922 m_forum_tree->changeUnreadCount(-1); 845 923 } 846 else 847 { 848 if (info->Info.HasUnreadChild == 2) 849 item->setIcon(0, m_message_unread_my); 850 else 851 item->setIcon(0, m_message_unread); 852 924 else // if (is_read == true) 925 { 926 // TODO: Доделать пометку родителей, если отметилось сообщение, которое является ответом мне 927 928 // установка иконки помечаемому сообщению 929 item->setIcon(0, m_message_unread); 930 931 // установка флагов и иконок у родительских сообщений 853 932 MessageTreeWidgetItem* parent_item = static_cast<MessageTreeWidgetItem*>(item->parent()); 854 933 … … 857 936 AMessageInfoGUI* parent_info = parent_item->pag(); 858 937 938 // смена иконки при необходимости 939 if (parent_info->IsRead == true && parent_info->HasUnreadChild == false) 940 parent_item->setIcon(0, m_child_unread); 941 859 942 parent_info->UnreadChildCount++; 860 parent_info->Info.HasUnreadChild = 1; // TODO: обновить в соответствии с ответами мне 861 862 if (parent_info->Info.IsRead == true) 863 { 864 if (parent_info->Info.HasUnreadChild == 2) 865 parent_item->setIcon(0, m_child_unread_my); 866 else 867 parent_item->setIcon(0, m_child_unread); 868 } 943 parent_info->HasUnreadChild = true; 869 944 870 945 parent_item = static_cast<MessageTreeWidgetItem*>(parent_item->parent()); … … 873 948 // увеличение количества непрочитанных в дереве форума 874 949 m_forum_tree->changeUnreadCount(1); 875 } 950 951 } // if (is_read == true) ... else 876 952 } 877 953 //---------------------------------------------------------------------------------------------- … … 899 975 //---------------------------------------------------------------------------------------------- 900 976 901 void AMessageTree::markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count) 902 { 903 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 904 905 if (item_parent->pag()->Info.IsRead != is_read) 906 count++; 907 908 if (is_read == true) 909 { 910 item_parent->setIcon(0, m_message_read); 911 912 item_parent->pag()->Info.IsRead = is_read; 913 item_parent->pag()->UnreadChildCount = 0; 914 item_parent->pag()->Info.HasUnreadChild = (is_read == true ? 1 : 0); // TODO: обновить в соответствии с ответами мне 915 916 for (int i = 0; i < item_parent->childCount(); i++) 917 markThreadAsRead(item_parent->child(i), is_read, count); 977 bool 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 997 void 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); 918 1021 } 919 1022 else 920 1023 { 921 item_parent->setIcon(0, m_message_unread); 922 923 item_parent->pag()->Info.IsRead = is_read; 924 925 MessageTreeWidgetItem* temp_parent = static_cast<MessageTreeWidgetItem*>(parent->parent()); 926 927 while (temp_parent != NULL) 928 { 929 temp_parent->pag()->Info.HasUnreadChild = (is_read == true ? 1 : 0); // TODO: обновить в соответствии с ответами мне 930 temp_parent->pag()->UnreadChildCount++; 931 temp_parent = static_cast<MessageTreeWidgetItem*>(temp_parent->parent()); 932 } 933 934 for (int i = 0; i < item_parent->childCount(); i++) 935 markThreadAsRead(item_parent->child(i), is_read, count); 936 } 937 } 938 //---------------------------------------------------------------------------------------------- 939 940 void AMessageTree::menu_mark_thread_as_read_triggered () 1024 parent->setIcon(0, m_message_read); 1025 1026 AMessageInfoGUI* info = parent->pag(); 1027 1028 info->HasUnreadChild = false; 1029 info->HasUnreadChildMy = false; 1030 info->UnreadChildCount = 0; 1031 info->UnreadChildCountMy = 0; 1032 1033 // поскольку дочерние элементы еще не загружены, 1034 // обновление количества непрочитаных в дереве форума 1035 m_forum_tree->reloadUnread(false); 1036 } 1037 } 1038 //---------------------------------------------------------------------------------------------- 1039 1040 void AMessageTree::menu_mark_thread_as_unread_triggered () 941 1041 { 942 1042 QTreeWidgetItem* item = currentItem(); … … 946 1046 947 1047 // поиск родителя 948 QTreeWidgetItem* parent = item; 949 950 while (parent->parent() != NULL) 951 parent = parent->parent(); 952 953 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 954 955 AMessageInfoGUI* info = item_parent->pag(); 956 957 // обновление данных в хранилище 958 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 959 960 if (storage.get() == NULL) 961 { 962 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 963 return; 964 } 965 966 if (storage->setIDsAsRead(QList<int>() << info->Info.ID, idsTopic, true, QDateTime(), NULL) == false) 967 { 968 storage->showError(m_parent); 969 return; 970 } 971 972 // обновление данных в дереве 1048 MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 1049 1050 AMessageInfoGUI* info = parent->pag(); 1051 1052 // пометка в хранилище 1053 if (markThreadAsRead(info->ID, false) != true) 1054 return; 1055 1056 // пометка в дереве 973 1057 if (info->IsChildLoaded == true) 974 1058 { 975 1059 int count = 0; 976 1060 977 markThreadAsRead(parent, true, count); 978 979 item_parent->pag()->Info.HasUnreadChild = 0; // TODO: обновить в соответствии с ответами мне 980 981 m_forum_tree->changeUnreadCount(-count); 1061 markThreadAsRead(parent, false, count); 1062 1063 m_forum_tree->changeUnreadCount(count); 982 1064 } 983 1065 else 984 1066 { 985 item_parent->setIcon(0, m_message_read); 986 987 item_parent->pag()->Info.HasUnreadChild = 0; // TODO: обновить в соответствии с ответами мне 988 989 // поскольку дочерние элементы еще не загружены, 990 // обновление количества непрочитаных в дереве форума 991 m_forum_tree->reloadUnread(false); 992 } 993 } 994 //---------------------------------------------------------------------------------------------- 995 996 void AMessageTree::menu_mark_thread_as_unread_triggered () 997 { 998 QTreeWidgetItem* item = currentItem(); 1067 parent->setIcon(0, m_message_unread); 1068 1069 AMessageInfoGUI* info = parent->pag(); 1070 1071 if (info->HasChild == true) 1072 info->HasUnreadChild = true; 1073 else 1074 info->HasUnreadChild = false; 1075 1076 info->HasUnreadChildMy = false; 1077 1078 // поскольку дочерние элементы еще не загружены, 1079 // обновление количества непрочитаных в дереве форума 1080 m_forum_tree->reloadUnread(false); 1081 } 1082 } 1083 //---------------------------------------------------------------------------------------------- 1084 1085 void AMessageTree::menu_reply_triggered () 1086 { 1087 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 999 1088 1000 1089 if (item == NULL) 1001 1090 return; 1002 1091 1003 // поиск родителя 1004 QTreeWidgetItem* parent = item; 1005 1006 while (parent->parent() != NULL) 1007 parent = parent->parent(); 1008 1009 MessageTreeWidgetItem* item_parent = static_cast<MessageTreeWidgetItem*>(parent); 1010 1011 AMessageInfoGUI* info = item_parent->pag(); 1012 1013 // обновление данных в хранилище 1014 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 1015 1016 if (storage.get() == NULL) 1017 { 1018 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 1019 return; 1020 } 1021 1022 if (storage->setIDsAsRead(QList<int>() << info->Info.ID, idsTopic, false, QDateTime(), NULL) == false) 1023 { 1024 storage->showError(m_parent); 1025 return; 1026 } 1027 1028 // обновление данных в дереве 1029 if (info->IsChildLoaded == true) 1030 { 1031 int count = 0; 1032 1033 markThreadAsRead(parent, false, count); 1034 1035 item_parent->pag()->Info.HasUnreadChild = 1; // TODO: Обновить в соответствии с ответами мне 1036 1037 m_forum_tree->changeUnreadCount(count); 1038 } 1039 else 1040 { 1041 item_parent->setIcon(0, m_message_unread); 1042 1043 item_parent->pag()->Info.HasUnreadChild = 1; // TODO: Обновить в соответствии с ответами мне 1044 1045 // поскольку дочерние элементы еще не загружены, 1046 // обновление количества непрочитаных в дереве форума 1047 m_forum_tree->reloadUnread(false); 1048 } 1049 } 1050 //---------------------------------------------------------------------------------------------- 1051 1052 void AMessageTree::menu_reply_triggered () 1053 { 1054 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 1055 1056 if (item == NULL) 1057 return; 1058 1059 FormMessage* form = new FormMessage(NULL, true, item->pag()->Info); 1092 FormMessage* form = new FormMessage(NULL, true, *(item->pag())); 1060 1093 1061 1094 form->setForumTree(m_forum_tree); … … 1086 1119 QList<QTreeWidgetItem*> items; 1087 1120 1121 AGlobal* global = AGlobal::getInstance(); 1122 1088 1123 for (int i = 0; i < list.count(); i++) 1089 1124 { 1090 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 1091 1092 AMessageInfoGUI* info = item->pag(); 1093 1094 info->Info.ID = list[i].ID; 1095 info->Info.IDTopic = list[i].IDTopic; 1096 info->Info.IDParent = list[i].IDParent; 1097 info->Info.IDUser = list[i].IDUser; 1098 info->Info.IDForum = list[i].IDForum; 1099 info->Info.Subject = list[i].Subject; 1100 info->Info.MessageName = list[i].MessageName; 1101 info->Info.UserNick = list[i].UserNick; 1102 info->Info.Message = list[i].Message; 1103 info->Info.IDArticle = list[i].IDArticle; 1104 info->Info.MessageDate = list[i].MessageDate; 1105 info->Info.UpdateDate = list[i].UpdateDate; 1106 info->Info.UserRole = list[i].UserRole; 1107 info->Info.UserTitle = list[i].UserTitle; 1108 info->Info.UserTitleColor = list[i].UserTitleColor; 1109 info->Info.LastModerated = list[i].LastModerated; 1110 1111 info->Info.IsRead = true; 1112 1113 info->Info.HasChild = false; 1114 info->Info.HasUnreadChild = 0; 1115 1116 info->IsInfoLoaded = true; 1117 info->IsChildLoaded = true; 1118 info->UnreadChildCount = 0; 1119 info->IsBodyLoaded = true; 1120 info->Special = list[i].ID; 1121 1122 item->setText(0, info->Info.Subject); 1123 1124 if (info->Info.IDUser == 0) 1125 { 1126 info->Info.UserNick = QString::fromUtf8("(локальный)"); 1127 item->setText(1, info->Info.UserNick); 1125 AMessageInfoGUI* info = createItem(); 1126 1127 info->ID = list[i].ID; 1128 info->IDTopic = list[i].IDTopic; 1129 info->IDParent = list[i].IDParent; 1130 info->IDUser = list[i].IDUser; 1131 info->IDForum = list[i].IDForum; 1132 info->Subject = list[i].Subject; 1133 info->MessageName = list[i].MessageName; 1134 info->UserNick = list[i].UserNick; 1135 info->Message = list[i].Message; 1136 info->IDArticle = list[i].IDArticle; 1137 info->MessageDate = list[i].MessageDate; 1138 info->UpdateDate = list[i].UpdateDate; 1139 info->UserRole = list[i].UserRole; 1140 info->UserTitle = list[i].UserTitle; 1141 info->UserTitleColor = list[i].UserTitleColor; 1142 info->LastModerated = list[i].LastModerated; 1143 1144 info->IsInfoLoaded = true; 1145 info->IsRead = true; 1146 info->IsBodyLoaded = true; 1147 info->IsChildLoaded = true; 1148 info->HasUnreadChild = 0; 1149 info->HasUnreadChildMy = 0; 1150 info->Special = list[i].ID; 1151 1152 info->Item->setText(0, info->Subject); 1153 1154 if (info->IDUser == 0) 1155 { 1156 info->UserNick = QString::fromUtf8("(локальный)"); 1157 info->Item->setText(1, info->UserNick); 1128 1158 } 1129 1159 else 1130 i tem->setText(1, info->Info.UserNick);1131 1132 i tem->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss"));1133 1134 items.append(i tem);1160 info->Item->setText(1, info->UserNick); 1161 1162 info->Item->setText(2, info->MessageDate.toString(global->DateFormat)); 1163 1164 items.append(info->Item); 1135 1165 } 1136 1166 … … 1201 1231 else if (url == "avalon:moderate") 1202 1232 { 1203 FormModerate* form = new FormModerate(m_parent, item->pag()->I nfo.ID);1233 FormModerate* form = new FormModerate(m_parent, item->pag()->ID); 1204 1234 1205 1235 form->setForumTree(m_forum_tree); … … 1227 1257 ARating2Send info; 1228 1258 1229 info.IDMessage = item->pag()->I nfo.ID;1259 info.IDMessage = item->pag()->ID; 1230 1260 info.Rate = rate; 1231 1261 info.Date = QDateTime::currentDateTime(); … … 1239 1269 } 1240 1270 1241 // обновление в дереве форумов количества непрочитан ых сообщений1271 // обновление в дереве форумов количества непрочитанных сообщений 1242 1272 if (m_forum_tree != NULL) 1243 1273 m_forum_tree->reloadUnread(false); … … 1245 1275 //---------------------------------------------------------------------------------------------- 1246 1276 1247 void AMessageTree::gotoNextUnreadArticle () 1248 { 1249 if (checkCurrentItem() == false) 1250 return; 1277 void 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 1390 void 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 1480 void 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 1553 void AMessageTree::gotoNextUnreadThread () 1554 { 1555 AMessageInfoGUI* info = NULL; 1251 1556 1252 1557 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 1253 1558 1559 // если не было выделения, то ищем следующую непрочитанную статью (она будет первой) 1560 if (item == NULL) 1561 { 1562 gotoNextUnreadArticle(NULL); 1563 return; 1564 } 1565 1566 // item установлен на топик 1567 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(item)); 1568 info = item->pag(); 1569 1570 // флаг петли 1571 bool loopback = false; 1572 1573 // поиск следующего топика с непрочитанными сообщениями 1254 1574 while (true) 1255 1575 { 1256 if (item->pag()->Info.IsRead == false) 1576 // следующий топик за текущим 1577 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 1578 1579 // если достигнут конец дерева, то переходим в корень 1580 if (item == NULL) 1581 item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 1582 1583 info = item->pag(); 1584 1585 // если найденый топик с незагруженной информацией 1586 if (info->IsInfoLoaded == false) 1587 { 1588 if (loopback == true) 1589 return; 1590 1591 item = static_cast<MessageTreeWidgetItem*>(topLevelItem(0)); 1592 info = item->pag(); 1593 1594 loopback = true; 1595 } 1596 1597 if (info->IsRead == false) 1257 1598 break; 1258 1599 1259 if (item->pag()->Info.HasUnreadChild != 0) 1260 item->setExpanded(true); 1261 1262 MessageTreeWidgetItem* next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextItem(item)); 1263 1264 if (next_item == NULL) 1265 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 1266 else 1267 item = next_item; 1268 1269 if (item->pag()->IsInfoLoaded == false) 1270 { 1271 // 1272 // было 1273 // 1274 // setCurrentItem(item); 1275 // 1276 // Однако, если элемент не загружен, то ниже, скорее всего, больше нет непрочитанных сообщений 1277 // иначе, начинают сканироваться все топики до конца, что занимает много времени (т.к. приходится их все грузить) 1278 // по этому, переходим на корневой элемент 1279 // 1280 1281 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 1600 if (info->HasUnreadChild == true) 1601 { 1602 gotoNextUnreadArticle(item); 1603 return; 1282 1604 } 1283 1605 } 1284 1606 1285 1607 setCurrentItem(item); 1286 } 1287 //---------------------------------------------------------------------------------------------- 1288 1289 void AMessageTree::gotoNextUnreadThread () 1290 { 1291 if (currentItem() == NULL) 1292 { 1293 if (checkCurrentItem() == false) 1294 return; 1295 1296 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(currentItem())); 1297 1298 if (item->pag()->Info.HasUnreadChild != 0 || item->pag()->Info.IsRead == false) 1299 return; 1300 } 1301 1302 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::rootItem(currentItem())); 1303 1304 while (true) 1305 { 1306 MessageTreeWidgetItem* next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::nextSibling(item)); 1307 1308 if (next_item == NULL) 1309 next_item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(item)); 1310 1311 item = next_item; 1312 1313 // 1314 // было 1315 // 1316 // if (item->pag()->IsInfoLoaded == false || item->pag()->IsChildLoaded == false) 1317 // setCurrentItem(item); 1318 // 1319 // Однако, если элемент не загружен, то ниже, скорее всего, больше нет непрочитанных сообщений 1320 // иначе, начинают сканироваться все топики до конца, что занимает много времени (т.к. приходится их все грузить) 1321 // по этому, переходим на корневой топик 1322 // 1323 1324 if (item->pag()->IsInfoLoaded == false) 1325 item = static_cast<MessageTreeWidgetItem*>(ATreeWidgetItem::firstSibling(ATreeWidgetItem::rootItem(item))); 1326 1327 if (item->pag()->Info.HasUnreadChild != 0 || item->pag()->Info.IsRead == false) 1328 break; 1329 } 1330 1331 setCurrentItem(item); 1332 } 1333 //---------------------------------------------------------------------------------------------- 1334 1335 void AMessageTree::loadRating2Send () 1336 { 1608 1609 scrollToItem(item, QAbstractItemView::PositionAtCenter); 1610 } 1611 //---------------------------------------------------------------------------------------------- 1612 1613 void AMessageTree::menu_special_delete_triggered () 1614 { 1615 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 1616 1617 if (item == NULL) 1618 return; 1619 1620 if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 1621 m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND || 1622 m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 1623 )) 1624 return; 1625 1337 1626 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 1338 1627 … … 1343 1632 } 1344 1633 1345 AMessageInfoList message_list; 1346 ARating2SendList rating_list; 1347 1348 if (storage->getRating2SendList(message_list, rating_list, NULL) == false) 1634 if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_current_forum.ID, NULL) == false) 1349 1635 { 1350 1636 storage->showError(m_parent); … … 1352 1638 } 1353 1639 1354 QList<QTreeWidgetItem*> items; 1355 1356 for (int i = 0; i < message_list.count(); i++) 1357 { 1358 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 1359 1360 AMessageInfoGUI* info = item->pag(); 1361 1362 info->Info.ID = message_list[i].ID; 1363 info->Info.IDTopic = message_list[i].IDTopic; 1364 info->Info.IDParent = message_list[i].IDParent; 1365 info->Info.IDUser = message_list[i].IDUser; 1366 info->Info.IDForum = message_list[i].IDForum; 1367 info->Info.Subject = message_list[i].Subject; 1368 info->Info.MessageName = message_list[i].MessageName; 1369 info->Info.UserNick = message_list[i].UserNick; 1370 info->Info.Message = message_list[i].Message; 1371 info->Info.IDArticle = message_list[i].IDArticle; 1372 info->Info.MessageDate = message_list[i].MessageDate; 1373 info->Info.UpdateDate = message_list[i].UpdateDate; 1374 info->Info.UserRole = message_list[i].UserRole; 1375 info->Info.UserTitle = message_list[i].UserTitle; 1376 info->Info.UserTitleColor = message_list[i].UserTitleColor; 1377 info->Info.LastModerated = message_list[i].LastModerated; 1378 1379 info->Info.IsRead = true; 1380 1381 info->Info.HasChild = false; 1382 info->Info.HasUnreadChild = 0; 1383 1384 info->IsInfoLoaded = true; 1385 info->IsChildLoaded = true; 1386 info->UnreadChildCount = 0; 1387 info->IsBodyLoaded = true; 1388 info->Special = rating_list[i].ID; 1389 1390 item->setText(0, info->Info.Subject); 1391 1392 if (info->Info.IDUser == 0) 1393 { 1394 info->Info.UserNick = QString::fromUtf8("(локальный)"); 1395 item->setText(1, info->Info.UserNick); 1396 } 1397 else 1398 item->setText(1, info->Info.UserNick); 1399 1400 item->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 1401 1402 int rate = rating_list[i].Rate; 1403 1404 if (rate == -4) 1405 item->setIcon(0, m_rating_plus); 1406 else if (rate == -3) 1407 item->setIcon(0, m_rating_plus_1); 1408 else if (rate == -2) 1409 item->setIcon(0, m_rating_smile); 1410 else if (rate == -1) 1411 item->setIcon(0, m_rating_cross); 1412 else if (rate == 0) 1413 item->setIcon(0, m_rating_minus); 1414 else if (rate == 1) 1415 item->setIcon(0, m_rating_1); 1416 else if (rate == 2) 1417 item->setIcon(0, m_rating_2); 1418 else if (rate == 3) 1419 item->setIcon(0, m_rating_3); 1420 1421 items.append(item); 1422 } 1423 1424 addTopLevelItems(items); 1425 } 1426 //---------------------------------------------------------------------------------------------- 1427 1428 void AMessageTree::loadModerate2Send () 1429 { 1430 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 1431 1432 if (storage.get() == NULL) 1433 { 1434 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 1435 return; 1436 } 1437 1438 AMessageInfoList message_list; 1439 AModerate2SendList moderate_list; 1440 1441 if (storage->getModerate2SendList(message_list, moderate_list, NULL) == false) 1442 { 1443 storage->showError(m_parent); 1444 return; 1445 } 1446 1447 QList<QTreeWidgetItem*> items; 1448 1449 for (int i = 0; i < message_list.count(); i++) 1450 { 1451 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 1452 1453 AMessageInfoGUI* info = item->pag(); 1454 1455 info->Info.ID = message_list[i].ID; 1456 info->Info.IDTopic = message_list[i].IDTopic; 1457 info->Info.IDParent = message_list[i].IDParent; 1458 info->Info.IDUser = message_list[i].IDUser; 1459 info->Info.IDForum = message_list[i].IDForum; 1460 info->Info.Subject = message_list[i].Subject; 1461 info->Info.MessageName = message_list[i].MessageName; 1462 info->Info.UserNick = message_list[i].UserNick; 1463 info->Info.Message = message_list[i].Message; 1464 info->Info.IDArticle = message_list[i].IDArticle; 1465 info->Info.MessageDate = message_list[i].MessageDate; 1466 info->Info.UpdateDate = message_list[i].UpdateDate; 1467 info->Info.UserRole = message_list[i].UserRole; 1468 info->Info.UserTitle = message_list[i].UserTitle; 1469 info->Info.UserTitleColor = message_list[i].UserTitleColor; 1470 info->Info.LastModerated = message_list[i].LastModerated; 1471 1472 info->Info.IsRead = true; 1473 1474 info->Info.HasChild = false; 1475 info->Info.HasUnreadChild = 0; 1476 1477 info->IsInfoLoaded = true; 1478 info->IsChildLoaded = true; 1479 info->UnreadChildCount = 0; 1480 info->IsBodyLoaded = true; 1481 info->Special = moderate_list[i].ID; 1482 1483 item->setText(0, info->Info.Subject); 1484 1485 if (info->Info.IDUser == 0) 1486 { 1487 info->Info.UserNick = QString::fromUtf8("(локальный)"); 1488 item->setText(1, info->Info.UserNick); 1489 } 1490 else 1491 item->setText(1, info->Info.UserNick); 1492 1493 item->setText(2, info->Info.MessageDate.toString("dd.MM.yyyy hh:mm:ss")); 1494 1495 item->setIcon(0, m_moderate); 1496 1497 items.append(item); 1498 } 1499 1500 addTopLevelItems(items); 1501 } 1502 //---------------------------------------------------------------------------------------------- 1503 1504 void AMessageTree::menu_special_delete_triggered () 1505 { 1506 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(currentItem()); 1507 1508 if (item == NULL) 1509 return; 1510 1511 if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 1512 return; 1513 1514 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); 1515 1516 if (storage.get() == NULL) 1517 { 1518 QMessageBox::critical(m_parent, QString::fromUtf8("Ошибка!"), QString::fromUtf8("Не выбрано хранилище данных")); 1519 return; 1520 } 1521 1522 if (storage->deleteSpecial(QList<int>() << item->pag()->Special, m_id_forum, NULL) == false) 1523 { 1524 storage->showError(m_parent); 1525 return; 1526 } 1527 1528 // обновление в дереве форумов количества непрочитаных сообщений 1640 // обновление в дереве форумов количества непрочитанных сообщений 1529 1641 if (m_forum_tree != NULL) 1530 1642 m_forum_tree->reloadUnread(true); … … 1539 1651 setCurrentItem(item); 1540 1652 1541 if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 1653 if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 1654 m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND || 1655 m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 1656 )) 1542 1657 return; 1543 1658 … … 1553 1668 return; 1554 1669 1555 if (!(m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND || m_id_forum == SPECIAL_ID_FORUM_RATING2SEND || m_id_forum == SPECIAL_ID_FORUM_MODERATE2SEND)) 1556 return; 1557 1558 if (m_id_forum == SPECIAL_ID_FORUM_MESSAGE2SEND) 1559 { 1560 FormMessage* form = new FormMessage(NULL, false, item->pag()->Info, item->pag()->Special); 1670 if (!(m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND || 1671 m_current_forum.ID == SPECIAL_ID_FORUM_RATING2SEND || 1672 m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND 1673 )) 1674 return; 1675 1676 if (m_current_forum.ID == SPECIAL_ID_FORUM_MESSAGE2SEND) 1677 { 1678 FormMessage* form = new FormMessage(NULL, false, *(item->pag()), item->pag()->Special); 1561 1679 1562 1680 form->setForumTree(m_forum_tree); … … 1565 1683 form->show(); 1566 1684 } 1567 else if (m_ id_forum== SPECIAL_ID_FORUM_MODERATE2SEND)1568 { 1569 FormModerate* form = new FormModerate(m_parent, item->pag()->I nfo.ID, item->pag()->Special);1685 else if (m_current_forum.ID == SPECIAL_ID_FORUM_MODERATE2SEND) 1686 { 1687 FormModerate* form = new FormModerate(m_parent, item->pag()->ID, item->pag()->Special); 1570 1688 1571 1689 form->setForumTree(m_forum_tree); … … 1585 1703 return; 1586 1704 1587 if (m_ id_forum!= SPECIAL_ID_FORUM_RATING2SEND)1705 if (m_current_forum.ID != SPECIAL_ID_FORUM_RATING2SEND) 1588 1706 return; 1589 1707 … … 1670 1788 return; 1671 1789 1672 path.insert(0, item->pag()->I nfo.ID);1790 path.insert(0, item->pag()->ID); 1673 1791 1674 1792 while (true) … … 1677 1795 1678 1796 if (item != NULL) 1679 path.insert(0, item->pag()->I nfo.ID);1797 path.insert(0, item->pag()->ID); 1680 1798 else 1681 1799 break; … … 1698 1816 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(topLevelItem(i)); 1699 1817 1700 if (item->pag()->IsInfoLoaded == false) 1701 return false; 1702 1703 if (item->pag()->Info.ID == root_id) 1818 AMessageInfoGUI* info = item->pag(); 1819 1820 if (item->pag()->ID == root_id) 1704 1821 { 1705 1822 root_item = item; 1706 1823 1707 // переход на корень 1708 setCurrentItem(root_item); 1824 // переход на корень (и его загрузка, при необходимости) 1825 if (info->IsInfoLoaded == false) 1826 setCurrentItem(root_item); 1709 1827 1710 1828 // ... и разворот, если ищется некорневое сообщение … … 1716 1834 } 1717 1835 1836 if (root_item == NULL) 1837 return false; 1838 1718 1839 // поиск в дочерних 1719 1840 for (int i = 1; i < path->count(); i++) … … 1727 1848 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(root_item->child(j)); 1728 1849 1729 if (item->pag()->IsInfoLoaded == false) 1730 setCurrentItem(item); 1731 1732 if (item->pag()->Info.ID == next_id) 1850 if (item->pag()->ID == next_id) 1733 1851 { 1734 found = true;1852 found = true; 1735 1853 root_item = item; 1736 1737 setCurrentItem(root_item);1738 1854 1739 1855 if (i + 1 != path->count() && root_item->isExpanded() == false) … … 1745 1861 1746 1862 if (found == false) 1863 { 1864 setCurrentItem(root_item); 1865 1747 1866 return false; 1748 } 1867 } 1868 } 1869 1870 setCurrentItem(root_item); 1871 1872 scrollToItem(root_item, QAbstractItemView::PositionAtCenter); 1749 1873 1750 1874 return true; 1751 1875 } 1752 1876 //---------------------------------------------------------------------------------------------- 1877 1878 void AMessageTree::gotoNextUnreadArticle () 1879 { 1880 gotoNextUnreadArticle(currentItem()); 1881 } 1882 //---------------------------------------------------------------------------------------------- 1883 1884 1885 AMessageInfoGUI* AMessageTree::createItem () 1886 { 1887 MessageTreeWidgetItem* item = new MessageTreeWidgetItem(); 1888 1889 AMessageInfoGUI* info = item->pag(); 1890 1891 info->Item = item; 1892 1893 return info; 1894 } 1895 //---------------------------------------------------------------------------------------------- 1896 1897 void AMessageTree::markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count) 1898 { 1899 MessageTreeWidgetItem* item = static_cast<MessageTreeWidgetItem*>(parent); 1900 1901 AMessageInfoGUI* info = item->pag(); 1902 1903 if (info->IsRead != is_read) 1904 count++; 1905 1906 info->IsRead = is_read; 1907 1908 if (is_read == true) 1909 { 1910 item->setIcon(0, m_message_read); 1911 1912 info->HasUnreadChild = false; 1913 info->HasUnreadChildMy = false; 1914 info->UnreadChildCount = 0; 1915 info->UnreadChildCountMy = 0; 1916 1917 for (int i = 0; i < item->childCount(); i++) 1918 markThreadAsRead(item->child(i), is_read, count); 1919 } 1920 else // if (is_read == true) 1921 { 1922 item->setIcon(0, m_message_unread); 1923 1924 info->HasUnreadChild = false; 1925 info->HasUnreadChildMy = false; 1926 info->UnreadChildCount = 0; 1927 info->UnreadChildCountMy = 0; 1928 1929 MessageTreeWidgetItem* parent = static_cast<MessageTreeWidgetItem*>(item->parent()); 1930 1931 while (parent != NULL) 1932 { 1933 info = parent->pag(); 1934 1935 info->HasUnreadChild = true; 1936 info->UnreadChildCount++; 1937 1938 parent = static_cast<MessageTreeWidgetItem*>(parent->parent()); 1939 } 1940 1941 for (int i = 0; i < item->childCount(); i++) 1942 markThreadAsRead(item->child(i), is_read, count); 1943 1944 } // if (is_read == true) ... else 1945 } 1946 //---------------------------------------------------------------------------------------------- -
trunk/message_tree.h
r175 r191 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 … … 70 71 private: 71 72 72 /*! 73 * \brief Главная форма приложения (для отображения сообщений об ошибках) 74 */ 75 QWidget* m_parent; 73 QWidget* m_parent; /*!< \brief Главная форма приложения (для отображения сообщений об ошибках) */ 76 74 77 75 IForumTree* m_forum_tree; /*!< \brief Интерфейс дерева форумов */ … … 79 77 IFormMain* m_main_form; /*!< \brief Интерфейс главной формы */ 80 78 79 // 81 80 // иконки для отображения статусов сообщений 81 // 82 82 83 QIcon m_message_read; /*!< \brief Сообщение прочитано */ 83 84 QIcon m_child_unread; /*!< \brief Есть непрочитанные дочерние сообщения */ … … 86 87 QIcon m_message_unread_my; /*!< \brief В ветке есть сообщение для меня */ 87 88 89 // 88 90 // иконки для отображения оценок 91 // 92 89 93 QIcon m_rating_plus_1; /*!< \brief "+1" */ 90 94 QIcon m_rating_1; /*!< \brief "1" */ … … 103 107 104 108 /*! 105 * \brief Высплывающее меню109 * \brief Основное контекстное меню (для основного дерева сообщений) 106 110 */ 107 111 QMenu* m_menu; … … 114 118 115 119 /*! 116 * \brief Высплывающее меню в спец-фоорумах120 * \brief Контекстное меню в спец-фоорумах (оценки, модерилки, исходящие сообщения) 117 121 */ 118 122 QMenu* m_menu_special; … … 129 133 QAction* m_menu_special_minus; /*!< \brief - (несогласен) */ 130 134 131 /*! 132 * \brief ID текущей группы 133 */ 134 int m_id_group; 135 136 /*! 137 * \brief ID текущего форума 138 */ 139 int m_id_forum; 140 141 /*! 142 * \brief Оценивается ли форум 143 */ 144 bool m_forum_rated; 145 146 /*! 147 * \brief ID текущего пользователя RSDN 148 */ 149 AUserInfo m_me; 150 151 /*! 152 * \brief Функция проверки установки выделения, в случае отсутствия выделения, выделяет элемент, согласно параметру select_first 153 * \param select_first Флаг выделения, если имеет значение true, то выделяется первый элемент, иначе, последний (из корневых) 154 * \return true, если есть выделение, false при отсутствии элементов 155 */ 156 bool checkCurrentItem (bool select_first = true); 157 158 /*! 159 * \brief Загружает незагруженные топики при скроллинге (см. алгоритм работы с деревом в trac) 135 // 136 // внутренние переменные 137 // 138 139 AForumInfo m_current_forum; /*!< \brief Текущий отображаемый форум */ 140 AUserInfo m_me; /*!< \brief Текущий пользователь avalon */ 141 142 /*! 143 * \brief Дозагрузка информации о топиках, находящихся в видимой области отображения 160 144 */ 161 145 void scrollTopics (); 162 146 163 147 /*! 164 * \brief Разворачивает ветку до непрочитанных сообщений 165 * \param item Элемент для разворачивания 166 */ 167 void expandUnreadChild (QTreeWidgetItem* item); 168 169 /*! 170 * \brief Построение веток 171 * \param parent Родительский элемент 172 * \param list список _всех_ дочерних веток (все уровни вложенности) 173 */ 174 void buildTree (QTreeWidgetItem* parent, ATopicInfoList* list); 175 176 /*! 177 * \brief Пометка сообщения как прочитанного 148 * \brief Построение дерева (топика) из списка элементов 149 * \param root Родительский элемент 150 * \param list Список дочерних элементов для построения 151 */ 152 void buildTree (AMessageInfoGUI* root, AMessageInfoGUIPtrList* list); 153 154 /*! 155 * \brief Раскрытие дерева элементов до всех непрочитанных сообщений 156 * \param root Родительский элемент дерева для раскрытия 157 */ 158 void expandUnreadChild (QTreeWidgetItem* widget_item); 159 160 /*! 161 * \brief Функция проверки установки выделения, в случае отсутствия выделения, выделяет элемент, согласно параметру select_first 162 * \param select_first Флаг выделения, если имеет значение true, то выделяется первый элемент, иначе, последний (из корневых) 163 * \return true, если есть выделение, false при отсутствии элементов 164 */ 165 bool checkCurrentItem (bool select_first = true); 166 167 /*! 168 * \brief Редактирование оценки к отправке 169 * \param new_rate Новая оценка 170 */ 171 void changeRating (int new_rate); 172 173 /* 174 * \brief Расширенная реализация IMessageTree::gotoNextUnreadArticle 175 * \param item Элемент дерева, относительно которого требуется вести поиск 176 */ 177 void gotoNextUnreadArticle (QTreeWidgetItem* current_item); 178 179 /* 180 * \brief Пометка сообщения как прочитанного/непрочитанного 178 181 * \param item Элемент дерева 179 * \param is_read Флаг прочитанно сти/непрочитанности182 * \param is_read Флаг прочитанного 180 183 */ 181 184 void markItemAsRead (QTreeWidgetItem* item, bool is_read); 182 185 183 /* !184 * \brief Пометка ветки как прочитан ой185 * \param parent Родительский элемент ветки186 * \param is_read Флаг прочитанно сти/непрочитанности187 * \param count Количество отмеченных элементов186 /* 187 * \brief Пометка ветки как прочитанной/непрочитанной 188 * \param item Элемент дерева 189 * \param is_read Флаг прочитанного 190 * \param count Количество элементов, которые были помечены 188 191 */ 189 192 void markThreadAsRead (QTreeWidgetItem* parent, bool is_read, int& count); 190 193 194 /* 195 * \brief Пометка ветки как прочитанной/непрочитанной в хранилище 196 * \param id ID топика 197 * \param is_read Флаг прочитанного 198 * \return true, если ветка в хранилище помечена 199 */ 200 bool markThreadAsRead (int id, bool is_read); 201 191 202 /*! 192 203 * \brief Загрузить сообщения к отправке … … 203 214 */ 204 215 void loadModerate2Send (); 205 206 /*!207 * \brief Смена оценки208 * \param new_rate Новая оценка209 */210 void changeRating (int new_rate);211 216 212 217 // IMessageTree … … 225 230 bool selectByPath (const QList<int>* path); 226 231 232 // IMessageInfoGUIFactory 233 private: 234 235 AMessageInfoGUI* createItem (); 236 227 237 private slots: 228 238 … … 243 253 244 254 /*! 245 * \brief Двойной клик 255 * \brief Двойной клик (редактирование) 246 256 */ 247 257 void item_double_clicked (QTreeWidgetItem* item, int column); … … 257 267 void context_menu_request (const QPoint& pos); 258 268 259 // меню 269 // 270 // Основное контекстное меню 271 // 272 260 273 void menu_reply_triggered (); /*!< \brief Ответить */ 261 274 void menu_mark_message_as_read_triggered (); /*!< \brief Пометить сообщение как прочитанное */ … … 265 278 266 279 // 267 // Специальное меню280 // Специальное контекстное меню 268 281 // 269 282 -
trunk/model/message.h
r118 r191 67 67 * \brief Расширенная информация о сообщении для отображения в дереве в GUI 68 68 */ 69 typedef struct AMessageInfo Ex: AMessageInfo69 typedef struct AMessageInfoGUI : AMessageInfo 70 70 { 71 bool IsRead; /*!< \brief Прочитано ли сообщение */ 71 bool IsInfoLoaded; /*!< \brief Загружена ли какая-нибудь информация кроме ID */ 72 bool IsRead; /*!< \brief Прочитано ли сообщение */ 73 bool HasChild; /*!< \brief Имеются ли дочерние сообщения */ 74 bool IsBodyLoaded; /*!< \brief Загружено ли тело сообщения */ 75 bool IsChildLoaded; /*!< \brief Загружены ли дочерние сообщения */ 76 bool HasUnreadChild; /*!< \brief Наличие непрочитанных дочерних */ 77 bool HasUnreadChildMy; /*!< \brief Наличие непрочитанных дочерних мне */ 78 int UnreadChildCount; /*!< \brief Количество непрочитанных дочерних */ 79 int UnreadChildCountMy; /*!< \brief Количество непрочитанных дочерних мне */ 80 int Special; /*!< \brief Спец-данные */ 81 82 QTreeWidgetItem* Item; /*!< \brief Слинкованный элемент дерева */ 83 84 AMessageInfoGUI () 85 { 86 // AMessageInfo 87 ID = -1; 88 IDTopic = -1; 89 IDParent = -1; 90 IDUser = -1; 91 IDForum = -1; 92 IDArticle = -1; 93 UserTitleColor = -1; 94 95 // AMessageInfoGUI 96 IsInfoLoaded = false; 97 IsRead = true; 98 HasChild = false; 99 IsBodyLoaded = false; 100 IsChildLoaded = false; 101 HasUnreadChild = false; 102 HasUnreadChildMy = false; 103 UnreadChildCount = -1; 104 UnreadChildCountMy = -1; 105 Special = -1; 106 107 Item = NULL; 108 } 109 72 110 } AMessageInfoEx; 73 111 … … 75 113 * \brief Список сообщений для отображения в дереве в GUI 76 114 */ 77 typedef QList<AMessageInfoEx> AMessageInfoExList; 78 79 /*! 80 * \brief Информация о топике для отображения дерева в GUI 81 */ 82 typedef struct ATopicInfo : AMessageInfoEx 83 { 84 bool HasChild; /*!< \brief Есть ли дочерние сообщения */ 85 int HasUnreadChild; /*!< \brief Есть ли дочерние непрочитанные сообщения 0 - нет, 1 - да, 2 - есть непрочитанные для текущего пользователя */ 86 } ATopicInfo; 115 typedef QList<AMessageInfoGUI> AMessageInfoGUIList; 87 116 88 117 /*! 89 118 * \brief Список сообщений для отображения в дереве в GUI 90 119 */ 91 typedef QList<ATopicInfo> ATopicInfoList; 120 typedef QList<AMessageInfoGUI*> AMessageInfoGUIPtrList; 121 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 }; 92 136 93 137 /*! -
trunk/storage/istorage.h
r175 r191 17 17 18 18 /*! 19 * \brief Типы множеств для групповой обработки (см. IAStorage:: SetIDsAsRead и IAStorage::Unsubscribe).19 * \brief Типы множеств для групповой обработки (см. IAStorage::setIDsAsRead и IAStorage::unsubscribe). 20 20 */ 21 21 typedef enum AIDSet … … 136 136 137 137 /*! 138 * \brief Заполняет полную информацию о топиках за исключением тела самого сообщения, 139 * тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 140 * \param list Список топиков. 141 * \param id_me ID текущего пользователя 142 * \param progress Прогресс выполнения операции. 143 */ 144 virtual bool getTopicInfoList (ATopicInfoList& list, int id_me, IProgress* progress = NULL) = 0; 145 146 /*! 147 * \brief Возвращает список _всех_ сообщений в топике (родительской ветке) за исключением тел самих сообщений, 148 * тело сообщения будет запрошено при помощи IAStorage::GetMessageBody, по мере необходимости. 138 * \brief Заполняет информацию о топиках в форуме 139 * 140 * Поля списка (кроме ID и Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) 141 * и не меняются без необходимости. 142 * 143 * Функция ДОЛЖНА заполнить все поля AMessageInfo плюс установить флаги AMessageInfoGUI::IsRead, AMessageInfoGUI::HasUnreadChild, 144 * AMessageInfoGUI::HasUnreadChildMy в актуальные значения. 145 * 146 * Функция НЕ должна устанавливать флаг AMessageInfoGUI::IsInfoLoaded (устанавливается вызвающим кодом). 147 * 148 * Функция МОЖЕТ оставить некоторые поля AMessageInfo, которые не используются в текущем GUI, незаполненными в целях оптимизации 149 * скорости работы - в этом случае они должны иметь значения по умолчанию (к таким полям, например, может относиться поле 150 * AMessageInfo::LastModerated и т.д.) 151 * 152 * \param id_forum ID форума, для которого запрашивается список топиков 153 * (для ненулевого значения, будет произведено исключение одного лишнего преобразования из QVariant на каждый элемент, 154 * что положительно влияет на скорость) 155 * \param list Список топиков (с установленным полем ID, по которому будет производиться дальнейшее заполнение информацией). 156 * \param id_me ID текущего пользователя avalon. 157 * \param progress Прогресс выполнения операции. 158 */ 159 virtual bool getTopicInfoList (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress = NULL) = 0; 160 161 /*! 162 * \brief Заполняет информацию о всех сообщениях в топике (родительской ветке). 163 * 164 * Функция ДОЛЖНА заполнить все поля AMessageInfo плюс установить флаги AMessageInfoGUI::IsRead, AMessageInfo::HasChild в актуальные 165 * значения. 166 * 167 * Функция НЕ должна устанавливать флаг AMessageInfoGUI::IsInfoLoaded (устанавливается вызвающим кодом). 168 * 169 * Функция МОЖЕТ оставить некоторые поля AMessageInfo, которые не используются в текущем GUI, незаполненными в целях оптимизации 170 * скорости работы - в этом случае они должны иметь значения по умолчанию (к таким полям, например, может относиться поле 171 * AMessageInfo::LastModerated и т.д.) 172 * 173 * \param id_forum ID форума, для которого запрашивается список топиков 174 * (для ненулевого значения, будет произведено исключение одного лишнего преобразования из QVariant на каждый элемент, 175 * что положительно влияет на скорость) 149 176 * \param id_topic ID топика (темы, родительской ветки). 150 * \param list Список сообщений. 151 * \param id_me ID текущего пользователя 152 * \param progress Прогресс выполнения операции. 153 */ 154 virtual bool getTopicMessageList (int id_topic, ATopicInfoList& list, int id_me, IProgress* progress = NULL) = 0; 177 * \param list Список сообщений (изначально пустой, на выходе заполненый _не_ включая сообщение id_topic). 178 * \param factory Фабрика для создания элементов (каждый элемент списка создается вызовом IMessageInfoGUIFactory::createItem), 179 * поля (кроме Item) предполагаются заполненными значениями полей по умолчанию (см. AMessageInfoGUI::AMessageInfoGUI) 180 * и не меняются без необходимости. 181 * \param progress Прогресс выполнения операции. 182 */ 183 virtual bool getTopicMessageList (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress = NULL) = 0; 155 184 156 185 /*! -
trunk/storage/mysql_storage.cpp
r175 r191 34 34 else 35 35 IAStorage::setLastError(message); 36 37 close(); 36 38 37 39 return false; … … 1834 1836 sql += " `id_forum` = " + QString::number(id_forum) + "\n"; 1835 1837 sql += "ORDER BY\n"; 1836 sql += " `message_date` DESC"; 1838 // поскльку id_message автоинкремент и растет вместе с датой, то 1839 // можно условно положиться на то, что бОльшему id_message соответствует 1840 // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 1841 //sql += " `message_date` DESC"; 1842 sql += " `id_message` DESC"; 1837 1843 1838 1844 if (count > 0) … … 1846 1852 if (query_select.get() == NULL) 1847 1853 return returnError(AMySQLDatabase::getLastError()); 1854 1855 query_select->setForwardOnly(true); 1848 1856 1849 1857 if (query_select->exec() == false) … … 1875 1883 return returnError(AMySQLDatabase::getLastError()); 1876 1884 1885 query_select_unread_child->setForwardOnly(true); 1886 1877 1887 if (query_select_unread_child->exec() == false) 1878 1888 return returnError(query_select_unread_child->getLastError()); … … 1910 1920 return returnError(AMySQLDatabase::getLastError()); 1911 1921 1922 query_select_unread_topic->setForwardOnly(true); 1923 1912 1924 if (query_select_unread_topic->exec() == false) 1913 1925 return returnError(query_select_unread_topic->getLastError()); … … 1929 1941 //---------------------------------------------------------------------------------------------- 1930 1942 1931 bool AMySQLStorage::getTopicInfoList ( ATopicInfoList& list, int id_me, IProgress* progress)1943 bool AMySQLStorage::getTopicInfoList (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress) 1932 1944 { 1933 1945 if (progress != NULL) … … 1939 1951 for (int i = 0; i < list.count(); i++) 1940 1952 { 1941 ids += QString::number(list[i] .ID);1953 ids += QString::number(list[i]->ID); 1942 1954 1943 1955 if (i < list.count() - 1) … … 1949 1961 // 1950 1962 // получение инфы топика 1963 // часть полей, не принимающих участия в GUI, пропущена 1951 1964 // 1952 1965 1953 1966 sql += "SELECT\n"; 1954 1967 sql += " `id`,\n"; 1955 sql += " `id_topic`,\n";1956 sql += " `id_parent`,\n";1957 1968 sql += " `id_user`,\n"; 1958 1969 sql += " `id_forum`,\n"; 1959 1970 sql += " `subject`,\n"; 1960 sql += " `message_name`,\n";1961 1971 sql += " `user_nick`,\n"; 1962 sql += " `id_article`,\n";1963 1972 sql += " `message_date`,\n"; 1964 sql += " `update_date`,\n";1965 sql += " `user_role`,\n";1966 sql += " `user_title`,\n";1967 sql += " `user_title_color`,\n";1968 sql += " `last_moderated`,\n";1969 1973 sql += " `has_child`\n"; 1970 1974 sql += "FROM\n"; … … 1978 1982 return returnError(AMySQLDatabase::getLastError()); 1979 1983 1984 query_select->setForwardOnly(true); 1985 1980 1986 if (query_select->exec() == false) 1981 1987 return returnError(query_select->getLastError()); … … 1986 1992 1987 1993 for (int i = 0; i < list.count(); i++) 1988 if (id == list[i].ID) 1994 { 1995 AMessageInfoGUI* info = list[i]; 1996 1997 if (id == info->ID) 1989 1998 { 1990 list[i].IDTopic = query_select->value(1).toInt(); 1991 list[i].IDParent = query_select->value(2).toInt(); 1992 list[i].IDUser = query_select->value(3).toInt(); 1993 list[i].IDForum = query_select->value(4).toInt(); 1994 list[i].Subject = query_select->value(5).toString(); 1995 list[i].MessageName = query_select->value(6).toString(); 1996 list[i].UserNick = query_select->value(7).toString(); 1997 list[i].IDArticle = query_select->value(8).toInt(); 1998 list[i].MessageDate = query_select->value(9).toDateTime(); 1999 list[i].UpdateDate = query_select->value(10).toDateTime(); 2000 list[i].UserRole = query_select->value(11).toString(); 2001 list[i].UserTitle = query_select->value(12).toString(); 2002 list[i].UserTitleColor = query_select->value(13).toInt(); 2003 list[i].LastModerated = query_select->value(14).toDateTime(); 2004 list[i].HasChild = query_select->value(15).toInt(); 2005 2006 list[i].IsRead = true; 2007 list[i].HasUnreadChild = 0; 1999 // часть полей, не принимающих участия в GUI, оставлена без изменений 2000 info->IDTopic = 0; // всегда 0 для топиков 2001 info->IDParent = 0; // всегда 0 для топиков 2002 info->IDUser = query_select->value(1).toInt(); 2003 2004 if (id_forum != 0) 2005 info->IDForum = id_forum; 2006 else 2007 info->IDForum = query_select->value(2).toInt(); 2008 2009 info->Subject = query_select->value(3).toString(); 2010 info->UserNick = query_select->value(4).toString(); 2011 info->MessageDate = query_select->value(5).toDateTime(); 2012 info->HasChild = query_select->value(6).toInt(); 2008 2013 2009 2014 break; 2010 2015 } 2011 } 2012 2013 // 2014 // получение списка непрочитаных 2016 } 2017 } 2018 2019 // 2020 // получение списка непрочитаных топиков 2015 2021 // 2016 2022 … … 2028 2034 return returnError(AMySQLDatabase::getLastError()); 2029 2035 2036 query_select_unread->setForwardOnly(true); 2037 2030 2038 if (query_select_unread->exec() == false) 2031 2039 return returnError(query_select_unread->getLastError()); … … 2036 2044 2037 2045 for (int i = 0; i < list.count(); i++) 2038 if (id == list[i].ID) 2046 { 2047 AMessageInfoGUI* info = list[i]; 2048 2049 if (id == info->ID) 2039 2050 { 2040 list[i].IsRead = false;2051 info->IsRead = false; 2041 2052 break; 2042 2053 } 2054 } 2043 2055 } 2044 2056 … … 2063 2075 return returnError(AMySQLDatabase::getLastError()); 2064 2076 2077 query_select_unread_child->setForwardOnly(true); 2078 2065 2079 if (query_select_unread_child->exec() == false) 2066 2080 return returnError(query_select_unread_child->getLastError()); … … 2072 2086 2073 2087 for (int i = 0; i < list.count(); i++) 2074 if (id == list[i].ID) 2088 { 2089 AMessageInfoGUI* info = list[i]; 2090 2091 if (id == info->ID) 2075 2092 { 2076 2093 if (id_parent_user > 1) 2077 list[i].HasUnreadChild = 2;2078 else 2079 list[i].HasUnreadChild = 1;2094 info->HasUnreadChildMy = true; 2095 2096 info->HasUnreadChild = true; 2080 2097 2081 2098 break; 2082 2099 } 2100 } 2083 2101 } 2084 2102 … … 2087 2105 //---------------------------------------------------------------------------------------------- 2088 2106 2089 bool AMySQLStorage::getTopicMessageList (int id_ topic, ATopicInfoList& list, int id_me, IProgress* progress)2107 bool AMySQLStorage::getTopicMessageList (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress) 2090 2108 { 2109 2091 2110 if (progress != NULL) 2092 2111 progress->onProgress(0); … … 2096 2115 // 2097 2116 // получение сообщений топика 2117 // часть полей, не принимающих участия в GUI, пропущена 2098 2118 // 2099 2119 2100 2120 sql += "SELECT\n"; 2101 2121 sql += " `id`,\n"; 2102 sql += " `id_topic`,\n";2103 2122 sql += " `id_parent`,\n"; 2104 2123 sql += " `id_user`,\n"; 2105 2124 sql += " `id_forum`,\n"; 2106 2125 sql += " `subject`,\n"; 2107 sql += " `message_name`,\n";2108 2126 sql += " `user_nick`,\n"; 2109 sql += " `id_article`,\n";2110 2127 sql += " `message_date`,\n"; 2111 sql += " `update_date`,\n";2112 sql += " `user_role`,\n";2113 sql += " `user_title`,\n";2114 sql += " `user_title_color`,\n";2115 sql += " `last_moderated`,\n";2116 2128 sql += " `has_child`\n"; 2117 2129 sql += "FROM\n"; … … 2120 2132 sql += " `id_topic` = " + QString::number(id_topic) + "\n"; 2121 2133 sql += "ORDER BY\n"; 2122 sql += " `message_date` DESC"; 2134 // поскльку id автоинкремент и растет вместе с датой, то 2135 // можно условно положиться на то, что бОльшему id_message соответствует 2136 // бОльшая дата - в результате сортировка дает ~50% выигрыша в производительности 2137 //sql += " `message_date` DESC"; 2138 sql += " `id` DESC"; 2123 2139 2124 2140 std::auto_ptr<AQuery> query_select(createQuery(sql, false)); … … 2126 2142 if (query_select.get() == NULL) 2127 2143 return returnError(AMySQLDatabase::getLastError()); 2144 2145 query_select->setForwardOnly(true); 2128 2146 2129 2147 if (query_select->exec() == false) … … 2132 2150 while (query_select->next()) 2133 2151 { 2134 ATopicInfo info; 2135 2136 info.ID = query_select->value(0).toInt(); 2137 info.IDTopic = query_select->value(1).toInt(); 2138 info.IDParent = query_select->value(2).toInt(); 2139 info.IDUser = query_select->value(3).toInt(); 2140 info.IDForum = query_select->value(4).toInt(); 2141 info.Subject = query_select->value(5).toString(); 2142 info.MessageName = query_select->value(6).toString(); 2143 info.UserNick = query_select->value(7).toString(); 2144 info.IDArticle = query_select->value(8).toInt(); 2145 info.MessageDate = query_select->value(9).toDateTime(); 2146 info.UpdateDate = query_select->value(10).toDateTime(); 2147 info.UserRole = query_select->value(11).toString(); 2148 info.UserTitle = query_select->value(12).toString(); 2149 info.UserTitleColor = query_select->value(13).toInt(); 2150 info.LastModerated = query_select->value(14).toDateTime(); 2151 info.HasChild = query_select->value(15).toInt(); 2152 2153 info.IsRead = true; 2154 info.HasUnreadChild = 0; 2152 AMessageInfoGUI* info = factory->createItem(); 2153 2154 // часть полей, не принимающих участия в GUI, оставлена без изменений 2155 info->ID = query_select->value(0).toInt(); 2156 info->IDTopic = id_topic; 2157 info->IDParent = query_select->value(1).toInt(); 2158 info->IDUser = query_select->value(2).toInt(); 2159 2160 if (id_forum != 0) 2161 info->IDForum = id_forum; 2162 else 2163 info->IDForum = query_select->value(3).toInt(); 2164 2165 info->Subject = query_select->value(4).toString(); 2166 info->UserNick = query_select->value(5).toString(); 2167 info->MessageDate = query_select->value(6).toDateTime(); 2168 info->HasChild = query_select->value(7).toInt(); 2155 2169 2156 2170 list.append(info); … … 2163 2177 sql = ""; 2164 2178 sql += "SELECT\n"; 2165 sql += " `id_message`,\n"; 2166 sql += " `id_parent_user`\n"; 2179 sql += " `id_message`\n"; 2167 2180 sql += "FROM\n"; 2168 2181 sql += " `unread`\n"; … … 2177 2190 return returnError(AMySQLDatabase::getLastError()); 2178 2191 2192 query_select_unread->setForwardOnly(true); 2193 2179 2194 if (query_select_unread->exec() == false) 2180 2195 return returnError(query_select_unread->getLastError()); … … 2183 2198 { 2184 2199 int id = query_select_unread->value(0).toInt(); 2185 int id_parent_user = query_select_unread->value(1).toInt();2186 2200 2187 2201 for (int i = 0; i < list.count(); i++) 2188 if (list[i] .ID == id)2202 if (list[i]->ID == id) 2189 2203 { 2190 if (id_parent_user == id_me) 2191 list[i].HasUnreadChild = 2; 2192 2193 list[i].IsRead = false; 2194 //list.move(i, 0); 2204 list[i]->IsRead = false; 2205 2206 list.move(i, 0); 2207 2195 2208 break; 2196 2209 } -
trunk/storage/mysql_storage.h
r175 r191 57 57 bool getUnreadCount (AUnreadForumCountInfoList& list, IProgress* progress = NULL); 58 58 bool getForumTopicList (int id_forum, int count, QList<int>& list, IProgress* progress = NULL); 59 bool getTopicInfoList ( ATopicInfoList& list, int id_me, IProgress* progress = NULL);60 bool getTopicMessageList (int id_ topic, ATopicInfoList& list, int id_me, IProgress* progress = NULL);59 bool getTopicInfoList (int id_forum, AMessageInfoGUIPtrList& list, int id_me, IProgress* progress = NULL); 60 bool getTopicMessageList (int id_forum, int id_topic, AMessageInfoGUIPtrList& list, IMessageInfoGUIFactory* factory, IProgress* progress = NULL); 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); -
trunk/sysheaders.h
r175 r191 82 82 #define DEBUG_MSG(x) QMessageBox::critical(0, QString::fromUtf8("Ошибка!"), x) 83 83 84 /*! 85 * \brief Макрос для отладки и легкого вывода алерта (числа), в релизе использоваться не должен. 86 * \param x число для вывода. 87 */ 88 #define DEBUG_INT(x) DEBUG_MSG(QString::number(x)) 89 84 90 #ifndef Q_WS_WIN 85 91 … … 91 97 class AProfiler 92 98 { 93 public:99 public: 94 100 95 101 /*! 96 102 * \brief При создании экземпляра создается первая отсечка времени. 97 103 */ 98 AProfiler ()99 {100 Start();101 }104 AProfiler () 105 { 106 start(); 107 } 102 108 103 109 /*! … … 105 111 * при повторном вызове заменяет старую отсечку времени текущей. 106 112 */ 107 void Start ()108 {109 gettimeofday(&m_start, 0);110 }113 void start () 114 { 115 gettimeofday(&m_start, 0); 116 } 111 117 112 118 /*! 113 119 * \brief Создание второй отсечки времени и вывод разницы между текущей отсечкой и стартовой в миллисекундах. 120 * \param ittr Количество итераций 114 121 */ 115 void Stop ()116 {117 gettimeofday(&m_stop, 0);122 void stop (int ittr = 1) 123 { 124 gettimeofday(&m_stop, 0); 118 125 119 long long int delta = (m_stop.tv_sec - m_start.tv_sec) * 1000 + (m_stop.tv_usec - m_start.tv_usec) / 1000;126 long long int delta = (m_stop.tv_sec - m_start.tv_sec) * 1000 + (m_stop.tv_usec - m_start.tv_usec) / 1000; 120 127 121 QString msg = QString::number(delta) + "ms";128 QString msg; 122 129 123 QMessageBox::information(0, QString::fromUtf8("Таймер!"), msg);124 } 130 msg += QString::fromUtf8("Общее время : ") + QString::number(delta) + " ms\n"; 131 msg += QString::fromUtf8("Среднее время : ") + QString::number(delta / ittr) + " ms"; 125 132 126 private: 133 QMessageBox::information(0, QString::fromUtf8("Таймер!"), msg); 134 } 135 136 private: 127 137 128 138 /*! 129 139 * \brief Время вызова функции Start(). 130 140 */ 131 timeval m_start; 141 timeval m_start; 142 132 143 /*! 133 144 * \brief Время вызова функции Stop(). 134 145 */ 135 timeval m_stop;146 timeval m_stop; 136 147 }; 137 148 -
trunk/version.h
r180 r191 20 20 * \brief Дата билда (заменяется автоматически при каждом билде в version.h, что и приводит к смене номера ревизии) 21 21 */ 22 #define AVALON_DATE " Пнд Мар 23 16:10:17MSK 2009"22 #define AVALON_DATE "Сбт Мар 28 03:20:28 MSK 2009" 23 23 24 24 #endif -
trunk/webservice.cpp
r152 r191 97 97 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 98 98 header += "Host: rsdn.ru\r\n"; 99 header += "Connection: close\r\n"; 100 header += "Accept-Encoding: gzip, deflate\r\n"; 101 header += "User-Agent: " + getVersionString() + "\r\n"; 99 102 header += "Content-Type: text/xml; charset=utf-8\r\n"; 100 103 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; … … 233 236 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 234 237 header += "Host: rsdn.ru\r\n"; 238 header += "Connection: close\r\n"; 239 header += "Accept-Encoding: gzip, deflate\r\n"; 240 header += "User-Agent: " + getVersionString() + "\r\n"; 235 241 header += "Content-Type: text/xml; charset=utf-8\r\n"; 236 242 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; … … 357 363 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 358 364 header += "Host: rsdn.ru\r\n"; 365 header += "Connection: close\r\n"; 366 header += "Accept-Encoding: gzip, deflate\r\n"; 367 header += "User-Agent: " + getVersionString() + "\r\n"; 359 368 header += "Content-Type: text/xml; charset=utf-8\r\n"; 360 369 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; … … 514 523 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 515 524 header += "Host: rsdn.ru\r\n"; 525 header += "Connection: close\r\n"; 526 header += "Accept-Encoding: gzip, deflate\r\n"; 527 header += "User-Agent: " + getVersionString() + "\r\n"; 516 528 header += "Content-Type: text/xml; charset=utf-8\r\n"; 517 529 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; … … 719 731 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 720 732 header += "Host: rsdn.ru\r\n"; 733 header += "Connection: close\r\n"; 734 header += "Accept-Encoding: gzip, deflate\r\n"; 735 header += "User-Agent: " + getVersionString() + "\r\n"; 721 736 header += "Content-Type: text/xml; charset=utf-8\r\n"; 722 737 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n"; … … 784 799 header += "POST /ws/janusAT.asmx HTTP/1.1\r\n"; 785 800 header += "Host: rsdn.ru\r\n"; 801 header += "Connection: close\r\n"; 802 header += "Accept-Encoding: gzip, deflate\r\n"; 803 header += "User-Agent: " + getVersionString() + "\r\n"; 786 804 header += "Content-Type: text/xml; charset=utf-8\r\n"; 787 805 header += (QString)"Content-Length: " + QString::number(data.length()) + "\r\n";
Note: See TracChangeset
for help on using the changeset viewer.
