Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: UNION labs от Апрель 30, 2014, 17:39



Название: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Апрель 30, 2014, 17:39
Всем привет.

Нужен такой текстовый редактор, который может работать с QTextDocument и в то же время отображать текст не сплошняком, как обычный QTextEdit, а по страницам, на подобии ворда. Может быть вам попадался такой компонент? Если нет, подскажите пожалуйста, как бы вы стали реализовывать таковой?


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: Hrundel от Май 01, 2014, 11:47
QGraphicsScene и там рисовать страницы с текстом.

Подробнее можно прочесть у

Марк Саммерфилд
Qt. Профессиональное программирование
Разработка кроссплатформенных приложений на С++

Начиная с главы 9 и до конца книги


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: _OLEGator_ от Май 01, 2014, 13:03
Судя по документации, у QTextDocument есть весь необходимый функционал:
Код
C++ (Qt)
void setPageSize ( const QSizeF & size )
void QTextDocument::drawContents ( QPainter * p, const QRectF & rect = QRectF() )


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: Hrundel от Май 01, 2014, 14:17
Судя по документации, у QTextDocument есть весь необходимый функционал:

Круто, я тоже не знал. Даже Layout блоками возможен.


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 02, 2014, 17:18
Спасибо, сделал. Если кому-нибудь будет интересно, вот исходники - https://github.com/dimkanovikov/QPagesTextEdit


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: kai666_73 от Май 05, 2014, 14:47
Спасибо, сделал. Если кому-нибудь будет интересно, вот исходники - https://github.com/dimkanovikov/QPagesTextEdit

Вау, спасибо за идею.
Воспользовался с небольшой корректировкой (размер документа задаю в пикселях).

Было бы совсем идеально, если бы можно было "дорастянуть" последнюю страницу до полного размера страницы.
Тогда можно было добавить футеры/хидеры.
Если у кого есть мысли на этот счет, был бы крайне признателен.


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 15, 2014, 05:26
kai666_73, пожалуйста. Почему не выложили свой патч?:)

Мне тоже понадобится данный функционал в будущем, пока просто руки не дошли, т.к. не критично. А кроме этого нужно ещё задание размера страницы в мм, и задание отступов от текста со всех четырёх сторон (т.к. QTextDocument не позволяет задать отступ для каждой стороны).


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: kai666_73 от Май 15, 2014, 15:37
kai666_73, пожалуйста. Почему не выложили свой патч?:)

Мне тоже понадобится данный функционал в будущем, пока просто руки не дошли, т.к. не критично. А кроме этого нужно ещё задание размера страницы в мм, и задание отступов от текста со всех четырёх сторон (т.к. QTextDocument не позволяет задать отступ для каждой стороны).

Пока в процессе...
Сделаны настройки:
1. Формата страницы (А3, А4...)
2. Отступов с краев... разные отступы задаются установкой свойств QTextFrameFormat для rootFrame документа
3. Хидеров и футеров
4. Отображение последней страницы целиком

... Выложить проблематично - все это уже вылилось в десяток файло-классов. Из Вашей репы взята, почитай, только идея ::)
Будут конкретные вопросы - обращайтесь, про отступы, вроде, уже ответил.


Название: Re: Редактор текста с постраничным выводом а-
Отправлено: UNION labs от Май 16, 2014, 06:11
Хорошо, спасибо, в ближайшем будущем обращусь. А вы не собираетесь выкладывать проект в общий доступ? Может быть просто оставили бы ссылку?


Название: Re: Редактор текста с постраничным выводом а-
Отправлено: kai666_73 от Май 16, 2014, 10:47
Хорошо, спасибо, в ближайшем будущем обращусь. А вы не собираетесь выкладывать проект в общий доступ? Может быть просто оставили бы ссылку?

