void tst_QStringMatcher::qstringmatcher() { QStringMatcher matcher; QCOMPARE(matcher.caseSensitivity(), Qt::CaseSensitive); QCOMPARE(matcher.indexIn("foo", 1), 1); QCOMPARE(matcher.pattern(), QString()); }
QString &WebKitMessageViewStyle::fillKeywords(QString &inString, const qutim_sdk_0_3::Message &message, bool contentIsSimilar) { Q_D(WebKitMessageViewStyle); UnitData contentSource = getSourceData(message); UnitData theSource; // if (message.isIncoming() && message.chatUnit()->upperUnit()) // theSource = getSourceData(message.chatUnit()->upperUnit()); // else theSource = contentSource; QStringList displayClasses = message.property("displayClasses", QStringList()); QString htmlEncodedMessage = message.html(); // Actions support if (htmlEncodedMessage.startsWith(QLatin1String("/me "), Qt::CaseInsensitive)) { displayClasses << QLatin1String("action"); htmlEncodedMessage.remove(0, 3); if (!hasAction()) htmlEncodedMessage = QString::fromLatin1(ACTION_SPAN).arg(contentSource.title, htmlEncodedMessage); } //date QDateTime date = message.time(); bool isService = message.property("service", false); bool isTopic = message.property("topic", false); bool isAutoreply = message.property("autoreply", false); //Replacements applicable to any AIContentObject inString.replace(QLatin1String("%time%"), convertTimeDate(d->timeStampFormatter, date)); QString messageId = message.property("messageId").toString(); if (messageId.isEmpty()) messageId = QString::number(message.id()); inString.replace(QLatin1String("%messageId%"), QLatin1String("message") + messageId); inString.replace(QLatin1String("%shortTime%"), date.toString(Qt::SystemLocaleShortDate)); // FIXME: Implement // inString.replace(QLatin1String("%senderStatusIcon%"), QUrl) // if ([inString rangeOfString:@"%senderStatusIcon%"].location != NSNotFound) { // //Only cache the status icon to disk if the message style will actually use it // [inString replaceKeyword:@"%senderStatusIcon%" // withString:[self statusIconPathForListObject:theSource]]; // } inString.replace(QLatin1String("%userIcons%"), QLatin1String(d->showUserIcons ? "showIcons" : "hideIcons")); // Known classes: // "mention" == highlight // "history" // "consecutive" // "action" == /me // "firstFocus" == first received message after we switched to another tab // "focus" == we haven't seen this message if (message.property("focus", false)) displayClasses << QLatin1String("focus"); if (message.property("firstFocus", false)) displayClasses << QLatin1String("firstFocus"); if (isAutoreply) displayClasses << QLatin1String("autoreply"); if (message.property("mention", false)) displayClasses << QLatin1String("mention"); if (!isTopic && isService) { displayClasses << QLatin1String("status"); // Implement more logic way // May be status messages should provide information about previous and current statuses? displayClasses << message.property("statusType", QString()); } else { if (message.property("history", false)) displayClasses << QLatin1String("history"); displayClasses << QLatin1String("message"); displayClasses << QLatin1String(message.isIncoming() ? "incoming" : "outgoing"); } inString.replace(QLatin1String("%messageClasses%"), QLatin1String(contentIsSimilar ? "consecutive " : "") + displayClasses.join(QLatin1String(" "))); inString.replace(QLatin1String("%senderColor%"), WebKitColorsAdditions::representedColorForObject(contentSource.id, validSenderColors())); inString.replace(QLatin1String("%messageDirection%"), QLatin1String(message.text().isRightToLeft() ? "rtl" : "ltr")); //Replaces %time{x}% with a timestamp formatted like x (using NSDateFormatter) const QStringMatcher matcher(QLatin1String("%time{")); const int matcherSize = matcher.pattern().size(); const QStringMatcher endMatcher(QLatin1String("}%")); const int endMatcherSize = endMatcher.pattern().size(); int range = 0; do { range = matcher.indexIn(inString, range); if (range != -1) { int endRange = endMatcher.indexIn(inString, range + matcherSize); if (endRange != -1) { QString timeFormat = inString.mid(range + matcherSize, endRange - range - matcherSize); QString time = convertTimeDate(timeFormat, date); inString.replace(range, endRange + endMatcherSize - range, time); range = range + time.size(); } } } while (range != -1); QString userIconPath; if (d->showUserIcons) userIconPath = urlFromFilePath(theSource.avatar); if (userIconPath.isEmpty()) userIconPath = QLatin1String(message.isIncoming() ? "Incoming/buddy_icon.png" : "Outgoing/buddy_icon.png"); inString.replace(QLatin1String("%userIconPath%"), userIconPath); // Implement the way to get shortDescription and icon path for service icons QString service = message.chatUnit() ? message.chatUnit()->account()->protocol()->id() : QString(); inString.replace(QLatin1String("%service%"), escapeString(service)); inString.replace(QLatin1String("%serviceIconPath%"), QString() /*content.chat->account.protocol.iconPath*/); inString.replace(QLatin1String("%variant%"), activeVariantPath()); bool replacedStatusPhrase = false; //message stuff if (isTopic || !isService) { //Use content.source directly rather than the potentially-metaContact theSource QString formattedUID = contentSource.id; QString displayName = contentSource.title; inString.replace(QLatin1String("%status%"), QString()); inString.replace(QLatin1String("%senderScreenName%"), escapeString(formattedUID)); // Should be used as %, @, + or something like irc's channel statuses inString.replace(QLatin1String("%senderPrefix%"), message.property("senderPrefix", QString())); QString senderDisplay = displayName; if (isAutoreply) { senderDisplay += " "; senderDisplay += QObject::tr("(Autoreply)"); } inString.replace(QLatin1String("%sender%"), escapeString(senderDisplay)); // Should be server-side display name if possible inString.replace(QLatin1String("%senderDisplayName%"), escapeString(displayName)); // Add support for %textbackgroundcolor{alpha?}% // Background should be caught from content's html // FIXME: Add support // if ([content isKindOfClass:[ESFileTransfer class]]) { //file transfers are an AIContentMessage subclass // ESFileTransfer *transfer = (ESFileTransfer *)content; // NSString *fileName = [[transfer remoteFilename] stringByEscapingForXMLWithEntities:nil]; // NSString *fileTransferID = [[transfer uniqueID] stringByEscapingForXMLWithEntities:nil]; // range = [inString rangeOfString:@"%fileIconPath%"]; // if (range.location != NSNotFound) { // NSString *iconPath = [self iconPathForFileTransfer:transfer]; // NSImage *icon = [transfer iconImage]; // do{ // [[icon TIFFRepresentation] writeToFile:iconPath atomically:YES]; // [inString safeReplaceCharactersInRange:range withString:iconPath]; // range = [inString rangeOfString:@"%fileIconPath%"]; // } while (range.location != NSNotFound); // } // [inString replaceKeyword:@"%fileName%" // withString:fileName]; // [inString replaceKeyword:@"%saveFileHandler%" // withString:[NSString stringWithFormat:@"client.handleFileTransfer('Save', '%@')", fileTransferID]]; // [inString replaceKeyword:@"%saveFileAsHandler%" // withString:[NSString stringWithFormat:@"client.handleFileTransfer('SaveAs', '%@')", fileTransferID]]; // [inString replaceKeyword:@"%cancelRequestHandler%" // withString:[NSString stringWithFormat:@"client.handleFileTransfer('Cancel', '%@')", fileTransferID]]; // } //Message (must do last) inString.replace(QLatin1String("%message%"), htmlEncodedMessage); // Topic replacement (if applicable) if (isTopic && inString.contains(QLatin1String("%topic%"))) { inString.replace(QLatin1String("%topic%"), QString::fromLatin1(TOPIC_INDIVIDUAL_WRAPPER).arg(htmlEncodedMessage)); } } else { inString.replace(QLatin1String("%status%"), escapeString(message.property("status", QString()))); inString.replace(QLatin1String("%statusSender%"), QString()); inString.replace(QLatin1String("%senderScreenName%"), QString()); inString.replace(QLatin1String("%senderPrefix%"), QString()); inString.replace(QLatin1String("%sender%"), QString()); QString statusPhrase = message.property("statusPhrase", QString()); if (!statusPhrase.isEmpty() && inString.contains(QLatin1String("%statusPhrase%"))) { inString.replace(QLatin1String("%statusPhrase%"), escapeString(statusPhrase)); replacedStatusPhrase = true; } //Message (must do last) inString.replace(QLatin1String("%message%"), replacedStatusPhrase ? QString() : htmlEncodedMessage); } return inString; }
QString &WebKitMessageViewStyle::fillKeywordsForBaseTemplate(QString &inString, qutim_sdk_0_3::ChatSession *session) { Q_D(WebKitMessageViewStyle); ChatUnit *unit = session->unit(); Account *account = unit->account(); Protocol *protocol = account->protocol(); // FIXME: Should be session->title inString.replace(QLatin1String("%chatName%"), escapeString(unit->title())); inString.replace(QLatin1String("%sourceName%"), escapeString(account->name())); inString.replace(QLatin1String("%destinationName%"), escapeString(unit->id())); inString.replace(QLatin1String("%destinationDisplayName%"), escapeString(unit->title())); QString iconPath; inString.replace(QLatin1String("%incomingColor%"), WebKitColorsAdditions::representedColorForObject(unit->id(), validSenderColors())); inString.replace(QLatin1String("%outgoingColor%"), WebKitColorsAdditions::representedColorForObject(account->name(), validSenderColors())); iconPath = urlFromFilePath(unit->property("avatar").toString()); if (iconPath.isEmpty()) { ChatUnit *contact = unit->upperUnit(); while (contact && iconPath.isEmpty()) { iconPath = contact->property("avatar").toString(); contact = contact->upperUnit(); } } inString.replace(QLatin1String("%incomingIconPath%"), iconPath.isEmpty() ? QString::fromLatin1("incoming_icon.png") : iconPath); iconPath = urlFromFilePath(account->property("avatar").toString()); inString.replace(QLatin1String("%outgoingIconPath%"), iconPath.isEmpty() ? QString::fromLatin1("outgoing_icon.png") : iconPath); // FIXME: Implement protocol.iconPath and protocol.shortDescription QString serviceIconPath = QString(); //account.protocol.iconPath; QString serviceIconTag = QString::fromLatin1("<img class=\"serviceIcon\" src=\"%1\" alt=\"%2\" title=\"%2\">") .arg(serviceIconPath.isEmpty() ? QString::fromLatin1("outgoing_icon.png") : serviceIconPath, protocol->id() /*shortDescription*/ ); inString.replace(QLatin1String("%serviceIconImg%"), serviceIconTag); inString.replace(QLatin1String("%serviceIconPath%"), serviceIconPath); inString.replace(QLatin1String("%timeOpened%"), convertTimeDate(d->timeStampFormatter, session->dateOpened())); //Replaces %time{x}% with a timestamp formatted like x (using NSDateFormatter) const QStringMatcher matcher(QLatin1String("%timeOpened{")); const int matcherSize = matcher.pattern().size(); const QStringMatcher endMatcher(QLatin1String("}%")); const int endMatcherSize = endMatcher.pattern().size(); int range = 0; do { range = matcher.indexIn(inString, range); if (range != -1) { int endRange = endMatcher.indexIn(inString, range + matcherSize); if (endRange != -1) { QString timeFormat = inString.mid(range + matcherSize, endRange - range - matcherSize); QString time = convertTimeDate(timeFormat, session->dateOpened()); inString.replace(range, endRange + endMatcherSize - range, time); range = range + time.size(); } } } while (range != -1); inString.replace(QLatin1String("%dateOpened%"), session->dateOpened().toString(Qt::SystemLocaleLongDate)); //Background { QLatin1String bodyBackground("==bodyBackground=="); range = inString.indexOf(bodyBackground); if (range != -1) { //a backgroundImage tag is not required QString bodyTag; if (d->allowsCustomBackground && (!d->customBackgroundPath.isEmpty() || d->customBackgroundColor.isValid())) { if (!d->customBackgroundPath.isNull()) { if (d->customBackgroundPath.length() > 0) { switch (d->customBackgroundType) { case BackgroundNormal: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: no-repeat; background-attachment:fixed;").arg(d->customBackgroundPath)); break; case BackgroundCenter: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-position: center; background-repeat: no-repeat; background-attachment:fixed;").arg(d->customBackgroundPath)); break; case BackgroundTile: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: repeat;").arg(d->customBackgroundPath)); break; case BackgroundTileCenter: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: repeat; background-position: center;").arg(d->customBackgroundPath)); break; case BackgroundScale: bodyTag.append(QString::fromLatin1("background-image: url('%1'); -webkit-background-size: 100%% 100%%; background-size: 100%% 100%%; background-attachment: fixed;").arg(d->customBackgroundPath)); break; } } else { bodyTag.append(QLatin1String("background-image: none; ")); } } if (d->customBackgroundColor.isValid()) { qreal red, green, blue, alpha; d->customBackgroundColor.getRgbF(&red, &green, &blue, &alpha); bodyTag.append(QString::fromLatin1("background-color: rgba(%1, %2, %3, %4); ") .arg(QString::number(int(red * 255.0)), QString::number(int(green * 255.0)), QString::number(int(blue * 255.0)), QString::number(alpha, 'f'))); } } //Replace the body background tag inString.replace(range, qstrlen(bodyBackground.latin1()), bodyTag); } } inString.replace(QLatin1String("%variant%"), activeVariantPath()); return inString; }