Пример #1
0
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("&gt;",  ">");
		m_info.Message.replace("&lt;",  "<");
		m_info.Message.replace("&amp;", "&");
	}

	// удаление таглайнов
	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()));
}
Пример #2
0
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("&gt;",  ">");
	data.replace("&lt;",  "<");
	data.replace("&amp;", "&");

	return data;
}