// Copyright (C) 2022 Jakub Melka // // This file is part of PDF4QT. // // PDF4QT is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // with the written consent of the copyright owner, any later version. // // PDF4QT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with PDF4QT. If not, see . #include "pdfpagecontenteditorwidget.h" #include "pdfpagecontenteditorstylesettings.h" #include "ui_pdfpagecontenteditorwidget.h" #include "pdfwidgetutils.h" #include "pdfpagecontentelements.h" #include "pdfutils.h" #include #include namespace pdf { PDFPageContentEditorWidget::PDFPageContentEditorWidget(QWidget* parent) : QDockWidget(parent), ui(new Ui::PDFPageContentEditorWidget), m_toolBoxColumnCount(6), m_scene(nullptr), m_selectionChangeEnabled(true), m_updatesEnabled(true) { ui->setupUi(this); m_toolButtonIconSize = PDFWidgetUtils::scaleDPI(this, QSize(32, 32)); for (QToolButton* button : findChildren()) { button->setIconSize(m_toolButtonIconSize); } m_operationMapper.setMapping(ui->alignVertTopButton, static_cast(PDFPageContentElementManipulator::Operation::AlignTop)); m_operationMapper.setMapping(ui->alignVertMiddleButton, static_cast(PDFPageContentElementManipulator::Operation::AlignCenterVertically)); m_operationMapper.setMapping(ui->alignVertBottomButton, static_cast(PDFPageContentElementManipulator::Operation::AlignBottom)); m_operationMapper.setMapping(ui->alignHorLeftButton, static_cast(PDFPageContentElementManipulator::Operation::AlignLeft)); m_operationMapper.setMapping(ui->alignHorMiddleButton, static_cast(PDFPageContentElementManipulator::Operation::AlignCenterHorizontally)); m_operationMapper.setMapping(ui->alignHorRightButton, static_cast(PDFPageContentElementManipulator::Operation::AlignRight)); m_operationMapper.setMapping(ui->setSameWidthButton, static_cast(PDFPageContentElementManipulator::Operation::SetSameWidth)); m_operationMapper.setMapping(ui->setSameHeightButton, static_cast(PDFPageContentElementManipulator::Operation::SetSameHeight)); m_operationMapper.setMapping(ui->setSameSizeButton, static_cast(PDFPageContentElementManipulator::Operation::SetSameSize)); m_operationMapper.setMapping(ui->centerHorizontallyButton, static_cast(PDFPageContentElementManipulator::Operation::CenterHorizontally)); m_operationMapper.setMapping(ui->centerVerticallyButton, static_cast(PDFPageContentElementManipulator::Operation::CenterVertically)); m_operationMapper.setMapping(ui->centerRectButton, static_cast(PDFPageContentElementManipulator::Operation::CenterHorAndVert)); m_operationMapper.setMapping(ui->layoutHorizontallyButton, static_cast(PDFPageContentElementManipulator::Operation::LayoutHorizontally)); m_operationMapper.setMapping(ui->layoutVerticallyButton, static_cast(PDFPageContentElementManipulator::Operation::LayoutVertically)); m_operationMapper.setMapping(ui->layoutFormButton, static_cast(PDFPageContentElementManipulator::Operation::LayoutForm)); m_operationMapper.setMapping(ui->layoutGridButton, static_cast(PDFPageContentElementManipulator::Operation::LayoutGrid)); connect(ui->alignVertTopButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->alignVertMiddleButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->alignVertBottomButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->alignHorLeftButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->alignHorMiddleButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->alignHorRightButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->setSameWidthButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->setSameHeightButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->setSameSizeButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->centerHorizontallyButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->centerVerticallyButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->centerRectButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->layoutHorizontallyButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->layoutVerticallyButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->layoutFormButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->layoutGridButton, &QToolButton::clicked, &m_operationMapper, QOverload<>::of(&QSignalMapper::map)); connect(&m_actionMapper, &QSignalMapper::mappedObject, this, &PDFPageContentEditorWidget::onActionTriggerRequest); connect(&m_operationMapper, &QSignalMapper::mappedInt, this, &PDFPageContentEditorWidget::operationTriggered); connect(ui->itemsListWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PDFPageContentEditorWidget::onItemSelectionChanged); connect(ui->appearanceSettingsWidget, &PDFPageContentEditorStyleSettings::penChanged, this, &PDFPageContentEditorWidget::penChanged); connect(ui->appearanceSettingsWidget, &PDFPageContentEditorStyleSettings::brushChanged, this, &PDFPageContentEditorWidget::brushChanged); connect(ui->appearanceSettingsWidget, &PDFPageContentEditorStyleSettings::fontChanged, this, &PDFPageContentEditorWidget::fontChanged); connect(ui->appearanceSettingsWidget, &PDFPageContentEditorStyleSettings::alignmentChanged, this, &PDFPageContentEditorWidget::alignmentChanged); connect(ui->appearanceSettingsWidget, &PDFPageContentEditorStyleSettings::textAngleChanged, this, &PDFPageContentEditorWidget::textAngleChanged); } PDFPageContentEditorWidget::~PDFPageContentEditorWidget() { delete ui; } void PDFPageContentEditorWidget::addAction(QAction* action) { // First, find position for our action int row = 0; int column = 0; while (true) { if (!ui->toolGroupBoxLayout->itemAtPosition(row, column)) { break; } ++column; if (column == m_toolBoxColumnCount) { column = 0; ++row; } } QToolButton* button = new QToolButton(this); button->setIcon(action->icon()); button->setText(action->text()); button->setToolTip(action->toolTip()); button->setCheckable(action->isCheckable()); button->setChecked(action->isChecked()); button->setEnabled(action->isEnabled()); button->setShortcut(action->shortcut()); button->setIconSize(m_toolButtonIconSize); m_actionMapper.setMapping(button, action); connect(button, &QToolButton::clicked, &m_actionMapper, QOverload<>::of(&QSignalMapper::map)); connect(action, &QAction::changed, this, &PDFPageContentEditorWidget::onActionChanged); ui->toolGroupBoxLayout->addWidget(button, row, column, Qt::AlignCenter); } QToolButton* PDFPageContentEditorWidget::getToolButtonForOperation(int operation) const { return qobject_cast(m_operationMapper.mapping(operation)); } void PDFPageContentEditorWidget::updateItemsInListWidget() { if (!m_updatesEnabled) { return; } pdf::PDFTemporaryValueChange guard(&m_updatesEnabled, false); ui->itemsListWidget->setUpdatesEnabled(false); if (m_scene) { std::set presentElementIds; std::set elementIds = m_scene->getElementIds(); // Remove items which are not here for (int i = 0; i < ui->itemsListWidget->count();) { QListWidgetItem* item = ui->itemsListWidget->item(i); const PDFInteger elementId = item->data(Qt::UserRole).toLongLong(); if (!elementIds.count(elementId)) { delete ui->itemsListWidget->takeItem(i); } else { presentElementIds.insert(elementId); ++i; } } // Add items which are here for (PDFInteger elementId : elementIds) { if (presentElementIds.count(elementId)) { continue; } const PDFPageContentElement* element = m_scene->getElementById(elementId); Q_ASSERT(element); QListWidgetItem* item = new QListWidgetItem(element->getDescription()); item->setData(Qt::UserRole, elementId); ui->itemsListWidget->addItem(item); } } else { ui->itemsListWidget->clear(); } ui->itemsListWidget->setUpdatesEnabled(true); } void PDFPageContentEditorWidget::onActionTriggerRequest(QObject* actionObject) { QAction* action = qobject_cast(actionObject); Q_ASSERT(action); action->trigger(); } void PDFPageContentEditorWidget::onActionChanged() { QAction* action = qobject_cast(sender()); QToolButton* button = qobject_cast(m_actionMapper.mapping(action)); Q_ASSERT(action); Q_ASSERT(button); button->setChecked(action->isChecked()); button->setEnabled(action->isEnabled()); } void PDFPageContentEditorWidget::onItemSelectionChanged() { if (m_selectionChangeEnabled) { emit itemSelectionChangedByUser(); } } PDFPageContentScene* PDFPageContentEditorWidget::scene() const { return m_scene; } void PDFPageContentEditorWidget::setScene(PDFPageContentScene* newScene) { if (m_scene != newScene) { m_scene = newScene; updateItemsInListWidget(); } } std::set PDFPageContentEditorWidget::getSelection() const { std::set result; for (int i = 0; i < ui->itemsListWidget->count(); ++i) { QListWidgetItem* item = ui->itemsListWidget->item(i); if (item->isSelected()) { const PDFInteger elementId = item->data(Qt::UserRole).toLongLong(); result.insert(elementId); } } return result; } void PDFPageContentEditorWidget::setSelection(const std::set& selection) { pdf::PDFTemporaryValueChange guard(&m_selectionChangeEnabled, false); for (int i = 0; i < ui->itemsListWidget->count(); ++i) { QListWidgetItem* item = ui->itemsListWidget->item(i); const PDFInteger elementId = item->data(Qt::UserRole).toLongLong(); item->setSelected(selection.count(elementId)); } } void PDFPageContentEditorWidget::loadStyleFromElement(const PDFPageContentElement* element) { ui->appearanceSettingsWidget->loadFromElement(element, false); } } // namespace pdf