/*!
    \fn QString QAbstractTextDocumentLayout::anchorAt(const QPointF &position) const

    Returns the reference of the anchor the given \a position, or an empty
    string if no anchor exists at that point.
*/
QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const
{
    int cursorPos = hitTest(pos, Qt::ExactHit);
    if (cursorPos == -1)
        return QString();

    // compensate for preedit in the hit text block
    QTextBlock block = document()->firstBlock();
    while (block.isValid()) {
        QRectF blockBr = blockBoundingRect(block);
        if (blockBr.contains(pos)) {
            QTextLayout *layout = block.layout();
            int relativeCursorPos = cursorPos - block.position();
            const int preeditLength = layout ? layout->preeditAreaText().length() : 0;
            if (preeditLength > 0 && relativeCursorPos > layout->preeditAreaPosition())
                cursorPos -= qMin(cursorPos - layout->preeditAreaPosition(), preeditLength);
            break;
        }
        block = block.next();
    }

    QTextDocumentPrivate *pieceTable = qobject_cast<const QTextDocument *>(parent())->docHandle();
    QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
    QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
    return fmt.anchorHref();
}
/*!
    \fn QString QAbstractTextDocumentLayout::anchorAt(const QPointF &position) const

    Returns the reference of the anchor the given \a position, or an empty
    string if no anchor exists at that point.
*/
QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const
{
    int cursorPos = hitTest(pos, Qt::ExactHit);
    if (cursorPos == -1)
        return QString();

    QTextDocumentPrivate *pieceTable = qobject_cast<const QTextDocument *>(parent())->docHandle();
    QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
    QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
    return fmt.anchorHref();
}
Exemple #3
0
void MoveViewController::selectAndMarkAnchor(const QString& link)
{
    QTextBlock block = this->document->begin();
    while(block != this->document->end())
    {
        QTextBlock::iterator it;
        for(it = block.begin(); !it.atEnd(); ++it)
        {
            QTextFragment fragment = it.fragment();
            if(!fragment.isValid())
            {
                continue;
            }
            QTextCharFormat format = fragment.charFormat();
            if(format.isAnchor() && format.anchorHref() == link)
            {
                QTextCursor cursor = this->textCursor();
                cursor.setPosition(fragment.position());
                int len = 0;
                bool finished = false;
                // we want to mark (highlight) everything from the
                // start of the anchor until the end of the move
                // the end of the move is indicated by an empty space
                // (there is always an empty space after a move)
                while(!finished && !it.atEnd()) {
                    if(it.fragment().text().startsWith(" ") || len >= 6) {
                        finished = true;
                    } else {
                        len+= it.fragment().text().length();
                        it++;
                    }
                }
                cursor.setPosition(fragment.position() + len, QTextCursor::KeepAnchor);
                setTextCursor(cursor);
                ensureCursorVisible();
                return;
            }
        }
    block = block.next();
    }
}
int TextCharFormat::anchorHref(lua_State * L) // const : QString
{
	QTextCharFormat* lhs = ValueInstaller2<QTextCharFormat>::check( L, 1 );
	lua_pushstring(L, lhs->anchorHref().toLatin1() );
	return 1;
}
Exemple #5
0
void KoTextWriter::saveParagraph(const QTextBlock &block, int from, int to)
{
    QString changeName = QString();

    QTextBlockFormat blockFormat = block.blockFormat();
    int outlineLevel = blockFormat.intProperty(KoParagraphStyle::OutlineLevel);
    if (outlineLevel > 0) {
        d->writer->startElement("text:h", false);
        d->writer->addAttribute("text:outline-level", outlineLevel);
    } else 
        d->writer->startElement("text:p", false);

    QString styleName = saveParagraphStyle(block);
    if (!styleName.isEmpty())
        d->writer->addAttribute("text:style-name", styleName);

    // Write the fragments and their formats
    QTextCursor cursor(block);
    QTextCharFormat blockCharFormat = cursor.blockCharFormat();
    QTextCharFormat previousCharFormat;
    QTextBlock::iterator it;
    for (it = block.begin(); !(it.atEnd()); ++it) {
        QTextFragment currentFragment = it.fragment();
        const int fragmentStart = currentFragment.position();
        const int fragmentEnd = fragmentStart + currentFragment.length();
        if (to != -1 && fragmentStart >= to)
            break;
        if (currentFragment.isValid()) {
            QTextCharFormat charFormat = currentFragment.charFormat();
            QTextCharFormat compFormat = charFormat;
            bool identical;
            previousCharFormat.clearProperty(KoCharacterStyle::ChangeTrackerId);
            compFormat.clearProperty(KoCharacterStyle::ChangeTrackerId);
            if (previousCharFormat == compFormat)
                identical = true;
            else
                identical = false;

            if ( d->changeTracker && d->changeTracker->containsInlineChanges(charFormat) && d->changeTracker->elementById(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt())->isEnabled()) {
                KoGenChange change;
                d->changeTracker->saveInlineChange(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt(), change);
                changeName = d->sharedData->genChanges().insert(change);
                d->writer->startElement("text:change-start", false);
                d->writer->addAttribute("text:change-id", changeName);
                d->writer->endElement();
            }

            KoInlineObject *inlineObject = d->layout->inlineTextObjectManager()->inlineTextObject(charFormat);
            if (currentFragment.length() == 1 && inlineObject
                    && currentFragment.text()[0].unicode() == QChar::ObjectReplacementCharacter) {
                inlineObject->saveOdf(d->context);
            } else {
                QString styleName = saveCharacterStyle(charFormat, blockCharFormat);
                if (charFormat.isAnchor()) {
                    d->writer->startElement("text:a", false);
                    d->writer->addAttribute("xlink:type", "simple");
                    d->writer->addAttribute("xlink:href", charFormat.anchorHref());
                } else if (!styleName.isEmpty() /*&& !identical*/) {
                    d->writer->startElement("text:span", false);
                    d->writer->addAttribute("text:style-name", styleName);
                }

                QString text = currentFragment.text();
                int spanFrom = fragmentStart >= from ? 0 : from;
                int spanTo = to == -1 ? fragmentEnd : (fragmentEnd > to ? to : fragmentEnd);
                if (spanFrom != fragmentStart || spanTo != fragmentEnd) { // avoid mid, if possible
                    d->writer->addTextSpan(text.mid(spanFrom - fragmentStart, spanTo - spanFrom));
                } else {
                    d->writer->addTextSpan(text);
                }

                if ((!styleName.isEmpty() /*&& !identical*/) || charFormat.isAnchor())
                    d->writer->endElement();
            } // if (inlineObject)

            if (!changeName.isEmpty()) {
                d->writer->startElement("text:change-end", false);
                d->writer->addAttribute("text:change-id",changeName);
                d->writer->endElement();
                changeName=QString();
            }
            previousCharFormat = charFormat;
        } // if (fragment.valid())
    } // foeach(fragment)

    d->writer->endElement();
}
Exemple #6
0
QString Format::frameToString( QTextFrame *frame )
{
  QString out;

  QTextFrame::iterator it;
  for( it = frame->begin(); it != frame->end(); ++it ) {
    QTextBlock block = it.currentBlock();
    if ( block.isValid() ) {
      out += "<block";

      QTextCursor c( block );

      QDateTime dt = TextFormats::lastModified( c );
      if ( dt.isValid() ) {
        out += " lastmodified=\"" + dt.toString( Qt::ISODate ) + "\"";
      }

      if ( TextFormats::isTitle( c ) ) {
        out += " titlestyle=\"title\"";
      } else if ( TextFormats::isSubTitle( c ) ) {
        out += " titlestyle=\"subtitle\"";
      }

      QTextBlockFormat blockFormat = block.blockFormat();
      if ( blockFormat.isValid() ) {
        QTextList *list = block.textList();
        if ( list ) {
          QTextListFormat f = list->format();
          out += " liststyle=\"";
          switch( f.style() ) {
            default:
            case QTextListFormat::ListDisc:
              out += "disc";
              break;
            case QTextListFormat::ListDecimal:
              out += "decimal";
              break;
          }
          out += "\"";

          out += " listindent=\"" + QString::number( f.indent() ) + "\"";
        } else {
          if ( blockFormat.indent() != 0 ) {
            out += " blockindent=\"" + QString::number( blockFormat.indent() ) +
              "\"";
          }
        }
      }

      out += ">\n";
      
      QTextBlock::iterator it2;
      for( it2 = block.begin(); it2 != block.end(); ++it2 ) {
        QTextFragment fragment = it2.fragment();
        if ( !fragment.isValid() ) continue;

        QString text = fragment.text();

        QString outText;
        for( int i = 0; i < text.size(); ++i ) {
          if ( text.at( i ) == 0xfffc ) {
            outText += "<todo status=\"";

            QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
            if ( imageFormat.isValid() ) {
              if ( imageFormat.name().contains( "done" ) ) outText += "done";
              else outText += "todo";
            } else {
              dbg() << "NO IMAGE FORMAT" << endl;
            }
            
            outText += "\"/>";
          } else {
            outText += escape( QString( text.at( i ) ) );
          }
        }

        out += "  <fragment";

        QTextCharFormat format = fragment.charFormat();
        if ( !format.anchorHref().isEmpty() ) {
          out += " link=\"" + escape( format.anchorHref() ) + "\"";
        }
        if ( format.fontWeight() == QFont::Bold ) {
          out += " bold=\"true\"";
        }
        if ( format.fontItalic() ) {
          out += " italic=\"true\"";
        }
        if ( format.hasProperty( QTextFormat::FontPointSize ) &&
             format.fontPointSize() != 10 ) {
          out += " fontsize=\"" + QString::number( format.fontPointSize() ) +
            "\"";
        }

        if ( outText.trimmed().isEmpty() ) outText.replace( " ", "[FIXME:space]" );

        out += ">" + outText + "</fragment>\n";
      }
      
      out += "</block>";

      out += "\n";
    }
    QTextFrame *f = it.currentFrame();
    if ( f ) {
      QTextFrameFormat format = f->frameFormat();
      out += "<frame";
      if ( format.hasProperty( TextFormats::FrameType ) ) {
        out += " type=";
        if ( format.property( TextFormats::FrameType ) == TextFormats::CodeFrame ) {
          out += "\"code\"";
        } else {
          out += "\"undefined\"";
        }
      }
      out += ">\n";
      out += frameToString( f );
      out += "</frame>\n";
    }
  }

  return out;
}
QString validHtml(const QString &html, bool allowReplacement, QTextCursor *tc)
	{
	QDesktopWidget dw;
	ValidDocument oValidDocument(allowReplacement);

	QRectF qr = dw.availableGeometry();
	oValidDocument.setTextWidth(qr.width() / 2);
	oValidDocument.setDefaultStyleSheet(qApp->styleSheet());

	oValidDocument.setHtml(html);
	bool fIsValid = oValidDocument.isValid();

	QStringList qslAllowed = allowedSchemes();
	for (QTextBlock qtb = oValidDocument.begin(); qtb != oValidDocument.end(); qtb = qtb.next())
		{
		for (QTextBlock::iterator qtbi = qtb.begin(); qtbi != qtb.end(); ++qtbi)
			{
			const QTextFragment &qtf = qtbi.fragment();
			QTextCharFormat qcf = qtf.charFormat();
			if (! qcf.anchorHref().isEmpty())
				{
				QUrl url(qcf.anchorHref());
				if (! url.isValid() || ! qslAllowed.contains(url.scheme()))
					{
					QTextCharFormat qcfn = QTextCharFormat();
					QTextCursor qtc(&oValidDocument);
					qtc.setPosition(qtf.position(), QTextCursor::MoveAnchor);
					qtc.setPosition(qtf.position()+qtf.length(), QTextCursor::KeepAnchor);
					qtc.setCharFormat(qcfn);
					qtbi = qtb.begin();
					}
				}
			if (qcf.isImageFormat())
				{
				QTextImageFormat qtif = qcf.toImageFormat();
				QUrl url(qtif.name());
				if (! qtif.name().isEmpty() && ! url.isValid())
					fIsValid = false;
				}
			}
		}

	oValidDocument.adjustSize();
	QSizeF s = oValidDocument.size();

	if (!fIsValid || (s.width() > qr.width()) || (s.height() > qr.height())) {
		oValidDocument.setPlainText(html);
		oValidDocument.adjustSize();
		s = oValidDocument.size();

		if ((s.width() > qr.width()) || (s.height() > qr.height())) {
			QString errorMessage = "[[ Text object too large to display ]]";
			if (tc) {
				tc->insertText(errorMessage);
				return QString();
			} else {
				return errorMessage;
			}
		}
	}

	if (tc) {
		QTextCursor tcNew(&oValidDocument);
		tcNew.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
		tc->insertFragment(tcNew.selection());
		return QString();
	} else {
		return oValidDocument.toHtml();
	}
}
Exemple #8
0
void HtmlExporter::emitFragment( const QTextFragment &fragment, const QTextBlockFormat &blockFormat )
{
//     kDebug() << "html" << html;
    const QTextCharFormat format = fragment.charFormat();

    bool closeAnchor = false;
    bool anchorIsOpen = false;

    if ( format.isAnchor() ) {
//         const QStringList names = format.anchorNames();
//         if (!names.isEmpty()) {
//             html += QLatin1String("<a name=\"");
//             html += names.at(0);
//             html += QLatin1String("\" ");
//    anchorIsOpen = true;
//         }
        const QString href = format.anchorHref();
        if ( !href.isEmpty() ) {
//    if (!anchorIsOpen) {
//     html += QLatin1String("<a ");
//     anchorIsOpen = true;
//    }
            html += QLatin1String( "<a href=\"" );
            html += href;
            html += QLatin1String( "\"" );
            anchorIsOpen = true;
//             closeAnchor = true;
//    html += QLatin1String("\"");
        }
        if ( format.hasProperty( BilboTextFormat::AnchorTitle ) ) {
            const QString title = format.stringProperty( BilboTextFormat::AnchorTitle );
            if ( !title.isEmpty() ) {
                html += QLatin1String( " title=\"" );
                html += title;
                html += QLatin1String( "\"" );
            }
        }
        if ( format.hasProperty( BilboTextFormat::AnchorTarget ) ) {
            const QString target = format.stringProperty( BilboTextFormat::AnchorTarget );
            if ( !target.isEmpty() ) {
                html += QLatin1String( " target=\"" );
                html += target;
                html += QLatin1String( "\"" );
            }
        }
        if ( anchorIsOpen ) {
            html += QLatin1String( ">" );
            closeAnchor = true;
        }
    }

    QList<tag> tags = emitCharFormatStyle( format, blockFormat );
//  if ( !format.anchorHref().isNull() ) {
//   html += QLatin1String(">");
//   closeAnchor = true;
//  }
//     kDebug() << "tags count" << tags.count() << endl;
    for ( int i = 0; i < tags.count(); ++i ) {
        switch ( tags.at( i ) ) {
            case span:
                break; //Jump
//             case h1:
//                 html += QLatin1String( "<h1>" );
//                 break;
//             case h2:
//                 html += QLatin1String( "<h2>" );
//                 break;
//             case h3:
//                 html += QLatin1String( "<h3>" );
//                 break;
//             case h4:
//                 html += QLatin1String( "<h4>" );
//                 break;
//             case h5:
//                 html += QLatin1String( "<h5>" );
//                 break;
            case strong:
                html += QLatin1String( "<strong>" );
                break;
            case em:
                html += QLatin1String( "<em>" );
                break;
            case s:
                html += QLatin1String( "<s>" );
                break;
            case u:
                if ( !closeAnchor )
                    html += QLatin1String( "<u>" );
                break;
            case code:
                html += QLatin1String( "<code>" );
                break;
            case sub:
                html += QLatin1String( "<sub>" );
                break;
            case sup:
                html += QLatin1String( "<sup>" );
                break;
        }
    }

    /*     QLatin1String styleTag("<span style=\"");
         html += styleTag;
     
         const bool attributesEmitted = emitCharFormatStyle(format);
        if (attributesEmitted)
            html += QLatin1String("\">");
        else
            html.chop(qstrlen(styleTag.latin1()));
    */
    QString txt = fragment.text();
//     kDebug() << txt ;
    if ( txt.count() == 1 && txt.at( 0 ) == QChar::ObjectReplacementCharacter ) {
        if ( format.isImageFormat() ) {
            QTextImageFormat imgFmt = format.toImageFormat();

            html += QLatin1String( "<img" );

            if ( imgFmt.hasProperty( QTextFormat::ImageName ) ) {
                emitAttribute( "src", imgFmt.name() );
            }

            if ( imgFmt.hasProperty( BilboTextFormat::ImageTitle ) ) {
                const QString title = imgFmt.stringProperty( BilboTextFormat::ImageTitle );
                if ( !title.isEmpty() ) {
                    emitAttribute( "title", imgFmt.stringProperty( BilboTextFormat::ImageTitle ) );
                }
            }

            if ( imgFmt.hasProperty( BilboTextFormat::ImageAlternateText ) ) {
                const QString alternate = imgFmt.stringProperty( BilboTextFormat::ImageAlternateText );
                if ( !alternate.isEmpty() ) {
                    emitAttribute( "alt", imgFmt.stringProperty( BilboTextFormat::ImageAlternateText ) );
                }
            }

            if ( imgFmt.hasProperty( QTextFormat::ImageWidth ) ) {
                emitAttribute( "width", QString::number( imgFmt.width() ) );
            }

            if ( imgFmt.hasProperty( QTextFormat::ImageHeight ) ) {
                emitAttribute( "height", QString::number( imgFmt.height() ) );
            }

            if ( QTextFrame *imageFrame = qobject_cast<QTextFrame *>( doc->objectForFormat( imgFmt ) ) ) {
                emitFloatStyle( imageFrame->frameFormat().position() );
            }

            html += QLatin1String( " />" );
        }
    } else {
//         Q_ASSERT(!txt.contains(QChar::ObjectReplacementCharacter));

        txt = Qt::escape( txt );

        // split for [\n{LineSeparator}]
        QString forcedLineBreakRegExp = QString::fromLatin1( "[\\na]" );
        forcedLineBreakRegExp[3] = QChar::LineSeparator;

        const QStringList lines = txt.split( QRegExp( forcedLineBreakRegExp ) );
        for ( int i = 0; i < lines.count(); ++i ) {
            if ( i > 0 )
                html += QLatin1String( "<br />" ); // space on purpose for compatibility with Netscape, Lynx & Co.
            //and to convert LineSeparators to <br /> tags.
            html += lines.at( i );
        }
    }

//     kDebug() << html ;

    //Close Tags
    //if (!closeAnchor)
    for ( int i = tags.count(); i > 0; --i ) {
        switch ( tags.at( i - 1 ) ) {
            case span:
                html += QLatin1String( "</span>" );
                break; //Jump
//             case h1:
//                 html += QLatin1String( "</h1>" );
//                 break;
//             case h2:
//                 html += QLatin1String( "</h2>" );
//                 break;
//             case h3:
//                 html += QLatin1String( "</h3>" );
//                 break;
//             case h4:
//                 html += QLatin1String( "</h4>" );
//                 break;
//             case h5:
//                 html += QLatin1String( "</h5>" );
//                 break;
            case strong:
                html += QLatin1String( "</strong>" );
                break;
            case em:
                html += QLatin1String( "</em>" );
                break;
            case s:
                html += QLatin1String( "</s>" );
                break;
            case u:
                if ( !closeAnchor )
                    html += QLatin1String( "</u>" );
                break;
            case code:
                html += QLatin1String( "</code>" );
                break;
            case sub:
                html += QLatin1String( "</sub>" );
                break;
            case sup:
                html += QLatin1String( "</sup>" );
                break;
        }
    }
    /*    if (attributesEmitted)
            html += QLatin1String("</span>");
    */
    if ( closeAnchor ) {
        html += QLatin1String( "</a>" );
    }
//     kDebug() << "html=>" << html;
}