Планирую реализовать дизайнер отчетов на базе QTextEdit-а.
Возникла такая необходимость - заказ военных. Так что об общем доступе речи быть не может ((


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 19, 2014, 10:01
Ясно, ну тогда расскажите пожалуйста, как вы:
1. сделали задание размера страницы в миллиметрах?
2. дорисовываете страницу?


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: kai666_73 от Май 19, 2014, 10:52
Ясно, ну тогда расскажите пожалуйста, как вы:
1. сделали задание размера страницы в миллиметрах?
2. дорисовываете страницу?

1. Реализовал такой вот класс:
PageFormat.h
Код:
class PageFormat
{
public:
    PageFormat( QPaintDevice *device,
                const QString &format = "A4",
                bool  isPortrait = true,
                qreal mmLeftMargin = 15.0,
                qreal mmTopMargin = 15.0,
                qreal mmRightMargin = 15.0,
                qreal mmBottomMargin = 15.0 );

    void update( const QString &format = "A4",
                 bool  isPortrait = true,
                 qreal mmLeftMargin = 15.0,
                 qreal mmTopMargin = 15.0,
                 qreal mmRightMargin = 15.0,
                 qreal mmBottomMargin = 15.0 );

    void update( int   formatId,
                 bool  isPortrait = true,
                 qreal mmLeftMargin = 15.0,
                 qreal mmTopMargin = 15.0,
                 qreal mmRightMargin = 15.0,
                 qreal mmBottomMargin = 15.0 );

    inline qreal leftMargin() const { return m_leftMargin; }
    inline qreal topMargin() const { return m_topMargin; }
    inline qreal rightMargin() const { return m_rightMargin; }
    inline qreal bottomMargin() const { return m_bottomMargin; }

    inline qreal paperWidth() const { return m_paperWidth; }
    inline qreal pageWidth() const { return m_pageWidth; }
    inline qreal paperHeight() const { return m_paperHeight; }
    inline qreal pageHeight() const { return m_pageHeight; }

    inline int formatId() const { return m_formatId; }
    inline bool isPortrait() const { return m_isPortrait; }

    inline qreal mmLeftMargin() const { return m_mmLeftMargin; }
    inline qreal mmTopMargin() const { return m_mmTopMargin; }
    inline qreal mmRightMargin() const { return m_mmRightMargin; }
    inline qreal mmBottomMargin() const { return m_mmBottomMargin; }

    static QSizeF sizeForFormatId( int formatId, bool isPortrait );

private:
    QString m_format;       // Name of Page Format <=> QPrinter::PaperSize ("A4 (default), "Letter", "B5"...)
    bool m_isPortrait;     // true for Portrait Orientation

    qreal m_mmLeftMargin;   // Left Margin in mm
    qreal m_mmTopMargin;    // Top Margin in mm
    qreal m_mmRightMargin;  // Right Margin in mm
    qreal m_mmBottomMargin; // Right Margin in mm

    qreal m_leftMargin;     // Left Margin in px
    qreal m_topMargin;      // Top Margin in px
    qreal m_rightMargin;    // Right Margin in px
    qreal m_bottomMargin;   // Right Margin in px

    qreal m_paperWidth;     // Paper Width in px
    qreal m_pageWidth;      // Page Width in px (m_paperWidth - m_leftMargin - m_rightMargin)
    qreal m_paperHeight;    // Paper Height in px
    qreal m_pageHeight;     // Page Height in px (m_paperHeight - m_topMargin - m_bottomMargin)

    QPaintDevice *m_device;
    int m_formatId;
};

PageFormat.cpp
Код:
static inline double mmToInches(double mm) { return mm * 0.039370147; }

typedef struct tagPageFormatSize {
    QString formatName;
    qreal   wmm;
    qreal   hmm;
} PageFormatSize;

static PageFormatSize formats[30] = {
    {        "A0",  841.0, 1189.0 },
    {        "A1",  594.0,  841.0 },
    {        "A2",  420.0,  594.0 },
    {        "A3",  297.0,  420.0 },
    {        "A4",  210.0,  297.0 },
    {        "A5",  148.0,  210.0 },
    {        "A6",  105.0,  148.0 },
    {        "A7",   74.0,  105.0 },
    {        "A8",   52.0,   74.0 },
    {        "A9",   37.0,   52.0 },
    {        "B0", 1030.0, 1456.0 },
    {        "B1",  728.0, 1030.0 },
    {        "B2",  515.0,  728.0 },
    {        "B3",  364.0,  515.0 },
    {        "B4",  257.0,  364.0 },
    {        "B5",  182.0,  257.0 },
    {        "B6",  128.0,  182.0 },
    {        "B7",   91.0,  128.0 },
    {        "B8",   64.0,   91.0 },
    {        "B9",   45.0,   64.0 },
    {       "B10",   32.0,   45.0 },
    {       "C5E",  163.0,  229.0 },
    {   "Comm10E",  105.0,  241.0 },
    {       "DLE",  110.0,  220.0 },
    { "Executive",  191.0,  254.0 },
    {     "Folio",  210.0,  330.0 },
    {    "Ledger",  432.0,  279.0 },
    {     "Legal",  216.0,  356.0 },
    {    "Letter",  216.0,  279.0 },
    {   "Tabloid",  279.0,  432.0 }
};

static QSizeF sizeForPageFormat( const QString &format, bool isPortrait, int &formatId )
{
    for (int i = 0; i < 30; i++)
        if ( !format.compare(formats[i].formatName, Qt::CaseInsensitive) ) {
            formatId = i;
            return isPortrait ? QSizeF(formats[i].wmm, formats[i].hmm) : QSizeF(formats[i].hmm, formats[i].wmm);
        }

    formatId = 4;
    return isPortrait ? QSizeF(210.0, 297.0) : QSizeF(297.0, 210.0);
}

PageFormat::PageFormat( QPaintDevice *device,
                        const QString &format,
                        bool  isPortrait,
                        qreal mmLeftMargin,
                        qreal mmTopMargin,
                        qreal mmRightMargin,
                        qreal mmBottomMargin )
    : m_device(device)
{
    update(format, isPortrait, mmLeftMargin, mmTopMargin, mmRightMargin, mmBottomMargin);
}

void PageFormat::update( const QString &format,
                         bool  isPortrait,
                         qreal mmLeftMargin,
                         qreal mmTopMargin,
                         qreal mmRightMargin,
                         qreal mmBottomMargin )
{
    m_format = format;
    m_isPortrait = isPortrait;

    m_mmLeftMargin = mmLeftMargin;
    m_mmTopMargin = mmTopMargin;
    m_mmRightMargin = mmRightMargin;
    m_mmBottomMargin = mmBottomMargin;

    QSizeF mmSize = sizeForPageFormat(m_format, m_isPortrait, m_formatId);
    m_pageWidth = mmSize.width() - mmLeftMargin - mmRightMargin;
    m_pageHeight = mmSize.height() - mmTopMargin - mmBottomMargin;

    m_paperWidth = mmToInches(m_paperWidth) * m_device->logicalDpiX();
    m_pageWidth = mmToInches(m_pageWidth) * m_device->logicalDpiX();
    m_leftMargin = mmToInches(m_leftMargin) * m_device->logicalDpiX();
    m_rightMargin = mmToInches(m_rightMargin) * m_device->logicalDpiX();

    m_paperHeight = mmToInches(m_paperHeight) * m_device->logicalDpiY();
    m_pageHeight = mmToInches(m_pageHeight) * m_device->logicalDpiY();
    m_topMargin = mmToInches(m_topMargin) * m_device->logicalDpiY();
    m_bottomMargin = mmToInches(m_bottomMargin) * m_device->logicalDpiY();
}

void PageFormat::update( int formatId, bool isPortrait, qreal mmLeftMargin, qreal mmTopMargin, qreal mmRightMargin, qreal mmBottomMargin )
{
    m_format = formats[formatId].formatName;
    m_isPortrait = isPortrait;
    m_formatId = formatId;

    m_mmLeftMargin = mmLeftMargin;
    m_mmTopMargin = mmTopMargin;
    m_mmRightMargin = mmRightMargin;
    m_mmBottomMargin = mmBottomMargin;

    if ( isPortrait ) {
        m_paperWidth  = formats[formatId].wmm;
        m_paperHeight = formats[formatId].hmm;
    }
    else {
        m_paperHeight = formats[formatId].wmm;
        m_paperWidth  = formats[formatId].hmm;
    }

    m_pageWidth = m_paperWidth - mmLeftMargin - mmRightMargin;
    m_pageHeight = m_paperHeight - mmTopMargin - mmBottomMargin;

    m_paperWidth = mmToInches(m_paperWidth) * m_device->logicalDpiX();
    m_pageWidth = mmToInches(m_pageWidth) * m_device->logicalDpiX();
    m_leftMargin = mmToInches(m_leftMargin) * m_device->logicalDpiX();
    m_rightMargin = mmToInches(m_rightMargin) * m_device->logicalDpiX();

    m_paperHeight = mmToInches(m_paperHeight) * m_device->logicalDpiY();
    m_pageHeight = mmToInches(m_pageHeight) * m_device->logicalDpiY();
    m_topMargin = mmToInches(m_topMargin) * m_device->logicalDpiY();
    m_bottomMargin = mmToInches(m_bottomMargin) * m_device->logicalDpiY();
}

QSizeF PageFormat::sizeForFormatId( int formatId, bool isPortrait )
{
    if ( isPortrait )
        return QSizeF( formats[formatId].wmm, formats[formatId].hmm );

    return QSizeF( formats[formatId].hmm, formats[formatId].wmm );
}

2. В функции рисования едитора (в постраничном режиме) изменил диапазон вертикального скролбара
Код:
verticalScrollBar()->setRange(0, m_drawPageSize.height() * (document()->pageCount()) - viewport()->size().height());


Название: Re: Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 19, 2014, 14:25
Примного благодарен!


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: _OLEGator_ от Май 19, 2014, 22:57
Код
C++ (Qt)
qreal mmLeftMargin
qreal mmTopMargin
qreal mmRightMargin
qreal mmBottomMargin

Напрашивается как минимум на выделение в структуру.


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: gil9red от Май 20, 2014, 00:00
Код
C++ (Qt)
qreal mmLeftMargin
qreal mmTopMargin
qreal mmRightMargin
qreal mmBottomMargin

Напрашивается как минимум на выделение в структуру.

Или просто использовать для этого класс QMargins (http://qt-project.org/doc/qt-4.8/qmargins.html) ::)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: _OLEGator_ от Май 20, 2014, 09:14
Или просто использовать для этого класс QMargins (http://qt-project.org/doc/qt-4.8/qmargins.html) ::)

Вот, даже писать не надо что-то новое, все доступно из коробки =)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: kai666_73 от Май 20, 2014, 10:31
Отож набежало грамотных...
А QMargins содержит целые числа, нужны вещественные.


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: Johnik от Май 20, 2014, 12:57
в Qt 5.3 добавлен класс QMarginsF (http://qt-project.org/doc/qt-5/qmarginsf.html)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 22, 2014, 09:39
В Qt 5.3 ещё есть и QPageSize однако.

Обновил свой проект.


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: gil9red от Май 22, 2014, 10:51
В Qt 5.3 ещё есть и QPageSize однако.

Обновил свой проект.
Странно, гугл не нашел QPageSize  о.О


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 22, 2014, 16:20
Странно, гугл не нашел QPageSize  о.О

Просто класс новый, ещё не проиндексировались страницы. Вот ссылка - http://qt-project.org/doc/qt-5/qpagesize.html (http://qt-project.org/doc/qt-5/qpagesize.html)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: gil9red от Май 23, 2014, 05:44
Странно, гугл не нашел QPageSize  о.О

Просто класс новый, ещё не проиндексировались страницы. Вот ссылка - http://qt-project.org/doc/qt-5/qpagesize.html (http://qt-project.org/doc/qt-5/qpagesize.html)
О круто! :)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Май 30, 2014, 14:33
kai666_73, скажите пожалуйста, а вы не решали задачи масштабирования в своём редакторе? А то столкнулся с тем, что это довольно нетривиальная задача, т.к. стандартные zoomIn/zoomOut просто меняют размер шрифта, а нужно так же масштабировать отступы страницы, блоков, изображения и т.п....


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: kai666_73 от Июнь 01, 2014, 13:33
kai666_73, скажите пожалуйста, а вы не решали задачи масштабирования в своём редакторе? А то столкнулся с тем, что это довольно нетривиальная задача, т.к. стандартные zoomIn/zoomOut просто меняют размер шрифта, а нужно так же масштабировать отступы страницы, блоков, изображения и т.п....
Даже задумываться об этом боюсь :(
Если только как-то в купе с QGraphicsView и иже с ним...


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: UNION labs от Июнь 02, 2014, 11:57
Спасибо, тоже уже пришёл к такому выводу, ну будем думать как быть!:)


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: panAlexey от Июнь 03, 2014, 21:58
Код
C++ (Qt)
qreal mmLeftMargin
qreal mmTopMargin
qreal mmRightMargin
qreal mmBottomMargin

Напрашивается как минимум на выделение в структуру.

Или просто использовать для этого класс QMargins (http://qt-project.org/doc/qt-4.8/qmargins.html) ::)

НУ знаете, готовые классы использовать, это извращение.


Название: Re: [РЕШЕНО] Редактор текста с постраничным выводом а-ля Word
Отправлено: Dimka Novikov от Декабрь 29, 2014, 16:01
Всё-таки как и предполагали пришлось через QGraphicsXXX делать масштабирование. Если кому-нибудь будет нужно, то посмотреть, как я это сделал можно тут - https://github.com/dimkanovikov/ScalableWrapper