FormMessage::FormMessage (QWidget* parent, bool is_reply, const AMessageInfoGUI& info, int edit_id) : FormMessageUI (parent) { m_text_changed = false; if (edit_id != 0) is_reply = false; m_edit_id = edit_id; connect(m_text_view->View->page(), SIGNAL(linkClicked(const QUrl&)), this, SLOT(link_clicked(const QUrl&))); connect(m_text_view->View->page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)), this, SLOT(link_hover(const QString&, const QString&, const QString&))); m_forum_tree = NULL; m_main_form = NULL; m_info = info; if (m_edit_id == 0) { m_info.IDParent = m_info.ID; m_info.ID = 0; } // получение информации о форуме сообщения // работает "по тихому", т.к. если возникнет ошибка, то это не сильно принципиально // и можно продолжать нормальную работу, а не пугать пользователя // https://rsdn.ru/forum/janus/3315591.1 std::auto_ptr<IAStorage> storage(AStorageFactory::getStorage()); if (storage.get() != NULL) { AForumInfo forum_info; if (storage->getForumInfo(m_info.IDForum, forum_info) != false) m_forum_info = forum_info; } // формирование текста при ответе if (is_reply == true) { QString subject = m_info.Subject; QString body = m_info.Message; // // корректировка темы // if (subject.length() > 3 && subject.mid(0, 4) == "Re: ") subject.insert(2, "[2]"); else if (subject.length() > 3 && subject.mid(0, 3) == "Re[") { int pos = subject.indexOf("]"); if (pos != -1) { int num = subject.mid(3, pos - 3).toInt(); if (num == 0) subject = "Re: " + subject; else { subject.remove(3, pos - 3); subject.insert(3, QString::number(num + 1)); } } else subject = "Re: " + subject; } else subject = "Re: " + subject; m_info.Subject = subject; // // корректировка тела сообщения // body = AFormatter::normalizeBody(body, info.UserNick).trimmed(); if (body.length() > 0) body += "\r\n\r\n"; if (info.IDUser == 0) body = QString::fromUtf8("Здравствуйте, Аноним, Вы писали:\r\n\r\n") + body; else body = QString::fromUtf8("Здравствуйте, ") + info.UserNick + QString::fromUtf8(", Вы писали:\r\n\r\n") + body; m_info.Message = body; } // if (is_reply == true) else { // замена HTML спец-символов m_info.Message.replace(">", ">"); m_info.Message.replace("<", "<"); m_info.Message.replace("&", "&"); } // удаление таглайнов QRegExp tagline("\\[tagline\\](.+)\\[/tagline\\]"); tagline.setMinimal(true); m_info.Message.replace(tagline, ""); //m_info.Message = m_info.Message.trimmed(); // установка остальных полей m_text_subject->setText(m_info.Subject); m_text_source->setPlainText(m_info.Message); text_subject_text_changed(m_info.Subject); if (is_reply == true) { QIcon icon; icon.addFile(":/icons/reply16.png", QSize(16, 16)); icon.addFile(":/icons/reply22.png", QSize(22, 22)); icon.addFile(":/icons/reply32.png", QSize(32, 32)); icon.addFile(":/icons/reply48.png", QSize(48, 48)); setWindowIcon(icon); m_text_source->setFocus(); m_text_source->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); } else if (m_edit_id != 0) { QIcon icon; icon.addFile(":/icons/edit16.png", QSize(16, 16)); icon.addFile(":/icons/edit22.png", QSize(22, 22)); icon.addFile(":/icons/edit32.png", QSize(32, 32)); icon.addFile(":/icons/edit48.png", QSize(48, 48)); icon.addFile(":/icons/edit64.png", QSize(64, 64)); setWindowIcon(icon); m_text_source->setFocus(); m_text_source->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); } else { m_text_subject->setFocus(); m_text_subject->selectAll(); } // установка обработчиков формы connect(m_button_send, SIGNAL(triggered()), this, SLOT(button_send_triggered())); connect(m_button_draft, SIGNAL(triggered()), this, SLOT(button_draft_triggered())); connect(m_text_subject, SIGNAL(textChanged(const QString&)), this, SLOT(text_subject_text_changed(const QString&))); connect(m_tab_message, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int))); connect(m_text_source, SIGNAL(textChanged()), this, SLOT(text_changed())); }
QString AFormatter::normalizeBody (const QString& body, const QString& nick) { QString data = body; // отбрасываем "[tagline]" и "[moderator]" QRegExp tagline("\\[tagline\\](.+)\\[/tagline\\]", Qt::CaseInsensitive); QRegExp moderator("\\[moderator\\](.+)\\[/moderator\\]", Qt::CaseInsensitive); tagline.setMinimal(true); moderator.setMinimal(true); data.replace(tagline, ""); data.replace(moderator, ""); // удаляем img с даными вместо ссылки (например, см. http://www.rsdn.ru/forum/flame.comp/4077971.1.aspx) QRegExp img1("\\[img\\]data:(\\S+)\\[/img\\]", Qt::CaseInsensitive); img1.setMinimal(true); data.replace(img1, ""); // заменяем [img]...[/img] на ссылку QRegExp img2("\\[img\\](\\S+)\\[/img\\]", Qt::CaseInsensitive); img2.setMinimal(true); data.replace(img2, QString::fromUtf8("[url=\\1]\\1[/url]")); // укорачивание длинных ссылок (например, см. http://www.rsdn.ru/forum/web/4086359.1.aspx) QRegExp url1("\\[url=data:(\\S+)\\](.+)\\[/url\\]", Qt::CaseInsensitive); url1.setMinimal(true); data.replace(url1, "[url=bad%20link]\\2[/url]"); // удаление тэга цитирования QRegExp q1("(^|[^\\[])\\[q\\]", Qt::CaseInsensitive); q1.setMinimal(true); data.replace(q1, "\\1"); QRegExp q2("(^|[^\\[])\\[/q\\]", Qt::CaseInsensitive); q2.setMinimal(true); data.replace(q2, "\\1"); // удаление таблиц из цитирования QRegExp table("(^|[^\\[])\\[t\\](.+)\\[/t\\]", Qt::CaseInsensitive); table.setMinimal(true); data.replace(table, "\\1"); // удаление тэгов [h1]..[h6] из цитирования for (int i = 1; i < 7; i++) { QRegExp h1("(^|[^\\[])\\[h" + QString::number(i) + "\\]", Qt::CaseInsensitive); h1.setMinimal(true); data.replace(h1, "\\1"); QRegExp h2("(^|[^\\[])\\[/h" + QString::number(i) + "\\]", Qt::CaseInsensitive); h2.setMinimal(true); data.replace(h2, "\\1"); } data = data.trimmed(); // разбиение QStringList source = data.split("\n"); QString nick_3 = AFormatter::nick3(nick); // добавление квотинга к строкам for (int i = 0; i < source.size(); i++) if (source[i].trimmed().length()) source[i] = nick_3 + "> " + source[i]; // удаление дублирующихся пустых строк int index = 0; // регексп для приветствий в квотинге QRegExp hello(QString::fromUtf8(">\\s{0,}Здравствуйте,\\s.+,\\sВы писали:")); while (index < source.size() - 1) { if (source.at(index).trimmed().length() == 0 && source.at(index + 1).trimmed().length() == 0) { source.removeAt(index); continue; } else if (source.at(index).indexOf(hello) != -1) { source.removeAt(index); if (index > 0) index--; continue; } index++; } // вычисление уровня квотинга QList<int> quoting_level; int size = source.size(); for (int i = 0; i < size; i++) { QString temp = source.at(i).trimmed(); int level = 0; for (int j = 0; j < temp.length() - 3; j++) { if (temp[j] == ' ' && !(temp[j + 1] == '&' || temp[j + 2] == '&' || temp[j + 3] == '&')) break; else if (temp[j] == '&' && temp[j + 1] == 'g' && temp[j + 2] == 't' && temp[j + 3] == ';') { level++; j += 3; } else if (temp[j] == '&' && temp[j + 1] == 'l' && temp[j + 2] == 't' && temp[j + 3] == ';') break; } quoting_level.append(level); source[i] = temp; } // вставка пустых строк между разными уровнями квотинга for (int i = 0; i < size - 1; i++) { if (source[i].length() == 0) continue; if (quoting_level.at(i) != quoting_level.at(i + 1) && source[i + 1].length() /*&& (quoting_level.at(i) == 0 || quoting_level.at(i + 1) == 0)*/) source[i] = source[i] + "\r\n"; } data = source.join("\r\n").trimmed(); // замена HTML спец-символов data.replace(">", ">"); data.replace("<", "<"); data.replace("&", "&"); return data; }