diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a7c0862c..ebcb6e2e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,11 +39,6 @@ if (NOT DEFAULT_COMPILER_FLAGS_IS_SET) message(WARNING "Only MSVC toolchain is supported to build for Windows XP.") endif() - if (UNIX) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - endif() - if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -Werror=return-type -Wno-unused") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Werror=return-type -Wno-unused") @@ -60,7 +55,8 @@ if (NOT DEFAULT_COMPILER_FLAGS_IS_SET) endif() if (UNIX) - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + option(CMAKE_POSITION_INDEPENDENT_CODE "" ON) + option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "" ON) endif() include(cmake/SetDefaultBuildType.cmake) @@ -238,7 +234,7 @@ endif() enable_testing() # Prepare config.h -option(PORTABLE_VERSION "Whether to build the portable version or not." ON) +option(PORTABLE_VERSION "Whether to build the portable version." ON) if (PORTABLE_VERSION) set(PORTABLE_CONFIG_DIR "config") endif() @@ -251,6 +247,16 @@ else() set(PLUGIN_DIRS ".:../lib/${APPLICATION_NAME}") endif() configure_file(config.h.in "${CMAKE_BINARY_DIR}/config.h" @ONLY) +file(READ "${CMAKE_BINARY_DIR}/config.h" config_h_contents) +set(enable_developer_version_default OFF) +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(enable_developer_version_default ON) +endif() +option(DEVELOPER_VERSION "Whether to enable the internal debug features." ${enable_developer_version_default}) +if (NOT DEVELOPER_VERSION) + string(REGEX REPLACE "(#define[ \\t]+ENABLE_DEBUG_FEATURES[^\n]*)" "//\\1" config_h_contents ${config_h_contents}) +endif() +file(WRITE "${CMAKE_BINARY_DIR}/config.h" ${config_h_contents}) include_directories(BEFORE "${CMAKE_BINARY_DIR}") # Extract VERSION and VERSION_QUAD from version.h diff --git a/README.md b/README.md index a7ee131d2..dc3bd2a47 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ has't been moved due to dirty realization. Their functionality is fully covered * Page splitting settings now influence on the output by filling offcut. Fill offcut option has been added. - + * Page layout and all the other views now consider splitting settings. Corresponding improvements are done for thumbnails. @@ -187,8 +187,6 @@ has't been moved due to dirty realization. Their functionality is fully covered 3. UI: Added cutters interaction between each other. They can't more intersect each other, which created a wrong page layout configuration before. - * Optimized memory usage on the output stage. - * Reworking on [multi column thumbnails view](#multi-column-thumbnails-view-reworked) feature from ver. Enhanced. Now thumbnails are shown evenly. @@ -315,13 +313,19 @@ has't been moved due to dirty realization. Their functionality is fully covered Added sensitivity option. If sensitivity equals 25%, the results will be the same as they were in old "Quadro" mode, if 100% - as in old "Rectangular". * ##### New zone interaction modes - **`Shift+LMB`** on a zone - drag the zone. - **`Ctrl+Shift+LMB`** on a zone - drag the zone copying. - **`Del`** when the cursor is over a zone - delete the zone. - Hold **`Ctrl`** when dragging a zone vertex - make the angle of the vertex right. - **`Ctrl+Alt+Click`** - copy the latest created zone to the cursor position. - **`Ctrl`** while creating a new zone - switch to rectangular mode. - Hold **`Shift+Alt+LMB`** while creating a new zone - use lasso (free drawing) mode. + * Zone creation mode: + Press **`Z`** to switch to polygonal mode. + Press **`X`** to switch to lasso (free drawing) mode. + Press **`C`** to switch to rectangular mode. + Press **`Z`** or **`X`** while creating a new zone to switch between polygonal and rectangular modes respectively. + * Zone: + **`Shift+LMB`** on a zone - drag the zone. + **`Ctrl+Shift+LMB`** on a zone - drag the zone copying. + **`Ctrl+Alt+Click`** - copy the latest created zone to the current cursor position. + **`Del`** when the cursor is over a zone - delete the zone. + * Zone vertex: + **`D`** when the cursor is over a zone vertex - delete the vertex. + Hold **`Ctrl`** when dragging a zone vertex - make the angle of the vertex right. * ##### Saving zoom and focus on switching output tabs The save is precise and considers the images transformations. @@ -334,7 +338,7 @@ has't been moved due to dirty realization. Their functionality is fully covered The system affects every aspect of the program, so, for example, it's now possible to adjust margins in pixels, but not only in millimetres or inches. * ##### Status bar panel - The panel shows the next information: mouse position relative to the image, physical size of the image, position of the selected page in current order and the page name and type (`[L]` or `[R]` - left or right page, if the page has been splitted). + The panel shows the next information: zone creation mode icon, mouse position relative to the image, physical size of the image, position of the selected page in current order and the page name and type (`[L]` or `[R]` - left or right page, if the page has been splitted). This feature is also affected by [measurement units system](#measurement-units-system). @@ -381,7 +385,7 @@ has't been moved due to dirty realization. Their functionality is fully covered Capabilities: * **`Right-click`** to create/remove guides from the **context menu** called. * **`Right-click`** on a guide to delete that guide from the **context menu** called. - * **`Shift+LMB`** - drag the guide under the cursor. + * **`Ctrl+Alt+LMB`** - drag the guide under the cursor. * **`Shift/Ctrl+LMB`** on the content rectangle - drag the page content. Hold **`Shift`** pressed to restrict moving along the horizontal axis only or **`Ctrl`** for the vertical one. Hold **`Shift+Ctrl`** for usual dragging. diff --git a/config.h.in b/config.h.in index eadec1c42..18cde886f 100644 --- a/config.h.in +++ b/config.h.in @@ -7,6 +7,7 @@ #define PLUGIN_DIRS "@PLUGIN_DIRS@" #define PORTABLE_CONFIG_DIR "@PORTABLE_CONFIG_DIR@" +#define ENABLE_DEBUG_FEATURES #define APPLICATION_NAME "@APPLICATION_NAME@" #define ORGANIZATION_NAME APPLICATION_NAME diff --git a/src/app/DefaultParamsDialog.cpp b/src/app/DefaultParamsDialog.cpp index 43eb8673e..d22353416 100644 --- a/src/app/DefaultParamsDialog.cpp +++ b/src/app/DefaultParamsDialog.cpp @@ -96,7 +96,7 @@ DefaultParamsDialog::DefaultParamsDialog(QWidget* parent) Utils::mapSetValue(m_alignmentByButton, alignBottomBtn, Alignment(Alignment::BOTTOM, Alignment::HCENTER)); Utils::mapSetValue(m_alignmentByButton, alignBottomRightBtn, Alignment(Alignment::BOTTOM, Alignment::RIGHT)); - m_alignmentButtonGroup = std::make_unique(this); + m_alignmentButtonGroup = new QButtonGroup(this); for (const auto& buttonAndAlignment : m_alignmentByButton) { m_alignmentButtonGroup->addButton(buttonAndAlignment.first); } diff --git a/src/app/DefaultParamsDialog.h b/src/app/DefaultParamsDialog.h index 3c819a972..74f89c3f6 100644 --- a/src/app/DefaultParamsDialog.h +++ b/src/app/DefaultParamsDialog.h @@ -4,12 +4,13 @@ #ifndef SCANTAILOR_APP_DEFAULTPARAMSDIALOG_H_ #define SCANTAILOR_APP_DEFAULTPARAMSDIALOG_H_ +#include + #include #include #include #include #include -#include #include "DefaultParams.h" #include "DefaultParamsProfileManager.h" @@ -146,7 +147,7 @@ class DefaultParamsDialog : public QDialog, private Ui::DefaultParamsDialog { bool m_topBottomLinkEnabled; OrthogonalRotation m_orthogonalRotation; std::unordered_map m_alignmentByButton; - std::unique_ptr m_alignmentButtonGroup; + QButtonGroup* m_alignmentButtonGroup; DefaultParamsProfileManager m_profileManager; int m_customDpiItemIdx; QString m_customDpiValue; diff --git a/src/app/DefaultParamsDialog.ui b/src/app/DefaultParamsDialog.ui index f1c9baddf..db267bd2c 100644 --- a/src/app/DefaultParamsDialog.ui +++ b/src/app/DefaultParamsDialog.ui @@ -393,8 +393,8 @@ 0 0 - 193 - 162 + 637 + 442 @@ -470,8 +470,7 @@ - :/icons/single_page_uncut.svg - :/icons/single_page_uncut_selected.svg:/icons/single_page_uncut.svg + :/icons/single_page_uncut.svg:/icons/single_page_uncut.svg @@ -497,8 +496,7 @@ - :/icons/right_page_plus_offcut.svg - :/icons/right_page_plus_offcut_selected.svg:/icons/right_page_plus_offcut.svg + :/icons/right_page_plus_offcut.svg:/icons/right_page_plus_offcut.svg @@ -521,8 +519,7 @@ - :/icons/two_pages.svg - :/icons/two_pages_selected.svg:/icons/two_pages.svg + :/icons/two_pages.svg:/icons/two_pages.svg @@ -1117,8 +1114,8 @@ 0 0 - 637 - 442 + 406 + 237 @@ -1208,14 +1205,14 @@ - 18 - 46 + 20 + 36 - 18 - 46 + 20 + 36 @@ -1246,8 +1243,8 @@ QToolButton:pressed { - 10 - 30 + 18 + 24 @@ -1277,14 +1274,14 @@ QToolButton:pressed { - 18 - 46 + 20 + 36 - 18 - 46 + 20 + 36 @@ -1315,8 +1312,8 @@ QToolButton:pressed { - 10 - 30 + 18 + 24 diff --git a/src/app/FixDpiDialog.cpp b/src/app/FixDpiDialog.cpp index 96e5a88d6..f9eb427f9 100644 --- a/src/app/FixDpiDialog.cpp +++ b/src/app/FixDpiDialog.cpp @@ -188,13 +188,14 @@ class FixDpiDialog::FilterModel : private QSortFilterProxyModel { FixDpiDialog::FixDpiDialog(const std::vector& files, QWidget* parent) - : QDialog(parent), m_pages(new TreeModel(files)), m_undefinedDpiPages(new FilterModel(*m_pages)) { + : QDialog(parent), + m_pages(std::make_unique(files)), + m_undefinedDpiPages(std::make_unique(*m_pages)) { setupUi(this); m_normalPalette = xDpi->palette(); m_errorPalette = m_normalPalette; - const QColor errorTextColor - = ColorSchemeManager::instance().getColorParam(ColorScheme::FixDpiDialogErrorText, QColor(Qt::red)); + const QColor errorTextColor = ColorSchemeManager::instance().getColorParam("FixDpiDialogErrorText", QColor(Qt::red)); m_errorPalette.setColor(QPalette::Text, errorTextColor); dpiCombo->addItem("300 x 300", QSize(300, 300)); diff --git a/src/app/MainWindow.cpp b/src/app/MainWindow.cpp index c77827aaa..208e070b7 100644 --- a/src/app/MainWindow.cpp +++ b/src/app/MainWindow.cpp @@ -59,6 +59,7 @@ #include "UnitsProvider.h" #include "Utils.h" #include "WorkerThreadPool.h" +#include "config.h" #include "filters/deskew/CacheDrivenTask.h" #include "filters/deskew/Task.h" #include "filters/fix_orientation/CacheDrivenTask.h" @@ -97,11 +98,11 @@ class MainWindow::PageSelectionProviderImpl : public PageSelectionProvider { MainWindow::MainWindow() - : m_pages(new ProjectPages), - m_stages(new StageSequence(m_pages, newPageSelectionAccessor())), - m_workerThreadPool(new WorkerThreadPool), - m_interactiveQueue(new ProcessingTaskQueue()), - m_outOfMemoryDialog(new OutOfMemoryDialog), + : m_pages(std::make_shared()), + m_stages(std::make_shared(m_pages, newPageSelectionAccessor())), + m_workerThreadPool(std::make_unique()), + m_interactiveQueue(std::make_unique()), + m_outOfMemoryDialog(std::make_unique()), m_curFilter(0), m_ignoreSelectionChanges(0), m_ignorePageOrderingChanges(0), @@ -139,8 +140,8 @@ MainWindow::MainWindow() m_optionsFrameLayout = new QStackedLayout(filterOptions); - m_statusBarPanel = std::make_unique(); - QMainWindow::statusBar()->addPermanentWidget(m_statusBarPanel.get()); + m_statusBarPanel = new StatusBarPanel; + QMainWindow::statusBar()->addPermanentWidget(m_statusBarPanel); connect(m_thumbSequence.get(), &ThumbnailSequence::newSelectionLeader, [this](const PageInfo& pageInfo) { PageSequence pageSequence = m_thumbSequence->toPageSequence(); if (pageSequence.numPages() > 0) { @@ -150,7 +151,7 @@ MainWindow::MainWindow() } }); - m_unitsMenuActionGroup = std::make_unique(this); + m_unitsMenuActionGroup = new QActionGroup(this); for (QAction* action : menuUnits->actions()) { m_unitsMenuActionGroup->addAction(action); } @@ -194,6 +195,7 @@ MainWindow::MainWindow() }); thumbColumnViewBtn->setChecked(settings.isSingleColumnThumbnailDisplayEnabled()); + deviationHighlightingBtn->setChecked(settings.isHighlightDeviationEnabled()); addAction(actionFirstPage); addAction(actionLastPage); @@ -206,6 +208,9 @@ MainWindow::MainWindow() addAction(actionNextSelectedPageW); addAction(actionPrevSelectedPageQ); addAction(actionGotoPage); + addAction(actionMagnifyThumbnails); + addAction(actionDiminishThumbnails); + addAction(actionReloadPage); addAction(actionSwitchFilter1); addAction(actionSwitchFilter2); @@ -245,6 +250,14 @@ MainWindow::MainWindow() }); connect(gotoPageBtn, SIGNAL(clicked()), this, SLOT(execGotoPageDialog())); + auto magnifyThumbnails = [this]() { scaleThumbnails(1); }; + auto diminishThumbnails = [this]() { scaleThumbnails(-1); }; + connect(magnifyThumbnailsBtn, &QPushButton::clicked, magnifyThumbnails); + connect(diminishThumbnailsBtn, &QPushButton::clicked, diminishThumbnails); + connect(actionMagnifyThumbnails, &QAction::triggered, magnifyThumbnails); + connect(actionDiminishThumbnails, &QAction::triggered, diminishThumbnails); + connect(actionReloadPage, SIGNAL(triggered(bool)), SLOT(reloadCurrentPage())); + connect(actionSwitchFilter1, SIGNAL(triggered(bool)), SLOT(switchFilter1())); connect(actionSwitchFilter2, SIGNAL(triggered(bool)), SLOT(switchFilter2())); connect(actionSwitchFilter3, SIGNAL(triggered(bool)), SLOT(switchFilter3())); @@ -277,10 +290,16 @@ MainWindow::MainWindow() updateThumbnailViewMode(); m_thumbSequence->updateSceneItemsPos(); }); + connect(sortingOrderBtn, &QToolButton::clicked, this, + [this](bool) { pageOrderingChanged(m_stages->filterAt(m_curFilter)->selectedPageOrder()); }); + connect(deviationHighlightingBtn, &QToolButton::clicked, this, [this, &settings](bool checked) { + settings.setHighlightDeviationEnabled(checked); + m_thumbSequence->invalidateAllThumbnails(); + }); connect(actionFixDpi, SIGNAL(triggered(bool)), SLOT(fixDpiDialogRequested())); connect(actionRelinking, SIGNAL(triggered(bool)), SLOT(showRelinkingDialog())); -#ifndef NDEBUG +#ifdef ENABLE_DEBUG_FEATURES connect(actionDebug, SIGNAL(toggled(bool)), SLOT(debugToggled(bool))); #else actionDebug->setVisible(false); @@ -339,7 +358,7 @@ std::vector MainWindow::selectedRanges() const { return m_thumbSequence->selectedRanges(); } -void MainWindow::switchToNewProject(const intrusive_ptr& pages, +void MainWindow::switchToNewProject(const std::shared_ptr& pages, const QString& outDir, const QString& projectFilePath, const ProjectReader* projectReader) { @@ -356,7 +375,7 @@ void MainWindow::switchToNewProject(const intrusive_ptr& pages, m_selectedPage = projectReader->selectedPage(); } - intrusive_ptr disambiguator; + std::shared_ptr disambiguator; if (projectReader) { disambiguator = projectReader->namingDisambiguator(); } else { @@ -368,7 +387,7 @@ void MainWindow::switchToNewProject(const intrusive_ptr& pages, updateDisambiguationRecords(pages->toPageSequence(IMAGE_VIEW)); // Recreate the stages and load their state. - m_stages = make_intrusive(pages, newPageSelectionAccessor()); + m_stages = std::make_shared(pages, newPageSelectionAccessor()); if (projectReader) { projectReader->readFilterSettings(m_stages->filters()); } @@ -496,7 +515,11 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* ev) { if ((obj == thumbView || obj == thumbView->verticalScrollBar()) && (ev->type() == QEvent::Wheel)) { auto* wheelEvent = static_cast(ev); if (wheelEvent->modifiers() == Qt::AltModifier) { - scaleThumbnails(wheelEvent); + const QPoint& angleDelta = wheelEvent->angleDelta(); + const int wheelDist = angleDelta.x() + angleDelta.y(); + if (std::abs(wheelDist) >= 30) { + scaleThumbnails(std::copysign(1, wheelDist)); + } wheelEvent->accept(); return true; } @@ -572,20 +595,22 @@ bool MainWindow::compareFiles(const QString& fpath1, const QString& fpath2) { } } -intrusive_ptr MainWindow::currentPageOrderProvider() const { +std::shared_ptr MainWindow::currentPageOrderProvider() const { const int idx = sortOptions->currentIndex(); if (idx < 0) { return nullptr; } - const intrusive_ptr filter(m_stages->filterAt(m_curFilter)); - return filter->pageOrderOptions()[idx].provider(); + const std::shared_ptr filter(m_stages->filterAt(m_curFilter)); + std::shared_ptr currentOrderProvider = filter->pageOrderOptions()[idx].provider(); + return (currentOrderProvider && sortingOrderBtn->isChecked()) ? currentOrderProvider->reversed() + : currentOrderProvider; } void MainWindow::updateSortOptions() { const ScopedIncDec guard(m_ignorePageOrderingChanges); - const intrusive_ptr filter(m_stages->filterAt(m_curFilter)); + const std::shared_ptr filter(m_stages->filterAt(m_curFilter)); sortOptions->clear(); @@ -600,16 +625,16 @@ void MainWindow::updateSortOptions() { } } -void MainWindow::resetThumbSequence(const intrusive_ptr& pageOrderProvider, +void MainWindow::resetThumbSequence(const std::shared_ptr& pageOrderProvider, const ThumbnailSequence::SelectionAction selectionAction) { if (m_thumbnailCache) { - const intrusive_ptr task(createCompositeCacheDrivenTask(m_curFilter)); + const std::shared_ptr task(createCompositeCacheDrivenTask(m_curFilter)); m_thumbSequence->setThumbnailFactory( - make_intrusive(m_thumbnailCache, m_maxLogicalThumbSize, task)); + std::make_shared(m_thumbnailCache, m_maxLogicalThumbSize, task)); } - m_thumbSequence->reset(m_pages->toPageSequence(getCurrentView()), selectionAction, pageOrderProvider); + m_thumbSequence->reset(currentPageSequence(), selectionAction, pageOrderProvider); if (!m_thumbnailCache) { // Empty project. @@ -736,7 +761,7 @@ void MainWindow::invalidateAllThumbnails() { m_thumbSequence->invalidateAllThumbnails(); } -intrusive_ptr> MainWindow::relinkingDialogRequester() { +std::shared_ptr> MainWindow::relinkingDialogRequester() { class Requester : public AbstractCommand { public: explicit Requester(MainWindow* wnd) : m_wnd(wnd) {} @@ -750,7 +775,7 @@ intrusive_ptr> MainWindow::relinkingDialogRequester() { private: QPointer m_wnd; }; - return make_intrusive(this); + return std::make_shared(this); } void MainWindow::showRelinkingDialog() { @@ -770,7 +795,7 @@ void MainWindow::showRelinkingDialog() { dialog->show(); } -void MainWindow::performRelinking(const intrusive_ptr& relinker) { +void MainWindow::performRelinking(const std::shared_ptr& relinker) { assert(relinker); if (!isProjectLoaded()) { @@ -1034,13 +1059,6 @@ void MainWindow::filterSelectionChanged(const QItemSelection& selected) { thumbView->verticalScrollBar()->setValue(verScrollBarPos); } - // load default settings for all the pages - for (const PageInfo& pageInfo : m_thumbSequence->toPageSequence()) { - for (int i = 0; i < m_stages->count(); i++) { - m_stages->filterAt(i)->loadDefaultSettings(pageInfo); - } - } - updateMainArea(); } // MainWindow::filterSelectionChanged @@ -1078,8 +1096,7 @@ void MainWindow::pageOrderingChanged(int idx) { m_stages->filterAt(m_curFilter)->selectPageOrder(idx); - m_thumbSequence->reset(m_pages->toPageSequence(getCurrentView()), ThumbnailSequence::KEEP_SELECTION, - currentPageOrderProvider()); + m_thumbSequence->reset(currentPageSequence(), ThumbnailSequence::KEEP_SELECTION, currentPageOrderProvider()); if (!focusButton->isChecked()) { thumbView->horizontalScrollBar()->setValue(horScrollBarPos); @@ -1262,7 +1279,7 @@ void MainWindow::fixedDpiSubmitted() { m_pages->updateMetadataFrom(m_fixDpiDialog->files()); // The thumbnail list also stores page metadata, including the DPI. - m_thumbSequence->reset(m_pages->toPageSequence(getCurrentView()), ThumbnailSequence::KEEP_SELECTION, + m_thumbSequence->reset(currentPageSequence(), ThumbnailSequence::KEEP_SELECTION, m_thumbSequence->pageOrderProvider()); const PageInfo selectedPageAfter(m_thumbSequence->selectionLeader()); @@ -1332,7 +1349,7 @@ void MainWindow::newProject() { } void MainWindow::newProjectCreated(ProjectCreationContext* context) { - auto pages = make_intrusive(context->files(), ProjectPages::AUTO_PAGES, context->layoutDirection()); + auto pages = std::make_shared(context->files(), ProjectPages::AUTO_PAGES, context->layoutDirection()); switchToNewProject(pages, context->outDir()); } @@ -1671,7 +1688,7 @@ bool MainWindow::closeProjectInteractive() { } // MainWindow::closeProjectInteractive void MainWindow::closeProjectWithoutSaving() { - auto pages = make_intrusive(); + auto pages = std::make_shared(); switchToNewProject(pages, QString()); } @@ -1920,12 +1937,12 @@ BackgroundTaskPtr MainWindow::createCompositeTask(const PageInfo& page, const int lastFilterIdx, const bool batch, bool debug) { - intrusive_ptr fixOrientationTask; - intrusive_ptr pageSplitTask; - intrusive_ptr deskewTask; - intrusive_ptr selectContentTask; - intrusive_ptr pageLayoutTask; - intrusive_ptr outputTask; + std::shared_ptr fixOrientationTask; + std::shared_ptr pageSplitTask; + std::shared_ptr deskewTask; + std::shared_ptr selectContentTask; + std::shared_ptr pageLayoutTask; + std::shared_ptr outputTask; if (batch) { debug = false; @@ -1956,17 +1973,17 @@ BackgroundTaskPtr MainWindow::createCompositeTask(const PageInfo& page, debug = false; } assert(fixOrientationTask); - return make_intrusive(batch ? BackgroundTask::BATCH : BackgroundTask::INTERACTIVE, page, - m_thumbnailCache, m_pages, fixOrientationTask); + return std::make_shared(batch ? BackgroundTask::BATCH : BackgroundTask::INTERACTIVE, page, + m_thumbnailCache, m_pages, fixOrientationTask); } // MainWindow::createCompositeTask -intrusive_ptr MainWindow::createCompositeCacheDrivenTask(const int lastFilterIdx) { - intrusive_ptr fixOrientationTask; - intrusive_ptr pageSplitTask; - intrusive_ptr deskewTask; - intrusive_ptr selectContentTask; - intrusive_ptr pageLayoutTask; - intrusive_ptr outputTask; +std::shared_ptr MainWindow::createCompositeCacheDrivenTask(const int lastFilterIdx) { + std::shared_ptr fixOrientationTask; + std::shared_ptr pageSplitTask; + std::shared_ptr deskewTask; + std::shared_ptr selectContentTask; + std::shared_ptr pageLayoutTask; + std::shared_ptr outputTask; if (lastFilterIdx >= m_stages->outputFilterIdx()) { outputTask = m_stages->outputFilter()->createCacheDrivenTask(m_outFileNameGen); @@ -1998,7 +2015,7 @@ void MainWindow::updateDisambiguationRecords(const PageSequence& pages) { } PageSelectionAccessor MainWindow::newPageSelectionAccessor() { - auto provider = make_intrusive(this); + auto provider = std::make_shared(this); return PageSelectionAccessor(provider); } @@ -2021,22 +2038,16 @@ void MainWindow::setDockWidgetsVisible(bool state) { thumbnailsDockWidget->setVisible(state); } -void MainWindow::scaleThumbnails(const QWheelEvent* wheelEvent) { - const QPoint& angleDelta = wheelEvent->angleDelta(); - const int wheelDist = angleDelta.x() + angleDelta.y(); - - if (std::abs(wheelDist) >= 30) { - const double dx = std::copysign(25.0, wheelDist); - const double dy = std::copysign(16.0, wheelDist); - const double width = qBound(100.0, m_maxLogicalThumbSize.width() + dx, 1000.0); - const double height = qBound(64.0, m_maxLogicalThumbSize.height() + dy, 640.0); - m_maxLogicalThumbSize = QSizeF(width, height); - if (!m_maxLogicalThumbSizeUpdater.isActive()) { - m_maxLogicalThumbSizeUpdater.start(350); - } - - ApplicationSettings::getInstance().setMaxLogicalThumbnailSize(m_maxLogicalThumbSize); +void MainWindow::scaleThumbnails(int scaleFactor) { + const double dx = 25.0 * scaleFactor; + const double dy = 16.0 * scaleFactor; + const double width = qBound(100.0, m_maxLogicalThumbSize.width() + dx, 1000.0); + const double height = qBound(64.0, m_maxLogicalThumbSize.height() + dy, 640.0); + m_maxLogicalThumbSize = QSizeF(width, height); + if (!m_maxLogicalThumbSizeUpdater.isActive()) { + m_maxLogicalThumbSizeUpdater.start(350); } + ApplicationSettings::getInstance().setMaxLogicalThumbnailSize(m_maxLogicalThumbSize); } void MainWindow::updateMaxLogicalThumbSize() { @@ -2054,6 +2065,10 @@ void MainWindow::setupIcons() { gotoPageBtn->setIcon(iconProvider.getIcon("right-pointing")); selectionModeBtn->setIcon(iconProvider.getIcon("checkbox-styled")); thumbColumnViewBtn->setIcon(iconProvider.getIcon("column-view")); + sortingOrderBtn->setIcon(iconProvider.getIcon("sorting-order")); + deviationHighlightingBtn->setIcon(iconProvider.getIcon("six-spoked-asterisk")); + diminishThumbnailsBtn->setIcon(iconProvider.getIcon("diminishing-glass")); + magnifyThumbnailsBtn->setIcon(iconProvider.getIcon("magnifying-glass")); } void MainWindow::execGotoPageDialog() { @@ -2088,3 +2103,18 @@ void MainWindow::updateAutoSaveTimer() { m_autoSaveTimer.start(60000); } } + +PageSequence MainWindow::currentPageSequence() { + PageSequence pageSequence = m_pages->toPageSequence(getCurrentView()); + if (sortingOrderBtn->isChecked()) { + std::reverse(pageSequence.begin(), pageSequence.end()); + } + return pageSequence; +} + +void MainWindow::reloadCurrentPage() { + if (isBatchProcessingInProgress() || !isProjectLoaded()) + return; + + updateMainArea(); +} diff --git a/src/app/MainWindow.h b/src/app/MainWindow.h index f2cbf114e..ca3f63333 100644 --- a/src/app/MainWindow.h +++ b/src/app/MainWindow.h @@ -28,7 +28,6 @@ #include "SelectedPage.h" #include "StatusBarPanel.h" #include "ThumbnailSequence.h" -#include "intrusive_ptr.h" #include "ui_MainWindow.h" class AbstractFilter; @@ -185,12 +184,14 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma void handleOutOfMemorySituation(); + void reloadCurrentPage(); + private: class PageSelectionProviderImpl; enum SavePromptResult { SAVE, DONT_SAVE, CANCEL }; - using FilterPtr = intrusive_ptr; + using FilterPtr = std::shared_ptr; static void removeWidgetsFromLayout(QLayout* layout); @@ -201,9 +202,9 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma DebugImages* debugImages = nullptr, bool overlay = false) override; - intrusive_ptr> relinkingDialogRequester() override; + std::shared_ptr> relinkingDialogRequester() override; - void switchToNewProject(const intrusive_ptr& pages, + void switchToNewProject(const std::shared_ptr& pages, const QString& outDir, const QString& projectFilePath = QString(), const ProjectReader* projectReader = nullptr); @@ -218,11 +219,11 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma static bool compareFiles(const QString& fpath1, const QString& fpath2); - intrusive_ptr currentPageOrderProvider() const; + std::shared_ptr currentPageOrderProvider() const; void updateSortOptions(); - void resetThumbSequence(const intrusive_ptr& pageOrderProvider, + void resetThumbSequence(const std::shared_ptr& pageOrderProvider, ThumbnailSequence::SelectionAction selectionAction = ThumbnailSequence::RESET_SELECTION); void removeFilterOptionsWidget(); @@ -273,19 +274,19 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma BackgroundTaskPtr createCompositeTask(const PageInfo& page, int lastFilterIdx, bool batch, bool debug); - intrusive_ptr createCompositeCacheDrivenTask(int lastFilterIdx); + std::shared_ptr createCompositeCacheDrivenTask(int lastFilterIdx); void createBatchProcessingWidget(); void updateDisambiguationRecords(const PageSequence& pages); - void performRelinking(const intrusive_ptr& relinker); + void performRelinking(const std::shared_ptr& relinker); PageSelectionAccessor newPageSelectionAccessor(); void setDockWidgetsVisible(bool state); - void scaleThumbnails(const QWheelEvent* wheelEvent); + void scaleThumbnails(int scaleFactor); void updateMaxLogicalThumbSize(); @@ -293,14 +294,16 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma void updateAutoSaveTimer(); + PageSequence currentPageSequence(); + void setupIcons(); QSizeF m_maxLogicalThumbSize; - intrusive_ptr m_pages; - intrusive_ptr m_stages; + std::shared_ptr m_pages; + std::shared_ptr m_stages; QString m_projectFile; OutputFileNameGenerator m_outFileNameGen; - intrusive_ptr m_thumbnailCache; + std::shared_ptr m_thumbnailCache; std::unique_ptr m_thumbSequence; std::unique_ptr m_workerThreadPool; std::unique_ptr m_batchQueue; @@ -325,8 +328,8 @@ class MainWindow : public QMainWindow, private FilterUiInterface, private Ui::Ma bool m_debug; bool m_closing; QTimer m_autoSaveTimer; - std::unique_ptr m_statusBarPanel; - std::unique_ptr m_unitsMenuActionGroup; + StatusBarPanel* m_statusBarPanel; + QActionGroup* m_unitsMenuActionGroup; QTimer m_maxLogicalThumbSizeUpdater; QTimer m_sceneItemsPosUpdater; }; diff --git a/src/app/MainWindow.ui b/src/app/MainWindow.ui index 83eb86d38..0f541f36e 100644 --- a/src/app/MainWindow.ui +++ b/src/app/MainWindow.ui @@ -236,11 +236,6 @@ QToolButton:pressed { 22 - - - sta_thumbnail_panel_icons - - Previous page. @@ -298,11 +293,6 @@ QToolButton:pressed { 22 - - - sta_thumbnail_panel_icons - - Next page. @@ -360,11 +350,6 @@ QToolButton:pressed { 22 - - - sta_thumbnail_panel_icons - - Navigate through selected pages only. @@ -416,7 +401,64 @@ QToolButton:pressed { - + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + Magnify thumbnails. (Ctrl++) + + + QToolButton:!hover { + padding: 0; + border: none; + background-color: transparent; +} + +QToolButton:hover { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(base); +} + +QToolButton:pressed { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(alternative-base); +} + + + + + + + :/icons/magnifying-glass.svg:/icons/magnifying-glass.svg + + + + 16 + 16 + + + + + + 0 @@ -435,13 +477,75 @@ QToolButton:pressed { 22 - - - sta_thumbnail_panel_icons - + + Diminish thumbnails. (Ctrl+-) + + + QToolButton:!hover { + padding: 0; + border: none; + background-color: transparent; +} + +QToolButton:hover { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(base); +} + +QToolButton:pressed { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(alternative-base); +} + + + + + + + :/icons/diminishing-glass.svg:/icons/diminishing-glass.svg + + + + 16 + 16 + + + + + + + + QFrame::Raised + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + - Go To Page... + Go To Page... (Ctrl+G) QToolButton:!hover { @@ -497,11 +601,6 @@ QToolButton:pressed { 22 - - - sta_thumbnail_panel_icons - - Enable multi page selection mode. @@ -574,11 +673,6 @@ QToolButton:checked { 22 - - - sta_thumbnail_panel_icons - - Single/multi column display. @@ -619,6 +713,126 @@ QToolButton:pressed { + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + Sorting order. + + + QToolButton:!hover { + padding: 0; + border: none; + background-color: transparent; +} + +QToolButton:hover { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(base); +} + +QToolButton:pressed { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(alternative-base); +} + + + + + + + :/icons/ascending_sorting_order.svg:/icons/ascending_sorting_order.svg + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + Highlight deviation. + + + QToolButton:!hover { + padding: 0; + border: none; + background-color: transparent; +} + +QToolButton:hover { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(base); +} + +QToolButton:pressed { + padding: 0; + border: 1px solid palette(highlight); + background-color: palette(alternative-base); +} + + + + + + + :/icons/six-spoked-asterisk.svg:/icons/six-spoked-asterisk.svg + + + + 16 + 16 + + + + true + + + @@ -820,6 +1034,9 @@ QToolButton:pressed { + + false + @@ -828,6 +1045,9 @@ QToolButton:pressed { Ctrl+S + + false + @@ -836,6 +1056,9 @@ QToolButton:pressed { + + false + @@ -866,6 +1089,9 @@ QToolButton:pressed { Ctrl+N + + false + @@ -874,6 +1100,9 @@ QToolButton:pressed { Ctrl+O + + false + @@ -904,6 +1133,9 @@ QToolButton:pressed { Ctrl+W + + false + @@ -912,6 +1144,9 @@ QToolButton:pressed { Ctrl+Q + + false + @@ -920,6 +1155,9 @@ QToolButton:pressed { + + false + @@ -928,6 +1166,9 @@ QToolButton:pressed { Home + + false + @@ -936,6 +1177,9 @@ QToolButton:pressed { End + + false + @@ -944,6 +1188,9 @@ QToolButton:pressed { + + false + @@ -952,6 +1199,9 @@ QToolButton:pressed { + + false + @@ -960,6 +1210,9 @@ QToolButton:pressed { + + false + @@ -968,6 +1221,9 @@ QToolButton:pressed { O + + false + @@ -979,6 +1235,9 @@ QToolButton:pressed { E + + false + @@ -990,6 +1249,9 @@ QToolButton:pressed { N + + false + @@ -1001,6 +1263,9 @@ QToolButton:pressed { V + + false + @@ -1012,6 +1277,9 @@ QToolButton:pressed { K + + false + @@ -1023,6 +1291,9 @@ QToolButton:pressed { P + + false + @@ -1090,6 +1361,9 @@ QToolButton:pressed { + + false + @@ -1152,7 +1426,40 @@ QToolButton:pressed { Go To Page - Ctrl+G + Ctrl+G + + + false + + + + + Magnify thumbnails + + + Ctrl++ + + + + + Diminish thumbnails + + + Ctrl+- + + + + + Reload current page + + + Reload current page + + + F5 + + + false diff --git a/src/app/NewOpenProjectPanel.cpp b/src/app/NewOpenProjectPanel.cpp index c6c78f8ee..d0f08eb6d 100644 --- a/src/app/NewOpenProjectPanel.cpp +++ b/src/app/NewOpenProjectPanel.cpp @@ -15,7 +15,6 @@ using namespace core; NewOpenProjectPanel::NewOpenProjectPanel(QWidget* parent) : QWidget(parent) { setupUi(this); - recentProjectsGroup->setLayout(new QVBoxLayout); newProjectLabel->setText(Utils::richTextForLink(newProjectLabel->text())); openProjectLabel->setText(Utils::richTextForLink(openProjectLabel->text())); @@ -74,7 +73,7 @@ void NewOpenProjectPanel::paintEvent(QPaintEvent*) { QPainter painter(this); const QBrush borderBrush - = ColorSchemeManager::instance().getColorParam(ColorScheme::OpenNewProjectBorder, palette().windowText()); + = ColorSchemeManager::instance().getColorParam("OpenNewProjectBorder", palette().windowText()); painter.setPen(QPen(borderBrush, border)); painter.drawRect(exceptMargins); diff --git a/src/app/OutOfMemoryDialog.cpp b/src/app/OutOfMemoryDialog.cpp index df7a5fa89..691f2d167 100644 --- a/src/app/OutOfMemoryDialog.cpp +++ b/src/app/OutOfMemoryDialog.cpp @@ -26,8 +26,8 @@ OutOfMemoryDialog::OutOfMemoryDialog(QWidget* parent) : QDialog(parent) { } void OutOfMemoryDialog::setParams(const QString& projectFile, - intrusive_ptr stages, - intrusive_ptr pages, + std::shared_ptr stages, + std::shared_ptr pages, const SelectedPage& selectedPage, const OutputFileNameGenerator& outFileNameGen) { m_projectFile = projectFile; diff --git a/src/app/OutOfMemoryDialog.h b/src/app/OutOfMemoryDialog.h index 8946a71e3..95648335a 100644 --- a/src/app/OutOfMemoryDialog.h +++ b/src/app/OutOfMemoryDialog.h @@ -6,12 +6,12 @@ #include #include +#include #include "OutputFileNameGenerator.h" #include "ProjectPages.h" #include "SelectedPage.h" #include "StageSequence.h" -#include "intrusive_ptr.h" #include "ui_OutOfMemoryDialog.h" class OutOfMemoryDialog : public QDialog { @@ -21,8 +21,8 @@ class OutOfMemoryDialog : public QDialog { void setParams(const QString& projectFile, // may be empty - intrusive_ptr stages, - intrusive_ptr pages, + std::shared_ptr stages, + std::shared_ptr pages, const SelectedPage& selectedPage, const OutputFileNameGenerator& outFileNameGen); @@ -39,8 +39,8 @@ class OutOfMemoryDialog : public QDialog { Ui::OutOfMemoryDialog ui; QString m_projectFile; - intrusive_ptr m_stages; - intrusive_ptr m_pages; + std::shared_ptr m_stages; + std::shared_ptr m_pages; SelectedPage m_selectedPage; OutputFileNameGenerator m_outFileNameGen; }; diff --git a/src/app/ProjectFilesDialog.cpp b/src/app/ProjectFilesDialog.cpp index dc94689e4..28b2ac9a2 100644 --- a/src/app/ProjectFilesDialog.cpp +++ b/src/app/ProjectFilesDialog.cpp @@ -158,10 +158,10 @@ void ProjectFilesDialog::FileList::assign(It begin, It end) { ProjectFilesDialog::ProjectFilesDialog(QWidget* parent) : QDialog(parent), - m_offProjectFiles(new FileList), - m_offProjectFilesSorted(new SortedFileList(*m_offProjectFiles)), - m_inProjectFiles(new FileList), - m_inProjectFilesSorted(new SortedFileList(*m_inProjectFiles)), + m_offProjectFiles(std::make_unique()), + m_offProjectFilesSorted(std::make_unique(*m_offProjectFiles)), + m_inProjectFiles(std::make_unique()), + m_inProjectFilesSorted(std::make_unique(*m_inProjectFiles)), m_loadTimerId(0), m_metadataLoadFailed(false), m_autoOutDir(true) { diff --git a/src/app/ProjectFilesDialog.ui b/src/app/ProjectFilesDialog.ui index 89e81b1ea..3005bade2 100644 --- a/src/app/ProjectFilesDialog.ui +++ b/src/app/ProjectFilesDialog.ui @@ -104,11 +104,6 @@ 0 - - - sta_project_dialog_icons - - <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -120,7 +115,7 @@ p, li { white-space: pre-wrap; } - :/icons/rigth-arrow-inscribed.svg:/icons/rigth-arrow-inscribed.svg + :/icons/right-arrow-inscribed.svg:/icons/right-arrow-inscribed.svg @@ -138,11 +133,6 @@ p, li { white-space: pre-wrap; } 0 - - - sta_project_dialog_icons - - <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } diff --git a/src/app/RelinkablePathVisualization.cpp b/src/app/RelinkablePathVisualization.cpp index ec8b34c99..5ed335186 100644 --- a/src/app/RelinkablePathVisualization.cpp +++ b/src/app/RelinkablePathVisualization.cpp @@ -119,7 +119,7 @@ void RelinkablePathVisualization::setPath(const RelinkablePath& path, bool click void RelinkablePathVisualization::stylePathComponentButton(QAbstractButton* btn, bool exists) { const QColor borderColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::RelinkablePathVisualizationBorder, palette().color(QPalette::Window).darker(150)); + "RelinkablePathVisualizationBorder", palette().color(QPalette::Window).darker(150)); QString style = "QAbstractButton {\n" " border: 2px solid " diff --git a/src/app/RelinkingDialog.h b/src/app/RelinkingDialog.h index d3069f467..0a7b5f897 100644 --- a/src/app/RelinkingDialog.h +++ b/src/app/RelinkingDialog.h @@ -5,11 +5,11 @@ #define SCANTAILOR_APP_RELINKINGDIALOG_H_ #include +#include #include "AbstractRelinker.h" #include "RelinkablePath.h" #include "RelinkingModel.h" -#include "intrusive_ptr.h" #include "ui_RelinkingDialog.h" class RelinkingSortingModel; @@ -35,7 +35,7 @@ class RelinkingDialog : public QDialog { * This allows you to take the relinker right after construction * and then use it when accepted() signal is emitted. */ - intrusive_ptr relinker() const { return m_model.relinker(); } + std::shared_ptr relinker() const { return m_model.relinker(); } private slots: diff --git a/src/app/RelinkingModel.cpp b/src/app/RelinkingModel.cpp index d354d47f3..5ad67c860 100644 --- a/src/app/RelinkingModel.cpp +++ b/src/app/RelinkingModel.cpp @@ -90,8 +90,8 @@ class RelinkingModel::StatusUpdateThread : private QThread { RelinkingModel::RelinkingModel() : m_fileIcon(IconProvider::getInstance().getIcon("file").pixmap(16, 16)), m_folderIcon(IconProvider::getInstance().getIcon("folder").pixmap(16, 16)), - m_relinker(new Relinker), - m_statusUpdateThread(new StatusUpdateThread(this)), + m_relinker(std::make_shared()), + m_statusUpdateThread(std::make_unique(this)), m_haveUncommittedChanges(true) {} RelinkingModel::~RelinkingModel() = default; diff --git a/src/app/RelinkingModel.h b/src/app/RelinkingModel.h index b1154ae15..d5420910a 100644 --- a/src/app/RelinkingModel.h +++ b/src/app/RelinkingModel.h @@ -20,7 +20,6 @@ #include "NonCopyable.h" #include "RelinkablePath.h" #include "VirtualFunction.h" -#include "intrusive_ptr.h" class RelinkingModel : public QAbstractListModel { DECLARE_NON_COPYABLE(RelinkingModel) @@ -47,7 +46,7 @@ class RelinkingModel : public QAbstractListModel { * This allows you to take the relinker right after construction * and then use it when accepted() signal is emitted. */ - intrusive_ptr relinker() const { return m_relinker; } + std::shared_ptr relinker() const { return m_relinker; } void operator()(const RelinkablePath& path) { addPath(path); } @@ -112,7 +111,7 @@ class RelinkingModel : public QAbstractListModel { QPixmap m_folderIcon; std::vector m_items; std::set m_origPathSet; - const intrusive_ptr m_relinker; + const std::shared_ptr m_relinker; std::unique_ptr m_statusUpdateThread; bool m_haveUncommittedChanges; }; diff --git a/src/app/SettingsDialog.ui b/src/app/SettingsDialog.ui index 1c7f7869b..d02b1cdce 100644 --- a/src/app/SettingsDialog.ui +++ b/src/app/SettingsDialog.ui @@ -398,11 +398,14 @@ The minimum deviation to be highlighted. + + 1 + - 45.000000000000000 + 999.000000000000000 - 0.100000000000000 + 1.000000000000000 diff --git a/src/app/StatusBarPanel.cpp b/src/app/StatusBarPanel.cpp index eadc7df7e..bae94d7c9 100644 --- a/src/app/StatusBarPanel.cpp +++ b/src/app/StatusBarPanel.cpp @@ -3,6 +3,8 @@ #include "StatusBarPanel.h" +#include + #include #include @@ -28,7 +30,7 @@ void StatusBarPanel::onDpiChanged(const Dpi& dpi) { StatusBarPanel::m_dpi = dpi; } -void StatusBarPanel::onProviderStopped() { +void StatusBarPanel::onImageViewInfoProviderStopped() { onMousePosChanged(QPointF()); onPhysSizeChanged(QRectF().size()); m_dpi = Dpi(); @@ -36,6 +38,7 @@ void StatusBarPanel::onProviderStopped() { void StatusBarPanel::updatePage(int pageNumber, size_t pageCount, const PageId& pageId) { ui.pageNoLabel->setText(tr("p. %1 / %2").arg(pageNumber).arg(pageCount)); + ui.pageNoLabel->setVisible(true); QString pageFileInfo = QFileInfo(pageId.imageId().filePath()).completeBaseName(); if (pageFileInfo.size() > 15) { @@ -46,18 +49,28 @@ void StatusBarPanel::updatePage(int pageNumber, size_t pageCount, const PageId& } ui.pageInfoLine->setVisible(true); - ui.pageInfo->setText(pageFileInfo); + ui.pageInfoLabel->setText(pageFileInfo); + ui.pageInfoLabel->setVisible(true); +} + +namespace { +inline void clearAndHideLabel(QLabel* widget) { + widget->clear(); + widget->hide(); } +} // namespace void StatusBarPanel::clear() { - ui.mousePosLabel->clear(); - ui.physSizeLabel->clear(); - ui.pageNoLabel->clear(); - ui.pageInfo->clear(); + clearAndHideLabel(ui.mousePosLabel); + clearAndHideLabel(ui.physSizeLabel); + clearAndHideLabel(ui.pageNoLabel); + clearAndHideLabel(ui.pageInfoLabel); + clearAndHideLabel(ui.zoneModeLabel); ui.mousePosLine->setVisible(false); ui.physSizeLine->setVisible(false); ui.pageInfoLine->setVisible(false); + ui.zoneModeLine->setVisible(false); } void StatusBarPanel::onUnitsChanged(Units) { @@ -85,8 +98,9 @@ void StatusBarPanel::mousePosChanged() { ui.mousePosLine->setVisible(true); ui.mousePosLabel->setText(QString("%1, %2").arg(x).arg(y)); + ui.mousePosLabel->setVisible(true); } else { - ui.mousePosLabel->clear(); + clearAndHideLabel(ui.mousePosLabel); ui.mousePosLine->setVisible(false); } } @@ -119,8 +133,30 @@ void StatusBarPanel::physSizeChanged() { ui.physSizeLine->setVisible(true); ui.physSizeLabel->setText(QString("%1 x %2 %3").arg(width).arg(height).arg(unitsToLocalizedString(units))); + ui.physSizeLabel->setVisible(true); } else { - ui.physSizeLabel->clear(); + clearAndHideLabel(ui.physSizeLabel); ui.physSizeLine->setVisible(false); } } + +void StatusBarPanel::onZoneModeChanged(ZoneCreationMode mode) { + switch (mode) { + case ZoneCreationMode::RECTANGULAR: + ui.zoneModeLabel->setPixmap(IconProvider::getInstance().getIcon("rectangular-zone-mode").pixmap(16, 16)); + break; + case ZoneCreationMode::LASSO: + ui.zoneModeLabel->setPixmap(IconProvider::getInstance().getIcon("lasso-zone-mode").pixmap(16, 16)); + break; + case ZoneCreationMode::POLYGONAL: + ui.zoneModeLabel->setPixmap(IconProvider::getInstance().getIcon("polygonal-zone-mode").pixmap(16, 16)); + break; + } + ui.zoneModeLabel->setVisible(true); + ui.zoneModeLine->setVisible(true); +} + +void StatusBarPanel::onZoneModeProviderStopped() { + clearAndHideLabel(ui.zoneModeLabel); + ui.zoneModeLine->setVisible(false); +} diff --git a/src/app/StatusBarPanel.h b/src/app/StatusBarPanel.h index c579b0f0d..848bf94ce 100644 --- a/src/app/StatusBarPanel.h +++ b/src/app/StatusBarPanel.h @@ -4,6 +4,8 @@ #ifndef SCANTAILOR_APP_STATUSBARPANEL_H_ #define SCANTAILOR_APP_STATUSBARPANEL_H_ +#include + #include #include @@ -15,7 +17,7 @@ class PageId; -class StatusBarPanel : public QWidget, public UnitsListener, public ImageViewInfoListener { +class StatusBarPanel : public QWidget, public UnitsListener, public ImageViewInfoListener, public ZoneModeListener { Q_OBJECT public: StatusBarPanel(); @@ -29,7 +31,7 @@ class StatusBarPanel : public QWidget, public UnitsListener, public ImageViewInf void onDpiChanged(const Dpi& dpi) override; - void onProviderStopped() override; + void onImageViewInfoProviderStopped() override; void updatePage(int pageNumber, size_t pageCount, const PageId& pageId); @@ -37,6 +39,10 @@ class StatusBarPanel : public QWidget, public UnitsListener, public ImageViewInf void onUnitsChanged(Units) override; + void onZoneModeChanged(ZoneCreationMode mode) override; + + void onZoneModeProviderStopped() override; + private: void mousePosChanged(); diff --git a/src/app/StatusBarPanel.ui b/src/app/StatusBarPanel.ui index 9bb35adf2..d1828a06b 100644 --- a/src/app/StatusBarPanel.ui +++ b/src/app/StatusBarPanel.ui @@ -6,7 +6,7 @@ 0 0 - 327 + 300 16 @@ -26,17 +26,49 @@ 0 + + + + + 0 + 0 + + + + + 16 + 16 + + + + Zone creation mode. + + + The type of a new zone created. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + - + 0 0 - 100 + 0 0 @@ -61,22 +93,22 @@ - + 0 0 - 31 + 0 0 - Physical size. + Image size. - Physical size of image. + Image size in current units. Qt::AlignCenter @@ -96,14 +128,14 @@ - + 0 0 - 35 + 0 0 @@ -132,16 +164,16 @@ - + - + 0 0 - 100 + 0 0 diff --git a/src/app/ThumbnailSequence.cpp b/src/app/ThumbnailSequence.cpp index c1e48b5f0..9ad056b8b 100644 --- a/src/app/ThumbnailSequence.cpp +++ b/src/app/ThumbnailSequence.cpp @@ -83,15 +83,15 @@ class ThumbnailSequence::Impl { ~Impl(); - void setThumbnailFactory(intrusive_ptr factory); + void setThumbnailFactory(std::shared_ptr factory); void attachView(QGraphicsView* view); void reset(const PageSequence& pages, SelectionAction selectionAction, - intrusive_ptr provider); + std::shared_ptr provider); - intrusive_ptr pageOrderProvider() const; + std::shared_ptr pageOrderProvider() const; PageSequence toPageSequence() const; @@ -228,8 +228,8 @@ class ThumbnailSequence::Impl { SelectedThenUnselected& m_selectedThenUnselected; const Item* m_selectionLeader; - intrusive_ptr m_factory; - intrusive_ptr m_orderProvider; + std::shared_ptr m_factory; + std::shared_ptr m_orderProvider; GraphicsScene m_graphicsScene; QRectF m_sceneRect; bool m_selectionMode; @@ -310,11 +310,11 @@ class ThumbnailSequence::CompositeItem : public QGraphicsItemGroup { /*============================= ThumbnailSequence ===========================*/ ThumbnailSequence::ThumbnailSequence(const QSizeF& maxLogicalThumbSize, const ViewMode viewMode) - : m_impl(new Impl(*this, maxLogicalThumbSize, viewMode)) {} + : m_impl(std::make_unique(*this, maxLogicalThumbSize, viewMode)) {} ThumbnailSequence::~ThumbnailSequence() {} -void ThumbnailSequence::setThumbnailFactory(intrusive_ptr factory) { +void ThumbnailSequence::setThumbnailFactory(std::shared_ptr factory) { m_impl->setThumbnailFactory(std::move(factory)); } @@ -324,11 +324,11 @@ void ThumbnailSequence::attachView(QGraphicsView* const view) { void ThumbnailSequence::reset(const PageSequence& pages, const SelectionAction selectionAction, - intrusive_ptr orderProvider) { + std::shared_ptr orderProvider) { m_impl->reset(pages, selectionAction, std::move(orderProvider)); } -intrusive_ptr ThumbnailSequence::pageOrderProvider() const { +std::shared_ptr ThumbnailSequence::pageOrderProvider() const { return m_impl->pageOrderProvider(); } @@ -449,7 +449,7 @@ ThumbnailSequence::Impl::Impl(ThumbnailSequence& owner, const QSizeF& maxLogical ThumbnailSequence::Impl::~Impl() {} -void ThumbnailSequence::Impl::setThumbnailFactory(intrusive_ptr factory) { +void ThumbnailSequence::Impl::setThumbnailFactory(std::shared_ptr factory) { m_factory = std::move(factory); } @@ -459,7 +459,7 @@ void ThumbnailSequence::Impl::attachView(QGraphicsView* const view) { void ThumbnailSequence::Impl::reset(const PageSequence& pages, const SelectionAction selectionAction, - intrusive_ptr orderProvider) { + std::shared_ptr orderProvider) { m_orderProvider = std::move(orderProvider); std::set selected; @@ -525,7 +525,7 @@ void ThumbnailSequence::Impl::reset(const PageSequence& pages, } } // ThumbnailSequence::Impl::reset -intrusive_ptr ThumbnailSequence::Impl::pageOrderProvider() const { +std::shared_ptr ThumbnailSequence::Impl::pageOrderProvider() const { return m_orderProvider; } @@ -720,7 +720,7 @@ bool ThumbnailSequence::Impl::cancelingSelectionAccepted() { } bool ThumbnailSequence::Impl::setSelection(const PageId& pageId, const SelectionAction selectionAction) { - if ((selectionAction != KEEP_SELECTION) && !cancelingSelectionAccepted()) { + if ((selectionAction == RESET_SELECTION) && !cancelingSelectionAccepted()) { return false; } @@ -946,13 +946,13 @@ void ThumbnailSequence::Impl::insert(const PageInfo& newPage, BeforeOrAfter befo void ThumbnailSequence::Impl::removePages(const std::set& pagesToRemove) { m_sceneRect = QRectF(0, 0, 0, 0); - const std::set::const_iterator to_remove_end(pagesToRemove.end()); + const std::set::const_iterator toRemoveEnd(pagesToRemove.end()); QPointF posDelta(0, 0); ItemsInOrder::iterator ordIt(m_itemsInOrder.begin()); const ItemsInOrder::iterator ordEnd(m_itemsInOrder.end()); while (ordIt != ordEnd) { - if (pagesToRemove.find(ordIt->pageInfo.id()) == to_remove_end) { + if (pagesToRemove.find(ordIt->pageInfo.id()) == toRemoveEnd) { // Keeping this page. if (posDelta != QPointF(0, 0)) { ordIt->composite->setPos(ordIt->composite->pos() + posDelta); @@ -1312,9 +1312,9 @@ std::unique_ptr ThumbnailSequence::Impl::getLabel boldTextItem->setText(text); const QBrush selectedItemTextColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::ThumbnailSequenceSelectedItemText, QApplication::palette().highlightedText()); - const QBrush selectionLeaderTextColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::ThumbnailSequenceSelectionLeaderText, selectedItemTextColor); + "ThumbnailSequenceSelectedItemText", QApplication::palette().highlightedText()); + const QBrush selectionLeaderTextColor + = ColorSchemeManager::instance().getColorParam("ThumbnailSequenceSelectionLeaderText", selectedItemTextColor); boldTextItem->setBrush(selectionLeaderTextColor); QRectF normalTextBox(normalTextItem->boundingRect()); @@ -1471,10 +1471,10 @@ void ThumbnailSequence::LabelGroup::updateAppearence(bool selected, bool selecti m_normalLabel->setVisible(!selectionLeader); m_boldLabel->setVisible(selectionLeader); - const QBrush itemTextColor = ColorSchemeManager::instance().getColorParam(ColorScheme::ThumbnailSequenceItemText, - QApplication::palette().text()); + const QBrush itemTextColor + = ColorSchemeManager::instance().getColorParam("ThumbnailSequenceItemText", QApplication::palette().text()); const QBrush selectedItemTextColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::ThumbnailSequenceSelectedItemText, QApplication::palette().highlightedText()); + "ThumbnailSequenceSelectedItemText", QApplication::palette().highlightedText()); if (selectionLeader) { assert(selected); @@ -1499,7 +1499,7 @@ ThumbnailSequence::CompositeItem::CompositeItem(ThumbnailSequence::Impl& owner, const QSizeF thumbSize(thumbnail->boundingRect().size()); const QSizeF labelSize(labelGroup->boundingRect().size()); - const int thumbLabelSpacing = 1; + const int thumbLabelSpacing = 2; thumbnail->setPos(0.0, 0.0); labelGroup->setPos(thumbnail->pos().x() + 0.5 * (thumbSize.width() - labelSize.width()), thumbSize.height() + thumbLabelSpacing); @@ -1543,9 +1543,9 @@ void ThumbnailSequence::CompositeItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { const QBrush selectedItemBackgroundColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::ThumbnailSequenceSelectedItemBackground, QApplication::palette().color(QPalette::Highlight)); + "ThumbnailSequenceSelectedItemBackground", QApplication::palette().color(QPalette::Highlight)); const QBrush selectionLeaderBackgroundColor = ColorSchemeManager::instance().getColorParam( - ColorScheme::ThumbnailSequenceSelectionLeaderBackground, selectedItemBackgroundColor); + "ThumbnailSequenceSelectionLeaderBackground", selectedItemBackgroundColor); if (m_item->isSelectionLeader()) { painter->fillRect(boundingRect(), selectionLeaderBackgroundColor); diff --git a/src/app/ThumbnailSequence.h b/src/app/ThumbnailSequence.h index 22a441e2d..e5390b937 100644 --- a/src/app/ThumbnailSequence.h +++ b/src/app/ThumbnailSequence.h @@ -14,7 +14,6 @@ #include "NonCopyable.h" #include "PageOrderProvider.h" #include "PageRange.h" -#include "intrusive_ptr.h" class QGraphicsItem; class QGraphicsView; @@ -32,7 +31,7 @@ class ThumbnailSequence : public QObject { DECLARE_NON_COPYABLE(ThumbnailSequence) public: - enum SelectionAction { KEEP_SELECTION, RESET_SELECTION }; + enum SelectionAction { KEEP_SELECTION, RESET_SELECTION, FORCE_RESET_SELECTION }; enum SelectionFlags { DEFAULT_SELECTION_FLAGS = 0, @@ -65,7 +64,7 @@ class ThumbnailSequence : public QObject { ~ThumbnailSequence() override; - void setThumbnailFactory(intrusive_ptr factory); + void setThumbnailFactory(std::shared_ptr factory); void attachView(QGraphicsView* view); @@ -83,10 +82,10 @@ class ThumbnailSequence : public QObject { */ void reset(const PageSequence& pages, SelectionAction selectionAction, - intrusive_ptr orderProvider = nullptr); + std::shared_ptr orderProvider = nullptr); /** Returns the current page order provider, which may be null. */ - intrusive_ptr pageOrderProvider() const; + std::shared_ptr pageOrderProvider() const; PageSequence toPageSequence() const; @@ -138,7 +137,7 @@ class ThumbnailSequence : public QObject { * with REDUNDANT_SELECTION flag set, in case our page was already the * selection leader. */ - bool setSelection(const PageId& pageId, SelectionAction selectionAction = RESET_SELECTION); + bool setSelection(const PageId& pageId, SelectionAction selectionAction = FORCE_RESET_SELECTION); /** * \brief Returns the current selection leader. diff --git a/src/core/AbstractCommand.h b/src/core/AbstractCommand.h index b7a0f0c81..e8d3ff893 100644 --- a/src/core/AbstractCommand.h +++ b/src/core/AbstractCommand.h @@ -4,13 +4,14 @@ #ifndef SCANTAILOR_CORE_ABSTRACTCOMMAND_H_ #define SCANTAILOR_CORE_ABSTRACTCOMMAND_H_ -#include "intrusive_ptr.h" -#include "ref_countable.h" +#include template -class AbstractCommand : public ref_countable { +class AbstractCommand { public: - using Ptr = intrusive_ptr; + using Ptr = std::shared_ptr; + + virtual ~AbstractCommand() = default; virtual Res operator()(ArgTypes... args) = 0; }; diff --git a/src/core/AbstractFilter.h b/src/core/AbstractFilter.h index 73511a187..7c0b1a8ce 100644 --- a/src/core/AbstractFilter.h +++ b/src/core/AbstractFilter.h @@ -8,7 +8,6 @@ #include "PageOrderOption.h" #include "PageView.h" -#include "ref_countable.h" class FilterUiInterface; class PageInfo; @@ -22,9 +21,9 @@ class QDomElement; /** * Filters represent processing stages, like "Deskew", "Margins" and "Output". */ -class AbstractFilter : public ref_countable { +class AbstractFilter : public std::enable_shared_from_this { public: - ~AbstractFilter() override = default; + virtual ~AbstractFilter() = default; virtual QString getName() const = 0; diff --git a/src/core/AbstractRelinker.h b/src/core/AbstractRelinker.h index f39287df0..8cbd1916c 100644 --- a/src/core/AbstractRelinker.h +++ b/src/core/AbstractRelinker.h @@ -4,14 +4,13 @@ #ifndef SCANTAILOR_CORE_ABSTRACTRELINKER_H_ #define SCANTAILOR_CORE_ABSTRACTRELINKER_H_ -#include "ref_countable.h" class RelinkablePath; class QString; -class AbstractRelinker : public ref_countable { +class AbstractRelinker { public: - ~AbstractRelinker() override = default; + virtual ~AbstractRelinker() = default; /** * Returns the path to be used instead of the given path. diff --git a/src/core/BackgroundExecutor.cpp b/src/core/BackgroundExecutor.cpp index 68a4b987d..58b512eaf 100644 --- a/src/core/BackgroundExecutor.cpp +++ b/src/core/BackgroundExecutor.cpp @@ -43,7 +43,7 @@ class BackgroundExecutor::Impl : public QThread { /*============================ BackgroundExecutor ==========================*/ -BackgroundExecutor::BackgroundExecutor() : m_impl(new Impl(*this)) {} +BackgroundExecutor::BackgroundExecutor() : m_impl(std::make_unique(*this)) {} BackgroundExecutor::~BackgroundExecutor() = default; diff --git a/src/core/BackgroundExecutor.h b/src/core/BackgroundExecutor.h index 882ff4cf3..595734eba 100644 --- a/src/core/BackgroundExecutor.h +++ b/src/core/BackgroundExecutor.h @@ -9,14 +9,13 @@ #include "AbstractCommand.h" #include "NonCopyable.h" #include "PayloadEvent.h" -#include "intrusive_ptr.h" class BackgroundExecutor { DECLARE_NON_COPYABLE(BackgroundExecutor) public: - using TaskResultPtr = intrusive_ptr>; - using TaskPtr = intrusive_ptr>; + using TaskResultPtr = std::shared_ptr>; + using TaskPtr = std::shared_ptr>; BackgroundExecutor(); diff --git a/src/core/BackgroundTask.h b/src/core/BackgroundTask.h index d40df40d7..5c3b4d0fa 100644 --- a/src/core/BackgroundTask.h +++ b/src/core/BackgroundTask.h @@ -6,11 +6,11 @@ #include #include +#include #include "AbstractCommand.h" #include "FilterResult.h" #include "TaskStatus.h" -#include "intrusive_ptr.h" class BackgroundTask : public AbstractCommand, public TaskStatus { public: @@ -41,6 +41,6 @@ class BackgroundTask : public AbstractCommand, public TaskStatu }; -using BackgroundTaskPtr = intrusive_ptr; +using BackgroundTaskPtr = std::shared_ptr; #endif // ifndef SCANTAILOR_CORE_BACKGROUNDTASK_H_ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5d4c2d5a3..68e3a7292 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -81,7 +81,7 @@ set(common_sources FilterResult.h CompositeCacheDrivenTask.h ChangedStateItemDelegate.h - PageOrderProvider.h + PageOrderProvider.h PageOrderProvider.cpp PageOrderOption.h PayloadEvent.h AbstractFilterDataCollector.h @@ -112,14 +112,17 @@ set(common_sources AbstractIconPack.cpp AbstractIconPack.h StyledIconPack.cpp StyledIconPack.h FontIconPack.cpp FontIconPack.h - ConnectionManager.cpp ConnectionManager.h) + ConnectionManager.cpp ConnectionManager.h + ZoneEditorBase.cpp ZoneEditorBase.h + ZoneModeListener.h + ContentMask.cpp ContentMask.h) add_library(core STATIC ${common_sources} ${common_ui_files}) target_link_libraries( core PRIVATE TIFF::TIFF PNG::PNG ZLIB::ZLIB JPEG::JPEG PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Xml Qt5::Network Qt5::OpenGL Qt5::Svg - imageproc + imageproc zones fix_orientation page_split deskew select_content page_layout output) target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") set_target_properties(core PROPERTIES AUTOUIC ON) diff --git a/src/core/ColorScheme.h b/src/core/ColorScheme.h index 60d8cb8fe..31d6e298e 100644 --- a/src/core/ColorScheme.h +++ b/src/core/ColorScheme.h @@ -4,12 +4,13 @@ #ifndef SCANTAILOR_CORE_COLORSCHEME_H_ #define SCANTAILOR_CORE_COLORSCHEME_H_ +#include + #include #include class QStyle; class QPalette; -class QString; class ColorScheme { public: @@ -21,23 +22,7 @@ class ColorScheme { virtual const QString* getStyleSheet() const = 0; - enum ColorParam { - ThumbnailSequenceItemText, - ThumbnailSequenceSelectedItemText, - ThumbnailSequenceSelectedItemBackground, - ThumbnailSequenceSelectionLeaderText, - ThumbnailSequenceSelectionLeaderBackground, - RelinkablePathVisualizationBorder, - OpenNewProjectBorder, - ProcessingIndicationHeadColor, - ProcessingIndicationTail, - ProcessingIndicationFade, - StageListHead, - StageListTail, - FixDpiDialogErrorText - }; - - using ColorParams = std::unordered_map>; + using ColorParams = std::unordered_map>; /** * List of colors for elements that don't support styling. diff --git a/src/core/ColorSchemeManager.cpp b/src/core/ColorSchemeManager.cpp index ae5b7dd67..86e63d716 100644 --- a/src/core/ColorSchemeManager.cpp +++ b/src/core/ColorSchemeManager.cpp @@ -25,7 +25,7 @@ void ColorSchemeManager::setColorScheme(const ColorScheme& colorScheme) { } } -QBrush ColorSchemeManager::getColorParam(const ColorScheme::ColorParam colorParam, const QBrush& defaultBrush) const { +QBrush ColorSchemeManager::getColorParam(const QString& colorParam, const QBrush& defaultBrush) const { if (!m_colorParams) { return defaultBrush; } @@ -38,7 +38,7 @@ QBrush ColorSchemeManager::getColorParam(const ColorScheme::ColorParam colorPara } } -QColor ColorSchemeManager::getColorParam(const ColorScheme::ColorParam colorParam, const QColor& defaultColor) const { +QColor ColorSchemeManager::getColorParam(const QString& colorParam, const QColor& defaultColor) const { if (!m_colorParams) { return defaultColor; } diff --git a/src/core/ColorSchemeManager.h b/src/core/ColorSchemeManager.h index bd4f2d4e8..383947b72 100644 --- a/src/core/ColorSchemeManager.h +++ b/src/core/ColorSchemeManager.h @@ -22,9 +22,9 @@ class ColorSchemeManager { void setColorScheme(const ColorScheme& colorScheme); - QBrush getColorParam(ColorScheme::ColorParam colorParam, const QBrush& defaultBrush) const; + QBrush getColorParam(const QString& colorParam, const QBrush& defaultBrush) const; - QColor getColorParam(ColorScheme::ColorParam colorParam, const QColor& defaultColor) const; + QColor getColorParam(const QString& colorParam, const QColor& defaultColor) const; private: std::unique_ptr m_colorParams; diff --git a/src/core/CompositeCacheDrivenTask.h b/src/core/CompositeCacheDrivenTask.h index c2b497e76..534fa33ab 100644 --- a/src/core/CompositeCacheDrivenTask.h +++ b/src/core/CompositeCacheDrivenTask.h @@ -4,14 +4,13 @@ #ifndef SCANTAILOR_CORE_COMPOSITECACHEDRIVENTASK_H_ #define SCANTAILOR_CORE_COMPOSITECACHEDRIVENTASK_H_ -#include "ref_countable.h" class PageInfo; class AbstractFilterDataCollector; -class CompositeCacheDrivenTask : public ref_countable { +class CompositeCacheDrivenTask { public: - ~CompositeCacheDrivenTask() override = default; + virtual ~CompositeCacheDrivenTask() = default; virtual void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector) = 0; }; diff --git a/src/core/ContentBoxPropagator.cpp b/src/core/ContentBoxPropagator.cpp index 0bd3a0476..9a5174ef3 100644 --- a/src/core/ContentBoxPropagator.cpp +++ b/src/core/ContentBoxPropagator.cpp @@ -31,8 +31,8 @@ class ContentBoxPropagator::Collector : public ContentBoxCollector { }; -ContentBoxPropagator::ContentBoxPropagator(intrusive_ptr pageLayoutFilter, - intrusive_ptr task) +ContentBoxPropagator::ContentBoxPropagator(std::shared_ptr pageLayoutFilter, + std::shared_ptr task) : m_pageLayoutFilter(std::move(pageLayoutFilter)), m_task(std::move(task)) {} ContentBoxPropagator::~ContentBoxPropagator() = default; diff --git a/src/core/ContentBoxPropagator.h b/src/core/ContentBoxPropagator.h index 3d84fc1f7..678f1cfbe 100644 --- a/src/core/ContentBoxPropagator.h +++ b/src/core/ContentBoxPropagator.h @@ -5,8 +5,7 @@ #define SCANTAILOR_CORE_CONTENTBOXPROPAGATOR_H_ #include - -#include "intrusive_ptr.h" +#include class CompositeCacheDrivenTask; class ProjectPages; @@ -26,8 +25,8 @@ class Filter; */ class ContentBoxPropagator { public: - ContentBoxPropagator(intrusive_ptr pageLayoutFilter, - intrusive_ptr task); + ContentBoxPropagator(std::shared_ptr pageLayoutFilter, + std::shared_ptr task); ~ContentBoxPropagator(); @@ -36,8 +35,8 @@ class ContentBoxPropagator { private: class Collector; - intrusive_ptr m_pageLayoutFilter; - intrusive_ptr m_task; + std::shared_ptr m_pageLayoutFilter; + std::shared_ptr m_task; }; diff --git a/src/core/ContentMask.cpp b/src/core/ContentMask.cpp new file mode 100644 index 000000000..031c06387 --- /dev/null +++ b/src/core/ContentMask.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "ContentMask.h" + +#include +#include +#include +#include +#include + +#include + +#include "Despeckle.h" +#include "ImageTransformation.h" +#include "TaskStatus.h" + +using namespace imageproc; + +ContentMask::ContentMask(const GrayImage& grayImage, const ImageTransformation& xform, const TaskStatus& status) { + ImageTransformation xform150dpi(xform); + xform150dpi.preScaleToDpi(Dpi(150, 150)); + if (xform150dpi.resultingRect().toRect().isEmpty()) { + return; + } + m_originalToContentXform = xform150dpi.transform(); + m_contentToOriginalXform = m_originalToContentXform.inverted(); + + QImage gray150(transformToGray(grayImage, xform150dpi.transform(), xform150dpi.resultingRect().toRect(), + OutsidePixels::assumeColor(Qt::white))); + m_image = binarizeWolf(gray150, QSize(51, 51), 50); + PolygonRasterizer::fillExcept(m_image, WHITE, xform150dpi.resultingPreCropArea(), Qt::WindingFill); + Despeckle::despeckleInPlace(m_image, Dpi(150, 150), Despeckle::NORMAL, status); +} + +QRect ContentMask::findContentInArea(const QRect& area) const { + if (isNull()) + return QRect(); + + QRect findingArea = area.intersected(m_image.rect()); + if (findingArea.isEmpty()) + return QRect(); + + const uint32_t* imageLine = m_image.data(); + const int imageStride = m_image.wordsPerLine(); + const uint32_t msb = uint32_t(1) << 31; + + int top = std::numeric_limits::max(); + int left = std::numeric_limits::max(); + int bottom = std::numeric_limits::min(); + int right = std::numeric_limits::min(); + + imageLine += findingArea.top() * imageStride; + for (int y = findingArea.top(); y <= findingArea.bottom(); ++y) { + for (int x = findingArea.left(); x <= findingArea.right(); ++x) { + if (imageLine[x >> 5] & (msb >> (x & 31))) { + top = std::min(top, y); + left = std::min(left, x); + bottom = std::max(bottom, y); + right = std::max(right, x); + } + } + imageLine += imageStride; + } + + if (top > bottom) { + return QRect(); + } + + QRect foundArea = QRect(left, top, right - left + 1, bottom - top + 1); + foundArea.adjust(-1, -1, 1, 1); + return foundArea; +} diff --git a/src/core/ContentMask.h b/src/core/ContentMask.h new file mode 100644 index 000000000..11152bbbe --- /dev/null +++ b/src/core/ContentMask.h @@ -0,0 +1,40 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_CORE_CONTENTMASK_H_ +#define SCANTAILOR_CORE_CONTENTMASK_H_ + +#include + +#include + +namespace imageproc { +class GrayImage; +} +class ImageTransformation; +class TaskStatus; + +class ContentMask { + public: + ContentMask() = default; + + ContentMask(const imageproc::GrayImage& grayImage, const ImageTransformation& xform, const TaskStatus& status); + + QRect findContentInArea(const QRect& area) const; + + const imageproc::BinaryImage& image() const { return m_image; } + + const QTransform& originalToContentXform() const { return m_originalToContentXform; } + + const QTransform& contentToOriginalXform() const { return m_contentToOriginalXform; } + + bool isNull() const { return m_image.isNull(); } + + private: + imageproc::BinaryImage m_image; + QTransform m_originalToContentXform; + QTransform m_contentToOriginalXform; +}; + + +#endif // SCANTAILOR_CORE_CONTENTMASK_H_ diff --git a/src/core/DarkColorScheme.cpp b/src/core/DarkColorScheme.cpp index 86afbc98c..97de23413 100644 --- a/src/core/DarkColorScheme.cpp +++ b/src/core/DarkColorScheme.cpp @@ -80,13 +80,13 @@ void DarkColorScheme::loadStyleSheet() { } void DarkColorScheme::loadColorParams() { - m_customColors[ThumbnailSequenceSelectedItemBackground] = "#424242"; - m_customColors[ThumbnailSequenceSelectionLeaderBackground] = "#555555"; - m_customColors[OpenNewProjectBorder] = "#535353"; - m_customColors[ProcessingIndicationFade] = "#282828"; - m_customColors[ProcessingIndicationHeadColor] = m_palette.color(QPalette::WindowText); - m_customColors[ProcessingIndicationTail] = m_palette.color(QPalette::Highlight); - m_customColors[StageListHead] = m_customColors.at(ProcessingIndicationHeadColor); - m_customColors[StageListTail] = m_customColors.at(ProcessingIndicationTail); - m_customColors[FixDpiDialogErrorText] = "#F34941"; + m_customColors["ThumbnailSequenceSelectedItemBackground"] = "#424242"; + m_customColors["ThumbnailSequenceSelectionLeaderBackground"] = "#555555"; + m_customColors["OpenNewProjectBorder"] = "#535353"; + m_customColors["ProcessingIndicationFade"] = "#282828"; + m_customColors["ProcessingIndicationHead"] = m_palette.color(QPalette::WindowText); + m_customColors["ProcessingIndicationTail"] = m_palette.color(QPalette::Highlight); + m_customColors["StageListHead"] = m_customColors.at("ProcessingIndicationHead"); + m_customColors["StageListTail"] = m_customColors.at("ProcessingIndicationTail"); + m_customColors["FixDpiDialogErrorText"] = "#F34941"; } diff --git a/src/core/DebugImageView.cpp b/src/core/DebugImageView.cpp index 8469091bc..747214de2 100644 --- a/src/core/DebugImageView.cpp +++ b/src/core/DebugImageView.cpp @@ -35,7 +35,7 @@ class DebugImageView::ImageLoader : public AbstractCommand(m_owner, image); + return std::make_shared(m_owner, image); } private: @@ -57,7 +57,7 @@ DebugImageView::DebugImageView(AutoRemovingFile file, void DebugImageView::setLive(const bool live) { if (live && !m_isLive) { - ImageViewBase::backgroundExecutor().enqueueTask(make_intrusive(this, m_file.get())); + ImageViewBase::backgroundExecutor().enqueueTask(std::make_shared(this, m_file.get())); } else if (!live && m_isLive) { if (QWidget* wgt = currentWidget()) { if (wgt != m_placeholderWidget) { diff --git a/src/core/DebugImagesImpl.cpp b/src/core/DebugImagesImpl.cpp index 14298ebc0..4b7c8094f 100644 --- a/src/core/DebugImagesImpl.cpp +++ b/src/core/DebugImagesImpl.cpp @@ -27,7 +27,7 @@ void DebugImagesImpl::add(const QImage& image, return; } - m_sequence.push_back(make_intrusive(aremFile, label, imageViewFactory)); + m_sequence.push_back(std::make_shared(aremFile, label, imageViewFactory)); } void DebugImagesImpl::add(const imageproc::BinaryImage& image, diff --git a/src/core/DebugImagesImpl.h b/src/core/DebugImagesImpl.h index c26072234..114c645cf 100644 --- a/src/core/DebugImagesImpl.h +++ b/src/core/DebugImagesImpl.h @@ -9,10 +9,9 @@ #include #include #include +#include #include "AutoRemovingFile.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" /** * \brief A sequence of image + label pairs. @@ -42,16 +41,18 @@ class DebugImagesImpl : public DebugImages { boost::function* imageViewFactory = nullptr) override; private: - struct Item : public ref_countable { + struct Item { AutoRemovingFile file; QString label; boost::function imageViewFactory; Item(AutoRemovingFile f, const QString& l, const boost::function& imf) : file(f), label(l), imageViewFactory(imf) {} + + virtual ~Item() = default; }; - std::deque> m_sequence; + std::deque> m_sequence; }; diff --git a/src/core/DefaultParams.cpp b/src/core/DefaultParams.cpp index cb2289bc9..59a47e735 100644 --- a/src/core/DefaultParams.cpp +++ b/src/core/DefaultParams.cpp @@ -12,54 +12,6 @@ using namespace foundation; using namespace page_split; using namespace output; -const DefaultParams::FixOrientationParams& DefaultParams::getFixOrientationParams() const { - return m_fixOrientationParams; -} - -void DefaultParams::setFixOrientationParams(const DefaultParams::FixOrientationParams& fixOrientationParams) { - DefaultParams::m_fixOrientationParams = fixOrientationParams; -} - -const DefaultParams::DeskewParams& DefaultParams::getDeskewParams() const { - return m_deskewParams; -} - -void DefaultParams::setDeskewParams(const DefaultParams::DeskewParams& deskewParams) { - DefaultParams::m_deskewParams = deskewParams; -} - -const DefaultParams::PageSplitParams& DefaultParams::getPageSplitParams() const { - return m_pageSplitParams; -} - -void DefaultParams::setPageSplitParams(const DefaultParams::PageSplitParams& pageSplitParams) { - DefaultParams::m_pageSplitParams = pageSplitParams; -} - -const DefaultParams::SelectContentParams& DefaultParams::getSelectContentParams() const { - return m_selectContentParams; -} - -void DefaultParams::setSelectContentParams(const DefaultParams::SelectContentParams& selectContentParams) { - DefaultParams::m_selectContentParams = selectContentParams; -} - -const DefaultParams::PageLayoutParams& DefaultParams::getPageLayoutParams() const { - return m_pageLayoutParams; -} - -void DefaultParams::setPageLayoutParams(const DefaultParams::PageLayoutParams& pageLayoutParams) { - DefaultParams::m_pageLayoutParams = pageLayoutParams; -} - -const DefaultParams::OutputParams& DefaultParams::getOutputParams() const { - return m_outputParams; -} - -void DefaultParams::setOutputParams(const DefaultParams::OutputParams& outputParams) { - DefaultParams::m_outputParams = outputParams; -} - DefaultParams::DefaultParams(const DefaultParams::FixOrientationParams& fixOrientationParams, const DefaultParams::DeskewParams& deskewParams, const DefaultParams::PageSplitParams& pageSplitParams, @@ -97,22 +49,6 @@ QDomElement DefaultParams::toXml(QDomDocument& doc, const QString& name) const { DefaultParams::DefaultParams() : m_units(MILLIMETRES) {} -Units DefaultParams::getUnits() const { - return m_units; -} - -void DefaultParams::setUnits(Units units) { - DefaultParams::m_units = units; -} - -const OrthogonalRotation& DefaultParams::FixOrientationParams::getImageRotation() const { - return m_imageRotation; -} - -void DefaultParams::FixOrientationParams::setImageRotation(const OrthogonalRotation& imageRotation) { - FixOrientationParams::m_imageRotation = imageRotation; -} - DefaultParams::FixOrientationParams::FixOrientationParams(const OrthogonalRotation& imageRotation) : m_imageRotation(imageRotation) {} @@ -128,22 +64,6 @@ QDomElement DefaultParams::FixOrientationParams::toXml(QDomDocument& doc, const DefaultParams::DeskewParams::DeskewParams(double deskewAngleDeg, AutoManualMode mode) : m_deskewAngleDeg(deskewAngleDeg), m_mode(mode) {} -double DefaultParams::DeskewParams::getDeskewAngleDeg() const { - return m_deskewAngleDeg; -} - -void DefaultParams::DeskewParams::setDeskewAngleDeg(double deskewAngleDeg) { - DeskewParams::m_deskewAngleDeg = deskewAngleDeg; -} - -AutoManualMode DefaultParams::DeskewParams::getMode() const { - return m_mode; -} - -void DefaultParams::DeskewParams::setMode(AutoManualMode mode) { - DeskewParams::m_mode = mode; -} - DefaultParams::DeskewParams::DeskewParams() : m_deskewAngleDeg(0.0), m_mode(MODE_AUTO) {} DefaultParams::DeskewParams::DeskewParams(const QDomElement& el) @@ -159,14 +79,6 @@ QDomElement DefaultParams::DeskewParams::toXml(QDomDocument& doc, const QString& DefaultParams::PageSplitParams::PageSplitParams(page_split::LayoutType layoutType) : m_layoutType(layoutType) {} -LayoutType DefaultParams::PageSplitParams::getLayoutType() const { - return m_layoutType; -} - -void DefaultParams::PageSplitParams::setLayoutType(LayoutType layoutType) { - PageSplitParams::m_layoutType = layoutType; -} - DefaultParams::PageSplitParams::PageSplitParams() : m_layoutType(AUTO_LAYOUT_TYPE) {} DefaultParams::PageSplitParams::PageSplitParams(const QDomElement& el) @@ -193,30 +105,6 @@ DefaultParams::SelectContentParams::SelectContentParams() m_pageDetectMode(MODE_DISABLED), m_fineTuneCorners(false) {} -const QSizeF& DefaultParams::SelectContentParams::getPageRectSize() const { - return m_pageRectSize; -} - -void DefaultParams::SelectContentParams::setPageRectSize(const QSizeF& pageRectSize) { - SelectContentParams::m_pageRectSize = pageRectSize; -} - -bool DefaultParams::SelectContentParams::isContentDetectEnabled() const { - return m_contentDetectEnabled; -} - -void DefaultParams::SelectContentParams::setContentDetectEnabled(bool contentDetectEnabled) { - SelectContentParams::m_contentDetectEnabled = contentDetectEnabled; -} - -bool DefaultParams::SelectContentParams::isFineTuneCorners() const { - return m_fineTuneCorners; -} - -void DefaultParams::SelectContentParams::setFineTuneCorners(bool fineTuneCorners) { - SelectContentParams::m_fineTuneCorners = fineTuneCorners; -} - DefaultParams::SelectContentParams::SelectContentParams(const QDomElement& el) : m_pageRectSize(XmlUnmarshaller::sizeF(el.namedItem("pageRectSize").toElement())), m_contentDetectEnabled(el.attribute("contentDetectEnabled") == "1"), @@ -232,14 +120,6 @@ QDomElement DefaultParams::SelectContentParams::toXml(QDomDocument& doc, const Q return el; } -AutoManualMode DefaultParams::SelectContentParams::getPageDetectMode() const { - return m_pageDetectMode; -} - -void DefaultParams::SelectContentParams::setPageDetectMode(AutoManualMode pageDetectMode) { - SelectContentParams::m_pageDetectMode = pageDetectMode; -} - DefaultParams::PageLayoutParams::PageLayoutParams(const Margins& hardMargins, const page_layout::Alignment& alignment, bool autoMargins) @@ -247,30 +127,6 @@ DefaultParams::PageLayoutParams::PageLayoutParams(const Margins& hardMargins, DefaultParams::PageLayoutParams::PageLayoutParams() : m_hardMargins(10, 5, 10, 5), m_autoMargins(false) {} -const Margins& DefaultParams::PageLayoutParams::getHardMargins() const { - return m_hardMargins; -} - -void DefaultParams::PageLayoutParams::setHardMargins(const Margins& hardMargins) { - PageLayoutParams::m_hardMargins = hardMargins; -} - -const page_layout::Alignment& DefaultParams::PageLayoutParams::getAlignment() const { - return m_alignment; -} - -void DefaultParams::PageLayoutParams::setAlignment(const page_layout::Alignment& alignment) { - PageLayoutParams::m_alignment = alignment; -} - -bool DefaultParams::PageLayoutParams::isAutoMargins() const { - return m_autoMargins; -} - -void DefaultParams::PageLayoutParams::setAutoMargins(bool autoMargins) { - PageLayoutParams::m_autoMargins = autoMargins; -} - DefaultParams::PageLayoutParams::PageLayoutParams(const QDomElement& el) : m_hardMargins(el.namedItem("hardMargins").toElement()), m_alignment(el.namedItem("alignment").toElement()), @@ -301,62 +157,6 @@ DefaultParams::OutputParams::OutputParams(const Dpi& dpi, DefaultParams::OutputParams::OutputParams() : m_dpi(600, 600), m_despeckleLevel(1.0) {} -const Dpi& DefaultParams::OutputParams::getDpi() const { - return m_dpi; -} - -void DefaultParams::OutputParams::setDpi(const Dpi& dpi) { - OutputParams::m_dpi = dpi; -} - -const ColorParams& DefaultParams::OutputParams::getColorParams() const { - return m_colorParams; -} - -void DefaultParams::OutputParams::setColorParams(const ColorParams& colorParams) { - OutputParams::m_colorParams = colorParams; -} - -const SplittingOptions& DefaultParams::OutputParams::getSplittingOptions() const { - return m_splittingOptions; -} - -void DefaultParams::OutputParams::setSplittingOptions(const SplittingOptions& splittingOptions) { - OutputParams::m_splittingOptions = splittingOptions; -} - -const PictureShapeOptions& DefaultParams::OutputParams::getPictureShapeOptions() const { - return m_pictureShapeOptions; -} - -void DefaultParams::OutputParams::setPictureShapeOptions(const PictureShapeOptions& pictureShapeOptions) { - OutputParams::m_pictureShapeOptions = pictureShapeOptions; -} - -const DepthPerception& DefaultParams::OutputParams::getDepthPerception() const { - return m_depthPerception; -} - -void DefaultParams::OutputParams::setDepthPerception(const DepthPerception& depthPerception) { - OutputParams::m_depthPerception = depthPerception; -} - -const DewarpingOptions& DefaultParams::OutputParams::getDewarpingOptions() const { - return m_dewarpingOptions; -} - -void DefaultParams::OutputParams::setDewarpingOptions(const DewarpingOptions& dewarpingOptions) { - OutputParams::m_dewarpingOptions = dewarpingOptions; -} - -double DefaultParams::OutputParams::getDespeckleLevel() const { - return m_despeckleLevel; -} - -void DefaultParams::OutputParams::setDespeckleLevel(double despeckleLevel) { - OutputParams::m_despeckleLevel = despeckleLevel; -} - DefaultParams::OutputParams::OutputParams(const QDomElement& el) : m_dpi(el.namedItem("dpi").toElement()), m_colorParams(el.namedItem("colorParams").toElement()), diff --git a/src/core/DefaultParams.h b/src/core/DefaultParams.h index 1c39038cf..60b857da7 100644 --- a/src/core/DefaultParams.h +++ b/src/core/DefaultParams.h @@ -253,4 +253,206 @@ class DefaultParams { }; +inline Units DefaultParams::getUnits() const { + return m_units; +} + +inline void DefaultParams::setUnits(Units units) { + DefaultParams::m_units = units; +} + +inline const DefaultParams::FixOrientationParams& DefaultParams::getFixOrientationParams() const { + return m_fixOrientationParams; +} + +inline void DefaultParams::setFixOrientationParams(const DefaultParams::FixOrientationParams& fixOrientationParams) { + DefaultParams::m_fixOrientationParams = fixOrientationParams; +} + +inline const DefaultParams::DeskewParams& DefaultParams::getDeskewParams() const { + return m_deskewParams; +} + +inline void DefaultParams::setDeskewParams(const DefaultParams::DeskewParams& deskewParams) { + DefaultParams::m_deskewParams = deskewParams; +} + +inline const DefaultParams::PageSplitParams& DefaultParams::getPageSplitParams() const { + return m_pageSplitParams; +} + +inline void DefaultParams::setPageSplitParams(const DefaultParams::PageSplitParams& pageSplitParams) { + DefaultParams::m_pageSplitParams = pageSplitParams; +} + +inline const DefaultParams::SelectContentParams& DefaultParams::getSelectContentParams() const { + return m_selectContentParams; +} + +inline void DefaultParams::setSelectContentParams(const DefaultParams::SelectContentParams& selectContentParams) { + DefaultParams::m_selectContentParams = selectContentParams; +} + +inline const DefaultParams::PageLayoutParams& DefaultParams::getPageLayoutParams() const { + return m_pageLayoutParams; +} + +inline void DefaultParams::setPageLayoutParams(const DefaultParams::PageLayoutParams& pageLayoutParams) { + DefaultParams::m_pageLayoutParams = pageLayoutParams; +} + +inline const DefaultParams::OutputParams& DefaultParams::getOutputParams() const { + return m_outputParams; +} + +inline void DefaultParams::setOutputParams(const DefaultParams::OutputParams& outputParams) { + DefaultParams::m_outputParams = outputParams; +} + +inline const OrthogonalRotation& DefaultParams::FixOrientationParams::getImageRotation() const { + return m_imageRotation; +} + +inline void DefaultParams::FixOrientationParams::setImageRotation(const OrthogonalRotation& imageRotation) { + FixOrientationParams::m_imageRotation = imageRotation; +} + +inline double DefaultParams::DeskewParams::getDeskewAngleDeg() const { + return m_deskewAngleDeg; +} + +inline void DefaultParams::DeskewParams::setDeskewAngleDeg(double deskewAngleDeg) { + DeskewParams::m_deskewAngleDeg = deskewAngleDeg; +} + +inline AutoManualMode DefaultParams::DeskewParams::getMode() const { + return m_mode; +} + +inline void DefaultParams::DeskewParams::setMode(AutoManualMode mode) { + DeskewParams::m_mode = mode; +} + +inline page_split::LayoutType DefaultParams::PageSplitParams::getLayoutType() const { + return m_layoutType; +} + +inline void DefaultParams::PageSplitParams::setLayoutType(page_split::LayoutType layoutType) { + PageSplitParams::m_layoutType = layoutType; +} + +inline const QSizeF& DefaultParams::SelectContentParams::getPageRectSize() const { + return m_pageRectSize; +} + +inline void DefaultParams::SelectContentParams::setPageRectSize(const QSizeF& pageRectSize) { + SelectContentParams::m_pageRectSize = pageRectSize; +} + +inline bool DefaultParams::SelectContentParams::isContentDetectEnabled() const { + return m_contentDetectEnabled; +} + +inline void DefaultParams::SelectContentParams::setContentDetectEnabled(bool contentDetectEnabled) { + SelectContentParams::m_contentDetectEnabled = contentDetectEnabled; +} + +inline bool DefaultParams::SelectContentParams::isFineTuneCorners() const { + return m_fineTuneCorners; +} + +inline void DefaultParams::SelectContentParams::setFineTuneCorners(bool fineTuneCorners) { + SelectContentParams::m_fineTuneCorners = fineTuneCorners; +} + +inline AutoManualMode DefaultParams::SelectContentParams::getPageDetectMode() const { + return m_pageDetectMode; +} + +inline void DefaultParams::SelectContentParams::setPageDetectMode(AutoManualMode pageDetectMode) { + SelectContentParams::m_pageDetectMode = pageDetectMode; +} + +inline const Margins& DefaultParams::PageLayoutParams::getHardMargins() const { + return m_hardMargins; +} + +inline void DefaultParams::PageLayoutParams::setHardMargins(const Margins& hardMargins) { + PageLayoutParams::m_hardMargins = hardMargins; +} + +inline const page_layout::Alignment& DefaultParams::PageLayoutParams::getAlignment() const { + return m_alignment; +} + +inline void DefaultParams::PageLayoutParams::setAlignment(const page_layout::Alignment& alignment) { + PageLayoutParams::m_alignment = alignment; +} + +inline bool DefaultParams::PageLayoutParams::isAutoMargins() const { + return m_autoMargins; +} + +inline void DefaultParams::PageLayoutParams::setAutoMargins(bool autoMargins) { + PageLayoutParams::m_autoMargins = autoMargins; +} + +inline const Dpi& DefaultParams::OutputParams::getDpi() const { + return m_dpi; +} + +inline void DefaultParams::OutputParams::setDpi(const Dpi& dpi) { + OutputParams::m_dpi = dpi; +} + +inline const output::ColorParams& DefaultParams::OutputParams::getColorParams() const { + return m_colorParams; +} + +inline void DefaultParams::OutputParams::setColorParams(const output::ColorParams& colorParams) { + OutputParams::m_colorParams = colorParams; +} + +inline const output::SplittingOptions& DefaultParams::OutputParams::getSplittingOptions() const { + return m_splittingOptions; +} + +inline void DefaultParams::OutputParams::setSplittingOptions(const output::SplittingOptions& splittingOptions) { + OutputParams::m_splittingOptions = splittingOptions; +} + +inline const output::PictureShapeOptions& DefaultParams::OutputParams::getPictureShapeOptions() const { + return m_pictureShapeOptions; +} + +inline void DefaultParams::OutputParams::setPictureShapeOptions( + const output::PictureShapeOptions& pictureShapeOptions) { + OutputParams::m_pictureShapeOptions = pictureShapeOptions; +} + +inline const output::DepthPerception& DefaultParams::OutputParams::getDepthPerception() const { + return m_depthPerception; +} + +inline void DefaultParams::OutputParams::setDepthPerception(const output::DepthPerception& depthPerception) { + OutputParams::m_depthPerception = depthPerception; +} + +inline const output::DewarpingOptions& DefaultParams::OutputParams::getDewarpingOptions() const { + return m_dewarpingOptions; +} + +inline void DefaultParams::OutputParams::setDewarpingOptions(const output::DewarpingOptions& dewarpingOptions) { + OutputParams::m_dewarpingOptions = dewarpingOptions; +} + +inline double DefaultParams::OutputParams::getDespeckleLevel() const { + return m_despeckleLevel; +} + +inline void DefaultParams::OutputParams::setDespeckleLevel(double despeckleLevel) { + OutputParams::m_despeckleLevel = despeckleLevel; +} + + #endif // SCANTAILOR_CORE_DEFAULTPARAMS_H_ diff --git a/src/core/DefaultParamsProvider.cpp b/src/core/DefaultParamsProvider.cpp index 8b16bf1cd..27b2cace8 100644 --- a/src/core/DefaultParamsProvider.cpp +++ b/src/core/DefaultParamsProvider.cpp @@ -42,7 +42,7 @@ const QString& DefaultParamsProvider::getProfileName() const { return m_profileName; } -DefaultParams DefaultParamsProvider::getParams() const { +const DefaultParams& DefaultParamsProvider::getParams() const { assert(m_params != nullptr); return *m_params; } diff --git a/src/core/DefaultParamsProvider.h b/src/core/DefaultParamsProvider.h index e5fd78844..2b1cfa79c 100644 --- a/src/core/DefaultParamsProvider.h +++ b/src/core/DefaultParamsProvider.h @@ -21,7 +21,7 @@ class DefaultParamsProvider { const QString& getProfileName() const; - DefaultParams getParams() const; + const DefaultParams& getParams() const; void setParams(std::unique_ptr params, const QString& name); diff --git a/src/core/DeviationProvider.h b/src/core/DeviationProvider.h index 29c1b66cf..148e19d9f 100644 --- a/src/core/DeviationProvider.h +++ b/src/core/DeviationProvider.h @@ -18,7 +18,7 @@ class DeviationProvider { explicit DeviationProvider(const std::function& computeValueByKey); - bool isDeviant(const K& key, double coefficient = 1.0, double threshold = 0.0) const; + bool isDeviant(const K& key, double coefficient = 1.0, double threshold = 0.0, bool defaultVal = false) const; double getDeviationValue(const K& key) const; @@ -51,7 +51,7 @@ DeviationProvider::DeviationProvider(const std::function -bool DeviationProvider::isDeviant(const K& key, const double coefficient, const double threshold) const { +bool DeviationProvider::isDeviant(const K& key, double coefficient, double threshold, bool defaultVal) const { if (m_keyValueMap.find(key) == m_keyValueMap.end()) { return false; } @@ -59,19 +59,30 @@ bool DeviationProvider::isDeviant(const K& key, const double coefficien return false; } + double value = m_keyValueMap.at(key); + if (std::isnan(value)) { + return defaultVal; + } + update(); - return (std::abs(m_keyValueMap.at(key) - m_meanValue) > std::max((coefficient * m_standardDeviation), threshold)); + return (std::abs(value - m_meanValue) + > std::max((coefficient * m_standardDeviation), (threshold / 100) * m_meanValue)); } template double DeviationProvider::getDeviationValue(const K& key) const { if (m_keyValueMap.find(key) == m_keyValueMap.end()) { - return .0; + return -1.0; } if (m_keyValueMap.size() < 2) { return .0; } + double value = m_keyValueMap.at(key); + if (std::isnan(value)) { + return -1.0; + } + update(); return std::abs(m_keyValueMap.at(key) - m_meanValue); } @@ -97,7 +108,6 @@ void DeviationProvider::remove(const K& key) { if (m_keyValueMap.find(key) == m_keyValueMap.end()) { return; } - m_keyValueMap.erase(key); } @@ -110,20 +120,26 @@ void DeviationProvider::update() const { return; } + int count = 0; { double sum = .0; - for (const std::pair& keyAndValue : m_keyValueMap) { - sum += keyAndValue.second; + for (const auto& [key, value] : m_keyValueMap) { + if (!std::isnan(value)) { + sum += value; + count++; + } } - m_meanValue = sum / m_keyValueMap.size(); + m_meanValue = sum / count; } { double differencesSum = .0; - for (const std::pair& keyAndValue : m_keyValueMap) { - differencesSum += std::pow(keyAndValue.second - m_meanValue, 2); + for (const auto& [key, value] : m_keyValueMap) { + if (!std::isnan(value)) { + differencesSum += std::pow(value - m_meanValue, 2); + } } - m_standardDeviation = std::sqrt(differencesSum / (m_keyValueMap.size() - 1)); + m_standardDeviation = std::sqrt(differencesSum / (count - 1)); } m_needUpdate = false; diff --git a/src/core/FileNameDisambiguator.cpp b/src/core/FileNameDisambiguator.cpp index 0c7a22f43..f98bbe333 100644 --- a/src/core/FileNameDisambiguator.cpp +++ b/src/core/FileNameDisambiguator.cpp @@ -73,14 +73,16 @@ class FileNameDisambiguator::Impl { /*====================== FileNameDisambiguator =========================*/ -FileNameDisambiguator::FileNameDisambiguator() : m_impl(new Impl) {} +FileNameDisambiguator::FileNameDisambiguator() : m_impl(std::make_unique()) {} FileNameDisambiguator::FileNameDisambiguator(const QDomElement& disambiguatorEl) - : m_impl(new Impl(disambiguatorEl, boost::lambda::_1)) {} + : m_impl(std::make_unique(disambiguatorEl, boost::lambda::_1)) {} FileNameDisambiguator::FileNameDisambiguator(const QDomElement& disambiguatorEl, const boost::function& filePathUnpacker) - : m_impl(new Impl(disambiguatorEl, filePathUnpacker)) {} + : m_impl(std::make_unique(disambiguatorEl, filePathUnpacker)) {} + +FileNameDisambiguator::~FileNameDisambiguator() = default; QDomElement FileNameDisambiguator::toXml(QDomDocument& doc, const QString& name) const { return m_impl->toXml(doc, name, boost::lambda::_1); diff --git a/src/core/FileNameDisambiguator.h b/src/core/FileNameDisambiguator.h index 1bf75ba32..71daefa50 100644 --- a/src/core/FileNameDisambiguator.h +++ b/src/core/FileNameDisambiguator.h @@ -9,7 +9,6 @@ #include #include "NonCopyable.h" -#include "ref_countable.h" class AbstractRelinker; class QString; @@ -23,7 +22,7 @@ class QDomDocument; * * \note This class is thread-safe. */ -class FileNameDisambiguator : public ref_countable { +class FileNameDisambiguator { DECLARE_NON_COPYABLE(FileNameDisambiguator) public: @@ -45,6 +44,8 @@ class FileNameDisambiguator : public ref_countable { FileNameDisambiguator(const QDomElement& disambiguatorEl, const boost::function& filePathUnpacker); + virtual ~FileNameDisambiguator(); + /** * \brief Serialize disambiguation information to XML. */ diff --git a/src/core/FilterData.cpp b/src/core/FilterData.cpp index d4fe435e8..f382c87bd 100644 --- a/src/core/FilterData.cpp +++ b/src/core/FilterData.cpp @@ -24,26 +24,10 @@ imageproc::BinaryThreshold FilterData::bwThreshold() const { return m_imageParams.getBwThreshold(); } -const ImageTransformation& FilterData::xform() const { - return m_xform; -} - -const QImage& FilterData::origImage() const { - return m_origImage; -} - -const imageproc::GrayImage& FilterData::grayImage() const { - return m_grayImage; -} - bool FilterData::isBlackOnWhite() const { return m_imageParams.isBlackOnWhite(); } -void FilterData::updateImageParams(const ImageSettings::PageParams& imageParams) { - m_imageParams = imageParams; -} - imageproc::BinaryThreshold FilterData::bwThresholdBlackOnWhite() const { return isBlackOnWhite() ? bwThreshold() : BinaryThreshold(256 - int(bwThreshold())); } diff --git a/src/core/FilterData.h b/src/core/FilterData.h index c11b8faad..590e15caf 100644 --- a/src/core/FilterData.h +++ b/src/core/FilterData.h @@ -45,4 +45,21 @@ class FilterData { }; +inline const ImageTransformation& FilterData::xform() const { + return m_xform; +} + +inline const QImage& FilterData::origImage() const { + return m_origImage; +} + +inline const imageproc::GrayImage& FilterData::grayImage() const { + return m_grayImage; +} + +inline void FilterData::updateImageParams(const ImageSettings::PageParams& imageParams) { + m_imageParams = imageParams; +} + + #endif // ifndef SCANTAILOR_CORE_FILTERDATA_H_ diff --git a/src/core/FilterResult.h b/src/core/FilterResult.h index 17027bf0a..45360695c 100644 --- a/src/core/FilterResult.h +++ b/src/core/FilterResult.h @@ -4,14 +4,15 @@ #ifndef SCANTAILOR_CORE_FILTERRESULT_H_ #define SCANTAILOR_CORE_FILTERRESULT_H_ -#include "intrusive_ptr.h" -#include "ref_countable.h" +#include class AbstractFilter; class FilterUiInterface; -class FilterResult : public ref_countable { +class FilterResult { public: + virtual ~FilterResult() = default; + virtual void updateUI(FilterUiInterface* ui) = 0; /** @@ -21,10 +22,10 @@ class FilterResult : public ref_countable { * That would be LoadFileTask. */ - virtual intrusive_ptr filter() = 0; + virtual std::shared_ptr filter() = 0; }; -using FilterResultPtr = intrusive_ptr; +using FilterResultPtr = std::shared_ptr; #endif diff --git a/src/core/FilterUiInterface.h b/src/core/FilterUiInterface.h index 4738cf0fa..d6350fad3 100644 --- a/src/core/FilterUiInterface.h +++ b/src/core/FilterUiInterface.h @@ -4,9 +4,10 @@ #ifndef SCANTAILOR_CORE_FILTERUIINTERFACE_H_ #define SCANTAILOR_CORE_FILTERUIINTERFACE_H_ +#include + #include "AbstractCommand.h" #include "PageId.h" -#include "intrusive_ptr.h" class DebugImages; class FilterOptionsWidget; @@ -36,7 +37,7 @@ class FilterUiInterface { /** * Returns a callable object that when called will open a relinking dialog. */ - virtual intrusive_ptr> relinkingDialogRequester() = 0; + virtual std::shared_ptr> relinkingDialogRequester() = 0; }; diff --git a/src/core/ImageMetadataLoader.cpp b/src/core/ImageMetadataLoader.cpp index 15de951e5..d318c86ef 100644 --- a/src/core/ImageMetadataLoader.cpp +++ b/src/core/ImageMetadataLoader.cpp @@ -14,14 +14,14 @@ ImageMetadataLoader::LoaderList ImageMetadataLoader::m_sLoaders; -void ImageMetadataLoader::registerLoader(intrusive_ptr loader) { +void ImageMetadataLoader::registerLoader(std::shared_ptr loader) { m_sLoaders.push_back(std::move(loader)); } ImageMetadataLoader::StaticInit::StaticInit() { - registerLoader(make_intrusive()); - registerLoader(make_intrusive()); - registerLoader(make_intrusive()); + registerLoader(std::make_shared()); + registerLoader(std::make_shared()); + registerLoader(std::make_shared()); } ImageMetadataLoader::StaticInit ImageMetadataLoader::m_staticInit; diff --git a/src/core/ImageMetadataLoader.h b/src/core/ImageMetadataLoader.h index d8f072823..275816404 100644 --- a/src/core/ImageMetadataLoader.h +++ b/src/core/ImageMetadataLoader.h @@ -4,17 +4,16 @@ #ifndef SCANTAILOR_CORE_IMAGEMETADATALOADER_H_ #define SCANTAILOR_CORE_IMAGEMETADATALOADER_H_ +#include #include #include "VirtualFunction.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QString; class QIODevice; class ImageMetadata; -class ImageMetadataLoader : public ref_countable { +class ImageMetadataLoader { public: enum Status { LOADED, /**< Loaded successfully */ @@ -29,7 +28,7 @@ class ImageMetadataLoader : public ref_countable { * This function may not be called before main() or after additional * threads have been created. */ - static void registerLoader(intrusive_ptr loader); + static void registerLoader(std::shared_ptr loader); template static Status load(QIODevice& ioDevice, OutFunc out); @@ -38,7 +37,7 @@ class ImageMetadataLoader : public ref_countable { static Status load(const QString& filePath, OutFunc out); protected: - ~ImageMetadataLoader() override = default; + virtual ~ImageMetadataLoader() = default; /** * \brief Loads metadata from a particular image format. @@ -60,7 +59,7 @@ class ImageMetadataLoader : public ref_countable { static Status loadImpl(const QString& filePath, const VirtualFunction& out); - using LoaderList = std::vector>; + using LoaderList = std::vector>; static LoaderList m_sLoaders; diff --git a/src/core/ImageSettings.cpp b/src/core/ImageSettings.cpp index 2fe20b68a..4e2156348 100644 --- a/src/core/ImageSettings.cpp +++ b/src/core/ImageSettings.cpp @@ -58,20 +58,4 @@ QDomElement ImageSettings::PageParams::toXml(QDomDocument& doc, const QString& n el.setAttribute("bwThreshold", m_bwThreshold); el.setAttribute("blackOnWhite", m_blackOnWhite ? "1" : "0"); return el; -} - -const BinaryThreshold& ImageSettings::PageParams::getBwThreshold() const { - return m_bwThreshold; -} - -void ImageSettings::PageParams::setBwThreshold(const BinaryThreshold& bwThreshold) { - PageParams::m_bwThreshold = bwThreshold; -} - -bool ImageSettings::PageParams::isBlackOnWhite() const { - return m_blackOnWhite; -} - -void ImageSettings::PageParams::setBlackOnWhite(bool blackOnWhite) { - PageParams::m_blackOnWhite = blackOnWhite; -} +} \ No newline at end of file diff --git a/src/core/ImageSettings.h b/src/core/ImageSettings.h index a47985a1c..d2de3401f 100644 --- a/src/core/ImageSettings.h +++ b/src/core/ImageSettings.h @@ -5,7 +5,6 @@ #define SCANTAILOR_CORE_IMAGESETTINGS_H_ #include -#include #include #include @@ -17,7 +16,7 @@ class AbstractRelinker; -class ImageSettings : public ref_countable { +class ImageSettings { DECLARE_NON_COPYABLE(ImageSettings) public: class PageParams { @@ -45,7 +44,7 @@ class ImageSettings : public ref_countable { ImageSettings() = default; - ~ImageSettings() override = default; + virtual ~ImageSettings() = default; void clear(); @@ -63,4 +62,20 @@ class ImageSettings : public ref_countable { }; +inline const imageproc::BinaryThreshold& ImageSettings::PageParams::getBwThreshold() const { + return m_bwThreshold; +} + +inline void ImageSettings::PageParams::setBwThreshold(const imageproc::BinaryThreshold& bwThreshold) { + PageParams::m_bwThreshold = bwThreshold; +} + +inline bool ImageSettings::PageParams::isBlackOnWhite() const { + return m_blackOnWhite; +} + +inline void ImageSettings::PageParams::setBlackOnWhite(bool blackOnWhite) { + PageParams::m_blackOnWhite = blackOnWhite; +} + #endif // SCANTAILOR_CORE_IMAGESETTINGS_H_ diff --git a/src/core/ImageViewBase.cpp b/src/core/ImageViewBase.cpp index 550a28449..dc8a3e785 100644 --- a/src/core/ImageViewBase.cpp +++ b/src/core/ImageViewBase.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -29,7 +31,7 @@ using namespace core; using namespace imageproc; -class ImageViewBase::HqTransformTask : public AbstractCommand>>, public QObject { +class ImageViewBase::HqTransformTask : public AbstractCommand>>, public QObject { DECLARE_NON_COPYABLE(HqTransformTask) public: @@ -39,7 +41,7 @@ class ImageViewBase::HqTransformTask : public AbstractCommandisCancelled(); } - intrusive_ptr> operator()() override; + std::shared_ptr> operator()() override; private: class Result : public AbstractCommand { @@ -62,7 +64,7 @@ class ImageViewBase::HqTransformTask : public AbstractCommand m_result; + std::shared_ptr m_result; QImage m_image; QTransform m_xform; QSize m_targetSize; @@ -560,7 +562,6 @@ void ImageViewBase::leaveEvent(QEvent* event) { void ImageViewBase::showEvent(QShowEvent* event) { QWidget::showEvent(event); - if (auto* mainWindow = dynamic_cast(window())) { if (auto* infoListener = Utils::castOrFindChild(mainWindow->statusBar())) { infoProvider().addListener(infoListener); @@ -568,6 +569,11 @@ void ImageViewBase::showEvent(QShowEvent* event) { } } +void ImageViewBase::hideEvent(QHideEvent* event) { + infoProvider().removeAllListeners(); + QWidget::hideEvent(event); +} + /** * Called when any of the transformations change. */ @@ -927,7 +933,7 @@ void ImageViewBase::initiateBuildingHqVersion() { } const QTransform xform(m_imageToVirtual * m_virtualToWidget); - const auto task = make_intrusive(this, m_image, xform, viewport()->size()); + const auto task = std::make_shared(this, m_image, xform, viewport()->size()); backgroundExecutor().enqueueTask(task); @@ -999,9 +1005,9 @@ ImageViewBase::HqTransformTask::HqTransformTask(ImageViewBase* imageView, const QImage& image, const QTransform& xform, const QSize& targetSize) - : m_result(new Result(imageView)), m_image(image), m_xform(xform), m_targetSize(targetSize) {} + : m_result(std::make_shared(imageView)), m_image(image), m_xform(xform), m_targetSize(targetSize) {} -intrusive_ptr> ImageViewBase::HqTransformTask::operator()() { +std::shared_ptr> ImageViewBase::HqTransformTask::operator()() { if (isCancelled()) { return nullptr; } diff --git a/src/core/ImageViewBase.h b/src/core/ImageViewBase.h index e26ffe4d2..34efe6600 100644 --- a/src/core/ImageViewBase.h +++ b/src/core/ImageViewBase.h @@ -16,13 +16,13 @@ #include #include #include +#include #include "ImagePixmapUnion.h" #include "ImageViewInfoProvider.h" #include "InteractionHandler.h" #include "InteractionState.h" #include "Margins.h" -#include "intrusive_ptr.h" class QPainter; class BackgroundExecutor; @@ -246,6 +246,8 @@ class ImageViewBase : public QAbstractScrollArea { void showEvent(QShowEvent* event) override; + void hideEvent(QHideEvent* event) override; + /** * Returns the maximum viewport size (as if scrollbars are hidden) * reduced by margins. @@ -353,7 +355,7 @@ class ImageViewBase : public QAbstractScrollArea { /** * The pending (if any) high quality transformation task. */ - intrusive_ptr m_hqTransformTask; + std::shared_ptr m_hqTransformTask; /** * Transformation from m_pixmap coordinates to m_image coordinates. diff --git a/src/core/ImageViewInfoListener.h b/src/core/ImageViewInfoListener.h index d6fde9ebc..5c2d9f556 100644 --- a/src/core/ImageViewInfoListener.h +++ b/src/core/ImageViewInfoListener.h @@ -20,7 +20,7 @@ class ImageViewInfoListener { virtual void onDpiChanged(const Dpi& dpi) = 0; - virtual void onProviderStopped() = 0; + virtual void onImageViewInfoProviderStopped() = 0; }; diff --git a/src/core/ImageViewInfoProvider.cpp b/src/core/ImageViewInfoProvider.cpp index 426ce6342..460c98ad2 100644 --- a/src/core/ImageViewInfoProvider.cpp +++ b/src/core/ImageViewInfoProvider.cpp @@ -11,9 +11,7 @@ ImageViewInfoProvider::ImageViewInfoProvider(const Dpi& dpi) : m_dpi(dpi) {} ImageViewInfoProvider::~ImageViewInfoProvider() { - for (ImageViewInfoListener* listener : m_infoListeners) { - listener->onProviderStopped(); - } + notifyProviderStopped(); } void ImageViewInfoProvider::addListener(ImageViewInfoListener* listener) { @@ -21,11 +19,12 @@ void ImageViewInfoProvider::addListener(ImageViewInfoListener* listener) { listener->onPhysSizeChanged(m_physSize); listener->onMousePosChanged(m_mousePos); - m_infoListeners.push_back(listener); + m_listeners.push_back(listener); } -void ImageViewInfoProvider::removeListener(ImageViewInfoListener* listener) { - m_infoListeners.remove(listener); +void ImageViewInfoProvider::removeAllListeners() { + notifyProviderStopped(); + m_listeners.clear(); } void ImageViewInfoProvider::setPhysSize(const QSizeF& physSize) { @@ -39,13 +38,13 @@ void ImageViewInfoProvider::setMousePos(const QPointF& mousePos) { } void ImageViewInfoProvider::physSizeChanged(const QSizeF& physSize) const { - for (ImageViewInfoListener* listener : m_infoListeners) { + for (ImageViewInfoListener* listener : m_listeners) { listener->onPhysSizeChanged(physSize); } } void ImageViewInfoProvider::mousePosChanged(const QPointF& mousePos) const { - for (ImageViewInfoListener* listener : m_infoListeners) { + for (ImageViewInfoListener* listener : m_listeners) { listener->onMousePosChanged(mousePos); } } @@ -61,3 +60,9 @@ const QPointF& ImageViewInfoProvider::getMousePos() const { const QSizeF& ImageViewInfoProvider::getPhysSize() const { return m_physSize; } + +void ImageViewInfoProvider::notifyProviderStopped() const { + for (ImageViewInfoListener* listener : m_listeners) { + listener->onImageViewInfoProviderStopped(); + } +} diff --git a/src/core/ImageViewInfoProvider.h b/src/core/ImageViewInfoProvider.h index 281147bfd..f6c525ba2 100644 --- a/src/core/ImageViewInfoProvider.h +++ b/src/core/ImageViewInfoProvider.h @@ -24,7 +24,7 @@ class ImageViewInfoProvider { void addListener(ImageViewInfoListener* listener); - void removeListener(ImageViewInfoListener* listener); + void removeAllListeners(); void setPhysSize(const QSizeF& physSize); @@ -41,7 +41,9 @@ class ImageViewInfoProvider { void mousePosChanged(const QPointF& mousePos) const; - std::list m_infoListeners; + void notifyProviderStopped() const; + + std::list m_listeners; Dpi m_dpi; QPointF m_mousePos; QSizeF m_physSize; diff --git a/src/core/IncompleteThumbnail.cpp b/src/core/IncompleteThumbnail.cpp index 58fe400e2..5b5cb8d56 100644 --- a/src/core/IncompleteThumbnail.cpp +++ b/src/core/IncompleteThumbnail.cpp @@ -9,7 +9,7 @@ QPainterPath IncompleteThumbnail::m_sCachedPath; -IncompleteThumbnail::IncompleteThumbnail(intrusive_ptr thumbnailCache, +IncompleteThumbnail::IncompleteThumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform) diff --git a/src/core/IncompleteThumbnail.h b/src/core/IncompleteThumbnail.h index 5268344d0..22602ba81 100644 --- a/src/core/IncompleteThumbnail.h +++ b/src/core/IncompleteThumbnail.h @@ -5,9 +5,9 @@ #define SCANTAILOR_CORE_INCOMPLETETHUMBNAIL_H_ #include +#include #include "ThumbnailBase.h" -#include "intrusive_ptr.h" class ThumbnailPixmapCache; class QSizeF; @@ -27,7 +27,7 @@ class QRectF; */ class IncompleteThumbnail : public ThumbnailBase { public: - IncompleteThumbnail(intrusive_ptr thumbnailCache, + IncompleteThumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform); diff --git a/src/core/LightColorScheme.cpp b/src/core/LightColorScheme.cpp index 03e14c8b6..709cbc6d0 100644 --- a/src/core/LightColorScheme.cpp +++ b/src/core/LightColorScheme.cpp @@ -80,15 +80,15 @@ void LightColorScheme::loadStyleSheet() { } void LightColorScheme::loadColorParams() { - m_customColors[ThumbnailSequenceSelectedItemBackground] = "#727272"; - m_customColors[ThumbnailSequenceSelectedItemText] = Qt::white; - m_customColors[ThumbnailSequenceItemText] = Qt::black; - m_customColors[ThumbnailSequenceSelectionLeaderBackground] = "#5E5E5E"; - m_customColors[OpenNewProjectBorder] = "#CCCCCC"; - m_customColors[ProcessingIndicationFade] = "#939393"; - m_customColors[ProcessingIndicationHeadColor] = m_palette.color(QPalette::WindowText); - m_customColors[ProcessingIndicationTail] = m_palette.color(QPalette::Highlight); - m_customColors[StageListHead] = m_customColors.at(ProcessingIndicationHeadColor); - m_customColors[StageListTail] = m_customColors.at(ProcessingIndicationTail); - m_customColors[FixDpiDialogErrorText] = "#FB0000"; + m_customColors["ThumbnailSequenceSelectedItemBackground"] = "#727272"; + m_customColors["ThumbnailSequenceSelectedItemText"] = Qt::white; + m_customColors["ThumbnailSequenceItemText"] = Qt::black; + m_customColors["ThumbnailSequenceSelectionLeaderBackground"] = "#5E5E5E"; + m_customColors["OpenNewProjectBorder"] = "#CCCCCC"; + m_customColors["ProcessingIndicationFade"] = "#939393"; + m_customColors["ProcessingIndicationHead"] = m_palette.color(QPalette::WindowText); + m_customColors["ProcessingIndicationTail"] = m_palette.color(QPalette::Highlight); + m_customColors["StageListHead"] = m_customColors.at("ProcessingIndicationHead"); + m_customColors["StageListTail"] = m_customColors.at("ProcessingIndicationTail"); + m_customColors["FixDpiDialogErrorText"] = "#FB0000"; } diff --git a/src/core/LoadFileTask.cpp b/src/core/LoadFileTask.cpp index 58264515d..ce154a117 100644 --- a/src/core/LoadFileTask.cpp +++ b/src/core/LoadFileTask.cpp @@ -30,7 +30,7 @@ class LoadFileTask::ErrorResult : public FilterResult { void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return nullptr; } + std::shared_ptr filter() override { return nullptr; } private: QString m_filePath; @@ -40,9 +40,9 @@ class LoadFileTask::ErrorResult : public FilterResult { LoadFileTask::LoadFileTask(Type type, const PageInfo& page, - intrusive_ptr thumbnailCache, - intrusive_ptr pages, - intrusive_ptr nextTask) + std::shared_ptr thumbnailCache, + std::shared_ptr pages, + std::shared_ptr nextTask) : BackgroundTask(type), m_thumbnailCache(std::move(thumbnailCache)), m_imageId(page.imageId()), @@ -61,7 +61,7 @@ FilterResultPtr LoadFileTask::operator()() { throwIfCancelled(); if (image.isNull()) { - return make_intrusive(m_imageId.filePath()); + return std::make_shared(m_imageId.filePath()); } else { convertToSupportedFormat(image); updateImageSizeIfChanged(image); @@ -114,7 +114,7 @@ LoadFileTask::ErrorResult::ErrorResult(const QString& filePath) void LoadFileTask::ErrorResult::updateUI(FilterUiInterface* ui) { class ErrWidget : public ErrorWidget { public: - ErrWidget(intrusive_ptr> relinkingDialogRequester, + ErrWidget(std::shared_ptr> relinkingDialogRequester, const QString& text, Qt::TextFormat fmt = Qt::AutoText) : ErrorWidget(text, fmt), m_relinkingDialogRequester(std::move(relinkingDialogRequester)) {} @@ -122,7 +122,7 @@ void LoadFileTask::ErrorResult::updateUI(FilterUiInterface* ui) { private: void linkActivated(const QString&) override { (*m_relinkingDialogRequester)(); } - intrusive_ptr> m_relinkingDialogRequester; + std::shared_ptr> m_relinkingDialogRequester; }; diff --git a/src/core/LoadFileTask.h b/src/core/LoadFileTask.h index bdc781da0..8135ade4f 100644 --- a/src/core/LoadFileTask.h +++ b/src/core/LoadFileTask.h @@ -4,12 +4,13 @@ #ifndef SCANTAILOR_CORE_LOADFILETASK_H_ #define SCANTAILOR_CORE_LOADFILETASK_H_ +#include + #include "BackgroundTask.h" #include "FilterResult.h" #include "ImageId.h" #include "ImageMetadata.h" #include "NonCopyable.h" -#include "intrusive_ptr.h" class ThumbnailPixmapCache; class PageInfo; @@ -26,9 +27,9 @@ class LoadFileTask : public BackgroundTask { public: LoadFileTask(Type type, const PageInfo& page, - intrusive_ptr thumbnailCache, - intrusive_ptr pages, - intrusive_ptr nextTask); + std::shared_ptr thumbnailCache, + std::shared_ptr pages, + std::shared_ptr nextTask); ~LoadFileTask() override; @@ -43,11 +44,11 @@ class LoadFileTask : public BackgroundTask { void convertToSupportedFormat(QImage& image) const; - intrusive_ptr m_thumbnailCache; + std::shared_ptr m_thumbnailCache; ImageId m_imageId; ImageMetadata m_imageMetadata; - const intrusive_ptr m_pages; - const intrusive_ptr m_nextTask; + const std::shared_ptr m_pages; + const std::shared_ptr m_nextTask; }; diff --git a/src/core/Margins.cpp b/src/core/Margins.cpp index 6d48ec4a3..96d78d494 100644 --- a/src/core/Margins.cpp +++ b/src/core/Margins.cpp @@ -29,36 +29,4 @@ QDomElement Margins::toXml(QDomDocument& doc, const QString& name) const { el.setAttribute("top", Utils::doubleToString(m_top)); el.setAttribute("bottom", Utils::doubleToString(m_bottom)); return el; -} - -double Margins::top() const { - return m_top; -} - -void Margins::setTop(double val) { - m_top = val; -} - -double Margins::bottom() const { - return m_bottom; -} - -void Margins::setBottom(double val) { - m_bottom = val; -} - -double Margins::left() const { - return m_left; -} - -void Margins::setLeft(double val) { - m_left = val; -} - -double Margins::right() const { - return m_right; -} - -void Margins::setRight(double val) { - m_right = val; -} +} \ No newline at end of file diff --git a/src/core/Margins.h b/src/core/Margins.h index 0f617da6c..97ac7fa59 100644 --- a/src/core/Margins.h +++ b/src/core/Margins.h @@ -42,4 +42,36 @@ class Margins { }; +inline double Margins::top() const { + return m_top; +} + +inline void Margins::setTop(double val) { + m_top = val; +} + +inline double Margins::bottom() const { + return m_bottom; +} + +inline void Margins::setBottom(double val) { + m_bottom = val; +} + +inline double Margins::left() const { + return m_left; +} + +inline void Margins::setLeft(double val) { + m_left = val; +} + +inline double Margins::right() const { + return m_right; +} + +inline void Margins::setRight(double val) { + m_right = val; +} + #endif // ifndef SCANTAILOR_CORE_MARGINS_H_ diff --git a/src/core/NativeColorScheme.cpp b/src/core/NativeColorScheme.cpp index 98f7529c4..2922ecdff 100644 --- a/src/core/NativeColorScheme.cpp +++ b/src/core/NativeColorScheme.cpp @@ -39,14 +39,14 @@ void NativeColorScheme::loadStyleSheet() { void NativeColorScheme::loadColorParams() { const QPalette palette = QPalette(); - m_customColors[ThumbnailSequenceSelectedItemBackground] = palette.color(QPalette::Highlight).lighter(130); - m_customColors[ThumbnailSequenceSelectionLeaderBackground] = palette.color(QPalette::Highlight); - m_customColors[ProcessingIndicationFade] = palette.window().color().darker(115); + m_customColors["ThumbnailSequenceSelectedItemBackground"] = palette.color(QPalette::Highlight).lighter(130); + m_customColors["ThumbnailSequenceSelectionLeaderBackground"] = palette.color(QPalette::Highlight); + m_customColors["ProcessingIndicationFade"] = palette.window().color().darker(115); if (palette.window().color().lightnessF() < 0.5) { // If system scheme is dark, adapt some colors. - m_customColors[ProcessingIndicationHeadColor] = palette.color(QPalette::Window).lighter(200); - m_customColors[ProcessingIndicationTail] = palette.color(QPalette::Window).lighter(130); - m_customColors[StageListHead] = m_customColors.at(ProcessingIndicationHeadColor); - m_customColors[StageListTail] = m_customColors.at(ProcessingIndicationTail); + m_customColors["ProcessingIndicationHead"] = palette.color(QPalette::Window).lighter(200); + m_customColors["ProcessingIndicationTail"] = palette.color(QPalette::Window).lighter(130); + m_customColors["StageListHead"] = m_customColors.at("ProcessingIndicationHead"); + m_customColors["StageListTail"] = m_customColors.at("ProcessingIndicationTail"); } } diff --git a/src/core/OutputFileNameGenerator.cpp b/src/core/OutputFileNameGenerator.cpp index fc80d8bf3..14877830b 100644 --- a/src/core/OutputFileNameGenerator.cpp +++ b/src/core/OutputFileNameGenerator.cpp @@ -12,9 +12,9 @@ #include "RelinkablePath.h" OutputFileNameGenerator::OutputFileNameGenerator() - : m_disambiguator(new FileNameDisambiguator), m_outDir(), m_layoutDirection(Qt::LeftToRight) {} + : m_disambiguator(std::make_shared()), m_outDir(), m_layoutDirection(Qt::LeftToRight) {} -OutputFileNameGenerator::OutputFileNameGenerator(intrusive_ptr disambiguator, +OutputFileNameGenerator::OutputFileNameGenerator(std::shared_ptr disambiguator, const QString& outDir, Qt::LayoutDirection layoutDirection) : m_disambiguator(std::move(disambiguator)), m_outDir(outDir), m_layoutDirection(layoutDirection) { diff --git a/src/core/OutputFileNameGenerator.h b/src/core/OutputFileNameGenerator.h index 15612d7d0..ea9adedd5 100644 --- a/src/core/OutputFileNameGenerator.h +++ b/src/core/OutputFileNameGenerator.h @@ -6,9 +6,9 @@ #include #include +#include #include "FileNameDisambiguator.h" -#include "intrusive_ptr.h" class PageId; class AbstractRelinker; @@ -18,7 +18,7 @@ class OutputFileNameGenerator { public: OutputFileNameGenerator(); - OutputFileNameGenerator(intrusive_ptr disambiguator, + OutputFileNameGenerator(std::shared_ptr disambiguator, const QString& outDir, Qt::LayoutDirection layoutDirection); @@ -37,7 +37,7 @@ class OutputFileNameGenerator { QString filePathFor(const PageId& page) const; private: - intrusive_ptr m_disambiguator; + std::shared_ptr m_disambiguator; QString m_outDir; Qt::LayoutDirection m_layoutDirection; }; diff --git a/src/core/PageOrderOption.h b/src/core/PageOrderOption.h index ad6038b1f..ec0e11af8 100644 --- a/src/core/PageOrderOption.h +++ b/src/core/PageOrderOption.h @@ -5,14 +5,14 @@ #define SCANTAILOR_CORE_PAGEORDEROPTION_H_ #include +#include #include "PageOrderProvider.h" -#include "intrusive_ptr.h" class PageOrderOption { // Member-wise copying is OK. public: - using ProviderPtr = intrusive_ptr; + using ProviderPtr = std::shared_ptr; PageOrderOption(const QString& name, ProviderPtr provider) : m_name(name), m_provider(std::move(provider)) {} diff --git a/src/core/PageOrderProvider.cpp b/src/core/PageOrderProvider.cpp new file mode 100644 index 000000000..3c71619cf --- /dev/null +++ b/src/core/PageOrderProvider.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "PageOrderProvider.h" + +std::shared_ptr PageOrderProvider::reversed() const { + class ReversedPageOrderProvider : public PageOrderProvider { + public: + explicit ReversedPageOrderProvider(const PageOrderProvider* parent) : m_parent(parent->shared_from_this()) {} + + bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override { + return m_parent->precedes(rhsPage, rhsIncomplete, lhsPage, lhsIncomplete); + } + + private: + const std::shared_ptr m_parent; + }; + return std::make_shared(this); +} diff --git a/src/core/PageOrderProvider.h b/src/core/PageOrderProvider.h index 39c2c7b91..270f7dcff 100644 --- a/src/core/PageOrderProvider.h +++ b/src/core/PageOrderProvider.h @@ -4,21 +4,25 @@ #ifndef SCANTAILOR_CORE_PAGEORDERPROVIDER_H_ #define SCANTAILOR_CORE_PAGEORDERPROVIDER_H_ -#include "ref_countable.h" +#include class PageId; /** - * A base class for different page ordering strategies. + * A base interface for different page ordering strategies. */ -class PageOrderProvider : public ref_countable { +class PageOrderProvider : public std::enable_shared_from_this { public: + virtual ~PageOrderProvider() = default; + /** * Returns true if \p lhsPage precedes \p rhsPage. * \p lhsIncomplete and \p rhsIncomplete indicate whether * a page is represented by IncompleteThumbnail. */ virtual bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const = 0; + + virtual std::shared_ptr reversed() const; }; diff --git a/src/core/PageOrientationPropagator.cpp b/src/core/PageOrientationPropagator.cpp index 4b0c2397f..87c5eacf3 100644 --- a/src/core/PageOrientationPropagator.cpp +++ b/src/core/PageOrientationPropagator.cpp @@ -23,8 +23,8 @@ class PageOrientationPropagator::Collector : public PageOrientationCollector { }; -PageOrientationPropagator::PageOrientationPropagator(intrusive_ptr pageSplitFilter, - intrusive_ptr task) +PageOrientationPropagator::PageOrientationPropagator(std::shared_ptr pageSplitFilter, + std::shared_ptr task) : m_pageSplitFilter(std::move(pageSplitFilter)), m_task(std::move(task)) {} PageOrientationPropagator::~PageOrientationPropagator() = default; diff --git a/src/core/PageOrientationPropagator.h b/src/core/PageOrientationPropagator.h index 6e79220c2..9e89e9298 100644 --- a/src/core/PageOrientationPropagator.h +++ b/src/core/PageOrientationPropagator.h @@ -5,8 +5,7 @@ #define SCANTAILOR_CORE_PAGEORIENTATIONPROPAGATOR_H_ #include - -#include "intrusive_ptr.h" +#include class CompositeCacheDrivenTask; class ProjectPages; @@ -26,8 +25,8 @@ class Filter; */ class PageOrientationPropagator { public: - PageOrientationPropagator(intrusive_ptr pageSplitFilter, - intrusive_ptr task); + PageOrientationPropagator(std::shared_ptr pageSplitFilter, + std::shared_ptr task); ~PageOrientationPropagator(); @@ -36,8 +35,8 @@ class PageOrientationPropagator { private: class Collector; - intrusive_ptr m_pageSplitFilter; - intrusive_ptr m_task; + std::shared_ptr m_pageSplitFilter; + std::shared_ptr m_task; }; diff --git a/src/core/PageSelectionAccessor.cpp b/src/core/PageSelectionAccessor.cpp index e7b30025f..c6a5e66e3 100644 --- a/src/core/PageSelectionAccessor.cpp +++ b/src/core/PageSelectionAccessor.cpp @@ -7,7 +7,7 @@ #include "PageSequence.h" -PageSelectionAccessor::PageSelectionAccessor(intrusive_ptr provider) +PageSelectionAccessor::PageSelectionAccessor(std::shared_ptr provider) : m_provider(std::move(provider)) {} PageSequence PageSelectionAccessor::allPages() const { diff --git a/src/core/PageSelectionAccessor.h b/src/core/PageSelectionAccessor.h index 94546395b..30cb42c58 100644 --- a/src/core/PageSelectionAccessor.h +++ b/src/core/PageSelectionAccessor.h @@ -4,20 +4,20 @@ #ifndef SCANTAILOR_CORE_PAGESELECTIONACCESSOR_H_ #define SCANTAILOR_CORE_PAGESELECTIONACCESSOR_H_ +#include #include #include #include "PageId.h" #include "PageRange.h" #include "PageSelectionProvider.h" -#include "intrusive_ptr.h" class PageSequence; class PageSelectionAccessor { // Member-wise copying is OK. public: - explicit PageSelectionAccessor(intrusive_ptr provider); + explicit PageSelectionAccessor(std::shared_ptr provider); PageSequence allPages() const; @@ -26,7 +26,7 @@ class PageSelectionAccessor { std::vector selectedRanges() const; private: - intrusive_ptr m_provider; + std::shared_ptr m_provider; }; diff --git a/src/core/PageSelectionProvider.h b/src/core/PageSelectionProvider.h index 8054ca0aa..8e643118a 100644 --- a/src/core/PageSelectionProvider.h +++ b/src/core/PageSelectionProvider.h @@ -7,14 +7,15 @@ #include #include -#include "ref_countable.h" class PageSequence; class PageId; class PageRange; -class PageSelectionProvider : public ref_countable { +class PageSelectionProvider { public: + virtual ~PageSelectionProvider() = default; + virtual PageSequence allPages() const = 0; virtual std::set selectedPages() const = 0; diff --git a/src/core/PageSequence.cpp b/src/core/PageSequence.cpp index 304a66bac..f9031b606 100644 --- a/src/core/PageSequence.cpp +++ b/src/core/PageSequence.cpp @@ -7,6 +7,10 @@ void PageSequence::append(const PageInfo& pageInfo) { m_pages.push_back(pageInfo); } +size_t PageSequence::numPages() const { + return m_pages.size(); +} + const PageInfo& PageSequence::pageAt(const size_t idx) const { return m_pages.at(idx); // may throw } @@ -73,3 +77,19 @@ std::set PageSequence::selectEveryOther(const PageId& base) const { } return selection; } + +std::vector::iterator PageSequence::begin() { + return m_pages.begin(); +} + +std::vector::iterator PageSequence::end() { + return m_pages.end(); +} + +std::vector::const_iterator PageSequence::begin() const { + return m_pages.cbegin(); +} + +std::vector::const_iterator PageSequence::end() const { + return m_pages.cend(); +} diff --git a/src/core/PageSequence.h b/src/core/PageSequence.h index 423c06f7c..67ee1b76f 100644 --- a/src/core/PageSequence.h +++ b/src/core/PageSequence.h @@ -15,7 +15,7 @@ class PageSequence { public: void append(const PageInfo& pageInfo); - size_t numPages() const { return m_pages.size(); } + size_t numPages() const; const PageInfo& pageAt(PageId page) const; @@ -29,13 +29,13 @@ class PageSequence { std::set selectEveryOther(const PageId& base) const; - std::vector::iterator begin() { return m_pages.begin(); } + std::vector::iterator begin(); - std::vector::iterator end() { return m_pages.end(); } + std::vector::iterator end(); - std::vector::const_iterator begin() const { return m_pages.cbegin(); } + std::vector::const_iterator begin() const; - std::vector::const_iterator end() const { return m_pages.cend(); } + std::vector::const_iterator end() const; private: std::vector m_pages; diff --git a/src/core/ProcessingIndicationWidget.cpp b/src/core/ProcessingIndicationWidget.cpp index 78ea02d70..e1fb9ee5b 100644 --- a/src/core/ProcessingIndicationWidget.cpp +++ b/src/core/ProcessingIndicationWidget.cpp @@ -18,9 +18,9 @@ static const double distinctionDecrease = -1.0 / 3.0; ProcessingIndicationWidget::ProcessingIndicationWidget(QWidget* parent) : QWidget(parent), m_animation(10), m_distinction(1.0), m_distinctionDelta(distinctionIncrease), m_timerId(0) { - m_headColor = ColorSchemeManager::instance().getColorParam(ColorScheme::ProcessingIndicationHeadColor, + m_headColor = ColorSchemeManager::instance().getColorParam("ProcessingIndicationHead", palette().color(QPalette::Window).darker(200)); - m_tailColor = ColorSchemeManager::instance().getColorParam(ColorScheme::ProcessingIndicationTail, + m_tailColor = ColorSchemeManager::instance().getColorParam("ProcessingIndicationTail", palette().color(QPalette::Window).darker(130)); } @@ -54,7 +54,7 @@ void ProcessingIndicationWidget::paintEvent(QPaintEvent* event) { QPainter painter(this); QColor fadeColor - = ColorSchemeManager::instance().getColorParam(ColorScheme::ProcessingIndicationFade, palette().window().color()); + = ColorSchemeManager::instance().getColorParam("ProcessingIndicationFade", palette().window().color()); fadeColor.setAlpha(127); painter.fillRect(rect(), fadeColor); diff --git a/src/core/ProjectPages.h b/src/core/ProjectPages.h index 5af4ca687..37853f37d 100644 --- a/src/core/ProjectPages.h +++ b/src/core/ProjectPages.h @@ -20,7 +20,6 @@ #include "PageInfo.h" #include "PageView.h" #include "VirtualFunction.h" -#include "ref_countable.h" class ImageFileInfo; class ImageInfo; @@ -30,7 +29,7 @@ class RelinkablePath; class AbstractRelinker; class QDomElement; -class ProjectPages : public QObject, public ref_countable { +class ProjectPages : public QObject { Q_OBJECT DECLARE_NON_COPYABLE(ProjectPages) diff --git a/src/core/ProjectReader.cpp b/src/core/ProjectReader.cpp index 5fc347ffe..6fe6a4fbc 100644 --- a/src/core/ProjectReader.cpp +++ b/src/core/ProjectReader.cpp @@ -12,7 +12,8 @@ #include "XmlUnmarshaller.h" #include "version.h" -ProjectReader::ProjectReader(const QDomDocument& doc) : m_doc(doc), m_disambiguator(new FileNameDisambiguator) { +ProjectReader::ProjectReader(const QDomDocument& doc) + : m_doc(doc), m_disambiguator(std::make_shared()) { QDomElement projectEl(m_doc.documentElement()); m_version = projectEl.attribute("version"); @@ -53,7 +54,7 @@ ProjectReader::ProjectReader(const QDomDocument& doc) : m_doc(doc), m_disambigua // Load naming disambiguator. This needs to be done after processing pages. const QDomElement disambigEl(projectEl.namedItem("file-name-disambiguation").toElement()); m_disambiguator - = make_intrusive(disambigEl, boost::bind(&ProjectReader::expandFilePath, this, _1)); + = std::make_shared(disambigEl, boost::bind(&ProjectReader::expandFilePath, this, _1)); } ProjectReader::~ProjectReader() = default; @@ -189,7 +190,7 @@ void ProjectReader::processImages(const QDomElement& imagesEl, const Qt::LayoutD } if (!images.empty()) { - m_pages = make_intrusive(images, layoutDirection); + m_pages = std::make_shared(images, layoutDirection); } } // ProjectReader::processImages diff --git a/src/core/ProjectReader.h b/src/core/ProjectReader.h index c4df3ea87..f7f3c0478 100644 --- a/src/core/ProjectReader.h +++ b/src/core/ProjectReader.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,7 +16,6 @@ #include "ImageMetadata.h" #include "PageId.h" #include "SelectedPage.h" -#include "intrusive_ptr.h" class QDomElement; class ProjectPages; @@ -24,7 +24,7 @@ class AbstractFilter; class ProjectReader { public: - using FilterPtr = intrusive_ptr; + using FilterPtr = std::shared_ptr; explicit ProjectReader(const QDomDocument& doc); @@ -38,11 +38,11 @@ class ProjectReader { const QString& getVersion() const { return m_version; } - const intrusive_ptr& pages() const { return m_pages; } + const std::shared_ptr& pages() const { return m_pages; } const SelectedPage& selectedPage() const { return m_selectedPage; } - const intrusive_ptr& namingDisambiguator() const { return m_disambiguator; } + const std::shared_ptr& namingDisambiguator() const { return m_disambiguator; } ImageId imageId(int numericId) const; @@ -89,8 +89,8 @@ class ProjectReader { ImageMap m_imageMap; PageMap m_pageMap; SelectedPage m_selectedPage; - intrusive_ptr m_pages; - intrusive_ptr m_disambiguator; + std::shared_ptr m_pages; + std::shared_ptr m_disambiguator; }; diff --git a/src/core/ProjectWriter.cpp b/src/core/ProjectWriter.cpp index b03e3bcf4..f6178dc90 100644 --- a/src/core/ProjectWriter.cpp +++ b/src/core/ProjectWriter.cpp @@ -27,7 +27,7 @@ #include #include -ProjectWriter::ProjectWriter(const intrusive_ptr& pageSequence, +ProjectWriter::ProjectWriter(const std::shared_ptr& pageSequence, const SelectedPage& selectedPage, const OutputFileNameGenerator& outFileNameGen) : m_pageSequence(pageSequence->toPageSequence(PAGE_VIEW)), diff --git a/src/core/ProjectWriter.h b/src/core/ProjectWriter.h index 8fd855290..7dd425300 100644 --- a/src/core/ProjectWriter.h +++ b/src/core/ProjectWriter.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,7 +22,6 @@ #include "PageSequence.h" #include "SelectedPage.h" #include "VirtualFunction.h" -#include "intrusive_ptr.h" class AbstractFilter; class ProjectPages; @@ -33,9 +33,9 @@ class ProjectWriter { DECLARE_NON_COPYABLE(ProjectWriter) public: - using FilterPtr = intrusive_ptr; + using FilterPtr = std::shared_ptr; - ProjectWriter(const intrusive_ptr& pageSequence, + ProjectWriter(const std::shared_ptr& pageSequence, const SelectedPage& selectedPage, const OutputFileNameGenerator& outFileNameGen); diff --git a/src/core/StageListView.cpp b/src/core/StageListView.cpp index 008fd34cb..3ad8f4351 100644 --- a/src/core/StageListView.cpp +++ b/src/core/StageListView.cpp @@ -20,7 +20,7 @@ class StageListView::Model : public QAbstractTableModel { public: - Model(QObject* parent, intrusive_ptr stages); + Model(QObject* parent, std::shared_ptr stages); void updateBatchProcessingAnimation(int selectedRow, const QPixmap& animationFrame); @@ -33,7 +33,7 @@ class StageListView::Model : public QAbstractTableModel { QVariant data(const QModelIndex& index, int role) const override; private: - intrusive_ptr m_stages; + std::shared_ptr m_stages; QPixmap m_curAnimationFrame; int m_curSelectedRow; }; @@ -106,7 +106,7 @@ StageListView::StageListView(QWidget* parent) StageListView::~StageListView() = default; -void StageListView::setStages(const intrusive_ptr& stages) { +void StageListView::setStages(const std::shared_ptr& stages) { if (QAbstractItemModel* m = model()) { // Q*View classes don't own their models. m->deleteLater(); @@ -260,10 +260,10 @@ void StageListView::createBatchAnimationSequence(const int squareSide) { const int numFrames = 8; m_batchAnimationPixmaps.resize(numFrames); - const QColor headColor = ColorSchemeManager::instance().getColorParam(ColorScheme::StageListHead, - palette().color(QPalette::Window).darker(200)); - const QColor tailColor = ColorSchemeManager::instance().getColorParam(ColorScheme::StageListTail, - palette().color(QPalette::Window).darker(130)); + const QColor headColor + = ColorSchemeManager::instance().getColorParam("StageListHead", palette().color(QPalette::Window).darker(200)); + const QColor tailColor + = ColorSchemeManager::instance().getColorParam("StageListTail", palette().color(QPalette::Window).darker(130)); BubbleAnimation animation(numFrames); for (int i = 0; i < numFrames; ++i) { @@ -297,7 +297,7 @@ int StageListView::selectedRow() const { /*========================= StageListView::Model ======================*/ -StageListView::Model::Model(QObject* parent, intrusive_ptr stages) +StageListView::Model::Model(QObject* parent, std::shared_ptr stages) : QAbstractTableModel(parent), m_stages(std::move(stages)), m_curSelectedRow(0) { assert(m_stages); } diff --git a/src/core/StageListView.h b/src/core/StageListView.h index 5b6841f55..7e993dd5e 100644 --- a/src/core/StageListView.h +++ b/src/core/StageListView.h @@ -6,10 +6,9 @@ #include #include +#include #include -#include "intrusive_ptr.h" - class StageSequence; class StageListView : public QTableView { @@ -19,7 +18,7 @@ class StageListView : public QTableView { ~StageListView() override; - void setStages(const intrusive_ptr& stages); + void setStages(const std::shared_ptr& stages); QSize sizeHint() const override { return m_sizeHint; } diff --git a/src/core/StageSequence.cpp b/src/core/StageSequence.cpp index a359e7871..5866eaf70 100644 --- a/src/core/StageSequence.cpp +++ b/src/core/StageSequence.cpp @@ -5,14 +5,14 @@ #include "ProjectPages.h" -StageSequence::StageSequence(const intrusive_ptr& pages, +StageSequence::StageSequence(const std::shared_ptr& pages, const PageSelectionAccessor& pageSelectionAccessor) - : m_fixOrientationFilter(new fix_orientation::Filter(pageSelectionAccessor)), - m_pageSplitFilter(new page_split::Filter(pages, pageSelectionAccessor)), - m_deskewFilter(new deskew::Filter(pageSelectionAccessor)), - m_selectContentFilter(new select_content::Filter(pageSelectionAccessor)), - m_pageLayoutFilter(new page_layout::Filter(pages, pageSelectionAccessor)), - m_outputFilter(new output::Filter(pageSelectionAccessor)) { + : m_fixOrientationFilter(std::make_shared(pageSelectionAccessor)), + m_pageSplitFilter(std::make_shared(pages, pageSelectionAccessor)), + m_deskewFilter(std::make_shared(pageSelectionAccessor)), + m_selectContentFilter(std::make_shared(pageSelectionAccessor)), + m_pageLayoutFilter(std::make_shared(pages, pageSelectionAccessor)), + m_outputFilter(std::make_shared(pageSelectionAccessor)) { m_fixOrientationFilterIdx = static_cast(m_filters.size()); m_filters.emplace_back(m_fixOrientationFilter); diff --git a/src/core/StageSequence.h b/src/core/StageSequence.h index 2793bff1f..01d531da2 100644 --- a/src/core/StageSequence.h +++ b/src/core/StageSequence.h @@ -4,6 +4,7 @@ #ifndef SCANTAILOR_CORE_STAGESEQUENCE_H_ #define SCANTAILOR_CORE_STAGESEQUENCE_H_ +#include #include #include "AbstractFilter.h" @@ -14,21 +15,21 @@ #include "filters/page_layout/Filter.h" #include "filters/page_split/Filter.h" #include "filters/select_content/Filter.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class PageId; class ProjectPages; class PageSelectionAccessor; class AbstractRelinker; -class StageSequence : public ref_countable { +class StageSequence { DECLARE_NON_COPYABLE(StageSequence) public: - using FilterPtr = intrusive_ptr; + using FilterPtr = std::shared_ptr; - StageSequence(const intrusive_ptr& pages, const PageSelectionAccessor& pageSelectionAccessor); + StageSequence(const std::shared_ptr& pages, const PageSelectionAccessor& pageSelectionAccessor); + + virtual ~StageSequence() = default; void performRelinking(const AbstractRelinker& relinker); @@ -40,17 +41,17 @@ class StageSequence : public ref_countable { int findFilter(const FilterPtr& filter) const; - const intrusive_ptr& fixOrientationFilter() const { return m_fixOrientationFilter; } + const std::shared_ptr& fixOrientationFilter() const { return m_fixOrientationFilter; } - const intrusive_ptr& pageSplitFilter() const { return m_pageSplitFilter; } + const std::shared_ptr& pageSplitFilter() const { return m_pageSplitFilter; } - const intrusive_ptr& deskewFilter() const { return m_deskewFilter; } + const std::shared_ptr& deskewFilter() const { return m_deskewFilter; } - const intrusive_ptr& selectContentFilter() const { return m_selectContentFilter; } + const std::shared_ptr& selectContentFilter() const { return m_selectContentFilter; } - const intrusive_ptr& pageLayoutFilter() const { return m_pageLayoutFilter; } + const std::shared_ptr& pageLayoutFilter() const { return m_pageLayoutFilter; } - const intrusive_ptr& outputFilter() const { return m_outputFilter; } + const std::shared_ptr& outputFilter() const { return m_outputFilter; } int fixOrientationFilterIdx() const { return m_fixOrientationFilterIdx; } @@ -65,12 +66,12 @@ class StageSequence : public ref_countable { int outputFilterIdx() const { return m_outputFilterIdx; } private: - intrusive_ptr m_fixOrientationFilter; - intrusive_ptr m_pageSplitFilter; - intrusive_ptr m_deskewFilter; - intrusive_ptr m_selectContentFilter; - intrusive_ptr m_pageLayoutFilter; - intrusive_ptr m_outputFilter; + std::shared_ptr m_fixOrientationFilter; + std::shared_ptr m_pageSplitFilter; + std::shared_ptr m_deskewFilter; + std::shared_ptr m_selectContentFilter; + std::shared_ptr m_pageLayoutFilter; + std::shared_ptr m_outputFilter; std::vector m_filters; int m_fixOrientationFilterIdx; int m_pageSplitFilterIdx; diff --git a/src/core/ThumbnailBase.cpp b/src/core/ThumbnailBase.cpp index 851497031..de66f88fd 100644 --- a/src/core/ThumbnailBase.cpp +++ b/src/core/ThumbnailBase.cpp @@ -30,17 +30,13 @@ class ThumbnailBase::LoadCompletionHandler : public AbstractCommand thumbnailCache, +ThumbnailBase::ThumbnailBase(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform) - : ThumbnailBase(std::move(thumbnailCache), - maxSize, - imageId, - imageXform, - imageXform.resultingPostCropArea().boundingRect()) {} + : ThumbnailBase(std::move(thumbnailCache), maxSize, imageId, imageXform, imageXform.resultingRect()) {} -ThumbnailBase::ThumbnailBase(intrusive_ptr thumbnailCache, +ThumbnailBase::ThumbnailBase(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform, @@ -49,8 +45,7 @@ ThumbnailBase::ThumbnailBase(intrusive_ptr thumbnailCache, m_maxSize(maxSize), m_imageId(imageId), m_imageXform(imageXform), - m_displayArea(displayArea), - m_extendedClipArea(false) { + m_displayArea(displayArea) { setImageXform(m_imageXform); } @@ -71,8 +66,8 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt } } - const QTransform imageToDisplay(m_postScaleXform * painter->worldTransform()); - const QTransform thumbToDisplay(painter->worldTransform()); + const QTransform thumbToDisplay = painter->worldTransform(); + const QTransform imageToDisplay = m_postScaleXform * thumbToDisplay; if (pixmap.isNull()) { const double border = 1.0; @@ -87,7 +82,6 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt return; } - const QSizeF origImageSize(m_imageXform.origRect().size()); const double xPreScale = origImageSize.width() / pixmap.width(); const double yPreScale = origImageSize.height() / pixmap.height(); @@ -97,11 +91,8 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt const QTransform pixmapToThumb(preScaleXform * m_imageXform.transform() * m_postScaleXform); // The polygon to draw into in original image coordinates. - QPolygonF imagePoly(PolygonUtils::round(m_imageXform.resultingPreCropArea())); - if (!m_extendedClipArea) { - imagePoly = imagePoly.intersected(PolygonUtils::round(m_imageXform.resultingRect())); - } - + QPolygonF imagePoly + = PolygonUtils::round(m_imageXform.resultingPreCropArea().intersected(m_imageXform.resultingRect())); // The polygon to draw into in display coordinates. QPolygonF displayPoly(imageToDisplay.map(imagePoly)); @@ -134,13 +125,10 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt tempAdjustment.translate(-displayRect.left(), -displayRect.top()); tempPainter.setWorldTransform(pixmapToThumb * thumbToDisplay * tempAdjustment); - // Turn off alpha compositing. tempPainter.setCompositionMode(QPainter::CompositionMode_Source); - tempPainter.setRenderHint(QPainter::SmoothPixmapTransform); tempPainter.setRenderHint(QPainter::Antialiasing); - PixmapRenderer::drawPixmap(tempPainter, pixmap); // Turn alpha compositing on again. @@ -148,7 +136,6 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt // Setup the painter for drawing in thumbnail coordinates, // as required for paintOverImage(). tempPainter.setWorldTransform(thumbToDisplay * tempAdjustment); - tempPainter.save(); prePaintOverImage(tempPainter, imageToDisplay * tempAdjustment, thumbToDisplay * tempAdjustment); tempPainter.restore(); @@ -156,15 +143,12 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt tempPainter.setPen(Qt::NoPen); tempPainter.setBrush(Qt::transparent); tempPainter.setWorldTransform(tempAdjustment); - tempPainter.setCompositionMode(QPainter::CompositionMode_Clear); - { QPainterPath outerPath; outerPath.addRect(displayRect); QPainterPath innerPath; innerPath.addPolygon(displayPoly); - tempPainter.drawPath(outerPath.subtracted(innerPath)); } @@ -173,17 +157,17 @@ void ThumbnailBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt // Setup the painter for drawing in thumbnail coordinates, // as required for paintOverImage(). tempPainter.setWorldTransform(thumbToDisplay * tempAdjustment); - tempPainter.save(); paintOverImage(tempPainter, imageToDisplay * tempAdjustment, thumbToDisplay * tempAdjustment); tempPainter.restore(); tempPainter.end(); - painter->setClipRect(QRectF(QPointF(0, 0), displayRect.size())); + painter->setWorldTransform(QTransform()); + painter->setClipRect(displayRect); painter->setRenderHint(QPainter::SmoothPixmapTransform, false); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - painter->drawPixmap(QPointF(0, 0), tempPixmap); + painter->drawPixmap(displayRect.topLeft(), tempPixmap); } // ThumbnailBase::paint void ThumbnailBase::paintDeviant(QPainter& painter) { @@ -191,13 +175,11 @@ void ThumbnailBase::paintDeviant(QPainter& painter) { return; } - QPen pen(QColor(0xdd, 0x00, 0x00, 0xee)); + QPen pen(QColor(0xdd, 0x00, 0x00, 0xcc)); pen.setWidth(5); pen.setCosmetic(true); painter.setPen(pen); - painter.setBrush(QColor(0xdd, 0x00, 0x00, 0xee)); - QFont font("Serif"); font.setWeight(QFont::Bold); font.setPixelSize(static_cast(boundingRect().width() / 2)); diff --git a/src/core/ThumbnailBase.h b/src/core/ThumbnailBase.h index c435fe36c..f3a242be9 100644 --- a/src/core/ThumbnailBase.h +++ b/src/core/ThumbnailBase.h @@ -8,12 +8,12 @@ #include #include #include +#include #include "ImageId.h" #include "ImageTransformation.h" #include "NonCopyable.h" #include "ThumbnailPixmapCache.h" -#include "intrusive_ptr.h" class ThumbnailLoadResult; @@ -21,12 +21,12 @@ class ThumbnailBase : public QGraphicsItem { DECLARE_NON_COPYABLE(ThumbnailBase) public: - ThumbnailBase(intrusive_ptr thumbnailCache, + ThumbnailBase(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform); - ThumbnailBase(intrusive_ptr thumbnailCache, + ThumbnailBase(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& imageXform, @@ -69,16 +69,6 @@ class ThumbnailBase : public QGraphicsItem { virtual void paintDeviant(QPainter& painter); - /** - * By default, the image is clipped by both the crop area (as defined - * by imageXform().resultingPostCropArea()), and the physical boundaries of - * the image itself. Basically a point won't be clipped only if it's both - * inside of the crop area and inside the image. - * Extended clipping area only includes the cropping area, so it's possible - * to draw outside of the image but inside the crop area. - */ - void setExtendedClipArea(bool enabled) { m_extendedClipArea = enabled; } - void setImageXform(const ImageTransformation& imageXform); const ImageTransformation& imageXform() const { return m_imageXform; } @@ -95,7 +85,7 @@ class ThumbnailBase : public QGraphicsItem { void handleLoadResult(const ThumbnailLoadResult& result); - intrusive_ptr m_thumbnailCache; + std::shared_ptr m_thumbnailCache; QSizeF m_maxSize; ImageId m_imageId; ImageTransformation m_imageXform; @@ -109,7 +99,6 @@ class ThumbnailBase : public QGraphicsItem { QTransform m_postScaleXform; std::shared_ptr m_completionHandler; - bool m_extendedClipArea; }; diff --git a/src/core/ThumbnailCollector.h b/src/core/ThumbnailCollector.h index bf946bf50..69cd79455 100644 --- a/src/core/ThumbnailCollector.h +++ b/src/core/ThumbnailCollector.h @@ -16,7 +16,7 @@ class ThumbnailCollector : public AbstractFilterDataCollector { public: virtual void processThumbnail(std::unique_ptr) = 0; - virtual intrusive_ptr thumbnailCache() = 0; + virtual std::shared_ptr thumbnailCache() = 0; virtual QSizeF maxLogicalThumbSize() const = 0; }; diff --git a/src/core/ThumbnailFactory.cpp b/src/core/ThumbnailFactory.cpp index 4963bce73..a9dd95780 100644 --- a/src/core/ThumbnailFactory.cpp +++ b/src/core/ThumbnailFactory.cpp @@ -11,26 +11,26 @@ class ThumbnailFactory::Collector : public ThumbnailCollector { public: - Collector(intrusive_ptr cache, const QSizeF& maxSize); + Collector(std::shared_ptr cache, const QSizeF& maxSize); void processThumbnail(std::unique_ptr thumbnail) override; - intrusive_ptr thumbnailCache() override; + std::shared_ptr thumbnailCache() override; QSizeF maxLogicalThumbSize() const override; std::unique_ptr retrieveThumbnail() { return std::move(m_thumbnail); } private: - intrusive_ptr m_cache; + std::shared_ptr m_cache; QSizeF m_maxSize; std::unique_ptr m_thumbnail; }; -ThumbnailFactory::ThumbnailFactory(intrusive_ptr pixmapCache, +ThumbnailFactory::ThumbnailFactory(std::shared_ptr pixmapCache, const QSizeF& maxSize, - intrusive_ptr task) + std::shared_ptr task) : m_pixmapCache(std::move(pixmapCache)), m_maxSize(maxSize), m_task(std::move(task)) {} ThumbnailFactory::~ThumbnailFactory() = default; @@ -43,14 +43,14 @@ std::unique_ptr ThumbnailFactory::get(const PageInfo& pageInfo) { /*======================= ThumbnailFactory::Collector ======================*/ -ThumbnailFactory::Collector::Collector(intrusive_ptr cache, const QSizeF& maxSize) +ThumbnailFactory::Collector::Collector(std::shared_ptr cache, const QSizeF& maxSize) : m_cache(std::move(cache)), m_maxSize(maxSize) {} void ThumbnailFactory::Collector::processThumbnail(std::unique_ptr thumbnail) { m_thumbnail = std::move(thumbnail); } -intrusive_ptr ThumbnailFactory::Collector::thumbnailCache() { +std::shared_ptr ThumbnailFactory::Collector::thumbnailCache() { return m_cache; } diff --git a/src/core/ThumbnailFactory.h b/src/core/ThumbnailFactory.h index ddae75314..88a0bec49 100644 --- a/src/core/ThumbnailFactory.h +++ b/src/core/ThumbnailFactory.h @@ -9,31 +9,29 @@ #include "NonCopyable.h" #include "ThumbnailPixmapCache.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class PageInfo; class CompositeCacheDrivenTask; class QGraphicsItem; -class ThumbnailFactory : public ref_countable { +class ThumbnailFactory { DECLARE_NON_COPYABLE(ThumbnailFactory) public: - ThumbnailFactory(intrusive_ptr pixmapCache, + ThumbnailFactory(std::shared_ptr pixmapCache, const QSizeF& maxSize, - intrusive_ptr task); + std::shared_ptr task); - ~ThumbnailFactory() override; + virtual ~ThumbnailFactory(); std::unique_ptr get(const PageInfo& pageInfo); private: class Collector; - intrusive_ptr m_pixmapCache; + std::shared_ptr m_pixmapCache; QSizeF m_maxSize; - intrusive_ptr m_task; + std::shared_ptr m_task; }; diff --git a/src/core/ThumbnailPixmapCache.cpp b/src/core/ThumbnailPixmapCache.cpp index 1d90aabed..8f830a901 100644 --- a/src/core/ThumbnailPixmapCache.cpp +++ b/src/core/ThumbnailPixmapCache.cpp @@ -240,7 +240,10 @@ ThumbnailPixmapCache::ThumbnailPixmapCache(const QString& thumbDir, const QSize& maxThumbSize, const int maxCachedPixmaps, const int expirationThreshold) - : m_impl(new Impl(RelinkablePath::normalize(thumbDir), maxThumbSize, maxCachedPixmaps, expirationThreshold)) {} + : m_impl(std::make_unique(RelinkablePath::normalize(thumbDir), + maxThumbSize, + maxCachedPixmaps, + expirationThreshold)) {} ThumbnailPixmapCache::~ThumbnailPixmapCache() = default; diff --git a/src/core/ThumbnailPixmapCache.h b/src/core/ThumbnailPixmapCache.h index 3bd5fc64f..f6924a61a 100644 --- a/src/core/ThumbnailPixmapCache.h +++ b/src/core/ThumbnailPixmapCache.h @@ -10,7 +10,6 @@ #include "AbstractCommand.h" #include "NonCopyable.h" #include "ThumbnailLoadResult.h" -#include "ref_countable.h" class ImageId; class QImage; @@ -18,7 +17,7 @@ class QPixmap; class QString; class QSize; -class ThumbnailPixmapCache : public ref_countable { +class ThumbnailPixmapCache { DECLARE_NON_COPYABLE(ThumbnailPixmapCache) public: @@ -49,7 +48,7 @@ class ThumbnailPixmapCache : public ref_countable { /** * \brief Destructor. To be called from the GUI thread only. */ - ~ThumbnailPixmapCache() override; + virtual ~ThumbnailPixmapCache(); void setThumbDir(const QString& thumbDir); diff --git a/src/core/UnitsConverter.cpp b/src/core/UnitsConverter.cpp index 3298a6270..959fe62eb 100644 --- a/src/core/UnitsConverter.cpp +++ b/src/core/UnitsConverter.cpp @@ -95,11 +95,3 @@ QTransform UnitsConverter::transform(Units fromUnits, Units toUnits) const { convert(xScaleFactor, yScaleFactor, fromUnits, toUnits); return QTransform().scale(xScaleFactor, yScaleFactor); } - -const Dpi& UnitsConverter::getDpi() const { - return m_dpi; -} - -void UnitsConverter::setDpi(const Dpi& dpi) { - UnitsConverter::m_dpi = dpi; -} diff --git a/src/core/UnitsConverter.h b/src/core/UnitsConverter.h index 359cf198d..0c8ce0135 100644 --- a/src/core/UnitsConverter.h +++ b/src/core/UnitsConverter.h @@ -20,9 +20,9 @@ class UnitsConverter { QTransform transform(Units fromUnits, Units toUnits) const; - const Dpi& getDpi() const; + const Dpi& getDpi() const { return m_dpi; } - void setDpi(const Dpi& dpi); + void setDpi(const Dpi& dpi) { m_dpi = dpi; } private: Dpi m_dpi; diff --git a/src/core/UnitsProvider.cpp b/src/core/UnitsProvider.cpp index fcea2bd90..3cbc2fdbe 100644 --- a/src/core/UnitsProvider.cpp +++ b/src/core/UnitsProvider.cpp @@ -16,10 +16,6 @@ UnitsProvider& UnitsProvider::getInstance() { return instance; } -Units UnitsProvider::getUnits() const { - return m_units; -} - void UnitsProvider::setUnits(Units units) { UnitsProvider::m_units = units; unitsChanged(); diff --git a/src/core/UnitsProvider.h b/src/core/UnitsProvider.h index 5b62044ee..f6be5c0bb 100644 --- a/src/core/UnitsProvider.h +++ b/src/core/UnitsProvider.h @@ -21,7 +21,7 @@ class UnitsProvider { public: static UnitsProvider& getInstance(); - Units getUnits() const; + Units getUnits() const { return m_units; } void setUnits(Units units); diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp index 32e3b00ac..7ed7dd64c 100644 --- a/src/core/Utils.cpp +++ b/src/core/Utils.cpp @@ -47,10 +47,10 @@ QString Utils::outputDirToThumbDir(const QString& outputDir) { return outputDir + QLatin1String("/cache/thumbs"); } -intrusive_ptr Utils::createThumbnailCache(const QString& outputDir) { +std::shared_ptr Utils::createThumbnailCache(const QString& outputDir) { const QSize maxPixmapSize = ApplicationSettings::getInstance().getThumbnailQuality(); const QString thumbsCachePath(outputDirToThumbDir(outputDir)); - return make_intrusive(thumbsCachePath, maxPixmapSize, 40, 5); + return std::make_shared(thumbsCachePath, maxPixmapSize, 40, 5); } QString Utils::qssConvertPxToEm(const QString& stylesheet, const double base, const int precision) { diff --git a/src/core/Utils.h b/src/core/Utils.h index 205449173..7b7646c2e 100644 --- a/src/core/Utils.h +++ b/src/core/Utils.h @@ -35,7 +35,7 @@ class Utils { static QString outputDirToThumbDir(const QString& outputDir); - static intrusive_ptr createThumbnailCache(const QString& outputDir); + static std::shared_ptr createThumbnailCache(const QString& outputDir); /** * Unlike QFile::rename(), this one overwrites existing files. diff --git a/src/core/ZoneEditorBase.cpp b/src/core/ZoneEditorBase.cpp new file mode 100644 index 000000000..9814ed0ed --- /dev/null +++ b/src/core/ZoneEditorBase.cpp @@ -0,0 +1,104 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "ZoneEditorBase.h" + +#include +#include +#include +#include + +#include "Utils.h" +#include "ZoneModeListener.h" + +class ZoneEditorBase::ZoneModeProvider { + DECLARE_NON_COPYABLE(ZoneModeProvider) + public: + explicit ZoneModeProvider(const ZoneEditorBase& parent); + + ~ZoneModeProvider(); + + void addListener(ZoneModeListener* listener); + + void removeAllListeners(); + + void updateZoneMode(); + + private: + void notifyProviderStopped() const; + + std::list m_listeners; + const ZoneEditorBase& m_parent; +}; + +ZoneEditorBase::ZoneEditorBase(const QImage& image, + const ImagePixmapUnion& downscaledVersion, + const ImagePresentation& presentation, + const Margins& margins) + : ImageViewBase(image, downscaledVersion, presentation, margins), + m_context(*this, m_zones), + m_zoneModeProvider(std::make_unique(*this)) { + m_shortcutPolygonal = new QShortcut(Qt::Key_Z, this); + m_shortcutPolygonal->setAutoRepeat(false); + m_shortcutLasso = new QShortcut(Qt::Key_X, this); + m_shortcutLasso->setAutoRepeat(false); + m_shortcutRectangular = new QShortcut(Qt::Key_C, this); + m_shortcutRectangular->setAutoRepeat(false); + connect(m_shortcutPolygonal, &QShortcut::activated, [this]() { + m_context.setZoneCreationMode(ZoneCreationMode::POLYGONAL); + m_zoneModeProvider->updateZoneMode(); + }); + connect(m_shortcutLasso, &QShortcut::activated, [this]() { + m_context.setZoneCreationMode(ZoneCreationMode::LASSO); + m_zoneModeProvider->updateZoneMode(); + }); + connect(m_shortcutRectangular, &QShortcut::activated, [this]() { + m_context.setZoneCreationMode(ZoneCreationMode::RECTANGULAR); + m_zoneModeProvider->updateZoneMode(); + }); +} + +ZoneEditorBase::~ZoneEditorBase() = default; + +void ZoneEditorBase::showEvent(QShowEvent* event) { + ImageViewBase::showEvent(event); + if (auto* mainWindow = dynamic_cast(window())) { + if (auto* zoneModeListener = core::Utils::castOrFindChild(mainWindow->statusBar())) { + m_zoneModeProvider->addListener(zoneModeListener); + } + } +} + +void ZoneEditorBase::hideEvent(QHideEvent* event) { + m_zoneModeProvider->removeAllListeners(); + ImageViewBase::hideEvent(event); +} + +ZoneEditorBase::ZoneModeProvider::ZoneModeProvider(const ZoneEditorBase& parent) : m_parent(parent) {} + +ZoneEditorBase::ZoneModeProvider::~ZoneModeProvider() { + notifyProviderStopped(); +} + +void ZoneEditorBase::ZoneModeProvider::addListener(ZoneModeListener* listener) { + listener->onZoneModeChanged(m_parent.context().getZoneCreationMode()); + m_listeners.push_back(listener); +} + +void ZoneEditorBase::ZoneModeProvider::removeAllListeners() { + notifyProviderStopped(); + m_listeners.clear(); +} + +void ZoneEditorBase::ZoneModeProvider::updateZoneMode() { + ZoneCreationMode mode = m_parent.context().getZoneCreationMode(); + for (ZoneModeListener* listener : m_listeners) { + listener->onZoneModeChanged(mode); + } +} + +void ZoneEditorBase::ZoneModeProvider::notifyProviderStopped() const { + for (ZoneModeListener* listener : m_listeners) { + listener->onZoneModeProviderStopped(); + } +} diff --git a/src/core/ZoneEditorBase.h b/src/core/ZoneEditorBase.h new file mode 100644 index 000000000..ebcd71fa3 --- /dev/null +++ b/src/core/ZoneEditorBase.h @@ -0,0 +1,48 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_CORE_ZONEEDITORBASE_H_ +#define SCANTAILOR_CORE_ZONEEDITORBASE_H_ + +#include +#include + +#include "ImageViewBase.h" + +class QShortcut; + +class ZoneEditorBase : public ImageViewBase, protected InteractionHandler { + public: + ZoneEditorBase(const QImage& image, + const ImagePixmapUnion& downscaledVersion, + const ImagePresentation& presentation, + const Margins& margins = Margins()); + + ~ZoneEditorBase() override; + + EditableZoneSet& zones() { return m_zones; } + + const EditableZoneSet& zones() const { return m_zones; } + + ZoneInteractionContext& context() { return m_context; } + + const ZoneInteractionContext& context() const { return m_context; } + + protected: + void showEvent(QShowEvent* event) override; + + void hideEvent(QHideEvent* event) override; + + private: + class ZoneModeProvider; + + EditableZoneSet m_zones; + ZoneInteractionContext m_context; + std::unique_ptr m_zoneModeProvider; + QShortcut* m_shortcutPolygonal; + QShortcut* m_shortcutLasso; + QShortcut* m_shortcutRectangular; +}; + + +#endif // SCANTAILOR_CORE_ZONEEDITORBASE_H_ diff --git a/src/core/ZoneModeListener.h b/src/core/ZoneModeListener.h new file mode 100644 index 000000000..3ed55b74d --- /dev/null +++ b/src/core/ZoneModeListener.h @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_CORE_ZONEMODELISTENER_H_ +#define SCANTAILOR_CORE_ZONEMODELISTENER_H_ + +#include + +class ZoneModeListener { + public: + virtual ~ZoneModeListener() = default; + + virtual void onZoneModeChanged(ZoneCreationMode mode) = 0; + + virtual void onZoneModeProviderStopped() = 0; +}; + + +#endif // SCANTAILOR_CORE_ZONEMODELISTENER_H_ diff --git a/src/core/filters/deskew/ApplyDialog.h b/src/core/filters/deskew/ApplyDialog.h index 97a4db83e..5ea35dbd7 100644 --- a/src/core/filters/deskew/ApplyDialog.h +++ b/src/core/filters/deskew/ApplyDialog.h @@ -6,11 +6,11 @@ #include #include +#include #include #include "PageId.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ApplyDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/deskew/CMakeLists.txt b/src/core/filters/deskew/CMakeLists.txt index 2eeb57852..526b7d67e 100644 --- a/src/core/filters/deskew/CMakeLists.txt +++ b/src/core/filters/deskew/CMakeLists.txt @@ -14,7 +14,8 @@ set(sources CacheDrivenTask.cpp CacheDrivenTask.h Dependencies.cpp Dependencies.h Params.cpp Params.h - ApplyDialog.cpp ApplyDialog.h) + ApplyDialog.cpp ApplyDialog.h + Utils.cpp Utils.h) add_library(deskew STATIC ${sources} ${ui_files}) target_link_libraries(deskew PUBLIC core) diff --git a/src/core/filters/deskew/CacheDrivenTask.cpp b/src/core/filters/deskew/CacheDrivenTask.cpp index c0b1b1011..23afbfd7a 100644 --- a/src/core/filters/deskew/CacheDrivenTask.cpp +++ b/src/core/filters/deskew/CacheDrivenTask.cpp @@ -16,8 +16,8 @@ #include "filters/select_content/CacheDrivenTask.h" namespace deskew { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr settings, - intrusive_ptr nextTask) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr settings, + std::shared_ptr nextTask) : m_nextTask(std::move(nextTask)), m_settings(std::move(settings)) {} CacheDrivenTask::~CacheDrivenTask() = default; diff --git a/src/core/filters/deskew/CacheDrivenTask.h b/src/core/filters/deskew/CacheDrivenTask.h index 78bdd122b..a035324aa 100644 --- a/src/core/filters/deskew/CacheDrivenTask.h +++ b/src/core/filters/deskew/CacheDrivenTask.h @@ -4,9 +4,9 @@ #ifndef SCANTAILOR_DESKEW_CACHEDRIVENTASK_H_ #define SCANTAILOR_DESKEW_CACHEDRIVENTASK_H_ +#include + #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QSizeF; class PageInfo; @@ -20,19 +20,19 @@ class CacheDrivenTask; namespace deskew { class Settings; -class CacheDrivenTask : public ref_countable { +class CacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr settings, intrusive_ptr nextTask); + CacheDrivenTask(std::shared_ptr settings, std::shared_ptr nextTask); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector, const ImageTransformation& xform); private: - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; }; } // namespace deskew #endif // ifndef SCANTAILOR_DESKEW_CACHEDRIVENTASK_H_ diff --git a/src/core/filters/deskew/Filter.cpp b/src/core/filters/deskew/Filter.cpp index e201d1ac0..c2e062b15 100644 --- a/src/core/filters/deskew/Filter.cpp +++ b/src/core/filters/deskew/Filter.cpp @@ -3,14 +3,10 @@ #include "Filter.h" -#include -#include #include #include #include -#include -#include #include #include "AbstractRelinker.h" @@ -20,14 +16,17 @@ #include "ProjectReader.h" #include "ProjectWriter.h" #include "Task.h" +#include "Utils.h" namespace deskew { Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) - : m_settings(new Settings), m_imageSettings(new ImageSettings), m_selectedPageOrder(0) { + : m_settings(std::make_shared()), + m_imageSettings(std::make_shared()), + m_selectedPageOrder(0) { m_optionsWidget.reset(new OptionsWidget(m_settings, pageSelectionAccessor)); const PageOrderOption::ProviderPtr defaultOrder; - const auto orderByDeviation = make_intrusive(m_settings->deviationProvider()); + const auto orderByDeviation = std::make_shared(m_settings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), defaultOrder); m_pageOrderOptions.emplace_back(tr("Order by decreasing deviation"), orderByDeviation); } @@ -114,16 +113,17 @@ void Filter::writeParams(QDomDocument& doc, QDomElement& filterEl, const PageId& filterEl.appendChild(pageEl); } -intrusive_ptr Filter::createTask(const PageId& pageId, - intrusive_ptr nextTask, - const bool batchProcessing, - const bool debug) { - return make_intrusive(intrusive_ptr(this), m_settings, m_imageSettings, std::move(nextTask), pageId, - batchProcessing, debug); +std::shared_ptr Filter::createTask(const PageId& pageId, + std::shared_ptr nextTask, + const bool batchProcessing, + const bool debug) { + return std::make_shared(std::static_pointer_cast(shared_from_this()), m_settings, m_imageSettings, + std::move(nextTask), pageId, batchProcessing, debug); } -intrusive_ptr Filter::createCacheDrivenTask(intrusive_ptr nextTask) { - return make_intrusive(m_settings, std::move(nextTask)); +std::shared_ptr Filter::createCacheDrivenTask( + std::shared_ptr nextTask) { + return std::make_shared(m_settings, std::move(nextTask)); } std::vector Filter::pageOrderOptions() const { @@ -140,14 +140,10 @@ void Filter::selectPageOrder(int option) { } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->isParamsNull(pageInfo.id())) { + if (!m_settings->isParamsNull(pageInfo.id())) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::DeskewParams& deskewParams = defaultParams.getDeskewParams(); - m_settings->setPageParams(pageInfo.id(), - Params(deskewParams.getDeskewAngleDeg(), Dependencies(), deskewParams.getMode())); + m_settings->setPageParams(pageInfo.id(), Utils::buildDefaultParams()); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/deskew/Filter.h b/src/core/filters/deskew/Filter.h index 01ee5f7d0..485a59264 100644 --- a/src/core/filters/deskew/Filter.h +++ b/src/core/filters/deskew/Filter.h @@ -5,6 +5,7 @@ #define SCANTAILOR_DESKEW_FILTER_H_ #include +#include #include "AbstractFilter.h" #include "FilterResult.h" @@ -12,7 +13,6 @@ #include "PageView.h" #include "SafeDeletingQObjectPtr.h" #include "Settings.h" -#include "intrusive_ptr.h" class QString; class PageSelectionAccessor; @@ -52,12 +52,12 @@ class Filter : public AbstractFilter { void loadDefaultSettings(const PageInfo& pageInfo) override; - intrusive_ptr createTask(const PageId& pageId, - intrusive_ptr nextTask, - bool batchProcessing, - bool debug); + std::shared_ptr createTask(const PageId& pageId, + std::shared_ptr nextTask, + bool batchProcessing, + bool debug); - intrusive_ptr createCacheDrivenTask(intrusive_ptr nextTask); + std::shared_ptr createCacheDrivenTask(std::shared_ptr nextTask); OptionsWidget* optionsWidget(); @@ -76,8 +76,8 @@ class Filter : public AbstractFilter { void loadImageSettings(const ProjectReader& reader, const QDomElement& imageSettingsEl); - intrusive_ptr m_settings; - intrusive_ptr m_imageSettings; + std::shared_ptr m_settings; + std::shared_ptr m_imageSettings; SafeDeletingQObjectPtr m_optionsWidget; std::vector m_pageOrderOptions; int m_selectedPageOrder; diff --git a/src/core/filters/deskew/OptionsWidget.cpp b/src/core/filters/deskew/OptionsWidget.cpp index 37037e4e6..9d70fadf2 100644 --- a/src/core/filters/deskew/OptionsWidget.cpp +++ b/src/core/filters/deskew/OptionsWidget.cpp @@ -11,7 +11,7 @@ namespace deskew { const double OptionsWidget::MAX_ANGLE = 45.0; -OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) +OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pageSelectionAccessor(pageSelectionAccessor), m_connectionManager(std::bind(&OptionsWidget::setupUiConnections, this)) { @@ -94,9 +94,7 @@ void OptionsWidget::postUpdateUI(const UiData& uiData) { } void OptionsWidget::spinBoxValueChanged(const double value) { - if (m_ignoreSpinBoxChanges) { - return; - } + auto block = m_connectionManager.getScopedBlock(); const double degrees = spinBoxToDegrees(value); m_uiData.setEffectiveDeskewAngle(degrees); @@ -182,28 +180,4 @@ void OptionsWidget::setupUiConnections() { OptionsWidget::UiData::UiData() : m_effDeskewAngle(0.0), m_mode(MODE_AUTO) {} OptionsWidget::UiData::~UiData() = default; - -void OptionsWidget::UiData::setEffectiveDeskewAngle(const double degrees) { - m_effDeskewAngle = degrees; -} - -double OptionsWidget::UiData::effectiveDeskewAngle() const { - return m_effDeskewAngle; -} - -void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { - m_deps = deps; -} - -const Dependencies& OptionsWidget::UiData::dependencies() const { - return m_deps; -} - -void OptionsWidget::UiData::setMode(const AutoManualMode mode) { - m_mode = mode; -} - -AutoManualMode OptionsWidget::UiData::mode() const { - return m_mode; -} } // namespace deskew \ No newline at end of file diff --git a/src/core/filters/deskew/OptionsWidget.h b/src/core/filters/deskew/OptionsWidget.h index e89600abe..3f77020d8 100644 --- a/src/core/filters/deskew/OptionsWidget.h +++ b/src/core/filters/deskew/OptionsWidget.h @@ -7,6 +7,7 @@ #include #include +#include #include #include "AutoManualMode.h" @@ -14,7 +15,6 @@ #include "FilterOptionsWidget.h" #include "PageId.h" #include "PageSelectionAccessor.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" namespace deskew { @@ -49,7 +49,7 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { }; - OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); + OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -95,15 +95,39 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { static const double MAX_ANGLE; - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageId m_pageId; UiData m_uiData; - int m_ignoreAutoManualToggle; - int m_ignoreSpinBoxChanges; PageSelectionAccessor m_pageSelectionAccessor; ConnectionManager m_connectionManager; }; + + +inline void OptionsWidget::UiData::setEffectiveDeskewAngle(const double degrees) { + m_effDeskewAngle = degrees; +} + +inline double OptionsWidget::UiData::effectiveDeskewAngle() const { + return m_effDeskewAngle; +} + +inline void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { + m_deps = deps; +} + +inline const Dependencies& OptionsWidget::UiData::dependencies() const { + return m_deps; +} + +inline void OptionsWidget::UiData::setMode(const AutoManualMode mode) { + m_mode = mode; +} + +inline AutoManualMode OptionsWidget::UiData::mode() const { + return m_mode; +} } // namespace deskew + #endif // ifndef SCANTAILOR_DESKEW_OPTIONSWIDGET_H_ diff --git a/src/core/filters/deskew/Params.cpp b/src/core/filters/deskew/Params.cpp index d153d845b..62c020e5a 100644 --- a/src/core/filters/deskew/Params.cpp +++ b/src/core/filters/deskew/Params.cpp @@ -27,15 +27,4 @@ QDomElement Params::toXml(QDomDocument& doc, const QString& name) const { el.appendChild(m_deps.toXml(doc, "dependencies")); return el; } - -double Params::deskewAngle() const { - return m_deskewAngleDeg; -} -const Dependencies& Params::dependencies() const { - return m_deps; -} - -AutoManualMode Params::mode() const { - return m_mode; -} } // namespace deskew \ No newline at end of file diff --git a/src/core/filters/deskew/Params.h b/src/core/filters/deskew/Params.h index 15c5900b1..035ad84d9 100644 --- a/src/core/filters/deskew/Params.h +++ b/src/core/filters/deskew/Params.h @@ -38,5 +38,19 @@ class Params { Dependencies m_deps; AutoManualMode m_mode; }; + + +inline double Params::deskewAngle() const { + return m_deskewAngleDeg; +} + +inline const Dependencies& Params::dependencies() const { + return m_deps; +} + +inline AutoManualMode Params::mode() const { + return m_mode; +} } // namespace deskew + #endif // ifndef SCANTAILOR_DESKEW_PARAMS_H_ diff --git a/src/core/filters/deskew/Settings.cpp b/src/core/filters/deskew/Settings.cpp index 2a4345d76..656ff1f6e 100644 --- a/src/core/filters/deskew/Settings.cpp +++ b/src/core/filters/deskew/Settings.cpp @@ -16,9 +16,8 @@ Settings::Settings() { if (it != m_perPageParams.end()) { const Params& params = it->second; return params.deskewAngle(); - } else { - return .0; - }; + } + return NAN; }); } diff --git a/src/core/filters/deskew/Settings.h b/src/core/filters/deskew/Settings.h index 1b64c2c55..22d1baa89 100644 --- a/src/core/filters/deskew/Settings.h +++ b/src/core/filters/deskew/Settings.h @@ -14,18 +14,17 @@ #include "NonCopyable.h" #include "PageId.h" #include "Params.h" -#include "ref_countable.h" class AbstractRelinker; namespace deskew { -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) public: Settings(); - ~Settings() override; + virtual ~Settings(); void clear(); diff --git a/src/core/filters/deskew/Task.cpp b/src/core/filters/deskew/Task.cpp index aff68660e..f0d9cd156 100644 --- a/src/core/filters/deskew/Task.cpp +++ b/src/core/filters/deskew/Task.cpp @@ -35,7 +35,7 @@ using namespace imageproc; class Task::UiUpdater : public FilterResult { public: - UiUpdater(intrusive_ptr filter, + UiUpdater(std::shared_ptr filter, std::unique_ptr dbgImg, const QImage& image, const PageId& pageId, @@ -45,10 +45,10 @@ class Task::UiUpdater : public FilterResult { void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; + std::shared_ptr m_filter; std::unique_ptr m_dbg; QImage m_image; QImage m_downscaledImage; @@ -59,10 +59,10 @@ class Task::UiUpdater : public FilterResult { }; -Task::Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr imageSettings, - intrusive_ptr nextTask, +Task::Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr imageSettings, + std::shared_ptr nextTask, const PageId& pageId, const bool batchProcessing, const bool debug) @@ -150,8 +150,8 @@ FilterResultPtr Task::process(const TaskStatus& status, FilterData data) { if (m_nextTask) { return m_nextTask->process(status, FilterData(data, newXform)); } else { - return make_intrusive(m_filter, std::move(m_dbg), data.origImage(), m_pageId, newXform, uiData, - m_batchProcessing); + return std::make_shared(m_filter, std::move(m_dbg), data.origImage(), m_pageId, newXform, uiData, + m_batchProcessing); } } // Task::process @@ -227,7 +227,7 @@ void Task::updateFilterData(const TaskStatus& status, FilterData& data, bool nee /*============================ Task::UiUpdater ==========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, std::unique_ptr dbgImg, const QImage& image, const PageId& pageId, diff --git a/src/core/filters/deskew/Task.h b/src/core/filters/deskew/Task.h index a85480b13..af6391fa0 100644 --- a/src/core/filters/deskew/Task.h +++ b/src/core/filters/deskew/Task.h @@ -11,7 +11,6 @@ #include "FilterResult.h" #include "NonCopyable.h" #include "PageId.h" -#include "ref_countable.h" class TaskStatus; class QImage; @@ -31,19 +30,19 @@ namespace deskew { class Filter; class Settings; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: - Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr imageSettings, - intrusive_ptr nextTask, + Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr imageSettings, + std::shared_ptr nextTask, const PageId& pageId, bool batchProcessing, bool debug); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, FilterData data); @@ -58,10 +57,10 @@ class Task : public ref_countable { void updateFilterData(const TaskStatus& status, FilterData& data, bool needUpdate); - intrusive_ptr m_filter; - intrusive_ptr m_settings; - intrusive_ptr m_imageSettings; - intrusive_ptr m_nextTask; + std::shared_ptr m_filter; + std::shared_ptr m_settings; + std::shared_ptr m_imageSettings; + std::shared_ptr m_nextTask; std::unique_ptr m_dbg; PageId m_pageId; bool m_batchProcessing; diff --git a/src/core/filters/deskew/Thumbnail.cpp b/src/core/filters/deskew/Thumbnail.cpp index 699e25f96..6d3271827 100644 --- a/src/core/filters/deskew/Thumbnail.cpp +++ b/src/core/filters/deskew/Thumbnail.cpp @@ -7,7 +7,7 @@ #include namespace deskew { -Thumbnail::Thumbnail(intrusive_ptr thumbnailCache, +Thumbnail::Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/deskew/Thumbnail.h b/src/core/filters/deskew/Thumbnail.h index a5f48b3e6..6072fb801 100644 --- a/src/core/filters/deskew/Thumbnail.h +++ b/src/core/filters/deskew/Thumbnail.h @@ -4,8 +4,9 @@ #ifndef SCANTAILOR_DESKEW_THUMBNAIL_H_ #define SCANTAILOR_DESKEW_THUMBNAIL_H_ +#include + #include "ThumbnailBase.h" -#include "intrusive_ptr.h" class QSizeF; class ThumbnailPixmapCache; @@ -15,7 +16,7 @@ class ImageTransformation; namespace deskew { class Thumbnail : public ThumbnailBase { public: - Thumbnail(intrusive_ptr thumbnailCache, + Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/deskew/Utils.cpp b/src/core/filters/deskew/Utils.cpp new file mode 100644 index 000000000..5e4b6af4a --- /dev/null +++ b/src/core/filters/deskew/Utils.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "Utils.h" + +#include +#include + +#include "Params.h" + +using namespace deskew; + +Params Utils::buildDefaultParams() { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::DeskewParams& deskewParams = defaultParams.getDeskewParams(); + + return Params(deskewParams.getDeskewAngleDeg(), Dependencies(), deskewParams.getMode()); +} diff --git a/src/core/filters/deskew/Utils.h b/src/core/filters/deskew/Utils.h new file mode 100644 index 000000000..02884d64b --- /dev/null +++ b/src/core/filters/deskew/Utils.h @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_DESKEW_UTILS_H_ +#define SCANTAILOR_DESKEW_UTILS_H_ + +namespace deskew { +class Params; + +class Utils { + public: + Utils() = delete; + + static Params buildDefaultParams(); +}; +} // namespace deskew + +#endif // SCANTAILOR_DESKEW_UTILS_H_ diff --git a/src/core/filters/fix_orientation/ApplyDialog.h b/src/core/filters/fix_orientation/ApplyDialog.h index b05dacd45..4761cc23f 100644 --- a/src/core/filters/fix_orientation/ApplyDialog.h +++ b/src/core/filters/fix_orientation/ApplyDialog.h @@ -6,13 +6,13 @@ #include #include +#include #include #include #include "PageId.h" #include "PageRange.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ApplyDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/fix_orientation/CMakeLists.txt b/src/core/filters/fix_orientation/CMakeLists.txt index 4b8b63cea..e0668d98b 100644 --- a/src/core/filters/fix_orientation/CMakeLists.txt +++ b/src/core/filters/fix_orientation/CMakeLists.txt @@ -11,7 +11,8 @@ set(sources ApplyDialog.cpp ApplyDialog.h Settings.cpp Settings.h Task.cpp Task.h - CacheDrivenTask.cpp CacheDrivenTask.h) + CacheDrivenTask.cpp CacheDrivenTask.h + Utils.cpp Utils.h) add_library(fix_orientation STATIC ${sources} ${ui_files}) target_link_libraries(fix_orientation PUBLIC core) diff --git a/src/core/filters/fix_orientation/CacheDrivenTask.cpp b/src/core/filters/fix_orientation/CacheDrivenTask.cpp index f57fd76d8..52b7a14c7 100644 --- a/src/core/filters/fix_orientation/CacheDrivenTask.cpp +++ b/src/core/filters/fix_orientation/CacheDrivenTask.cpp @@ -15,7 +15,8 @@ #include "filters/page_split/CacheDrivenTask.h" namespace fix_orientation { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr settings, intrusive_ptr nextTask) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr settings, + std::shared_ptr nextTask) : m_nextTask(std::move(nextTask)), m_settings(std::move(settings)) {} CacheDrivenTask::~CacheDrivenTask() = default; diff --git a/src/core/filters/fix_orientation/CacheDrivenTask.h b/src/core/filters/fix_orientation/CacheDrivenTask.h index 58967059d..1f466945a 100644 --- a/src/core/filters/fix_orientation/CacheDrivenTask.h +++ b/src/core/filters/fix_orientation/CacheDrivenTask.h @@ -4,9 +4,10 @@ #ifndef SCANTAILOR_FIX_ORIENTATION_CACHEDRIVENTASK_H_ #define SCANTAILOR_FIX_ORIENTATION_CACHEDRIVENTASK_H_ +#include + #include "CompositeCacheDrivenTask.h" #include "NonCopyable.h" -#include "intrusive_ptr.h" class PageInfo; class AbstractFilterDataCollector; @@ -22,15 +23,15 @@ class CacheDrivenTask : public CompositeCacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr settings, intrusive_ptr nextTask); + CacheDrivenTask(std::shared_ptr settings, std::shared_ptr nextTask); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector) override; private: - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; }; } // namespace fix_orientation #endif // ifndef SCANTAILOR_FIX_ORIENTATION_CACHEDRIVENTASK_H_ diff --git a/src/core/filters/fix_orientation/Filter.cpp b/src/core/filters/fix_orientation/Filter.cpp index 8f0f897d0..2bf825f94 100644 --- a/src/core/filters/fix_orientation/Filter.cpp +++ b/src/core/filters/fix_orientation/Filter.cpp @@ -3,14 +3,10 @@ #include "Filter.h" -#include -#include #include #include #include -#include -#include #include #include "CacheDrivenTask.h" @@ -21,12 +17,12 @@ #include "ProjectWriter.h" #include "Settings.h" #include "Task.h" +#include "Utils.h" #include "XmlMarshaller.h" -#include "XmlUnmarshaller.h" namespace fix_orientation { Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) - : m_settings(new Settings), m_imageSettings(new ImageSettings) { + : m_settings(std::make_shared()), m_imageSettings(std::make_shared()) { m_optionsWidget.reset(new OptionsWidget(m_settings, pageSelectionAccessor)); } @@ -97,15 +93,15 @@ void Filter::loadSettings(const ProjectReader& reader, const QDomElement& filter loadImageSettings(reader, filterEl.namedItem("image-settings").toElement()); } // Filter::loadSettings -intrusive_ptr Filter::createTask(const PageId& pageId, - intrusive_ptr nextTask, - const bool batchProcessing) { - return make_intrusive(pageId, intrusive_ptr(this), m_settings, m_imageSettings, std::move(nextTask), - batchProcessing); +std::shared_ptr Filter::createTask(const PageId& pageId, + std::shared_ptr nextTask, + const bool batchProcessing) { + return std::make_shared(pageId, std::static_pointer_cast(shared_from_this()), m_settings, + m_imageSettings, std::move(nextTask), batchProcessing); } -intrusive_ptr Filter::createCacheDrivenTask(intrusive_ptr nextTask) { - return make_intrusive(m_settings, std::move(nextTask)); +std::shared_ptr Filter::createCacheDrivenTask(std::shared_ptr nextTask) { + return std::make_shared(m_settings, std::move(nextTask)); } void Filter::writeParams(QDomDocument& doc, QDomElement& filterEl, const ImageId& imageId, int numericId) const { @@ -123,13 +119,10 @@ void Filter::writeParams(QDomDocument& doc, QDomElement& filterEl, const ImageId } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->isRotationNull(pageInfo.id().imageId())) { + if (!m_settings->isRotationNull(pageInfo.id().imageId())) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::FixOrientationParams& fixOrientationParams = defaultParams.getFixOrientationParams(); - m_settings->applyRotation(pageInfo.id().imageId(), fixOrientationParams.getImageRotation()); + m_settings->applyRotation(pageInfo.id().imageId(), Utils::getDefaultOrthogonalRotation()); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/fix_orientation/Filter.h b/src/core/filters/fix_orientation/Filter.h index e956935f0..753b86638 100644 --- a/src/core/filters/fix_orientation/Filter.h +++ b/src/core/filters/fix_orientation/Filter.h @@ -4,12 +4,13 @@ #ifndef SCANTAILOR_FIX_ORIENTATION_FILTER_H_ #define SCANTAILOR_FIX_ORIENTATION_FILTER_H_ +#include + #include "AbstractFilter.h" #include "FilterResult.h" #include "NonCopyable.h" #include "PageView.h" #include "SafeDeletingQObjectPtr.h" -#include "intrusive_ptr.h" class ImageId; class PageSelectionAccessor; @@ -55,9 +56,11 @@ class Filter : public AbstractFilter { void loadDefaultSettings(const PageInfo& pageInfo) override; - intrusive_ptr createTask(const PageId& pageId, intrusive_ptr nextTask, bool batchProcessing); + std::shared_ptr createTask(const PageId& pageId, + std::shared_ptr nextTask, + bool batchProcessing); - intrusive_ptr createCacheDrivenTask(intrusive_ptr nextTask); + std::shared_ptr createCacheDrivenTask(std::shared_ptr nextTask); OptionsWidget* optionsWidget(); @@ -70,8 +73,8 @@ class Filter : public AbstractFilter { void loadImageSettings(const ProjectReader& reader, const QDomElement& imageSettingsEl); - intrusive_ptr m_settings; - intrusive_ptr m_imageSettings; + std::shared_ptr m_settings; + std::shared_ptr m_imageSettings; SafeDeletingQObjectPtr m_optionsWidget; }; } // namespace fix_orientation diff --git a/src/core/filters/fix_orientation/OptionsWidget.cpp b/src/core/filters/fix_orientation/OptionsWidget.cpp index 0b277d1b1..398882214 100644 --- a/src/core/filters/fix_orientation/OptionsWidget.cpp +++ b/src/core/filters/fix_orientation/OptionsWidget.cpp @@ -14,7 +14,7 @@ #include "Settings.h" namespace fix_orientation { -OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) +OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pageSelectionAccessor(pageSelectionAccessor), m_connectionManager(std::bind(&OptionsWidget::setupUiConnections, this)) { diff --git a/src/core/filters/fix_orientation/OptionsWidget.h b/src/core/filters/fix_orientation/OptionsWidget.h index cac2787ea..776a98548 100644 --- a/src/core/filters/fix_orientation/OptionsWidget.h +++ b/src/core/filters/fix_orientation/OptionsWidget.h @@ -7,12 +7,12 @@ #include #include +#include #include "FilterOptionsWidget.h" #include "OrthogonalRotation.h" #include "PageId.h" #include "PageSelectionAccessor.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" namespace fix_orientation { @@ -21,7 +21,7 @@ class Settings; class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { Q_OBJECT public: - OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); + OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -56,7 +56,7 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { void setupIcons(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageSelectionAccessor m_pageSelectionAccessor; PageId m_pageId; OrthogonalRotation m_rotation; diff --git a/src/core/filters/fix_orientation/Settings.h b/src/core/filters/fix_orientation/Settings.h index edf81c3ed..3e5edd829 100644 --- a/src/core/filters/fix_orientation/Settings.h +++ b/src/core/filters/fix_orientation/Settings.h @@ -12,18 +12,17 @@ #include "NonCopyable.h" #include "OrthogonalRotation.h" #include "PageId.h" -#include "ref_countable.h" class AbstractRelinker; namespace fix_orientation { -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) public: Settings(); - ~Settings() override; + virtual ~Settings(); void clear(); diff --git a/src/core/filters/fix_orientation/Task.cpp b/src/core/filters/fix_orientation/Task.cpp index eadcf63d9..1a446a620 100644 --- a/src/core/filters/fix_orientation/Task.cpp +++ b/src/core/filters/fix_orientation/Task.cpp @@ -21,7 +21,7 @@ using imageproc::BinaryThreshold; class Task::UiUpdater : public FilterResult { public: - UiUpdater(intrusive_ptr filter, + UiUpdater(std::shared_ptr filter, const QImage& image, const ImageId& imageId, const ImageTransformation& xform, @@ -29,10 +29,10 @@ class Task::UiUpdater : public FilterResult { void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; + std::shared_ptr m_filter; QImage m_image; QImage m_downscaledImage; ImageId m_imageId; @@ -42,10 +42,10 @@ class Task::UiUpdater : public FilterResult { Task::Task(const PageId& pageId, - intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr imageSettings, - intrusive_ptr nextTask, + std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr imageSettings, + std::shared_ptr nextTask, const bool batchProcessing) : m_filter(std::move(filter)), m_nextTask(std::move(nextTask)), @@ -69,7 +69,7 @@ FilterResultPtr Task::process(const TaskStatus& status, FilterData data) { if (m_nextTask) { return m_nextTask->process(status, FilterData(data, xform)); } else { - return make_intrusive(m_filter, data.origImage(), m_imageId, xform, m_batchProcessing); + return std::make_shared(m_filter, data.origImage(), m_imageId, xform, m_batchProcessing); } } @@ -86,7 +86,7 @@ void Task::updateFilterData(FilterData& data) { /*============================ Task::UiUpdater ========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, const QImage& image, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/fix_orientation/Task.h b/src/core/filters/fix_orientation/Task.h index 900e31779..6dcbfad04 100644 --- a/src/core/filters/fix_orientation/Task.h +++ b/src/core/filters/fix_orientation/Task.h @@ -6,11 +6,11 @@ #include +#include + #include "FilterResult.h" #include "ImageId.h" #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class TaskStatus; class QImage; @@ -23,18 +23,18 @@ namespace fix_orientation { class Filter; class Settings; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: Task(const PageId& pageId, - intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr imageSettings, - intrusive_ptr nextTask, + std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr imageSettings, + std::shared_ptr nextTask, bool batchProcessing); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, FilterData data); @@ -43,10 +43,10 @@ class Task : public ref_countable { void updateFilterData(FilterData& data); - intrusive_ptr m_filter; - intrusive_ptr m_nextTask; // if null, this task is the final one - intrusive_ptr m_settings; - intrusive_ptr m_imageSettings; + std::shared_ptr m_filter; + std::shared_ptr m_nextTask; // if null, this task is the final one + std::shared_ptr m_settings; + std::shared_ptr m_imageSettings; PageId m_pageId; ImageId m_imageId; bool m_batchProcessing; diff --git a/src/core/filters/fix_orientation/Utils.cpp b/src/core/filters/fix_orientation/Utils.cpp new file mode 100644 index 000000000..4816846fb --- /dev/null +++ b/src/core/filters/fix_orientation/Utils.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "Utils.h" + +#include +#include + +using namespace fix_orientation; + +OrthogonalRotation Utils::getDefaultOrthogonalRotation() { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::FixOrientationParams& fixOrientationParams = defaultParams.getFixOrientationParams(); + + return fixOrientationParams.getImageRotation(); +} diff --git a/src/core/filters/fix_orientation/Utils.h b/src/core/filters/fix_orientation/Utils.h new file mode 100644 index 000000000..2550f22d8 --- /dev/null +++ b/src/core/filters/fix_orientation/Utils.h @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_FIX_ORIENTATION_UTILS_H_ +#define SCANTAILOR_FIX_ORIENTATION_UTILS_H_ + +class OrthogonalRotation; + +namespace fix_orientation { +class Utils { + public: + Utils() = delete; + + static OrthogonalRotation getDefaultOrthogonalRotation(); +}; +} // namespace fix_orientation + +#endif // SCANTAILOR_FIX_ORIENTATION_UTILS_H_ diff --git a/src/core/filters/output/ApplyColorsDialog.h b/src/core/filters/output/ApplyColorsDialog.h index 3993a68f6..79c603288 100644 --- a/src/core/filters/output/ApplyColorsDialog.h +++ b/src/core/filters/output/ApplyColorsDialog.h @@ -6,11 +6,11 @@ #include #include +#include #include #include "PageId.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ApplyColorsDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/output/BlackWhiteOptions.cpp b/src/core/filters/output/BlackWhiteOptions.cpp index fa88c6b50..4f81e9091 100644 --- a/src/core/filters/output/BlackWhiteOptions.cpp +++ b/src/core/filters/output/BlackWhiteOptions.cpp @@ -67,70 +67,6 @@ bool BlackWhiteOptions::operator!=(const BlackWhiteOptions& other) const { return !(*this == other); } -bool BlackWhiteOptions::isSavitzkyGolaySmoothingEnabled() const { - return m_savitzkyGolaySmoothingEnabled; -} - -void BlackWhiteOptions::setSavitzkyGolaySmoothingEnabled(bool savitzkyGolaySmoothingEnabled) { - BlackWhiteOptions::m_savitzkyGolaySmoothingEnabled = savitzkyGolaySmoothingEnabled; -} - -bool BlackWhiteOptions::isMorphologicalSmoothingEnabled() const { - return m_morphologicalSmoothingEnabled; -} - -void BlackWhiteOptions::setMorphologicalSmoothingEnabled(bool morphologicalSmoothingEnabled) { - BlackWhiteOptions::m_morphologicalSmoothingEnabled = morphologicalSmoothingEnabled; -} - -int BlackWhiteOptions::getWindowSize() const { - return m_windowSize; -} - -void BlackWhiteOptions::setWindowSize(int windowSize) { - BlackWhiteOptions::m_windowSize = windowSize; -} - -double BlackWhiteOptions::getSauvolaCoef() const { - return m_sauvolaCoef; -} - -void BlackWhiteOptions::setSauvolaCoef(double sauvolaCoef) { - BlackWhiteOptions::m_sauvolaCoef = sauvolaCoef; -} - -int BlackWhiteOptions::getWolfLowerBound() const { - return m_wolfLowerBound; -} - -void BlackWhiteOptions::setWolfLowerBound(int wolfLowerBound) { - BlackWhiteOptions::m_wolfLowerBound = wolfLowerBound; -} - -int BlackWhiteOptions::getWolfUpperBound() const { - return m_wolfUpperBound; -} - -void BlackWhiteOptions::setWolfUpperBound(int wolfUpperBound) { - BlackWhiteOptions::m_wolfUpperBound = wolfUpperBound; -} - -double BlackWhiteOptions::getWolfCoef() const { - return m_wolfCoef; -} - -void BlackWhiteOptions::setWolfCoef(double wolfCoef) { - BlackWhiteOptions::m_wolfCoef = wolfCoef; -} - -BinarizationMethod BlackWhiteOptions::getBinarizationMethod() const { - return m_binarizationMethod; -} - -void BlackWhiteOptions::setBinarizationMethod(BinarizationMethod binarizationMethod) { - BlackWhiteOptions::m_binarizationMethod = binarizationMethod; -} - BinarizationMethod BlackWhiteOptions::parseBinarizationMethod(const QString& str) { if (str == "wolf") { return WOLF; @@ -157,31 +93,6 @@ QString BlackWhiteOptions::formatBinarizationMethod(BinarizationMethod type) { return str; } -int BlackWhiteOptions::thresholdAdjustment() const { - return m_thresholdAdjustment; -} - -void BlackWhiteOptions::setThresholdAdjustment(int val) { - m_thresholdAdjustment = val; -} - -bool BlackWhiteOptions::normalizeIllumination() const { - return m_normalizeIllumination; -} - -void BlackWhiteOptions::setNormalizeIllumination(bool val) { - m_normalizeIllumination = val; -} - -const BlackWhiteOptions::ColorSegmenterOptions& BlackWhiteOptions::getColorSegmenterOptions() const { - return m_colorSegmenterOptions; -} - -void BlackWhiteOptions::setColorSegmenterOptions( - const BlackWhiteOptions::ColorSegmenterOptions& colorSegmenterOptions) { - BlackWhiteOptions::m_colorSegmenterOptions = colorSegmenterOptions; -} - /*=============================== BlackWhiteOptions::ColorSegmenterOptions ==================================*/ BlackWhiteOptions::ColorSegmenterOptions::ColorSegmenterOptions() @@ -218,45 +129,4 @@ bool BlackWhiteOptions::ColorSegmenterOptions::operator==(const BlackWhiteOption bool BlackWhiteOptions::ColorSegmenterOptions::operator!=(const BlackWhiteOptions::ColorSegmenterOptions& other) const { return !(*this == other); } - -bool BlackWhiteOptions::ColorSegmenterOptions::isEnabled() const { - return m_isEnabled; -} - -void BlackWhiteOptions::ColorSegmenterOptions::setEnabled(bool enabled) { - ColorSegmenterOptions::m_isEnabled = enabled; -} - -int BlackWhiteOptions::ColorSegmenterOptions::getNoiseReduction() const { - return m_noiseReduction; -} - -void BlackWhiteOptions::ColorSegmenterOptions::setNoiseReduction(int noiseReduction) { - ColorSegmenterOptions::m_noiseReduction = noiseReduction; -} - -int BlackWhiteOptions::ColorSegmenterOptions::getRedThresholdAdjustment() const { - return m_redThresholdAdjustment; -} - -void BlackWhiteOptions::ColorSegmenterOptions::setRedThresholdAdjustment(int redThresholdAdjustment) { - ColorSegmenterOptions::m_redThresholdAdjustment = redThresholdAdjustment; -} - -int BlackWhiteOptions::ColorSegmenterOptions::getGreenThresholdAdjustment() const { - return m_greenThresholdAdjustment; -} - -void BlackWhiteOptions::ColorSegmenterOptions::setGreenThresholdAdjustment(int greenThresholdAdjustment) { - ColorSegmenterOptions::m_greenThresholdAdjustment = greenThresholdAdjustment; -} - -int BlackWhiteOptions::ColorSegmenterOptions::getBlueThresholdAdjustment() const { - return m_blueThresholdAdjustment; -} - -void BlackWhiteOptions::ColorSegmenterOptions::setBlueThresholdAdjustment(int blueThresholdAdjustment) { - ColorSegmenterOptions::m_blueThresholdAdjustment = blueThresholdAdjustment; -} - } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/BlackWhiteOptions.h b/src/core/filters/output/BlackWhiteOptions.h index 449d9b0ff..90ba63883 100644 --- a/src/core/filters/output/BlackWhiteOptions.h +++ b/src/core/filters/output/BlackWhiteOptions.h @@ -126,5 +126,135 @@ class BlackWhiteOptions { BinarizationMethod m_binarizationMethod; ColorSegmenterOptions m_colorSegmenterOptions; }; + + +inline bool BlackWhiteOptions::isSavitzkyGolaySmoothingEnabled() const { + return m_savitzkyGolaySmoothingEnabled; +} + +inline void BlackWhiteOptions::setSavitzkyGolaySmoothingEnabled(bool savitzkyGolaySmoothingEnabled) { + BlackWhiteOptions::m_savitzkyGolaySmoothingEnabled = savitzkyGolaySmoothingEnabled; +} + +inline bool BlackWhiteOptions::isMorphologicalSmoothingEnabled() const { + return m_morphologicalSmoothingEnabled; +} + +inline void BlackWhiteOptions::setMorphologicalSmoothingEnabled(bool morphologicalSmoothingEnabled) { + BlackWhiteOptions::m_morphologicalSmoothingEnabled = morphologicalSmoothingEnabled; +} + +inline int BlackWhiteOptions::getWindowSize() const { + return m_windowSize; +} + +inline void BlackWhiteOptions::setWindowSize(int windowSize) { + BlackWhiteOptions::m_windowSize = windowSize; +} + +inline double BlackWhiteOptions::getSauvolaCoef() const { + return m_sauvolaCoef; +} + +inline void BlackWhiteOptions::setSauvolaCoef(double sauvolaCoef) { + BlackWhiteOptions::m_sauvolaCoef = sauvolaCoef; +} + +inline int BlackWhiteOptions::getWolfLowerBound() const { + return m_wolfLowerBound; +} + +inline void BlackWhiteOptions::setWolfLowerBound(int wolfLowerBound) { + BlackWhiteOptions::m_wolfLowerBound = wolfLowerBound; +} + +inline int BlackWhiteOptions::getWolfUpperBound() const { + return m_wolfUpperBound; +} + +inline void BlackWhiteOptions::setWolfUpperBound(int wolfUpperBound) { + BlackWhiteOptions::m_wolfUpperBound = wolfUpperBound; +} + +inline double BlackWhiteOptions::getWolfCoef() const { + return m_wolfCoef; +} + +inline void BlackWhiteOptions::setWolfCoef(double wolfCoef) { + BlackWhiteOptions::m_wolfCoef = wolfCoef; +} + +inline BinarizationMethod BlackWhiteOptions::getBinarizationMethod() const { + return m_binarizationMethod; +} + +inline void BlackWhiteOptions::setBinarizationMethod(BinarizationMethod binarizationMethod) { + BlackWhiteOptions::m_binarizationMethod = binarizationMethod; +} + +inline int BlackWhiteOptions::thresholdAdjustment() const { + return m_thresholdAdjustment; +} + +inline void BlackWhiteOptions::setThresholdAdjustment(int val) { + m_thresholdAdjustment = val; +} + +inline bool BlackWhiteOptions::normalizeIllumination() const { + return m_normalizeIllumination; +} + +inline void BlackWhiteOptions::setNormalizeIllumination(bool val) { + m_normalizeIllumination = val; +} + +inline const BlackWhiteOptions::ColorSegmenterOptions& BlackWhiteOptions::getColorSegmenterOptions() const { + return m_colorSegmenterOptions; +} + +inline void BlackWhiteOptions::setColorSegmenterOptions( + const BlackWhiteOptions::ColorSegmenterOptions& colorSegmenterOptions) { + BlackWhiteOptions::m_colorSegmenterOptions = colorSegmenterOptions; +} + +inline bool BlackWhiteOptions::ColorSegmenterOptions::isEnabled() const { + return m_isEnabled; +} + +inline void BlackWhiteOptions::ColorSegmenterOptions::setEnabled(bool enabled) { + ColorSegmenterOptions::m_isEnabled = enabled; +} + +inline int BlackWhiteOptions::ColorSegmenterOptions::getNoiseReduction() const { + return m_noiseReduction; +} + +inline void BlackWhiteOptions::ColorSegmenterOptions::setNoiseReduction(int noiseReduction) { + ColorSegmenterOptions::m_noiseReduction = noiseReduction; +} + +inline int BlackWhiteOptions::ColorSegmenterOptions::getRedThresholdAdjustment() const { + return m_redThresholdAdjustment; +} + +inline void BlackWhiteOptions::ColorSegmenterOptions::setRedThresholdAdjustment(int redThresholdAdjustment) { + ColorSegmenterOptions::m_redThresholdAdjustment = redThresholdAdjustment; +} + +inline int BlackWhiteOptions::ColorSegmenterOptions::getGreenThresholdAdjustment() const { + return m_greenThresholdAdjustment; +} + +inline void BlackWhiteOptions::ColorSegmenterOptions::setGreenThresholdAdjustment(int greenThresholdAdjustment) { + ColorSegmenterOptions::m_greenThresholdAdjustment = greenThresholdAdjustment; +} + +inline int BlackWhiteOptions::ColorSegmenterOptions::getBlueThresholdAdjustment() const { + return m_blueThresholdAdjustment; +} + +inline void BlackWhiteOptions::ColorSegmenterOptions::setBlueThresholdAdjustment(int blueThresholdAdjustment) { + ColorSegmenterOptions::m_blueThresholdAdjustment = blueThresholdAdjustment; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_BLACKWHITEOPTIONS_H_ diff --git a/src/core/filters/output/CMakeLists.txt b/src/core/filters/output/CMakeLists.txt index 495ec7ecc..a19e41e78 100644 --- a/src/core/filters/output/CMakeLists.txt +++ b/src/core/filters/output/CMakeLists.txt @@ -68,7 +68,7 @@ set(sources OutputImageBuilder.cpp OutputImageBuilder.h ForegroundType.h) add_library(output STATIC ${sources} ${ui_files}) -target_link_libraries(output PUBLIC core interaction PRIVATE dewarping zones) +target_link_libraries(output PUBLIC core PRIVATE dewarping) target_include_directories(output PRIVATE "$") translation_sources(scantailor ${sources} ${ui_files}) \ No newline at end of file diff --git a/src/core/filters/output/CacheDrivenTask.cpp b/src/core/filters/output/CacheDrivenTask.cpp index 21e2f08df..d0f503378 100644 --- a/src/core/filters/output/CacheDrivenTask.cpp +++ b/src/core/filters/output/CacheDrivenTask.cpp @@ -22,7 +22,7 @@ #include "core/ThumbnailCollector.h" namespace output { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr settings, const OutputFileNameGenerator& outFileNameGen) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr settings, const OutputFileNameGenerator& outFileNameGen) : m_settings(std::move(settings)), m_outFileNameGen(outFileNameGen) {} CacheDrivenTask::~CacheDrivenTask() = default; @@ -32,16 +32,17 @@ void CacheDrivenTask::process(const PageInfo& pageInfo, const ImageTransformation& xform, const QPolygonF& contentRectPhys) { if (auto* thumbCol = dynamic_cast(collector)) { + const QFileInfo sourceFileInfo(pageInfo.id().imageId().filePath()); const QString outFilePath(m_outFileNameGen.filePathFor(pageInfo.id())); const QFileInfo outFileInfo(outFilePath); const QString foregroundDir(Utils::foregroundDir(m_outFileNameGen.outDir())); const QString backgroundDir(Utils::backgroundDir(m_outFileNameGen.outDir())); const QString originalBackgroundDir(Utils::originalBackgroundDir(m_outFileNameGen.outDir())); const QString foregroundFilePath(QDir(foregroundDir).absoluteFilePath(outFileInfo.fileName())); - const QString backgroundFilePath(QDir(backgroundDir).absoluteFilePath(outFileInfo.fileName())); - const QString originalBackgroundFilePath(QDir(originalBackgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo foregroundFileInfo(foregroundFilePath); + const QString backgroundFilePath(QDir(backgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo backgroundFileInfo(backgroundFilePath); + const QString originalBackgroundFilePath(QDir(originalBackgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo originalBackgroundFileInfo(originalBackgroundFilePath); const Params params(m_settings->getParams(pageInfo.id())); @@ -84,12 +85,15 @@ void CacheDrivenTask::process(const PageInfo& pageInfo, break; } + if (!storedOutputParams->sourceFileParams().matches(OutputFileParams(sourceFileInfo))) { + needReprocess = true; + break; + } if (!renderParams.splitOutput()) { if (!outFileInfo.exists()) { needReprocess = true; break; } - if (!storedOutputParams->outputFileParams().matches(OutputFileParams(outFileInfo))) { needReprocess = true; break; @@ -104,7 +108,6 @@ void CacheDrivenTask::process(const PageInfo& pageInfo, needReprocess = true; break; } - if (renderParams.originalBackground()) { if (!originalBackgroundFileInfo.exists()) { needReprocess = true; diff --git a/src/core/filters/output/CacheDrivenTask.h b/src/core/filters/output/CacheDrivenTask.h index 90b088dbb..df5ed35fb 100644 --- a/src/core/filters/output/CacheDrivenTask.h +++ b/src/core/filters/output/CacheDrivenTask.h @@ -4,10 +4,10 @@ #ifndef SCANTAILOR_OUTPUT_CACHEDRIVENTASK_H_ #define SCANTAILOR_OUTPUT_CACHEDRIVENTASK_H_ +#include + #include "NonCopyable.h" #include "OutputFileNameGenerator.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QPolygonF; class PageInfo; @@ -17,13 +17,13 @@ class ImageTransformation; namespace output { class Settings; -class CacheDrivenTask : public ref_countable { +class CacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr settings, const OutputFileNameGenerator& outFileNameGen); + CacheDrivenTask(std::shared_ptr settings, const OutputFileNameGenerator& outFileNameGen); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector, @@ -31,7 +31,7 @@ class CacheDrivenTask : public ref_countable { const QPolygonF& contentRectPhys); private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; OutputFileNameGenerator m_outFileNameGen; }; } // namespace output diff --git a/src/core/filters/output/ChangeDewarpingDialog.h b/src/core/filters/output/ChangeDewarpingDialog.h index 56537fa82..2b98e563c 100644 --- a/src/core/filters/output/ChangeDewarpingDialog.h +++ b/src/core/filters/output/ChangeDewarpingDialog.h @@ -7,12 +7,12 @@ #include #include #include +#include #include #include "DewarpingOptions.h" #include "PageId.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ChangeDewarpingDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/output/ChangeDpiDialog.h b/src/core/filters/output/ChangeDpiDialog.h index 8c8c83cbf..bba5bfa6f 100644 --- a/src/core/filters/output/ChangeDpiDialog.h +++ b/src/core/filters/output/ChangeDpiDialog.h @@ -7,11 +7,11 @@ #include #include #include +#include #include #include "PageId.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ChangeDpiDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/output/ColorCommonOptions.cpp b/src/core/filters/output/ColorCommonOptions.cpp index 0c2f083c5..1b77084a0 100644 --- a/src/core/filters/output/ColorCommonOptions.cpp +++ b/src/core/filters/output/ColorCommonOptions.cpp @@ -36,14 +36,6 @@ bool ColorCommonOptions::operator!=(const ColorCommonOptions& other) const { return !(*this == other); } -FillingColor ColorCommonOptions::getFillingColor() const { - return m_fillingColor; -} - -void ColorCommonOptions::setFillingColor(FillingColor fillingColor) { - ColorCommonOptions::m_fillingColor = fillingColor; -} - FillingColor ColorCommonOptions::parseFillingColor(const QString& str) { if (str == "white") { return FILL_WHITE; @@ -65,38 +57,6 @@ QString ColorCommonOptions::formatFillingColor(FillingColor type) { return str; } -void ColorCommonOptions::setFillMargins(bool val) { - m_fillMargins = val; -} - -bool ColorCommonOptions::fillMargins() const { - return m_fillMargins; -} - -bool ColorCommonOptions::normalizeIllumination() const { - return m_normalizeIllumination; -} - -void ColorCommonOptions::setNormalizeIllumination(bool val) { - m_normalizeIllumination = val; -} - -const ColorCommonOptions::PosterizationOptions& ColorCommonOptions::getPosterizationOptions() const { - return m_posterizationOptions; -} - -void ColorCommonOptions::setPosterizationOptions(const ColorCommonOptions::PosterizationOptions& posterizationOptions) { - ColorCommonOptions::m_posterizationOptions = posterizationOptions; -} - -bool ColorCommonOptions::fillOffcut() const { - return m_fillOffcut; -} - -void ColorCommonOptions::setFillOffcut(bool fillOffcut) { - m_fillOffcut = fillOffcut; -} - /*=============================== ColorCommonOptions::PosterizationOptions ==================================*/ ColorCommonOptions::PosterizationOptions::PosterizationOptions() @@ -126,36 +86,4 @@ bool ColorCommonOptions::PosterizationOptions::operator==(const ColorCommonOptio bool ColorCommonOptions::PosterizationOptions::operator!=(const ColorCommonOptions::PosterizationOptions& other) const { return !(*this == other); } - -bool ColorCommonOptions::PosterizationOptions::isEnabled() const { - return m_isEnabled; -} - -void ColorCommonOptions::PosterizationOptions::setEnabled(bool enabled) { - PosterizationOptions::m_isEnabled = enabled; -} - -int ColorCommonOptions::PosterizationOptions::getLevel() const { - return m_level; -} - -void ColorCommonOptions::PosterizationOptions::setLevel(int level) { - PosterizationOptions::m_level = level; -} - -bool ColorCommonOptions::PosterizationOptions::isNormalizationEnabled() const { - return m_isNormalizationEnabled; -} - -void ColorCommonOptions::PosterizationOptions::setNormalizationEnabled(bool normalizationEnabled) { - PosterizationOptions::m_isNormalizationEnabled = normalizationEnabled; -} - -bool ColorCommonOptions::PosterizationOptions::isForceBlackAndWhite() const { - return m_forceBlackAndWhite; -} - -void ColorCommonOptions::PosterizationOptions::setForceBlackAndWhite(bool forceBlackAndWhite) { - PosterizationOptions::m_forceBlackAndWhite = forceBlackAndWhite; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/ColorCommonOptions.h b/src/core/filters/output/ColorCommonOptions.h index 9745caa12..7e181189d 100644 --- a/src/core/filters/output/ColorCommonOptions.h +++ b/src/core/filters/output/ColorCommonOptions.h @@ -92,5 +92,79 @@ class ColorCommonOptions { FillingColor m_fillingColor; PosterizationOptions m_posterizationOptions; }; + + +inline FillingColor ColorCommonOptions::getFillingColor() const { + return m_fillingColor; +} + +inline void ColorCommonOptions::setFillingColor(FillingColor fillingColor) { + ColorCommonOptions::m_fillingColor = fillingColor; +} + +inline void ColorCommonOptions::setFillMargins(bool val) { + m_fillMargins = val; +} + +inline bool ColorCommonOptions::fillMargins() const { + return m_fillMargins; +} + +inline bool ColorCommonOptions::normalizeIllumination() const { + return m_normalizeIllumination; +} + +inline void ColorCommonOptions::setNormalizeIllumination(bool val) { + m_normalizeIllumination = val; +} + +inline const ColorCommonOptions::PosterizationOptions& ColorCommonOptions::getPosterizationOptions() const { + return m_posterizationOptions; +} + +inline void ColorCommonOptions::setPosterizationOptions( + const ColorCommonOptions::PosterizationOptions& posterizationOptions) { + ColorCommonOptions::m_posterizationOptions = posterizationOptions; +} + +inline bool ColorCommonOptions::fillOffcut() const { + return m_fillOffcut; +} + +inline void ColorCommonOptions::setFillOffcut(bool fillOffcut) { + m_fillOffcut = fillOffcut; +} + +inline bool ColorCommonOptions::PosterizationOptions::isEnabled() const { + return m_isEnabled; +} + +inline void ColorCommonOptions::PosterizationOptions::setEnabled(bool enabled) { + PosterizationOptions::m_isEnabled = enabled; +} + +inline int ColorCommonOptions::PosterizationOptions::getLevel() const { + return m_level; +} + +inline void ColorCommonOptions::PosterizationOptions::setLevel(int level) { + PosterizationOptions::m_level = level; +} + +inline bool ColorCommonOptions::PosterizationOptions::isNormalizationEnabled() const { + return m_isNormalizationEnabled; +} + +inline void ColorCommonOptions::PosterizationOptions::setNormalizationEnabled(bool normalizationEnabled) { + PosterizationOptions::m_isNormalizationEnabled = normalizationEnabled; +} + +inline bool ColorCommonOptions::PosterizationOptions::isForceBlackAndWhite() const { + return m_forceBlackAndWhite; +} + +inline void ColorCommonOptions::PosterizationOptions::setForceBlackAndWhite(bool forceBlackAndWhite) { + PosterizationOptions::m_forceBlackAndWhite = forceBlackAndWhite; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_COLORCOMMONOPTIONS_H_ diff --git a/src/core/filters/output/ColorParams.cpp b/src/core/filters/output/ColorParams.cpp index 591ec5827..a55c945f9 100644 --- a/src/core/filters/output/ColorParams.cpp +++ b/src/core/filters/output/ColorParams.cpp @@ -46,28 +46,4 @@ QString ColorParams::formatColorMode(const ColorMode mode) { } return QString::fromLatin1(str); } - -ColorMode ColorParams::colorMode() const { - return m_colorMode; -} - -void ColorParams::setColorMode(ColorMode mode) { - m_colorMode = mode; -} - -const ColorCommonOptions& ColorParams::colorCommonOptions() const { - return m_colorCommonOptions; -} - -void ColorParams::setColorCommonOptions(const ColorCommonOptions& opt) { - m_colorCommonOptions = opt; -} - -const BlackWhiteOptions& ColorParams::blackWhiteOptions() const { - return m_bwOptions; -} - -void ColorParams::setBlackWhiteOptions(const BlackWhiteOptions& opt) { - m_bwOptions = opt; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/ColorParams.h b/src/core/filters/output/ColorParams.h index 8bfd5b2f1..56fe32f53 100644 --- a/src/core/filters/output/ColorParams.h +++ b/src/core/filters/output/ColorParams.h @@ -39,10 +39,34 @@ class ColorParams { static QString formatColorMode(ColorMode mode); - ColorMode m_colorMode; ColorCommonOptions m_colorCommonOptions; BlackWhiteOptions m_bwOptions; }; + + +inline ColorMode ColorParams::colorMode() const { + return m_colorMode; +} + +inline void ColorParams::setColorMode(ColorMode mode) { + m_colorMode = mode; +} + +inline const ColorCommonOptions& ColorParams::colorCommonOptions() const { + return m_colorCommonOptions; +} + +inline void ColorParams::setColorCommonOptions(const ColorCommonOptions& opt) { + m_colorCommonOptions = opt; +} + +inline const BlackWhiteOptions& ColorParams::blackWhiteOptions() const { + return m_bwOptions; +} + +inline void ColorParams::setBlackWhiteOptions(const BlackWhiteOptions& opt) { + m_bwOptions = opt; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_COLORPARAMS_H_ diff --git a/src/core/filters/output/ColorPickupInteraction.cpp b/src/core/filters/output/ColorPickupInteraction.cpp index 08c5b06ff..1b7f36441 100644 --- a/src/core/filters/output/ColorPickupInteraction.cpp +++ b/src/core/filters/output/ColorPickupInteraction.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "ImageViewBase.h" #include "ScopedIncDec.h" @@ -14,12 +15,21 @@ namespace output { ColorPickupInteraction::ColorPickupInteraction(EditableZoneSet& zones, ZoneInteractionContext& context) : m_zones(zones), m_context(context), m_dontDrawCircle(0) { m_interaction.setInteractionStatusTip(tr("Click on an area to pick up its color, or ESC to cancel.")); + + m_cancelShortcut = std::make_unique(Qt::Key_Escape, &m_context.imageView()); + m_cancelShortcut->setAutoRepeat(false); + m_cancelShortcut->setEnabled(false); + QObject::connect(m_cancelShortcut.get(), &QShortcut::activated, &m_context.imageView(), + std::bind(&ColorPickupInteraction::switchToDefaultInteraction, this)); } +ColorPickupInteraction::~ColorPickupInteraction() = default; + void ColorPickupInteraction::startInteraction(const EditableZoneSet::Zone& zone, InteractionState& interaction) { using FCP = FillColorProperty; m_fillColorProp = zone.properties()->locateOrCreate(); interaction.capture(m_interaction); + m_cancelShortcut->setEnabled(true); } bool ColorPickupInteraction::isActive(const InteractionState& interaction) const { @@ -53,13 +63,6 @@ void ColorPickupInteraction::onMouseMoveEvent(QMouseEvent* event, InteractionSta m_context.imageView().update(); } -void ColorPickupInteraction::onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) { - if (event->key() == Qt::Key_Escape) { - event->accept(); - switchToDefaultInteraction(); - } -} - void ColorPickupInteraction::takeColor() { const ScopedIncDec guard(m_dontDrawCircle); @@ -123,6 +126,7 @@ QRect ColorPickupInteraction::targetBoundingRect() const { void ColorPickupInteraction::switchToDefaultInteraction() { m_fillColorProp.reset(); m_interaction.release(); + m_cancelShortcut->setEnabled(false); makePeerPreceeder(*m_context.createDefaultInteraction()); unlink(); m_context.imageView().update(); diff --git a/src/core/filters/output/ColorPickupInteraction.h b/src/core/filters/output/ColorPickupInteraction.h index 6b78f391f..ec08b5938 100644 --- a/src/core/filters/output/ColorPickupInteraction.h +++ b/src/core/filters/output/ColorPickupInteraction.h @@ -7,14 +7,15 @@ #include #include #include +#include #include "EditableZoneSet.h" #include "FillColorProperty.h" #include "InteractionHandler.h" #include "InteractionState.h" -#include "intrusive_ptr.h" class ZoneInteractionContext; +class QShortcut; namespace output { class ColorPickupInteraction : public InteractionHandler { @@ -22,6 +23,8 @@ class ColorPickupInteraction : public InteractionHandler { public: ColorPickupInteraction(EditableZoneSet& zones, ZoneInteractionContext& context); + ~ColorPickupInteraction() override; + void startInteraction(const EditableZoneSet::Zone& zone, InteractionState& interaction); bool isActive(const InteractionState& interaction) const; @@ -33,8 +36,6 @@ class ColorPickupInteraction : public InteractionHandler { void onMouseMoveEvent(QMouseEvent* event, InteractionState& interaction) override; - void onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) override; - private: void takeColor(); @@ -49,8 +50,9 @@ class ColorPickupInteraction : public InteractionHandler { EditableZoneSet& m_zones; ZoneInteractionContext& m_context; InteractionState::Captor m_interaction; - intrusive_ptr m_fillColorProp; + std::shared_ptr m_fillColorProp; int m_dontDrawCircle; + std::unique_ptr m_cancelShortcut; static const uint32_t m_sBitMixingLUT[3][256]; static const uint32_t m_sBitUnmixingLUT[3][256]; diff --git a/src/core/filters/output/DepthPerception.cpp b/src/core/filters/output/DepthPerception.cpp index 602b7d0e7..a8c51caa2 100644 --- a/src/core/filters/output/DepthPerception.cpp +++ b/src/core/filters/output/DepthPerception.cpp @@ -29,20 +29,4 @@ QString DepthPerception::toString() const { void DepthPerception::setValue(double value) { m_value = qBound(minValue(), value, maxValue()); } - -double DepthPerception::value() const { - return m_value; -} - -double DepthPerception::minValue() { - return 1.0; -} - -double DepthPerception::defaultValue() { - return 2.0; -} - -double DepthPerception::maxValue() { - return 3.0; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/DepthPerception.h b/src/core/filters/output/DepthPerception.h index d56774f3a..9aa399576 100644 --- a/src/core/filters/output/DepthPerception.h +++ b/src/core/filters/output/DepthPerception.h @@ -24,14 +24,30 @@ class DepthPerception { double value() const; - static double minValue(); + static constexpr double minValue(); - static double defaultValue(); + static constexpr double defaultValue(); - static double maxValue(); + static constexpr double maxValue(); private: double m_value; }; + +inline double DepthPerception::value() const { + return m_value; +} + +constexpr double DepthPerception::minValue() { + return 1.0; +} + +constexpr double DepthPerception::defaultValue() { + return 2.0; +} + +constexpr double DepthPerception::maxValue() { + return 3.0; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_DEPTHPERCEPTION_H_ diff --git a/src/core/filters/output/DespeckleState.cpp b/src/core/filters/output/DespeckleState.cpp index 9c2bbb5e5..da6b12517 100644 --- a/src/core/filters/output/DespeckleState.cpp +++ b/src/core/filters/output/DespeckleState.cpp @@ -110,8 +110,4 @@ BinaryImage DespeckleState::extractBW(const QImage& mixed) { } return result; } - -double DespeckleState::level() const { - return m_despeckleLevel; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/DespeckleState.h b/src/core/filters/output/DespeckleState.h index 5fc9e51f7..bb4506ade 100644 --- a/src/core/filters/output/DespeckleState.h +++ b/src/core/filters/output/DespeckleState.h @@ -68,5 +68,10 @@ class DespeckleState { */ double m_despeckleLevel; }; + + +inline double DespeckleState::level() const { + return m_despeckleLevel; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_DESPECKLESTATE_H_ diff --git a/src/core/filters/output/DespeckleView.cpp b/src/core/filters/output/DespeckleView.cpp index 8f71e3ca2..a2363be48 100644 --- a/src/core/filters/output/DespeckleView.cpp +++ b/src/core/filters/output/DespeckleView.cpp @@ -28,7 +28,7 @@ class DespeckleView::TaskCancelException : public std::exception { }; -class DespeckleView::TaskCancelHandle : public TaskStatus, public ref_countable { +class DespeckleView::TaskCancelHandle : public TaskStatus { public: void cancel() override; @@ -45,7 +45,7 @@ class DespeckleView::DespeckleTask : public AbstractCommand cancelHandle, + std::shared_ptr cancelHandle, double level, bool debug); @@ -54,7 +54,7 @@ class DespeckleView::DespeckleTask : public AbstractCommand m_owner; DespeckleState m_despeckleState; - intrusive_ptr m_cancelHandle; + std::shared_ptr m_cancelHandle; std::unique_ptr m_dbg; double m_despeckleLevel; }; @@ -63,7 +63,7 @@ class DespeckleView::DespeckleTask : public AbstractCommand { public: DespeckleResult(QPointer owner, - intrusive_ptr cancelHandle, + std::shared_ptr cancelHandle, const DespeckleState& despeckleState, const DespeckleVisualization& visualization, std::unique_ptr debugImages); @@ -73,7 +73,7 @@ class DespeckleView::DespeckleResult : public AbstractCommand { private: QPointer m_owner; - intrusive_ptr m_cancelHandle; + std::shared_ptr m_cancelHandle; std::unique_ptr m_dbg; DespeckleState m_despeckleState; DespeckleVisualization m_visualization; @@ -149,7 +149,7 @@ void DespeckleView::initiateDespeckling(const AnimationAction animAction) { // Note that we are getting rid of m_initialSpeckles, // as we wouldn't need it any more. - const auto task = make_intrusive(this, m_despeckleState, m_cancelHandle, m_despeckleLevel, m_debug); + const auto task = std::make_shared(this, m_despeckleState, m_cancelHandle, m_despeckleLevel, m_debug); ImageViewBase::backgroundExecutor().enqueueTask(task); } @@ -201,7 +201,7 @@ void DespeckleView::removeImageViewWidget() { DespeckleView::DespeckleTask::DespeckleTask(DespeckleView* owner, const DespeckleState& despeckleState, - intrusive_ptr cancelHandle, + std::shared_ptr cancelHandle, const double level, const bool debug) : m_owner(owner), @@ -224,7 +224,8 @@ BackgroundExecutor::TaskResultPtr DespeckleView::DespeckleTask::operator()() { DespeckleVisualization visualization(m_despeckleState.visualize()); m_cancelHandle->throwIfCancelled(); - return make_intrusive(m_owner, m_cancelHandle, m_despeckleState, visualization, std::move(m_dbg)); + return std::make_shared(m_owner, m_cancelHandle, m_despeckleState, visualization, + std::move(m_dbg)); } catch (const TaskCancelException&) { return nullptr; } @@ -233,7 +234,7 @@ BackgroundExecutor::TaskResultPtr DespeckleView::DespeckleTask::operator()() { /*======================== DespeckleResult ===========================*/ DespeckleView::DespeckleResult::DespeckleResult(QPointer owner, - intrusive_ptr cancelHandle, + std::shared_ptr cancelHandle, const DespeckleState& despeckleState, const DespeckleVisualization& visualization, std::unique_ptr debugImages) diff --git a/src/core/filters/output/DespeckleView.h b/src/core/filters/output/DespeckleView.h index 43020cef4..b2c701946 100644 --- a/src/core/filters/output/DespeckleView.h +++ b/src/core/filters/output/DespeckleView.h @@ -9,11 +9,11 @@ #include #include +#include #include "DespeckleLevel.h" #include "DespeckleState.h" #include "Dpi.h" -#include "intrusive_ptr.h" class DebugImages; class ProcessingIndicationWidget; @@ -68,7 +68,7 @@ class DespeckleView : public QStackedWidget { void removeImageViewWidget(); DespeckleState m_despeckleState; - intrusive_ptr m_cancelHandle; + std::shared_ptr m_cancelHandle; ProcessingIndicationWidget* m_processingIndicator; double m_despeckleLevel; bool m_debug; diff --git a/src/core/filters/output/DespeckleVisualization.cpp b/src/core/filters/output/DespeckleVisualization.cpp index e6bf34fe6..d579e034f 100644 --- a/src/core/filters/output/DespeckleVisualization.cpp +++ b/src/core/filters/output/DespeckleVisualization.cpp @@ -41,7 +41,7 @@ void DespeckleVisualization::colorizeSpeckles(QImage& image, const imageproc::Bi const uint32_t* sedmLine = sedm.data(); const int sedmStride = sedm.stride(); - const float radius = static_cast(15.0 * std::max(dpi.horizontal(), dpi.vertical()) / 600); + const float radius = static_cast(45.0 * std::max(dpi.horizontal(), dpi.vertical()) / 600); const float sqRadius = radius * radius; for (int y = 0; y < h; ++y) { @@ -56,9 +56,10 @@ void DespeckleVisualization::colorizeSpeckles(QImage& image, const imageproc::Bi continue; } - const float alphaUpperBound = 0.8f; + const float alphaUpperBound = 0.7f; + const float noSpecklesOverlayAlpha = 0.3f; const float scale = alphaUpperBound / sqRadius; - const float alpha = alphaUpperBound - scale * sqDist; + const float alpha = (sqDist == SEDM::INF_DIST) ? noSpecklesOverlayAlpha : alphaUpperBound - scale * sqDist; if (alpha > 0) { const float alpha2 = 1.0f - alpha; const float overlayR = 255; @@ -78,12 +79,4 @@ void DespeckleVisualization::colorizeSpeckles(QImage& image, const imageproc::Bi bool DespeckleVisualization::isNull() const { return m_image.isNull(); } - -const QImage& DespeckleVisualization::image() const { - return m_image; -} - -const QImage& DespeckleVisualization::downscaledImage() const { - return m_downscaledImage; -} -} // namespace output \ No newline at end of file +} // namespace output diff --git a/src/core/filters/output/DespeckleVisualization.h b/src/core/filters/output/DespeckleVisualization.h index ab97c3d1d..6e63bde6e 100644 --- a/src/core/filters/output/DespeckleVisualization.h +++ b/src/core/filters/output/DespeckleVisualization.h @@ -39,9 +39,17 @@ class DespeckleVisualization { private: static void colorizeSpeckles(QImage& image, const imageproc::BinaryImage& speckles, const Dpi& dpi); - QImage m_image; QImage m_downscaledImage; }; + + +inline const QImage& DespeckleVisualization::image() const { + return m_image; +} + +inline const QImage& DespeckleVisualization::downscaledImage() const { + return m_downscaledImage; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_DESPECKLEVISUALIZATION_H_ diff --git a/src/core/filters/output/DewarpingOptions.cpp b/src/core/filters/output/DewarpingOptions.cpp index fa66712e8..46c9c8d08 100644 --- a/src/core/filters/output/DewarpingOptions.cpp +++ b/src/core/filters/output/DewarpingOptions.cpp @@ -34,30 +34,6 @@ bool DewarpingOptions::operator!=(const DewarpingOptions& other) const { return !(*this == other); } -void DewarpingOptions::setDewarpingMode(DewarpingMode mode) { - DewarpingOptions::m_mode = mode; -} - -void DewarpingOptions::setPostDeskew(bool postDeskew) { - DewarpingOptions::m_needPostDeskew = postDeskew; -} - -bool DewarpingOptions::needPostDeskew() const { - return m_needPostDeskew; -} - -double DewarpingOptions::getPostDeskewAngle() const { - return m_postDeskewAngle; -} - -void DewarpingOptions::setPostDeskewAngle(double postDeskewAngle) { - m_postDeskewAngle = postDeskewAngle; -} - -DewarpingMode DewarpingOptions::dewarpingMode() const { - return m_mode; -} - DewarpingMode DewarpingOptions::parseDewarpingMode(const QString& str) { if (str == "auto") { return AUTO; diff --git a/src/core/filters/output/DewarpingOptions.h b/src/core/filters/output/DewarpingOptions.h index 5825a3e98..3a6828fe2 100644 --- a/src/core/filters/output/DewarpingOptions.h +++ b/src/core/filters/output/DewarpingOptions.h @@ -43,5 +43,30 @@ class DewarpingOptions { bool m_needPostDeskew; double m_postDeskewAngle; }; + + +inline void DewarpingOptions::setDewarpingMode(DewarpingMode mode) { + DewarpingOptions::m_mode = mode; +} + +inline void DewarpingOptions::setPostDeskew(bool postDeskew) { + DewarpingOptions::m_needPostDeskew = postDeskew; +} + +inline bool DewarpingOptions::needPostDeskew() const { + return m_needPostDeskew; +} + +inline double DewarpingOptions::getPostDeskewAngle() const { + return m_postDeskewAngle; +} + +inline void DewarpingOptions::setPostDeskewAngle(double postDeskewAngle) { + m_postDeskewAngle = postDeskewAngle; +} + +inline DewarpingMode DewarpingOptions::dewarpingMode() const { + return m_mode; +} } // namespace output #endif diff --git a/src/core/filters/output/DewarpingView.cpp b/src/core/filters/output/DewarpingView.cpp index f2f7ad280..646977b78 100644 --- a/src/core/filters/output/DewarpingView.cpp +++ b/src/core/filters/output/DewarpingView.cpp @@ -3,13 +3,12 @@ #include "DewarpingView.h" -#include #include #include #include +#include #include -#include #include "ImagePresentation.h" #include "ToLineProjector.h" @@ -34,6 +33,8 @@ DewarpingView::DewarpingView(const QImage& image, m_dewarpingOptions(dewarpingOptions), m_distortionModel(distortionModel), m_depthPerception(depthPerception), + m_topSpline(*this), + m_bottomSpline(*this), m_dragHandler(*this), m_zoomHandler(*this) { setMouseTracking(true); @@ -89,6 +90,12 @@ DewarpingView::DewarpingView(const QImage& image, rootInteractionHandler().makeLastFollower(*this); rootInteractionHandler().makeLastFollower(m_dragHandler); rootInteractionHandler().makeLastFollower(m_zoomHandler); + + m_removeControlPointShortcut = new QShortcut(Qt::Key_D, this); + QObject::connect(m_removeControlPointShortcut, &QShortcut::activated, [this]() { + m_topSpline.removeControlPointUnderMouse(); + m_bottomSpline.removeControlPointUnderMouse(); + }); } DewarpingView::~DewarpingView() = default; diff --git a/src/core/filters/output/DewarpingView.h b/src/core/filters/output/DewarpingView.h index c50acfa70..7621e4f6d 100644 --- a/src/core/filters/output/DewarpingView.h +++ b/src/core/filters/output/DewarpingView.h @@ -22,6 +22,8 @@ #include "Settings.h" #include "ZoomHandler.h" +class QShortcut; + namespace output { class DewarpingView : public ImageViewBase, protected InteractionHandler { Q_OBJECT @@ -78,6 +80,7 @@ class DewarpingView : public ImageViewBase, protected InteractionHandler { InteractiveXSpline m_bottomSpline; DragHandler m_dragHandler; ZoomHandler m_zoomHandler; + QShortcut* m_removeControlPointShortcut; }; } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_DEWARPINGVIEW_H_ diff --git a/src/core/filters/output/FillColorProperty.cpp b/src/core/filters/output/FillColorProperty.cpp index 00a30e12b..eebef1dfe 100644 --- a/src/core/filters/output/FillColorProperty.cpp +++ b/src/core/filters/output/FillColorProperty.cpp @@ -16,8 +16,8 @@ void FillColorProperty::registerIn(PropertyFactory& factory) { factory.registerProperty(m_propertyName, &FillColorProperty::construct); } -intrusive_ptr FillColorProperty::clone() const { - return make_intrusive(*this); +std::shared_ptr FillColorProperty::clone() const { + return std::make_shared(*this); } QDomElement FillColorProperty::toXml(QDomDocument& doc, const QString& name) const { @@ -27,8 +27,8 @@ QDomElement FillColorProperty::toXml(QDomDocument& doc, const QString& name) con return el; } -intrusive_ptr FillColorProperty::construct(const QDomElement& el) { - return make_intrusive(el); +std::shared_ptr FillColorProperty::construct(const QDomElement& el) { + return std::make_shared(el); } QRgb FillColorProperty::rgbFromString(const QString& str) { diff --git a/src/core/filters/output/FillColorProperty.h b/src/core/filters/output/FillColorProperty.h index 21419dce9..482ac5803 100644 --- a/src/core/filters/output/FillColorProperty.h +++ b/src/core/filters/output/FillColorProperty.h @@ -6,9 +6,9 @@ #include #include +#include #include "Property.h" -#include "intrusive_ptr.h" class PropertyFactory; class QDomDocument; @@ -24,7 +24,7 @@ class FillColorProperty : public Property { static void registerIn(PropertyFactory& factory); - intrusive_ptr clone() const override; + std::shared_ptr clone() const override; QDomElement toXml(QDomDocument& doc, const QString& name) const override; @@ -33,7 +33,7 @@ class FillColorProperty : public Property { void setColor(const QColor& color); private: - static intrusive_ptr construct(const QDomElement& el); + static std::shared_ptr construct(const QDomElement& el); static QRgb rgbFromString(const QString& str); diff --git a/src/core/filters/output/FillZoneComparator.cpp b/src/core/filters/output/FillZoneComparator.cpp index fc7294367..085101c99 100644 --- a/src/core/filters/output/FillZoneComparator.cpp +++ b/src/core/filters/output/FillZoneComparator.cpp @@ -12,16 +12,16 @@ using namespace imageproc; namespace output { bool FillZoneComparator::equal(const ZoneSet& lhs, const ZoneSet& rhs) { - ZoneSet::const_iterator lhs_it(lhs.begin()); - ZoneSet::const_iterator rhs_it(rhs.begin()); - const ZoneSet::const_iterator lhs_end(lhs.end()); - const ZoneSet::const_iterator rhs_end(rhs.end()); - for (; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it) { - if (!equal(*lhs_it, *rhs_it)) { + ZoneSet::const_iterator lhsIt(lhs.begin()); + ZoneSet::const_iterator rhsIt(rhs.begin()); + const ZoneSet::const_iterator lhsEnd(lhs.end()); + const ZoneSet::const_iterator rhsEnd(rhs.end()); + for (; lhsIt != lhsEnd && rhsIt != rhsEnd; ++lhsIt, ++rhsIt) { + if (!equal(*lhsIt, *rhsIt)) { return false; } } - return lhs_it == lhs_end && rhs_it == rhs_end; + return lhsIt == lhsEnd && rhsIt == rhsEnd; } bool FillZoneComparator::equal(const Zone& lhs, const Zone& rhs) { diff --git a/src/core/filters/output/FillZoneEditor.cpp b/src/core/filters/output/FillZoneEditor.cpp index cf36517f8..e241071b0 100644 --- a/src/core/filters/output/FillZoneEditor.cpp +++ b/src/core/filters/output/FillZoneEditor.cpp @@ -36,26 +36,25 @@ FillZoneEditor::FillZoneEditor(const QImage& image, const boost::function& origToImage, const boost::function& imageToOrig, const PageId& pageId, - intrusive_ptr settings) - : ImageViewBase(image, downscaledVersion, ImagePresentation(QTransform(), QRectF(image.rect())), OutputMargins()), - m_colorAdapter(colorAdapterFor(image)), - m_context(*this, m_zones), - m_colorPickupInteraction(m_zones, m_context), + std::shared_ptr settings) + : ZoneEditorBase(image, downscaledVersion, ImagePresentation(QTransform(), QRectF(image.rect())), OutputMargins()), m_dragHandler(*this), m_zoomHandler(*this), + m_colorAdapter(colorAdapterFor(image)), + m_colorPickupInteraction(zones(), context()), m_origToImage(origToImage), m_imageToOrig(imageToOrig), m_pageId(pageId), m_settings(std::move(settings)) { - m_zones.setDefaultProperties(m_settings->defaultFillZoneProperties()); + zones().setDefaultProperties(m_settings->defaultFillZoneProperties()); setMouseTracking(true); - m_context.setContextMenuInteractionCreator(boost::bind(&FillZoneEditor::createContextMenuInteraction, this, _1)); + context().setContextMenuInteractionCreator(boost::bind(&FillZoneEditor::createContextMenuInteraction, this, _1)); - connect(&m_zones, SIGNAL(committed()), SLOT(commitZones())); + connect(&zones(), SIGNAL(committed()), SLOT(commitZones())); - makeLastFollower(*m_context.createDefaultInteraction()); + makeLastFollower(*context().createDefaultInteraction()); rootInteractionHandler().makeLastFollower(*this); @@ -66,13 +65,13 @@ FillZoneEditor::FillZoneEditor(const QImage& image, rootInteractionHandler().makeLastFollower(m_zoomHandler); for (const Zone& zone : m_settings->fillZonesForPage(pageId)) { - auto spline = make_intrusive(zone.spline().transformed(m_origToImage)); - m_zones.addZone(spline, zone.properties()); + auto spline = std::make_shared(zone.spline().transformed(m_origToImage)); + zones().addZone(spline, zone.properties()); } } FillZoneEditor::~FillZoneEditor() { - m_settings->setDefaultFillZoneProperties(m_zones.defaultProperties()); + m_settings->setDefaultFillZoneProperties(zones().defaultProperties()); } void FillZoneEditor::onPaint(QPainter& painter, const InteractionState& interaction) { @@ -86,7 +85,7 @@ void FillZoneEditor::onPaint(QPainter& painter, const InteractionState& interact painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : zones()) { using FCP = FillColorProperty; const QColor color(zone.properties()->locateOrDefault()->color()); painter.setBrush(m_colorAdapter(color)); @@ -96,7 +95,7 @@ void FillZoneEditor::onPaint(QPainter& painter, const InteractionState& interact InteractionHandler* FillZoneEditor::createContextMenuInteraction(InteractionState& interaction) { // Return a standard ZoneContextMenuInteraction but with a customized menu. - return ZoneContextMenuInteraction::create(m_context, interaction, MenuCustomizer(this)); + return ZoneContextMenuInteraction::create(context(), interaction, MenuCustomizer(this)); } InteractionHandler* FillZoneEditor::createColorPickupInteraction(const EditableZoneSet::Zone& zone, @@ -108,7 +107,7 @@ InteractionHandler* FillZoneEditor::createColorPickupInteraction(const EditableZ void FillZoneEditor::commitZones() { ZoneSet zones; - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : this->zones()) { const SerializableSpline spline = SerializableSpline(*zone.spline()).transformed(m_imageToOrig); zones.add(Zone(spline, *zone.properties())); } diff --git a/src/core/filters/output/FillZoneEditor.h b/src/core/filters/output/FillZoneEditor.h index 2298b2a9e..2573a60a2 100644 --- a/src/core/filters/output/FillZoneEditor.h +++ b/src/core/filters/output/FillZoneEditor.h @@ -9,19 +9,18 @@ #include #include #include +#include #include "ColorPickupInteraction.h" #include "DragHandler.h" #include "EditableSpline.h" #include "EditableZoneSet.h" #include "ImagePixmapUnion.h" -#include "ImageViewBase.h" #include "NonCopyable.h" #include "PageId.h" +#include "ZoneEditorBase.h" #include "ZoneInteractionContext.h" #include "ZoomHandler.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class InteractionState; class QPainter; @@ -29,7 +28,7 @@ class QPainter; namespace output { class Settings; -class FillZoneEditor : public ImageViewBase, private InteractionHandler { +class FillZoneEditor : public ZoneEditorBase { Q_OBJECT public: FillZoneEditor(const QImage& image, @@ -37,7 +36,7 @@ class FillZoneEditor : public ImageViewBase, private InteractionHandler { const boost::function& origToImage, const boost::function& imageToOrig, const PageId& pageId, - intrusive_ptr settings); + std::shared_ptr settings); ~FillZoneEditor() override; @@ -71,21 +70,16 @@ class FillZoneEditor : public ImageViewBase, private InteractionHandler { static ColorAdapter colorAdapterFor(const QImage& image); + DragHandler m_dragHandler; + ZoomHandler m_zoomHandler; ColorAdapter m_colorAdapter; - EditableZoneSet m_zones; - - // Must go after m_zones. - ZoneInteractionContext m_context; - // Must go after m_context. ColorPickupInteraction m_colorPickupInteraction; - DragHandler m_dragHandler; - ZoomHandler m_zoomHandler; boost::function m_origToImage; boost::function m_imageToOrig; PageId m_pageId; - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_FILLZONEEDITOR_H_ diff --git a/src/core/filters/output/Filter.cpp b/src/core/filters/output/Filter.cpp index 1483ced05..0aca85f03 100644 --- a/src/core/filters/output/Filter.cpp +++ b/src/core/filters/output/Filter.cpp @@ -3,13 +3,8 @@ #include "Filter.h" -#include -#include #include -#include -#include -#include #include #include "CacheDrivenTask.h" @@ -20,13 +15,15 @@ #include "Settings.h" #include "Task.h" #include "ThumbnailPixmapCache.h" +#include "Utils.h" namespace output { -Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) : m_settings(new Settings), m_selectedPageOrder(0) { +Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) + : m_settings(std::make_shared()), m_selectedPageOrder(0) { m_optionsWidget.reset(new OptionsWidget(m_settings, pageSelectionAccessor)); const PageOrderOption::ProviderPtr defaultOrder; - const auto orderByCompleteness = make_intrusive(); + const auto orderByCompleteness = std::make_shared(); m_pageOrderOptions.emplace_back(tr("Natural order"), defaultOrder); m_pageOrderOptions.emplace_back(tr("Order by completeness"), orderByCompleteness); } @@ -134,34 +131,28 @@ void Filter::loadSettings(const ProjectReader& reader, const QDomElement& filter } } // Filter::loadSettings -intrusive_ptr Filter::createTask(const PageId& pageId, - intrusive_ptr thumbnailCache, - const OutputFileNameGenerator& outFileNameGen, - const bool batch, - const bool debug) { +std::shared_ptr Filter::createTask(const PageId& pageId, + std::shared_ptr thumbnailCache, + const OutputFileNameGenerator& outFileNameGen, + const bool batch, + const bool debug) { ImageViewTab lastTab(TAB_OUTPUT); if (m_optionsWidget.get() != nullptr) { lastTab = m_optionsWidget->lastTab(); } - return make_intrusive(intrusive_ptr(this), m_settings, std::move(thumbnailCache), pageId, - outFileNameGen, lastTab, batch, debug); + return std::make_shared(std::static_pointer_cast(shared_from_this()), m_settings, + std::move(thumbnailCache), pageId, outFileNameGen, lastTab, batch, debug); } -intrusive_ptr Filter::createCacheDrivenTask(const OutputFileNameGenerator& outFileNameGen) { - return make_intrusive(m_settings, outFileNameGen); +std::shared_ptr Filter::createCacheDrivenTask(const OutputFileNameGenerator& outFileNameGen) { + return std::make_shared(m_settings, outFileNameGen); } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->isParamsNull(pageInfo.id())) { + if (!m_settings->isParamsNull(pageInfo.id())) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::OutputParams& outputParams = defaultParams.getOutputParams(); - m_settings->setParams(pageInfo.id(), Params(outputParams.getDpi(), outputParams.getColorParams(), - outputParams.getSplittingOptions(), outputParams.getPictureShapeOptions(), - dewarping::DistortionModel(), outputParams.getDepthPerception(), - outputParams.getDewarpingOptions(), outputParams.getDespeckleLevel())); + m_settings->setParams(pageInfo.id(), Utils::buildDefaultParams()); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/output/Filter.h b/src/core/filters/output/Filter.h index b9cd9e6ff..b3779386b 100644 --- a/src/core/filters/output/Filter.h +++ b/src/core/filters/output/Filter.h @@ -6,6 +6,7 @@ #include #include +#include #include "AbstractFilter.h" #include "FillZonePropFactory.h" @@ -14,7 +15,6 @@ #include "PageView.h" #include "PictureZonePropFactory.h" #include "SafeDeletingQObjectPtr.h" -#include "intrusive_ptr.h" class PageSelectionAccessor; class ThumbnailPixmapCache; @@ -50,13 +50,13 @@ class Filter : public AbstractFilter { void loadDefaultSettings(const PageInfo& pageInfo) override; - intrusive_ptr createTask(const PageId& pageId, - intrusive_ptr thumbnailCache, - const OutputFileNameGenerator& outFileNameGen, - bool batch, - bool debug); + std::shared_ptr createTask(const PageId& pageId, + std::shared_ptr thumbnailCache, + const OutputFileNameGenerator& outFileNameGen, + bool batch, + bool debug); - intrusive_ptr createCacheDrivenTask(const OutputFileNameGenerator& outFileNameGen); + std::shared_ptr createCacheDrivenTask(const OutputFileNameGenerator& outFileNameGen); OptionsWidget* optionsWidget(); @@ -69,7 +69,7 @@ class Filter : public AbstractFilter { private: void writePageSettings(QDomDocument& doc, QDomElement& filterEl, const PageId& pageId, int numericId) const; - intrusive_ptr m_settings; + std::shared_ptr m_settings; SafeDeletingQObjectPtr m_optionsWidget; PictureZonePropFactory m_pictureZonePropFactory; FillZonePropFactory m_fillZonePropFactory; diff --git a/src/core/filters/output/OptionsWidget.cpp b/src/core/filters/output/OptionsWidget.cpp index 2c2192196..81859a4a9 100644 --- a/src/core/filters/output/OptionsWidget.cpp +++ b/src/core/filters/output/OptionsWidget.cpp @@ -19,7 +19,7 @@ using namespace core; namespace output { -OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) +OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pageSelectionAccessor(pageSelectionAccessor), m_despeckleLevel(1.0), diff --git a/src/core/filters/output/OptionsWidget.h b/src/core/filters/output/OptionsWidget.h index 28e1a4bcc..9e73891d7 100644 --- a/src/core/filters/output/OptionsWidget.h +++ b/src/core/filters/output/OptionsWidget.h @@ -4,6 +4,8 @@ #ifndef SCANTAILOR_OUTPUT_OPTIONSWIDGET_H_ #define SCANTAILOR_OUTPUT_OPTIONSWIDGET_H_ +#include + #include #include #include @@ -11,7 +13,6 @@ #include #include #include -#include #include "BinarizationOptionsWidget.h" #include "ColorParams.h" @@ -25,7 +26,6 @@ #include "PageId.h" #include "PageSelectionAccessor.h" #include "Params.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" namespace dewarping { @@ -38,7 +38,7 @@ class Settings; class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { Q_OBJECT public: - OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); + OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -175,7 +175,7 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { void setupUiConnections(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageSelectionAccessor m_pageSelectionAccessor; PageId m_pageId; Dpi m_outputDpi; diff --git a/src/core/filters/output/OtsuBinarizationOptionsWidget.cpp b/src/core/filters/output/OtsuBinarizationOptionsWidget.cpp index a1d02a2df..b8c7b4b4f 100644 --- a/src/core/filters/output/OtsuBinarizationOptionsWidget.cpp +++ b/src/core/filters/output/OtsuBinarizationOptionsWidget.cpp @@ -14,7 +14,7 @@ using namespace core; namespace output { -OtsuBinarizationOptionsWidget::OtsuBinarizationOptionsWidget(intrusive_ptr settings) +OtsuBinarizationOptionsWidget::OtsuBinarizationOptionsWidget(std::shared_ptr settings) : m_settings(std::move(settings)), m_connectionManager(std::bind(&OtsuBinarizationOptionsWidget::setupUiConnections, this)) { setupUi(this); diff --git a/src/core/filters/output/OtsuBinarizationOptionsWidget.h b/src/core/filters/output/OtsuBinarizationOptionsWidget.h index c444e6061..c67de6a8c 100644 --- a/src/core/filters/output/OtsuBinarizationOptionsWidget.h +++ b/src/core/filters/output/OtsuBinarizationOptionsWidget.h @@ -4,21 +4,22 @@ #ifndef SCANTAILOR_OUTPUT_OTSUBINARIZATIONOPTIONSWIDGET_H_ #define SCANTAILOR_OUTPUT_OTSUBINARIZATIONOPTIONSWIDGET_H_ +#include + #include #include -#include +#include #include "BinarizationOptionsWidget.h" #include "ColorParams.h" #include "Settings.h" -#include "intrusive_ptr.h" #include "ui_OtsuBinarizationOptionsWidget.h" namespace output { class OtsuBinarizationOptionsWidget : public BinarizationOptionsWidget, private Ui::OtsuBinarizationOptionsWidget { Q_OBJECT public: - explicit OtsuBinarizationOptionsWidget(intrusive_ptr settings); + explicit OtsuBinarizationOptionsWidget(std::shared_ptr settings); ~OtsuBinarizationOptionsWidget() override = default; @@ -45,7 +46,7 @@ class OtsuBinarizationOptionsWidget : public BinarizationOptionsWidget, private void setupUiConnections(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageId m_pageId; ColorParams m_colorParams; QTimer m_delayedStateChanger; diff --git a/src/core/filters/output/OutputFileParams.cpp b/src/core/filters/output/OutputFileParams.cpp index 0c5e33922..ccf0002ed 100644 --- a/src/core/filters/output/OutputFileParams.cpp +++ b/src/core/filters/output/OutputFileParams.cpp @@ -36,12 +36,4 @@ QDomElement OutputFileParams::toXml(QDomDocument& doc, const QString& name) cons return QDomElement(); } } - -bool OutputFileParams::matches(const OutputFileParams& other) const { - return isValid() && other.isValid() && m_size == other.m_size /* && m_mtime == other.m_mtime*/; -} - -bool OutputFileParams::isValid() const { - return m_size >= 0; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/OutputFileParams.h b/src/core/filters/output/OutputFileParams.h index 37147c40f..4e1b1a464 100644 --- a/src/core/filters/output/OutputFileParams.h +++ b/src/core/filters/output/OutputFileParams.h @@ -36,5 +36,14 @@ class OutputFileParams { qint64 m_size; time_t m_modifiedTime; }; + + +inline bool OutputFileParams::matches(const OutputFileParams& other) const { + return isValid() && other.isValid() && m_size == other.m_size /*&& m_modifiedTime == other.m_modifiedTime*/; +} + +inline bool OutputFileParams::isValid() const { + return m_size >= 0; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_OUTPUTFILEPARAMS_H_ diff --git a/src/core/filters/output/OutputGenerator.cpp b/src/core/filters/output/OutputGenerator.cpp index 687d380d3..48ce8bbc0 100644 --- a/src/core/filters/output/OutputGenerator.cpp +++ b/src/core/filters/output/OutputGenerator.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -91,15 +92,11 @@ QSize OutputGenerator::outputImageSize() const { return m_outRect.size(); } -QRect OutputGenerator::outputContentRect() const { - return m_contentRect; -} - class OutputGenerator::Processor { public: Processor(const OutputGenerator& generator, const PageId& pageId, - const intrusive_ptr& settings, + const std::shared_ptr& settings, const FilterData& input, const TaskStatus& status, DebugImages* dbg); @@ -212,7 +209,7 @@ class OutputGenerator::Processor { const QRect& m_contentRect; const PageId m_pageId; - const intrusive_ptr m_settings; + const std::shared_ptr m_settings; Dpi m_dpi; ColorParams m_colorParams; @@ -259,14 +256,14 @@ std::unique_ptr OutputGenerator::process(const TaskStatus& status, BinaryImage* specklesImage, DebugImages* dbg, const PageId& pageId, - const intrusive_ptr& settings) const { + const std::shared_ptr& settings) const { return Processor(*this, pageId, settings, input, status, dbg) .process(pictureZones, fillZones, distortionModel, depthPerception, autoPictureMask, specklesImage); } OutputGenerator::Processor::Processor(const OutputGenerator& generator, const PageId& pageId, - const intrusive_ptr& settings, + const std::shared_ptr& settings, const FilterData& input, const TaskStatus& status, DebugImages* dbg) @@ -2636,4 +2633,4 @@ DistortionModel OutputGenerator::Processor::buildMarginalDistortionModel() const } return distortionModel; } -} // namespace output \ No newline at end of file +} // namespace output diff --git a/src/core/filters/output/OutputGenerator.h b/src/core/filters/output/OutputGenerator.h index ca1b105ae..0470dc6d3 100644 --- a/src/core/filters/output/OutputGenerator.h +++ b/src/core/filters/output/OutputGenerator.h @@ -9,7 +9,6 @@ #include "ImageTransformation.h" #include "OutputImage.h" -#include "intrusive_ptr.h" class TaskStatus; class DebugImages; @@ -72,14 +71,14 @@ class OutputGenerator { imageproc::BinaryImage* specklesImage, DebugImages* dbg, const PageId& pageId, - const intrusive_ptr& settings) const; + const std::shared_ptr& settings) const; QSize outputImageSize() const; /** * \brief Returns the content rectangle in output image coordinates. */ - QRect outputContentRect() const; + QRect outputContentRect() const { return m_contentRect; } private: class Processor; diff --git a/src/core/filters/output/OutputImageParams.cpp b/src/core/filters/output/OutputImageParams.cpp index 194bc964e..d7a89c71f 100644 --- a/src/core/filters/output/OutputImageParams.cpp +++ b/src/core/filters/output/OutputImageParams.cpp @@ -165,42 +165,6 @@ bool OutputImageParams::colorParamsMatch(const ColorParams& cp1, return true; } -void OutputImageParams::setOutputProcessingParams(const OutputProcessingParams& outputProcessingParams) { - OutputImageParams::m_outputProcessingParams = outputProcessingParams; -} - -const PictureShapeOptions& OutputImageParams::getPictureShapeOptions() const { - return m_pictureShapeOptions; -} - -const QPolygonF& OutputImageParams::getCropArea() const { - return m_cropArea; -} - -const DewarpingOptions& OutputImageParams::dewarpingMode() const { - return m_dewarpingOptions; -} - -const dewarping::DistortionModel& OutputImageParams::distortionModel() const { - return m_distortionModel; -} - -void OutputImageParams::setDistortionModel(const dewarping::DistortionModel& model) { - m_distortionModel = model; -} - -const DepthPerception& OutputImageParams::depthPerception() const { - return m_depthPerception; -} - -double OutputImageParams::despeckleLevel() const { - return m_despeckleLevel; -} - -void OutputImageParams::setBlackOnWhite(bool blackOnWhite) { - m_blackOnWhite = blackOnWhite; -} - /*=============================== PartialXform =============================*/ OutputImageParams::PartialXform::PartialXform() : m_11(), m_12(), m_21(), m_22() {} diff --git a/src/core/filters/output/OutputImageParams.h b/src/core/filters/output/OutputImageParams.h index 428c2fd26..ad02a3375 100644 --- a/src/core/filters/output/OutputImageParams.h +++ b/src/core/filters/output/OutputImageParams.h @@ -146,5 +146,42 @@ class OutputImageParams { /** Whether the page has dark content on light background */ bool m_blackOnWhite; }; + + +inline void OutputImageParams::setOutputProcessingParams(const OutputProcessingParams& outputProcessingParams) { + OutputImageParams::m_outputProcessingParams = outputProcessingParams; +} + +inline const PictureShapeOptions& OutputImageParams::getPictureShapeOptions() const { + return m_pictureShapeOptions; +} + +inline const QPolygonF& OutputImageParams::getCropArea() const { + return m_cropArea; +} + +inline const DewarpingOptions& OutputImageParams::dewarpingMode() const { + return m_dewarpingOptions; +} + +inline const dewarping::DistortionModel& OutputImageParams::distortionModel() const { + return m_distortionModel; +} + +inline void OutputImageParams::setDistortionModel(const dewarping::DistortionModel& model) { + m_distortionModel = model; +} + +inline const DepthPerception& OutputImageParams::depthPerception() const { + return m_depthPerception; +} + +inline double OutputImageParams::despeckleLevel() const { + return m_despeckleLevel; +} + +inline void OutputImageParams::setBlackOnWhite(bool blackOnWhite) { + m_blackOnWhite = blackOnWhite; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_OUTPUTIMAGEPARAMS_H_ diff --git a/src/core/filters/output/OutputParams.cpp b/src/core/filters/output/OutputParams.cpp index d1d572227..481ee6df9 100644 --- a/src/core/filters/output/OutputParams.cpp +++ b/src/core/filters/output/OutputParams.cpp @@ -10,6 +10,7 @@ namespace output { OutputParams::OutputParams(const OutputImageParams& outputImageParams, + const OutputFileParams& sourceFileParams, const OutputFileParams& outputFileParams, const OutputFileParams& foregroundFileParams, const OutputFileParams& backgroundFileParams, @@ -19,6 +20,7 @@ OutputParams::OutputParams(const OutputImageParams& outputImageParams, const ZoneSet& pictureZones, const ZoneSet& fillZones) : m_outputImageParams(outputImageParams), + m_sourceFileParams(sourceFileParams), m_outputFileParams(outputFileParams), m_foregroundFileParams(foregroundFileParams), m_backgroundFileParams(backgroundFileParams), @@ -30,6 +32,7 @@ OutputParams::OutputParams(const OutputImageParams& outputImageParams, OutputParams::OutputParams(const QDomElement& el) : m_outputImageParams(el.namedItem("image").toElement()), + m_sourceFileParams(el.namedItem("source_file").toElement()), m_outputFileParams(el.namedItem("file").toElement()), m_foregroundFileParams(el.namedItem("foreground_file").toElement()), m_backgroundFileParams(el.namedItem("background_file").toElement()), @@ -42,6 +45,7 @@ OutputParams::OutputParams(const QDomElement& el) QDomElement OutputParams::toXml(QDomDocument& doc, const QString& name) const { QDomElement el(doc.createElement(name)); el.appendChild(m_outputImageParams.toXml(doc, "image")); + el.appendChild(m_sourceFileParams.toXml(doc, "source_file")); el.appendChild(m_outputFileParams.toXml(doc, "file")); el.appendChild(m_foregroundFileParams.toXml(doc, "foreground_file")); el.appendChild(m_backgroundFileParams.toXml(doc, "background_file")); @@ -52,40 +56,4 @@ QDomElement OutputParams::toXml(QDomDocument& doc, const QString& name) const { el.appendChild(m_fillZones.toXml(doc, "fill-zones")); return el; } - -const OutputImageParams& OutputParams::outputImageParams() const { - return m_outputImageParams; -} - -const OutputFileParams& OutputParams::outputFileParams() const { - return m_outputFileParams; -} - -const OutputFileParams& OutputParams::foregroundFileParams() const { - return m_foregroundFileParams; -} - -const OutputFileParams& OutputParams::backgroundFileParams() const { - return m_backgroundFileParams; -} - -const OutputFileParams& OutputParams::originalBackgroundFileParams() const { - return m_originalBackgroundFileParams; -} - -const OutputFileParams& OutputParams::automaskFileParams() const { - return m_automaskFileParams; -} - -const OutputFileParams& OutputParams::specklesFileParams() const { - return m_specklesFileParams; -} - -const ZoneSet& OutputParams::pictureZones() const { - return m_pictureZones; -} - -const ZoneSet& OutputParams::fillZones() const { - return m_fillZones; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/OutputParams.h b/src/core/filters/output/OutputParams.h index accece8a2..b6de0e668 100644 --- a/src/core/filters/output/OutputParams.h +++ b/src/core/filters/output/OutputParams.h @@ -16,6 +16,7 @@ namespace output { class OutputParams { public: OutputParams(const OutputImageParams& outputImageParams, + const OutputFileParams& sourceFileParams, const OutputFileParams& outputFileParams, const OutputFileParams& foregroundFileParams, const OutputFileParams& backgroundFileParams, @@ -31,6 +32,8 @@ class OutputParams { const OutputImageParams& outputImageParams() const; + const OutputFileParams& sourceFileParams() const; + const OutputFileParams& outputFileParams() const; const OutputFileParams& foregroundFileParams() const; @@ -49,6 +52,7 @@ class OutputParams { private: OutputImageParams m_outputImageParams; + OutputFileParams m_sourceFileParams; OutputFileParams m_outputFileParams; OutputFileParams m_foregroundFileParams; OutputFileParams m_backgroundFileParams; @@ -58,5 +62,46 @@ class OutputParams { ZoneSet m_pictureZones; ZoneSet m_fillZones; }; + + +inline const OutputImageParams& OutputParams::outputImageParams() const { + return m_outputImageParams; +} + +inline const OutputFileParams& OutputParams::outputFileParams() const { + return m_outputFileParams; +} + +inline const OutputFileParams& OutputParams::foregroundFileParams() const { + return m_foregroundFileParams; +} + +inline const OutputFileParams& OutputParams::backgroundFileParams() const { + return m_backgroundFileParams; +} + +inline const OutputFileParams& OutputParams::originalBackgroundFileParams() const { + return m_originalBackgroundFileParams; +} + +inline const OutputFileParams& OutputParams::automaskFileParams() const { + return m_automaskFileParams; +} + +inline const OutputFileParams& OutputParams::specklesFileParams() const { + return m_specklesFileParams; +} + +inline const ZoneSet& OutputParams::pictureZones() const { + return m_pictureZones; +} + +inline const ZoneSet& OutputParams::fillZones() const { + return m_fillZones; +} + +inline const OutputFileParams& OutputParams::sourceFileParams() const { + return m_sourceFileParams; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_OUTPUTPARAMS_H_ diff --git a/src/core/filters/output/OutputProcessingParams.cpp b/src/core/filters/output/OutputProcessingParams.cpp index dce3d6b08..68a2e694e 100644 --- a/src/core/filters/output/OutputProcessingParams.cpp +++ b/src/core/filters/output/OutputProcessingParams.cpp @@ -29,20 +29,4 @@ bool OutputProcessingParams::operator==(const OutputProcessingParams& other) con bool OutputProcessingParams::operator!=(const OutputProcessingParams& other) const { return !(*this == other); } - -bool output::OutputProcessingParams::isAutoZonesFound() const { - return m_autoZonesFound; -} - -void output::OutputProcessingParams::setAutoZonesFound(bool autoZonesFound) { - OutputProcessingParams::m_autoZonesFound = autoZonesFound; -} - -bool OutputProcessingParams::isBlackOnWhiteSetManually() const { - return m_blackOnWhiteSetManually; -} - -void OutputProcessingParams::setBlackOnWhiteSetManually(bool blackOnWhiteSetManually) { - OutputProcessingParams::m_blackOnWhiteSetManually = blackOnWhiteSetManually; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/OutputProcessingParams.h b/src/core/filters/output/OutputProcessingParams.h index 323dce0e8..23e9c924d 100644 --- a/src/core/filters/output/OutputProcessingParams.h +++ b/src/core/filters/output/OutputProcessingParams.h @@ -33,6 +33,23 @@ class OutputProcessingParams { bool m_autoZonesFound; bool m_blackOnWhiteSetManually; }; + + +inline bool output::OutputProcessingParams::isAutoZonesFound() const { + return m_autoZonesFound; +} + +inline void output::OutputProcessingParams::setAutoZonesFound(bool autoZonesFound) { + OutputProcessingParams::m_autoZonesFound = autoZonesFound; +} + +inline bool OutputProcessingParams::isBlackOnWhiteSetManually() const { + return m_blackOnWhiteSetManually; +} + +inline void OutputProcessingParams::setBlackOnWhiteSetManually(bool blackOnWhiteSetManually) { + OutputProcessingParams::m_blackOnWhiteSetManually = blackOnWhiteSetManually; +} } // namespace output diff --git a/src/core/filters/output/Params.cpp b/src/core/filters/output/Params.cpp index 973ff41c1..00b1a1a08 100644 --- a/src/core/filters/output/Params.cpp +++ b/src/core/filters/output/Params.cpp @@ -56,76 +56,4 @@ QDomElement Params::toXml(QDomDocument& doc, const QString& name) const { el.setAttribute("blackOnWhite", m_blackOnWhite ? "1" : "0"); return el; } - -const Dpi& Params::outputDpi() const { - return m_dpi; -} - -void Params::setOutputDpi(const Dpi& dpi) { - m_dpi = dpi; -} - -const ColorParams& Params::colorParams() const { - return m_colorParams; -} - -const PictureShapeOptions& Params::pictureShapeOptions() const { - return m_pictureShapeOptions; -} - -void Params::setPictureShapeOptions(const PictureShapeOptions& opt) { - m_pictureShapeOptions = opt; -} - -void Params::setColorParams(const ColorParams& params) { - m_colorParams = params; -} - -const SplittingOptions& Params::splittingOptions() const { - return m_splittingOptions; -} - -void Params::setSplittingOptions(const SplittingOptions& opt) { - m_splittingOptions = opt; -} - -const DewarpingOptions& Params::dewarpingOptions() const { - return m_dewarpingOptions; -} - -void Params::setDewarpingOptions(const DewarpingOptions& opt) { - m_dewarpingOptions = opt; -} - -const dewarping::DistortionModel& Params::distortionModel() const { - return m_distortionModel; -} - -void Params::setDistortionModel(const dewarping::DistortionModel& model) { - m_distortionModel = model; -} - -const DepthPerception& Params::depthPerception() const { - return m_depthPerception; -} - -void Params::setDepthPerception(DepthPerception depthPerception) { - m_depthPerception = depthPerception; -} - -double Params::despeckleLevel() const { - return m_despeckleLevel; -} - -void Params::setDespeckleLevel(double level) { - m_despeckleLevel = level; -} - -bool Params::isBlackOnWhite() const { - return m_blackOnWhite; -} - -void Params::setBlackOnWhite(bool isBlackOnWhite) { - Params::m_blackOnWhite = isBlackOnWhite; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/Params.h b/src/core/filters/output/Params.h index bd509ffbe..7407be259 100644 --- a/src/core/filters/output/Params.h +++ b/src/core/filters/output/Params.h @@ -4,7 +4,7 @@ #ifndef SCANTAILOR_OUTPUT_PARAMS_H_ #define SCANTAILOR_OUTPUT_PARAMS_H_ -#include +#include #include "ColorParams.h" #include "DepthPerception.h" @@ -81,5 +81,78 @@ class Params { double m_despeckleLevel; bool m_blackOnWhite; }; + + +inline const Dpi& Params::outputDpi() const { + return m_dpi; +} + +inline void Params::setOutputDpi(const Dpi& dpi) { + m_dpi = dpi; +} + +inline const ColorParams& Params::colorParams() const { + return m_colorParams; +} + +inline const PictureShapeOptions& Params::pictureShapeOptions() const { + return m_pictureShapeOptions; +} + +inline void Params::setPictureShapeOptions(const PictureShapeOptions& opt) { + m_pictureShapeOptions = opt; +} + +inline void Params::setColorParams(const ColorParams& params) { + m_colorParams = params; +} + +inline const SplittingOptions& Params::splittingOptions() const { + return m_splittingOptions; +} + +inline void Params::setSplittingOptions(const SplittingOptions& opt) { + m_splittingOptions = opt; +} + +inline const DewarpingOptions& Params::dewarpingOptions() const { + return m_dewarpingOptions; +} + +inline void Params::setDewarpingOptions(const DewarpingOptions& opt) { + m_dewarpingOptions = opt; +} + +inline const dewarping::DistortionModel& Params::distortionModel() const { + return m_distortionModel; +} + +inline void Params::setDistortionModel(const dewarping::DistortionModel& model) { + m_distortionModel = model; +} + +inline const DepthPerception& Params::depthPerception() const { + return m_depthPerception; +} + +inline void Params::setDepthPerception(DepthPerception depthPerception) { + m_depthPerception = depthPerception; +} + +inline double Params::despeckleLevel() const { + return m_despeckleLevel; +} + +inline void Params::setDespeckleLevel(double level) { + m_despeckleLevel = level; +} + +inline bool Params::isBlackOnWhite() const { + return m_blackOnWhite; +} + +inline void Params::setBlackOnWhite(bool isBlackOnWhite) { + Params::m_blackOnWhite = isBlackOnWhite; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_PARAMS_H_ diff --git a/src/core/filters/output/PictureLayerProperty.cpp b/src/core/filters/output/PictureLayerProperty.cpp index aa8b61e5b..3b29f659a 100644 --- a/src/core/filters/output/PictureLayerProperty.cpp +++ b/src/core/filters/output/PictureLayerProperty.cpp @@ -16,8 +16,8 @@ void PictureLayerProperty::registerIn(PropertyFactory& factory) { factory.registerProperty(m_propertyName, &PictureLayerProperty::construct); } -intrusive_ptr PictureLayerProperty::clone() const { - return make_intrusive(*this); +std::shared_ptr PictureLayerProperty::clone() const { + return std::make_shared(*this); } QDomElement PictureLayerProperty::toXml(QDomDocument& doc, const QString& name) const { @@ -27,8 +27,8 @@ QDomElement PictureLayerProperty::toXml(QDomDocument& doc, const QString& name) return el; } -intrusive_ptr PictureLayerProperty::construct(const QDomElement& el) { - return make_intrusive(el); +std::shared_ptr PictureLayerProperty::construct(const QDomElement& el) { + return std::make_shared(el); } PictureLayerProperty::Layer PictureLayerProperty::layerFromString(const QString& str) { @@ -64,12 +64,4 @@ QString PictureLayerProperty::layerToString(Layer layer) { } PictureLayerProperty::PictureLayerProperty(PictureLayerProperty::Layer layer) : m_layer(layer) {} - -PictureLayerProperty::Layer PictureLayerProperty::layer() const { - return m_layer; -} - -void PictureLayerProperty::setLayer(PictureLayerProperty::Layer layer) { - m_layer = layer; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/PictureLayerProperty.h b/src/core/filters/output/PictureLayerProperty.h index 525e360d1..392764c18 100644 --- a/src/core/filters/output/PictureLayerProperty.h +++ b/src/core/filters/output/PictureLayerProperty.h @@ -4,8 +4,9 @@ #ifndef SCANTAILOR_OUTPUT_PICTURELAYERPROPERTY_H_ #define SCANTAILOR_OUTPUT_PICTURELAYERPROPERTY_H_ +#include + #include "Property.h" -#include "intrusive_ptr.h" class PropertyFactory; class QDomDocument; @@ -23,7 +24,7 @@ class PictureLayerProperty : public Property { static void registerIn(PropertyFactory& factory); - intrusive_ptr clone() const override; + std::shared_ptr clone() const override; QDomElement toXml(QDomDocument& doc, const QString& name) const override; @@ -32,7 +33,7 @@ class PictureLayerProperty : public Property { void setLayer(Layer layer); private: - static intrusive_ptr construct(const QDomElement& el); + static std::shared_ptr construct(const QDomElement& el); static Layer layerFromString(const QString& str); @@ -42,5 +43,14 @@ class PictureLayerProperty : public Property { static const char m_propertyName[]; Layer m_layer; }; + + +inline PictureLayerProperty::Layer PictureLayerProperty::layer() const { + return m_layer; +} + +inline void PictureLayerProperty::setLayer(PictureLayerProperty::Layer layer) { + m_layer = layer; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_PICTURELAYERPROPERTY_H_ diff --git a/src/core/filters/output/PictureShapeOptions.cpp b/src/core/filters/output/PictureShapeOptions.cpp index a423f4445..a4138d790 100644 --- a/src/core/filters/output/PictureShapeOptions.cpp +++ b/src/core/filters/output/PictureShapeOptions.cpp @@ -56,29 +56,4 @@ QString PictureShapeOptions::formatPictureShape(PictureShape type) { } return str; } - -PictureShape PictureShapeOptions::getPictureShape() const { - return m_pictureShape; -} - -void PictureShapeOptions::setPictureShape(PictureShape pictureShape) { - PictureShapeOptions::m_pictureShape = pictureShape; -} - -int PictureShapeOptions::getSensitivity() const { - return m_sensitivity; -} - -void PictureShapeOptions::setSensitivity(int sensitivity) { - PictureShapeOptions::m_sensitivity = sensitivity; -} - -bool PictureShapeOptions::isHigherSearchSensitivity() const { - return m_higherSearchSensitivity; -} - -void PictureShapeOptions::setHigherSearchSensitivity(bool higherSearchSensitivity) { - PictureShapeOptions::m_higherSearchSensitivity = higherSearchSensitivity; -} - } // namespace output diff --git a/src/core/filters/output/PictureShapeOptions.h b/src/core/filters/output/PictureShapeOptions.h index e636f83a7..28b93cebb 100644 --- a/src/core/filters/output/PictureShapeOptions.h +++ b/src/core/filters/output/PictureShapeOptions.h @@ -45,6 +45,31 @@ class PictureShapeOptions { int m_sensitivity; bool m_higherSearchSensitivity; }; + + +inline PictureShape PictureShapeOptions::getPictureShape() const { + return m_pictureShape; +} + +inline void PictureShapeOptions::setPictureShape(PictureShape pictureShape) { + PictureShapeOptions::m_pictureShape = pictureShape; +} + +inline int PictureShapeOptions::getSensitivity() const { + return m_sensitivity; +} + +inline void PictureShapeOptions::setSensitivity(int sensitivity) { + PictureShapeOptions::m_sensitivity = sensitivity; +} + +inline bool PictureShapeOptions::isHigherSearchSensitivity() const { + return m_higherSearchSensitivity; +} + +inline void PictureShapeOptions::setHigherSearchSensitivity(bool higherSearchSensitivity) { + PictureShapeOptions::m_higherSearchSensitivity = higherSearchSensitivity; +} } // namespace output #endif // SCANTAILOR_OUTPUT_PICTURESHAPEOPTIONS_H_ diff --git a/src/core/filters/output/PictureZoneComparator.cpp b/src/core/filters/output/PictureZoneComparator.cpp index 873510b9a..633996c33 100644 --- a/src/core/filters/output/PictureZoneComparator.cpp +++ b/src/core/filters/output/PictureZoneComparator.cpp @@ -8,16 +8,16 @@ namespace output { bool PictureZoneComparator::equal(const ZoneSet& lhs, const ZoneSet& rhs) { - ZoneSet::const_iterator lhs_it(lhs.begin()); - ZoneSet::const_iterator rhs_it(rhs.begin()); - const ZoneSet::const_iterator lhs_end(lhs.end()); - const ZoneSet::const_iterator rhs_end(rhs.end()); - for (; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it) { - if (!equal(*lhs_it, *rhs_it)) { + ZoneSet::const_iterator lhsIt(lhs.begin()); + ZoneSet::const_iterator rhsIt(rhs.begin()); + const ZoneSet::const_iterator lhsEnd(lhs.end()); + const ZoneSet::const_iterator rhsEnd(rhs.end()); + for (; lhsIt != lhsEnd && rhsIt != rhsEnd; ++lhsIt, ++rhsIt) { + if (!equal(*lhsIt, *rhsIt)) { return false; } } - return lhs_it == lhs_end && rhs_it == rhs_end; + return lhsIt == lhsEnd && rhsIt == rhsEnd; } bool PictureZoneComparator::equal(const Zone& lhs, const Zone& rhs) { diff --git a/src/core/filters/output/PictureZoneEditor.cpp b/src/core/filters/output/PictureZoneEditor.cpp index a47510fac..529abb52b 100644 --- a/src/core/filters/output/PictureZoneEditor.cpp +++ b/src/core/filters/output/PictureZoneEditor.cpp @@ -28,7 +28,7 @@ static const QRgb maskColor = 0xff587ff4; using namespace imageproc; -class PictureZoneEditor::MaskTransformTask : public AbstractCommand>>, +class PictureZoneEditor::MaskTransformTask : public AbstractCommand>>, public QObject { DECLARE_NON_COPYABLE(MaskTransformTask) @@ -42,7 +42,7 @@ class PictureZoneEditor::MaskTransformTask : public AbstractCommandisCancelled(); } - intrusive_ptr> operator()() override; + std::shared_ptr> operator()() override; private: class Result : public AbstractCommand { @@ -65,7 +65,7 @@ class PictureZoneEditor::MaskTransformTask : public AbstractCommand m_result; + std::shared_ptr m_result; BinaryImage m_origMask; QTransform m_xform; QSize m_targetSize; @@ -78,24 +78,23 @@ PictureZoneEditor::PictureZoneEditor(const QImage& image, const QTransform& imageToVirt, const QPolygonF& virtDisplayArea, const PageId& pageId, - intrusive_ptr settings) - : ImageViewBase(image, downscaledImage, ImagePresentation(imageToVirt, virtDisplayArea), OutputMargins()), - m_context(*this, m_zones), + std::shared_ptr settings) + : ZoneEditorBase(image, downscaledImage, ImagePresentation(imageToVirt, virtDisplayArea), OutputMargins()), m_dragHandler(*this), m_zoomHandler(*this), m_origPictureMask(pictureMask), m_pictureMaskAnimationPhase(270), m_pageId(pageId), m_settings(std::move(settings)) { - m_zones.setDefaultProperties(m_settings->defaultPictureZoneProperties()); + zones().setDefaultProperties(m_settings->defaultPictureZoneProperties()); setMouseTracking(true); - m_context.setShowPropertiesCommand(boost::bind(&PictureZoneEditor::showPropertiesDialog, this, _1)); + context().setShowPropertiesCommand(boost::bind(&PictureZoneEditor::showPropertiesDialog, this, _1)); - connect(&m_zones, SIGNAL(committed()), SLOT(commitZones())); + connect(&zones(), SIGNAL(committed()), SLOT(commitZones())); - makeLastFollower(*m_context.createDefaultInteraction()); + makeLastFollower(*context().createDefaultInteraction()); rootInteractionHandler().makeLastFollower(*this); @@ -114,13 +113,13 @@ PictureZoneEditor::PictureZoneEditor(const QImage& image, m_pictureMaskRebuildTimer.setInterval(150); for (const Zone& zone : m_settings->pictureZonesForPage(pageId)) { - auto spline = make_intrusive(zone.spline()); - m_zones.addZone(spline, zone.properties()); + auto spline = std::make_shared(zone.spline()); + zones().addZone(spline, zone.properties()); } } PictureZoneEditor::~PictureZoneEditor() { - m_settings->setDefaultPictureZoneProperties(m_zones.defaultProperties()); + m_settings->setDefaultPictureZoneProperties(zones().defaultProperties()); } void PictureZoneEditor::onPaint(QPainter& painter, const InteractionState& interaction) { @@ -187,7 +186,7 @@ void PictureZoneEditor::initiateBuildingScreenPictureMask() { } const QTransform xform(virtualToWidget()); - const auto task = make_intrusive(this, m_origPictureMask, xform, viewport()->size()); + const auto task = std::make_shared(this, m_origPictureMask, xform, viewport()->size()); backgroundExecutor().enqueueTask(task); @@ -216,7 +215,7 @@ void PictureZoneEditor::paintOverPictureMask(QPainter& painter) { painter.setCompositionMode(QPainter::CompositionMode_Clear); // First pass: ERASER1 - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : zones()) { if (zone.properties()->locateOrDefault()->layer() == PLP::ERASER1) { painter.drawPolygon(zone.spline()->toPolygon(), Qt::WindingFill); } @@ -225,7 +224,7 @@ void PictureZoneEditor::paintOverPictureMask(QPainter& painter) { painter.setCompositionMode(QPainter::CompositionMode_SourceOver); // Second pass: PAINTER2 - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : zones()) { if (zone.properties()->locateOrDefault()->layer() == PLP::PAINTER2) { painter.drawPolygon(zone.spline()->toPolygon(), Qt::WindingFill); } @@ -234,7 +233,7 @@ void PictureZoneEditor::paintOverPictureMask(QPainter& painter) { painter.setCompositionMode(QPainter::CompositionMode_Clear); // Third pass: ERASER3 - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : zones()) { if (zone.properties()->locateOrDefault()->layer() == PLP::ERASER3) { painter.drawPolygon(zone.spline()->toPolygon(), Qt::WindingFill); } @@ -253,9 +252,9 @@ void PictureZoneEditor::showPropertiesDialog(const EditableZoneSet::Zone& zone) connect(&dialog, SIGNAL(updated()), SLOT(updateRequested())); if (dialog.exec() == QDialog::Accepted) { - m_zones.setDefaultProperties(*zone.properties()); - m_zones.commit(); - m_settings->setDefaultPictureZoneProperties(m_zones.defaultProperties()); + zones().setDefaultProperties(*zone.properties()); + zones().commit(); + m_settings->setDefaultPictureZoneProperties(zones().defaultProperties()); } else { zone.properties()->swap(savedProperties); update(); @@ -265,7 +264,7 @@ void PictureZoneEditor::showPropertiesDialog(const EditableZoneSet::Zone& zone) void PictureZoneEditor::commitZones() { ZoneSet zones; - for (const EditableZoneSet::Zone& zone : m_zones) { + for (const EditableZoneSet::Zone& zone : this->zones()) { zones.add(Zone(*zone.spline(), *zone.properties())); } @@ -284,9 +283,9 @@ PictureZoneEditor::MaskTransformTask::MaskTransformTask(PictureZoneEditor* zoneE const BinaryImage& mask, const QTransform& xform, const QSize& targetSize) - : m_result(new Result(zoneEditor)), m_origMask(mask), m_xform(xform), m_targetSize(targetSize) {} + : m_result(std::make_shared(zoneEditor)), m_origMask(mask), m_xform(xform), m_targetSize(targetSize) {} -intrusive_ptr> PictureZoneEditor::MaskTransformTask::operator()() { +std::shared_ptr> PictureZoneEditor::MaskTransformTask::operator()() { if (isCancelled()) { return nullptr; } diff --git a/src/core/filters/output/PictureZoneEditor.h b/src/core/filters/output/PictureZoneEditor.h index 3c9b505ac..bf2a0fa8f 100644 --- a/src/core/filters/output/PictureZoneEditor.h +++ b/src/core/filters/output/PictureZoneEditor.h @@ -11,18 +11,17 @@ #include #include #include +#include #include "DragHandler.h" #include "EditableSpline.h" #include "EditableZoneSet.h" #include "ImagePixmapUnion.h" -#include "ImageViewBase.h" #include "NonCopyable.h" #include "PageId.h" +#include "ZoneEditorBase.h" #include "ZoneInteractionContext.h" #include "ZoomHandler.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class ImageTransformation; class InteractionState; @@ -33,7 +32,7 @@ namespace output { class Settings; -class PictureZoneEditor : public ImageViewBase, private InteractionHandler { +class PictureZoneEditor : public ZoneEditorBase { Q_OBJECT public: PictureZoneEditor(const QImage& image, @@ -42,7 +41,7 @@ class PictureZoneEditor : public ImageViewBase, private InteractionHandler { const QTransform& imageToVirt, const QPolygonF& virtDisplayArea, const PageId& pageId, - intrusive_ptr settings); + std::shared_ptr settings); ~PictureZoneEditor() override; @@ -76,11 +75,6 @@ class PictureZoneEditor : public ImageViewBase, private InteractionHandler { void showPropertiesDialog(const EditableZoneSet::Zone& zone); - EditableZoneSet m_zones; - - // Must go after m_zones. - ZoneInteractionContext m_context; - DragHandler m_dragHandler; ZoomHandler m_zoomHandler; @@ -92,10 +86,10 @@ class PictureZoneEditor : public ImageViewBase, private InteractionHandler { QTimer m_pictureMaskRebuildTimer; QTimer m_pictureMaskAnimateTimer; int m_pictureMaskAnimationPhase; // degrees - intrusive_ptr m_maskTransformTask; + std::shared_ptr m_maskTransformTask; PageId m_pageId; - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_PICTUREZONEEDITOR_H_ diff --git a/src/core/filters/output/PictureZonePropDialog.cpp b/src/core/filters/output/PictureZonePropDialog.cpp index 5ba7b4ce2..ad1728927 100644 --- a/src/core/filters/output/PictureZonePropDialog.cpp +++ b/src/core/filters/output/PictureZonePropDialog.cpp @@ -8,7 +8,7 @@ #include "PictureLayerProperty.h" namespace output { -PictureZonePropDialog::PictureZonePropDialog(intrusive_ptr props, QWidget* parent) +PictureZonePropDialog::PictureZonePropDialog(std::shared_ptr props, QWidget* parent) : QDialog(parent), m_props(std::move(props)) { ui.setupUi(this); diff --git a/src/core/filters/output/PictureZonePropDialog.h b/src/core/filters/output/PictureZonePropDialog.h index 8afc33d24..8a7464b3f 100644 --- a/src/core/filters/output/PictureZonePropDialog.h +++ b/src/core/filters/output/PictureZonePropDialog.h @@ -5,16 +5,16 @@ #define SCANTAILOR_OUTPUT_PICTUREZONEPROPDIALOG_H_ #include +#include #include "PropertySet.h" -#include "intrusive_ptr.h" #include "ui_PictureZonePropDialog.h" namespace output { class PictureZonePropDialog : public QDialog { Q_OBJECT public: - explicit PictureZonePropDialog(intrusive_ptr props, QWidget* parent = nullptr); + explicit PictureZonePropDialog(std::shared_ptr props, QWidget* parent = nullptr); signals: void updated(); @@ -24,7 +24,7 @@ class PictureZonePropDialog : public QDialog { private: Ui::PictureZonePropDialog ui; - intrusive_ptr m_props; + std::shared_ptr m_props; }; } // namespace output #endif diff --git a/src/core/filters/output/RenderParams.cpp b/src/core/filters/output/RenderParams.cpp index 82be8a0d7..5852580d4 100644 --- a/src/core/filters/output/RenderParams.cpp +++ b/src/core/filters/output/RenderParams.cpp @@ -60,56 +60,4 @@ RenderParams::RenderParams(const ColorParams& colorParams, const SplittingOption m_mask |= NORMALIZE_ILLUMINATION_COLOR; } } - -bool RenderParams::fillMargins() const { - return (m_mask & FILL_MARGINS) != 0; -} - -bool RenderParams::normalizeIllumination() const { - return (m_mask & NORMALIZE_ILLUMINATION) != 0; -} - -bool RenderParams::normalizeIlluminationColor() const { - return (m_mask & NORMALIZE_ILLUMINATION_COLOR) != 0; -} - -bool RenderParams::needBinarization() const { - return (m_mask & NEED_BINARIZATION) != 0; -} - -bool RenderParams::mixedOutput() const { - return (m_mask & MIXED_OUTPUT) != 0; -} - -bool RenderParams::binaryOutput() const { - return (m_mask & (NEED_BINARIZATION | MIXED_OUTPUT)) == NEED_BINARIZATION; -} - -bool RenderParams::needSavitzkyGolaySmoothing() const { - return (m_mask & SAVITZKY_GOLAY_SMOOTHING) != 0; -} - -bool RenderParams::needMorphologicalSmoothing() const { - return (m_mask & MORPHOLOGICAL_SMOOTHING) != 0; -} - -bool RenderParams::splitOutput() const { - return (m_mask & SPLIT_OUTPUT) != 0; -} - -bool RenderParams::originalBackground() const { - return (m_mask & ORIGINAL_BACKGROUND) != 0; -} - -bool RenderParams::needColorSegmentation() const { - return (m_mask & COLOR_SEGMENTATION) != 0; -} - -bool RenderParams::posterize() const { - return (m_mask & POSTERIZE) != 0; -} - -bool RenderParams::fillOffcut() const { - return (m_mask & FILL_OFFCUT) != 0; -} } // namespace output diff --git a/src/core/filters/output/RenderParams.h b/src/core/filters/output/RenderParams.h index b0ddfb608..84cea268e 100644 --- a/src/core/filters/output/RenderParams.h +++ b/src/core/filters/output/RenderParams.h @@ -59,5 +59,58 @@ class RenderParams { int m_mask; }; + + +inline bool RenderParams::fillMargins() const { + return (m_mask & FILL_MARGINS) != 0; +} + +inline bool RenderParams::normalizeIllumination() const { + return (m_mask & NORMALIZE_ILLUMINATION) != 0; +} + +inline bool RenderParams::normalizeIlluminationColor() const { + return (m_mask & NORMALIZE_ILLUMINATION_COLOR) != 0; +} + +inline bool RenderParams::needBinarization() const { + return (m_mask & NEED_BINARIZATION) != 0; +} + +inline bool RenderParams::mixedOutput() const { + return (m_mask & MIXED_OUTPUT) != 0; +} + +inline bool RenderParams::binaryOutput() const { + return (m_mask & (NEED_BINARIZATION | MIXED_OUTPUT)) == NEED_BINARIZATION; +} + +inline bool RenderParams::needSavitzkyGolaySmoothing() const { + return (m_mask & SAVITZKY_GOLAY_SMOOTHING) != 0; +} + +inline bool RenderParams::needMorphologicalSmoothing() const { + return (m_mask & MORPHOLOGICAL_SMOOTHING) != 0; +} + +inline bool RenderParams::splitOutput() const { + return (m_mask & SPLIT_OUTPUT) != 0; +} + +inline bool RenderParams::originalBackground() const { + return (m_mask & ORIGINAL_BACKGROUND) != 0; +} + +inline bool RenderParams::needColorSegmentation() const { + return (m_mask & COLOR_SEGMENTATION) != 0; +} + +inline bool RenderParams::posterize() const { + return (m_mask & POSTERIZE) != 0; +} + +inline bool RenderParams::fillOffcut() const { + return (m_mask & FILL_OFFCUT) != 0; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_RENDERPARAMS_H_ diff --git a/src/core/filters/output/SauvolaBinarizationOptionsWidget.cpp b/src/core/filters/output/SauvolaBinarizationOptionsWidget.cpp index 119ae4bd9..cbe8eba72 100644 --- a/src/core/filters/output/SauvolaBinarizationOptionsWidget.cpp +++ b/src/core/filters/output/SauvolaBinarizationOptionsWidget.cpp @@ -8,7 +8,7 @@ namespace output { -SauvolaBinarizationOptionsWidget::SauvolaBinarizationOptionsWidget(intrusive_ptr settings) +SauvolaBinarizationOptionsWidget::SauvolaBinarizationOptionsWidget(std::shared_ptr settings) : m_settings(std::move(settings)), m_connectionManager(std::bind(&SauvolaBinarizationOptionsWidget::setupUiConnections, this)) { setupUi(this); diff --git a/src/core/filters/output/SauvolaBinarizationOptionsWidget.h b/src/core/filters/output/SauvolaBinarizationOptionsWidget.h index aceb82617..0d7ca35d1 100644 --- a/src/core/filters/output/SauvolaBinarizationOptionsWidget.h +++ b/src/core/filters/output/SauvolaBinarizationOptionsWidget.h @@ -4,14 +4,15 @@ #ifndef SCANTAILOR_OUTPUT_SAUVOLABINARIZATIONOPTIONSWIDGET_H_ #define SCANTAILOR_OUTPUT_SAUVOLABINARIZATIONOPTIONSWIDGET_H_ +#include + #include #include -#include +#include #include "BinarizationOptionsWidget.h" #include "ColorParams.h" #include "Settings.h" -#include "intrusive_ptr.h" #include "ui_SauvolaBinarizationOptionsWidget.h" namespace output { @@ -19,7 +20,7 @@ class SauvolaBinarizationOptionsWidget : public BinarizationOptionsWidget, private Ui::SauvolaBinarizationOptionsWidget { Q_OBJECT public: - explicit SauvolaBinarizationOptionsWidget(intrusive_ptr settings); + explicit SauvolaBinarizationOptionsWidget(std::shared_ptr settings); ~SauvolaBinarizationOptionsWidget() override = default; @@ -38,7 +39,7 @@ class SauvolaBinarizationOptionsWidget : public BinarizationOptionsWidget, void setupUiConnections(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageId m_pageId; ColorParams m_colorParams; QTimer m_delayedStateChanger; diff --git a/src/core/filters/output/Settings.h b/src/core/filters/output/Settings.h index 420cf4e2c..49acb3adb 100644 --- a/src/core/filters/output/Settings.h +++ b/src/core/filters/output/Settings.h @@ -21,20 +21,19 @@ #include "Params.h" #include "PropertySet.h" #include "ZoneSet.h" -#include "ref_countable.h" class AbstractRelinker; namespace output { class Params; -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) public: Settings(); - ~Settings() override; + virtual ~Settings(); void clear(); diff --git a/src/core/filters/output/SplittingOptions.cpp b/src/core/filters/output/SplittingOptions.cpp index 547ba3da3..4db99088d 100644 --- a/src/core/filters/output/SplittingOptions.cpp +++ b/src/core/filters/output/SplittingOptions.cpp @@ -21,30 +21,6 @@ QDomElement SplittingOptions::toXml(QDomDocument& doc, const QString& name) cons return el; } -bool SplittingOptions::isSplitOutput() const { - return m_isSplitOutput; -} - -void SplittingOptions::setSplitOutput(bool splitOutput) { - SplittingOptions::m_isSplitOutput = splitOutput; -} - -SplittingMode SplittingOptions::getSplittingMode() const { - return m_splittingMode; -} - -void SplittingOptions::setSplittingMode(SplittingMode foregroundType) { - SplittingOptions::m_splittingMode = foregroundType; -} - -bool SplittingOptions::isOriginalBackgroundEnabled() const { - return m_isOriginalBackgroundEnabled; -} - -void SplittingOptions::setOriginalBackgroundEnabled(bool enable) { - SplittingOptions::m_isOriginalBackgroundEnabled = enable; -} - SplittingMode SplittingOptions::parseSplittingMode(const QString& str) { if (str == "color") { return COLOR_FOREGROUND; diff --git a/src/core/filters/output/SplittingOptions.h b/src/core/filters/output/SplittingOptions.h index 115621500..c635dcb94 100644 --- a/src/core/filters/output/SplittingOptions.h +++ b/src/core/filters/output/SplittingOptions.h @@ -42,6 +42,31 @@ class SplittingOptions { SplittingMode m_splittingMode; bool m_isOriginalBackgroundEnabled; }; + + +inline bool SplittingOptions::isSplitOutput() const { + return m_isSplitOutput; +} + +inline void SplittingOptions::setSplitOutput(bool splitOutput) { + SplittingOptions::m_isSplitOutput = splitOutput; +} + +inline SplittingMode SplittingOptions::getSplittingMode() const { + return m_splittingMode; +} + +inline void SplittingOptions::setSplittingMode(SplittingMode foregroundType) { + SplittingOptions::m_splittingMode = foregroundType; +} + +inline bool SplittingOptions::isOriginalBackgroundEnabled() const { + return m_isOriginalBackgroundEnabled; +} + +inline void SplittingOptions::setOriginalBackgroundEnabled(bool enable) { + SplittingOptions::m_isOriginalBackgroundEnabled = enable; +} } // namespace output diff --git a/src/core/filters/output/TabbedImageView.cpp b/src/core/filters/output/TabbedImageView.cpp index fb6dc76bc..daae84672 100644 --- a/src/core/filters/output/TabbedImageView.cpp +++ b/src/core/filters/output/TabbedImageView.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include "../../Utils.h" #include "DespeckleView.h" @@ -15,6 +15,12 @@ namespace output { TabbedImageView::TabbedImageView(QWidget* parent) : QTabWidget(parent), m_prevImageViewTabIndex(0) { connect(this, SIGNAL(currentChanged(int)), SLOT(tabChangedSlot(int))); setStatusTip(tr("Use Ctrl+1..5 to switch the tabs.")); + + for (int i = 0; i < 5; ++i) { + m_tabShortcuts[i] = new QShortcut(static_cast(Qt::CTRL + (Qt::Key_1 + i)), this); + m_tabShortcuts[i]->setAutoRepeat(false); + connect(m_tabShortcuts[i], &QShortcut::activated, std::bind(&QTabWidget::setCurrentIndex, this, i)); + } } void TabbedImageView::addTab(QWidget* widget, const QString& label, ImageViewTab tab) { @@ -120,36 +126,4 @@ void TabbedImageView::setFocus(QScrollBar& horBar, QScrollBar& verBar, const QRe horBar.setValue(horValue); verBar.setValue(verValue); } - -void TabbedImageView::keyReleaseEvent(QKeyEvent* event) { - event->setAccepted(false); - if (event->modifiers() != Qt::ControlModifier) { - return; - } - - switch (event->key()) { - case Qt::Key_1: - setCurrentIndex(0); - event->accept(); - break; - case Qt::Key_2: - setCurrentIndex(1); - event->accept(); - break; - case Qt::Key_3: - setCurrentIndex(2); - event->accept(); - break; - case Qt::Key_4: - setCurrentIndex(3); - event->accept(); - break; - case Qt::Key_5: - setCurrentIndex(4); - event->accept(); - break; - default: - break; - } -} } // namespace output diff --git a/src/core/filters/output/TabbedImageView.h b/src/core/filters/output/TabbedImageView.h index b4c442b52..e58d3a995 100644 --- a/src/core/filters/output/TabbedImageView.h +++ b/src/core/filters/output/TabbedImageView.h @@ -13,6 +13,7 @@ #include "ImageViewTab.h" class ImageViewBase; +class QShortcut; namespace output { class TabbedImageView : public QTabWidget { @@ -35,9 +36,6 @@ class TabbedImageView : public QTabWidget { void tabChanged(ImageViewTab tab); - protected: - void keyReleaseEvent(QKeyEvent* event) override; - private slots: void tabChangedSlot(int idx); @@ -52,6 +50,8 @@ class TabbedImageView : public QTabWidget { std::unordered_map m_registry; std::unique_ptr m_tabImageRectMap; int m_prevImageViewTabIndex; + + QShortcut* m_tabShortcuts[5]; }; } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_TABBEDIMAGEVIEW_H_ diff --git a/src/core/filters/output/Task.cpp b/src/core/filters/output/Task.cpp index 06403f68d..276747df0 100644 --- a/src/core/filters/output/Task.cpp +++ b/src/core/filters/output/Task.cpp @@ -47,8 +47,8 @@ namespace output { class Task::UiUpdater : public FilterResult { Q_DECLARE_TR_FUNCTIONS(output::Task::UiUpdater) public: - UiUpdater(intrusive_ptr filter, - intrusive_ptr settings, + UiUpdater(std::shared_ptr filter, + std::shared_ptr settings, std::unique_ptr dbgImg, const Params& params, const ImageTransformation& xform, @@ -64,11 +64,11 @@ class Task::UiUpdater : public FilterResult { void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; - intrusive_ptr m_settings; + std::shared_ptr m_filter; + std::shared_ptr m_settings; std::unique_ptr m_dbg; Params m_params; ImageTransformation m_xform; @@ -86,9 +86,9 @@ class Task::UiUpdater : public FilterResult { }; -Task::Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr thumbnailCache, +Task::Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr thumbnailCache, const PageId& pageId, const OutputFileNameGenerator& outFileNameGen, const ImageViewTab lastTab, @@ -115,20 +115,21 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, Params params = m_settings->getParams(m_pageId); RenderParams renderParams(params.colorParams(), params.splittingOptions()); - const QString outFilePath(m_outFileNameGen.filePathFor(m_pageId)); - const QFileInfo outFileInfo(outFilePath); ImageTransformation newXform(data.xform()); newXform.postScaleToDpi(params.outputDpi()); + const QFileInfo sourceFileInfo(m_pageId.imageId().filePath()); + const QString outFilePath(m_outFileNameGen.filePathFor(m_pageId)); + const QFileInfo outFileInfo(outFilePath); const QString foregroundDir(Utils::foregroundDir(m_outFileNameGen.outDir())); const QString backgroundDir(Utils::backgroundDir(m_outFileNameGen.outDir())); const QString originalBackgroundDir(Utils::originalBackgroundDir(m_outFileNameGen.outDir())); const QString foregroundFilePath(QDir(foregroundDir).absoluteFilePath(outFileInfo.fileName())); - const QString backgroundFilePath(QDir(backgroundDir).absoluteFilePath(outFileInfo.fileName())); - const QString originalBackgroundFilePath(QDir(originalBackgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo foregroundFileInfo(foregroundFilePath); + const QString backgroundFilePath(QDir(backgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo backgroundFileInfo(backgroundFilePath); + const QString originalBackgroundFilePath(QDir(originalBackgroundDir).absoluteFilePath(outFileInfo.fileName())); const QFileInfo originalBackgroundFileInfo(originalBackgroundFilePath); const QString automaskDir(Utils::automaskDir(m_outFileNameGen.outDir())); @@ -141,7 +142,7 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, const bool needPictureEditor = renderParams.mixedOutput() && !m_batchProcessing; const bool needSpecklesImage - = params.despeckleLevel() != DESPECKLE_OFF && renderParams.needBinarization() && !m_batchProcessing; + = ((params.despeckleLevel() != .0) && renderParams.needBinarization() && !m_batchProcessing); { std::unique_ptr storedOutputParams(m_settings->getOutputParams(m_pageId)); @@ -190,12 +191,15 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, break; } + if (!storedOutputParams->sourceFileParams().matches(OutputFileParams(sourceFileInfo))) { + needReprocess = true; + break; + } if (!renderParams.splitOutput()) { if (!outFileInfo.exists()) { needReprocess = true; break; } - if (!storedOutputParams->outputFileParams().matches(OutputFileParams(outFileInfo))) { needReprocess = true; break; @@ -210,7 +214,6 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, needReprocess = true; break; } - if (renderParams.originalBackground()) { if (!originalBackgroundFileInfo.exists()) { needReprocess = true; @@ -301,7 +304,7 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, // for visualization purposes, but also for re-doing despeckling at // different levels without going through the whole output generation process. const bool writeAutomask = renderParams.mixedOutput(); - const bool writeSpecklesFile = params.despeckleLevel() != DESPECKLE_OFF && renderParams.needBinarization(); + const bool writeSpecklesFile = ((params.despeckleLevel() != .0) && renderParams.needBinarization()); automaskImg = BinaryImage(); specklesImg = BinaryImage(); @@ -407,7 +410,7 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, // Note that we can't reuse *_file_info objects // as we've just overwritten those files. const OutputParams outParams( - newOutputImageParams, OutputFileParams(QFileInfo(outFilePath)), + newOutputImageParams, OutputFileParams(sourceFileInfo), OutputFileParams(QFileInfo(outFilePath)), renderParams.splitOutput() ? OutputFileParams(QFileInfo(foregroundFilePath)) : OutputFileParams(), renderParams.splitOutput() ? OutputFileParams(QFileInfo(backgroundFilePath)) : OutputFileParams(), renderParams.originalBackground() ? OutputFileParams(QFileInfo(originalBackgroundFilePath)) @@ -431,9 +434,9 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, // Otherwise it will get constructed on demand. despeckleVisualization = despeckleState.visualize(); } - return make_intrusive(m_filter, m_settings, std::move(m_dbg), params, newXform, - generator.outputContentRect(), m_pageId, data.origImage(), outImg, automaskImg, - despeckleState, despeckleVisualization, m_batchProcessing, m_debug); + return std::make_shared(m_filter, m_settings, std::move(m_dbg), params, newXform, + generator.outputContentRect(), m_pageId, data.origImage(), outImg, automaskImg, + despeckleState, despeckleVisualization, m_batchProcessing, m_debug); } // Task::process /** @@ -454,8 +457,8 @@ void Task::deleteMutuallyExclusiveOutputFiles() { /*============================ Task::UiUpdater ==========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, - intrusive_ptr settings, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, + std::shared_ptr settings, std::unique_ptr dbgImg, const Params& params, const ImageTransformation& xform, diff --git a/src/core/filters/output/Task.h b/src/core/filters/output/Task.h index 78d5da44f..817282d51 100644 --- a/src/core/filters/output/Task.h +++ b/src/core/filters/output/Task.h @@ -13,7 +13,6 @@ #include "NonCopyable.h" #include "OutputFileNameGenerator.h" #include "PageId.h" -#include "ref_countable.h" class DebugImages; class TaskStatus; @@ -33,20 +32,20 @@ namespace output { class Filter; class Settings; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: - Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr thumbnailCache, + Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr thumbnailCache, const PageId& pageId, const OutputFileNameGenerator& outFileNameGen, ImageViewTab lastTab, bool batch, bool debug); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, const FilterData& data, const QPolygonF& contentRectPhys); @@ -55,9 +54,9 @@ class Task : public ref_countable { void deleteMutuallyExclusiveOutputFiles(); - intrusive_ptr m_filter; - intrusive_ptr m_settings; - intrusive_ptr m_thumbnailCache; + std::shared_ptr m_filter; + std::shared_ptr m_settings; + std::shared_ptr m_thumbnailCache; std::unique_ptr m_dbg; PageId m_pageId; OutputFileNameGenerator m_outFileNameGen; diff --git a/src/core/filters/output/Thumbnail.cpp b/src/core/filters/output/Thumbnail.cpp index 60435caef..ba18eb132 100644 --- a/src/core/filters/output/Thumbnail.cpp +++ b/src/core/filters/output/Thumbnail.cpp @@ -6,7 +6,7 @@ #include namespace output { -Thumbnail::Thumbnail(intrusive_ptr thumbnailCache, +Thumbnail::Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform) diff --git a/src/core/filters/output/Thumbnail.h b/src/core/filters/output/Thumbnail.h index f69ac3270..baebc71cd 100644 --- a/src/core/filters/output/Thumbnail.h +++ b/src/core/filters/output/Thumbnail.h @@ -4,8 +4,9 @@ #ifndef SCANTAILOR_OUTPUT_THUMBNAIL_H_ #define SCANTAILOR_OUTPUT_THUMBNAIL_H_ +#include + #include "ThumbnailBase.h" -#include "intrusive_ptr.h" class ThumbnailPixmapCache; class ImageTransformation; @@ -15,7 +16,7 @@ class QSizeF; namespace output { class Thumbnail : public ThumbnailBase { public: - Thumbnail(intrusive_ptr thumbnailCache, + Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform); diff --git a/src/core/filters/output/Utils.cpp b/src/core/filters/output/Utils.cpp index 91feb234e..55c65d776 100644 --- a/src/core/filters/output/Utils.cpp +++ b/src/core/filters/output/Utils.cpp @@ -3,11 +3,15 @@ #include "Utils.h" +#include +#include + #include #include #include #include "Dpi.h" +#include "Params.h" namespace output { QString Utils::automaskDir(const QString& outDir) { @@ -52,4 +56,13 @@ QTransform Utils::rotate(double degrees, const QRect& imageRect) { rotateXform *= QTransform().translate(origin.x(), origin.y()); return rotateXform; } + +Params Utils::buildDefaultParams() { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::OutputParams& outputParams = defaultParams.getOutputParams(); + + return Params(outputParams.getDpi(), outputParams.getColorParams(), outputParams.getSplittingOptions(), + outputParams.getPictureShapeOptions(), dewarping::DistortionModel(), outputParams.getDepthPerception(), + outputParams.getDewarpingOptions(), outputParams.getDespeckleLevel()); +} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/Utils.h b/src/core/filters/output/Utils.h index e9939dbf4..6fd8063eb 100644 --- a/src/core/filters/output/Utils.h +++ b/src/core/filters/output/Utils.h @@ -10,8 +10,12 @@ class QTransform; class QRect; namespace output { +class Params; + class Utils { public: + Utils() = default; + static QString automaskDir(const QString& outDir); static QString predespeckleDir(const QString& outDir); @@ -28,7 +32,7 @@ class Utils { static QTransform rotate(double degrees, const QRect& imageRect); - Utils() = delete; + static Params buildDefaultParams(); }; } // namespace output #endif diff --git a/src/core/filters/output/WolfBinarizationOptionsWidget.cpp b/src/core/filters/output/WolfBinarizationOptionsWidget.cpp index e8940eb77..1faf46811 100644 --- a/src/core/filters/output/WolfBinarizationOptionsWidget.cpp +++ b/src/core/filters/output/WolfBinarizationOptionsWidget.cpp @@ -7,7 +7,7 @@ namespace output { -WolfBinarizationOptionsWidget::WolfBinarizationOptionsWidget(intrusive_ptr settings) +WolfBinarizationOptionsWidget::WolfBinarizationOptionsWidget(std::shared_ptr settings) : m_settings(std::move(settings)), m_connectionManager(std::bind(&WolfBinarizationOptionsWidget::setupUiConnections, this)) { setupUi(this); diff --git a/src/core/filters/output/WolfBinarizationOptionsWidget.h b/src/core/filters/output/WolfBinarizationOptionsWidget.h index bdf6bd25f..c365a5407 100644 --- a/src/core/filters/output/WolfBinarizationOptionsWidget.h +++ b/src/core/filters/output/WolfBinarizationOptionsWidget.h @@ -8,18 +8,18 @@ #include #include +#include #include "BinarizationOptionsWidget.h" #include "ColorParams.h" #include "Settings.h" -#include "intrusive_ptr.h" #include "ui_WolfBinarizationOptionsWidget.h" namespace output { class WolfBinarizationOptionsWidget : public BinarizationOptionsWidget, private Ui::WolfBinarizationOptionsWidget { Q_OBJECT public: - explicit WolfBinarizationOptionsWidget(intrusive_ptr settings); + explicit WolfBinarizationOptionsWidget(std::shared_ptr settings); ~WolfBinarizationOptionsWidget() override = default; @@ -42,7 +42,7 @@ class WolfBinarizationOptionsWidget : public BinarizationOptionsWidget, private void setupUiConnections(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageId m_pageId; ColorParams m_colorParams; QTimer m_delayedStateChanger; diff --git a/src/core/filters/output/ZoneCategoryProperty.cpp b/src/core/filters/output/ZoneCategoryProperty.cpp index a98844026..47e68c39b 100644 --- a/src/core/filters/output/ZoneCategoryProperty.cpp +++ b/src/core/filters/output/ZoneCategoryProperty.cpp @@ -20,8 +20,8 @@ void ZoneCategoryProperty::registerIn(PropertyFactory& factory) { factory.registerProperty(m_propertyName, &ZoneCategoryProperty::construct); } -intrusive_ptr ZoneCategoryProperty::clone() const { - return make_intrusive(*this); +std::shared_ptr ZoneCategoryProperty::clone() const { + return std::make_shared(*this); } QDomElement ZoneCategoryProperty::toXml(QDomDocument& doc, const QString& name) const { @@ -31,8 +31,8 @@ QDomElement ZoneCategoryProperty::toXml(QDomDocument& doc, const QString& name) return el; } -intrusive_ptr ZoneCategoryProperty::construct(const QDomElement& el) { - return make_intrusive(el); +std::shared_ptr ZoneCategoryProperty::construct(const QDomElement& el) { + return std::make_shared(el); } ZoneCategoryProperty::ZoneCategory ZoneCategoryProperty::zoneCategoryFromString(const QString& str) { @@ -59,12 +59,4 @@ QString ZoneCategoryProperty::zoneCategoryToString(ZoneCategory zoneCategory) { } return str; } - -ZoneCategoryProperty::ZoneCategory ZoneCategoryProperty::zoneCategory() const { - return m_zoneCategory; -} - -void ZoneCategoryProperty::setZoneCategory(ZoneCategoryProperty::ZoneCategory zoneCategory) { - m_zoneCategory = zoneCategory; -} } // namespace output \ No newline at end of file diff --git a/src/core/filters/output/ZoneCategoryProperty.h b/src/core/filters/output/ZoneCategoryProperty.h index c58a3cb39..44f610f07 100644 --- a/src/core/filters/output/ZoneCategoryProperty.h +++ b/src/core/filters/output/ZoneCategoryProperty.h @@ -4,8 +4,9 @@ #ifndef SCANTAILOR_OUTPUT_ZONECATEGORYPROPERTY_H_ #define SCANTAILOR_OUTPUT_ZONECATEGORYPROPERTY_H_ +#include + #include "Property.h" -#include "intrusive_ptr.h" class PropertyFactory; class QDomDocument; @@ -23,7 +24,7 @@ class ZoneCategoryProperty : public Property { static void registerIn(PropertyFactory& factory); - intrusive_ptr clone() const override; + std::shared_ptr clone() const override; QDomElement toXml(QDomDocument& doc, const QString& name) const override; @@ -32,7 +33,7 @@ class ZoneCategoryProperty : public Property { void setZoneCategory(ZoneCategory zoneCategory); private: - static intrusive_ptr construct(const QDomElement& el); + static std::shared_ptr construct(const QDomElement& el); static ZoneCategory zoneCategoryFromString(const QString& str); @@ -42,6 +43,15 @@ class ZoneCategoryProperty : public Property { static const char m_propertyName[]; ZoneCategory m_zoneCategory; }; + + +inline ZoneCategoryProperty::ZoneCategory ZoneCategoryProperty::zoneCategory() const { + return m_zoneCategory; +} + +inline void ZoneCategoryProperty::setZoneCategory(ZoneCategoryProperty::ZoneCategory zoneCategory) { + m_zoneCategory = zoneCategory; +} } // namespace output #endif // ifndef SCANTAILOR_OUTPUT_ZONECATEGORYPROPERTY_H_ diff --git a/src/core/filters/page_layout/Alignment.cpp b/src/core/filters/page_layout/Alignment.cpp index 18fd578d7..42e6c0622 100644 --- a/src/core/filters/page_layout/Alignment.cpp +++ b/src/core/filters/page_layout/Alignment.cpp @@ -12,9 +12,9 @@ Alignment::Alignment(Vertical vertical, Horizontal horizontal) : m_vertical(vertical), m_horizontal(horizontal), m_isNull(false) {} Alignment::Alignment(const QDomElement& el) { - const QString vert(el.attribute("vert")); - const QString hor(el.attribute("hor")); - m_isNull = el.attribute("null").toInt() != 0; + const QString vert = el.attribute("vert"); + const QString hor = el.attribute("hor"); + m_isNull = (el.attribute("null").toInt() != 0); if (vert == "top") { m_vertical = TOP; @@ -34,7 +34,7 @@ Alignment::Alignment(const QDomElement& el) { m_horizontal = RIGHT; } else if (hor == "auto") { m_horizontal = HAUTO; - } else if (vert == "original") { + } else if (hor == "original") { m_horizontal = HORIGINAL; } else { m_horizontal = HCENTER; @@ -48,7 +48,7 @@ QDomElement Alignment::toXml(QDomDocument& doc, const QString& name) const { vert = "top"; break; case VCENTER: - vert = "vcenter"; + vert = "center"; break; case BOTTOM: vert = "bottom"; @@ -67,7 +67,7 @@ QDomElement Alignment::toXml(QDomDocument& doc, const QString& name) const { hor = "left"; break; case HCENTER: - hor = "hcenter"; + hor = "center"; break; case RIGHT: hor = "right"; @@ -94,36 +94,4 @@ bool Alignment::operator==(const Alignment& other) const { bool Alignment::operator!=(const Alignment& other) const { return !(*this == other); } - -Alignment::Vertical Alignment::vertical() const { - return m_vertical; -} - -void Alignment::setVertical(Alignment::Vertical vertical) { - m_vertical = vertical; -} - -Alignment::Horizontal Alignment::horizontal() const { - return m_horizontal; -} - -void Alignment::setHorizontal(Alignment::Horizontal horizontal) { - m_horizontal = horizontal; -} - -bool Alignment::isNull() const { - return m_isNull; -} - -void Alignment::setNull(bool isNull) { - m_isNull = isNull; -} - -bool Alignment::isAutoVertical() const { - return (m_vertical == VAUTO) || (m_vertical == VORIGINAL); -} - -bool Alignment::isAutoHorizontal() const { - return (m_horizontal == HAUTO) || (m_horizontal == HORIGINAL); -} } // namespace page_layout diff --git a/src/core/filters/page_layout/Alignment.h b/src/core/filters/page_layout/Alignment.h index e94f2e8e4..be9c4d9e7 100644 --- a/src/core/filters/page_layout/Alignment.h +++ b/src/core/filters/page_layout/Alignment.h @@ -55,5 +55,38 @@ class Alignment { Horizontal m_horizontal; bool m_isNull; }; + + +inline Alignment::Vertical Alignment::vertical() const { + return m_vertical; +} + +inline void Alignment::setVertical(Alignment::Vertical vertical) { + m_vertical = vertical; +} + +inline Alignment::Horizontal Alignment::horizontal() const { + return m_horizontal; +} + +inline void Alignment::setHorizontal(Alignment::Horizontal horizontal) { + m_horizontal = horizontal; +} + +inline bool Alignment::isNull() const { + return m_isNull; +} + +inline void Alignment::setNull(bool isNull) { + m_isNull = isNull; +} + +inline bool Alignment::isAutoVertical() const { + return (m_vertical == VAUTO) || (m_vertical == VORIGINAL); +} + +inline bool Alignment::isAutoHorizontal() const { + return (m_horizontal == HAUTO) || (m_horizontal == HORIGINAL); +} } // namespace page_layout #endif // ifndef SCANTAILOR_PAGE_LAYOUT_ALIGNMENT_H_ diff --git a/src/core/filters/page_layout/ApplyDialog.h b/src/core/filters/page_layout/ApplyDialog.h index aaa09a382..dadff1a59 100644 --- a/src/core/filters/page_layout/ApplyDialog.h +++ b/src/core/filters/page_layout/ApplyDialog.h @@ -6,12 +6,12 @@ #include #include +#include #include #include "PageId.h" #include "PageRange.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ApplyDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/page_layout/CMakeLists.txt b/src/core/filters/page_layout/CMakeLists.txt index 021e510fa..ef6368c32 100644 --- a/src/core/filters/page_layout/CMakeLists.txt +++ b/src/core/filters/page_layout/CMakeLists.txt @@ -21,6 +21,6 @@ set(sources Guide.cpp Guide.h) add_library(page_layout STATIC ${sources} ${ui_files}) -target_link_libraries(page_layout PUBLIC core interaction) +target_link_libraries(page_layout PUBLIC core) translation_sources(scantailor ${sources} ${ui_files}) \ No newline at end of file diff --git a/src/core/filters/page_layout/CacheDrivenTask.cpp b/src/core/filters/page_layout/CacheDrivenTask.cpp index 47abe5fdd..b43572b1b 100644 --- a/src/core/filters/page_layout/CacheDrivenTask.cpp +++ b/src/core/filters/page_layout/CacheDrivenTask.cpp @@ -18,7 +18,7 @@ #include "filters/output/CacheDrivenTask.h" namespace page_layout { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr nextTask, intrusive_ptr settings) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr nextTask, std::shared_ptr settings) : m_nextTask(std::move(nextTask)), m_settings(std::move(settings)) {} CacheDrivenTask::~CacheDrivenTask() = default; @@ -58,10 +58,9 @@ void CacheDrivenTask::process(const PageInfo& pageInfo, const double deviationThreshold = settings.getMarginsDeviationThreshold(); if (auto* thumbCol = dynamic_cast(collector)) { - thumbCol->processThumbnail(std::unique_ptr( - new Thumbnail(thumbCol->thumbnailCache(), thumbCol->maxLogicalThumbSize(), pageInfo.imageId(), newParams, xform, - contentRectPhys, xform.transform().map(pageRectPhys).boundingRect(), - m_settings->deviationProvider().isDeviant(pageInfo.id(), deviationCoef, deviationThreshold)))); + thumbCol->processThumbnail(std::unique_ptr(new Thumbnail( + thumbCol->thumbnailCache(), thumbCol->maxLogicalThumbSize(), pageInfo.imageId(), newParams, newXform, + contentRectPhys, m_settings->deviationProvider().isDeviant(pageInfo.id(), deviationCoef, deviationThreshold)))); } } } // namespace page_layout \ No newline at end of file diff --git a/src/core/filters/page_layout/CacheDrivenTask.h b/src/core/filters/page_layout/CacheDrivenTask.h index e897a21ff..900c26976 100644 --- a/src/core/filters/page_layout/CacheDrivenTask.h +++ b/src/core/filters/page_layout/CacheDrivenTask.h @@ -5,10 +5,9 @@ #define SCANTAILOR_PAGE_LAYOUT_CACHEDRIVENTASK_H_ #include +#include #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QRectF; class PageInfo; @@ -22,13 +21,13 @@ class CacheDrivenTask; namespace page_layout { class Settings; -class CacheDrivenTask : public ref_countable { +class CacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr nextTask, intrusive_ptr settings); + CacheDrivenTask(std::shared_ptr nextTask, std::shared_ptr settings); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector, @@ -37,8 +36,8 @@ class CacheDrivenTask : public ref_countable { const QRectF& contentRect); private: - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; }; } // namespace page_layout #endif // ifndef SCANTAILOR_PAGE_LAYOUT_CACHEDRIVENTASK_H_ diff --git a/src/core/filters/page_layout/Filter.cpp b/src/core/filters/page_layout/Filter.cpp index 702de18f9..557e0c8d9 100644 --- a/src/core/filters/page_layout/Filter.cpp +++ b/src/core/filters/page_layout/Filter.cpp @@ -3,15 +3,10 @@ #include "Filter.h" -#include -#include #include -#include #include #include -#include -#include #include #include "CacheDrivenTask.h" @@ -29,14 +24,14 @@ #include "Utils.h" namespace page_layout { -Filter::Filter(intrusive_ptr pages, const PageSelectionAccessor& pageSelectionAccessor) - : m_pages(std::move(pages)), m_settings(new Settings), m_selectedPageOrder(0) { +Filter::Filter(std::shared_ptr pages, const PageSelectionAccessor& pageSelectionAccessor) + : m_pages(std::move(pages)), m_settings(std::make_shared()), m_selectedPageOrder(0) { m_optionsWidget.reset(new OptionsWidget(m_settings, pageSelectionAccessor)); const PageOrderOption::ProviderPtr defaultOrder; - const auto orderByWidth = make_intrusive(m_settings); - const auto orderByHeight = make_intrusive(m_settings); - const auto orderByDeviation = make_intrusive(m_settings->deviationProvider()); + const auto orderByWidth = std::make_shared(m_settings); + const auto orderByHeight = std::make_shared(m_settings); + const auto orderByDeviation = std::make_shared(m_settings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), defaultOrder); m_pageOrderOptions.emplace_back(tr("Order by increasing width"), orderByWidth); m_pageOrderOptions.emplace_back(tr("Order by increasing height"), orderByHeight); @@ -176,37 +171,23 @@ bool Filter::checkReadyForOutput(const ProjectPages& pages, const PageId* ignore return m_settings->checkEverythingDefined(snapshot, ignore); } -intrusive_ptr Filter::createTask(const PageId& pageId, - intrusive_ptr nextTask, - const bool batch, - const bool debug) { - return make_intrusive(intrusive_ptr(this), std::move(nextTask), m_settings, pageId, batch, debug); +std::shared_ptr Filter::createTask(const PageId& pageId, + std::shared_ptr nextTask, + const bool batch, + const bool debug) { + return std::make_shared(std::static_pointer_cast(shared_from_this()), std::move(nextTask), m_settings, + pageId, batch, debug); } -intrusive_ptr Filter::createCacheDrivenTask(intrusive_ptr nextTask) { - return make_intrusive(std::move(nextTask), m_settings); +std::shared_ptr Filter::createCacheDrivenTask(std::shared_ptr nextTask) { + return std::make_shared(std::move(nextTask), m_settings); } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->isParamsNull(pageInfo.id())) { + if (!m_settings->isParamsNull(pageInfo.id())) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::PageLayoutParams& pageLayoutParams = defaultParams.getPageLayoutParams(); - - const UnitsConverter unitsConverter(pageInfo.metadata().dpi()); - - const Margins& margins = pageLayoutParams.getHardMargins(); - double leftMargin = margins.left(); - double topMargin = margins.top(); - double rightMargin = margins.right(); - double bottomMargin = margins.bottom(); - unitsConverter.convert(leftMargin, topMargin, defaultParams.getUnits(), MILLIMETRES); - unitsConverter.convert(rightMargin, bottomMargin, defaultParams.getUnits(), MILLIMETRES); - - m_settings->setPageParams( - pageInfo.id(), Params(Margins(leftMargin, topMargin, rightMargin, bottomMargin), QRectF(), QRectF(), QSizeF(), - pageLayoutParams.getAlignment(), pageLayoutParams.isAutoMargins())); + + m_settings->setPageParams(pageInfo.id(), Utils::buildDefaultParams(pageInfo.metadata().dpi())); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/page_layout/Filter.h b/src/core/filters/page_layout/Filter.h index 1ac3bce69..c2cdf670f 100644 --- a/src/core/filters/page_layout/Filter.h +++ b/src/core/filters/page_layout/Filter.h @@ -5,6 +5,7 @@ #define SCANTAILOR_PAGE_LAYOUT_FILTER_H_ #include +#include #include #include "AbstractFilter.h" @@ -13,7 +14,6 @@ #include "PageOrderOption.h" #include "PageView.h" #include "SafeDeletingQObjectPtr.h" -#include "intrusive_ptr.h" class ProjectPages; class PageSelectionAccessor; @@ -37,7 +37,7 @@ class Filter : public AbstractFilter { Q_DECLARE_TR_FUNCTIONS(page_layout::Filter) public: - Filter(intrusive_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor); + Filter(std::shared_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor); ~Filter() override; @@ -69,17 +69,20 @@ class Filter : public AbstractFilter { bool checkReadyForOutput(const ProjectPages& pages, const PageId* ignore = nullptr); - intrusive_ptr createTask(const PageId& pageId, intrusive_ptr nextTask, bool batch, bool debug); + std::shared_ptr createTask(const PageId& pageId, + std::shared_ptr nextTask, + bool batch, + bool debug); - intrusive_ptr createCacheDrivenTask(intrusive_ptr nextTask); + std::shared_ptr createCacheDrivenTask(std::shared_ptr nextTask); OptionsWidget* optionsWidget(); private: void writePageSettings(QDomDocument& doc, QDomElement& filterEl, const PageId& pageId, int numericId) const; - intrusive_ptr m_pages; - intrusive_ptr m_settings; + std::shared_ptr m_pages; + std::shared_ptr m_settings; SafeDeletingQObjectPtr m_optionsWidget; std::vector m_pageOrderOptions; int m_selectedPageOrder; diff --git a/src/core/filters/page_layout/Guide.cpp b/src/core/filters/page_layout/Guide.cpp index 79e48525b..8437359c9 100644 --- a/src/core/filters/page_layout/Guide.cpp +++ b/src/core/filters/page_layout/Guide.cpp @@ -14,18 +14,6 @@ Guide::Guide(const Qt::Orientation orientation, const double position) Guide::Guide(const QLineF& line) : m_orientation(lineOrientation(line)), m_position((m_orientation == Qt::Horizontal) ? line.y1() : line.x1()) {} -Qt::Orientation Guide::getOrientation() const { - return m_orientation; -} - -double Guide::getPosition() const { - return m_position; -} - -void Guide::setPosition(double position) { - Guide::m_position = position; -} - Qt::Orientation Guide::lineOrientation(const QLineF& line) { const double angleCos = std::abs((line.p2().x() - line.p1().x()) / line.length()); return (angleCos > (1.0 / std::sqrt(2))) ? Qt::Horizontal : Qt::Vertical; diff --git a/src/core/filters/page_layout/Guide.h b/src/core/filters/page_layout/Guide.h index 53e97a9e5..7b0560142 100644 --- a/src/core/filters/page_layout/Guide.h +++ b/src/core/filters/page_layout/Guide.h @@ -38,6 +38,19 @@ class Guide { Qt::Orientation m_orientation; double m_position; }; + + +inline Qt::Orientation Guide::getOrientation() const { + return m_orientation; +} + +inline double Guide::getPosition() const { + return m_position; +} + +inline void Guide::setPosition(double position) { + Guide::m_position = position; +} } // namespace page_layout #endif // ifndef SCANTAILOR_PAGE_LAYOUT_GUIDE_H_ \ No newline at end of file diff --git a/src/core/filters/page_layout/ImageView.cpp b/src/core/filters/page_layout/ImageView.cpp index 03703502e..586026ded 100644 --- a/src/core/filters/page_layout/ImageView.cpp +++ b/src/core/filters/page_layout/ImageView.cpp @@ -3,18 +3,15 @@ #include "ImageView.h" -#include -#include #include #include #include -#include #include -#include #include #include #include +#include #include #include @@ -27,11 +24,11 @@ using namespace imageproc; namespace page_layout { -ImageView::ImageView(const intrusive_ptr& settings, +ImageView::ImageView(const std::shared_ptr& settings, const PageId& pageId, const QImage& image, const QImage& downscaledImage, - const imageproc::GrayImage& grayImage, + const ContentMask& contentMask, const ImageTransformation& xform, const QRectF& adaptedContentRect, const OptionsWidget& optWidget) @@ -57,7 +54,8 @@ ImageView::ImageView(const intrusive_ptr& settings, m_guideUnderMouse(-1), m_innerRectVerticalDragModifier(Qt::ControlModifier), m_innerRectHorizontalDragModifier(Qt::ShiftModifier), - m_nullContentRect((m_innerRect.width() < 1) && (m_innerRect.height() < 1)) { + m_nullContentRect((m_innerRect.width() < 1) && (m_innerRect.height() < 1)), + m_contentMask(contentMask) { setMouseTracking(true); interactionState().setDefaultStatusTip(tr("Resize margins by dragging any of the solid lines.")); @@ -153,8 +151,6 @@ ImageView::ImageView(const intrusive_ptr& settings, setupGuides(); recalcBoxesAndFit(optWidget.marginsMM()); - - buildContentImage(grayImage, xform); } ImageView::~ImageView() = default; @@ -713,7 +709,7 @@ void ImageView::onContextMenuEvent(QContextMenuEvent* event, InteractionState& i void ImageView::setupGuides() { for (const Guide& guide : m_settings->guides()) { - m_guides[m_guidesFreeIndex] = guide; + m_guides[m_guidesFreeIndex] = m_mmToPixelsXform.map(guide); setupGuideInteraction(m_guidesFreeIndex++); } } @@ -787,7 +783,7 @@ QTransform ImageView::guideToWidgetCs() const { void ImageView::syncGuidesSettings() { m_settings->guides().clear(); for (const auto& idxAndGuide : m_guides) { - m_settings->guides().push_back(idxAndGuide.second); + m_settings->guides().emplace_back(m_pixelsToMmXform.map(idxAndGuide.second)); } } @@ -803,7 +799,7 @@ void ImageView::setupGuideInteraction(const int index) { m_draggableGuideHandlers[index].setProximityCursor(cursorShape); m_draggableGuideHandlers[index].setInteractionCursor(cursorShape); m_draggableGuideHandlers[index].setProximityStatusTip(tr("Drag the guide.")); - m_draggableGuideHandlers[index].setKeyboardModifiers({Qt::ShiftModifier}); + m_draggableGuideHandlers[index].setKeyboardModifiers({Qt::ControlModifier | Qt::AltModifier}); if (!m_alignment.isNull()) { makeLastFollower(m_draggableGuideHandlers[index]); @@ -940,59 +936,6 @@ Proximity ImageView::rectProximity(const QRectF& box, const QPointF& mousePos) c return Proximity::fromSqDist(value); } -void ImageView::buildContentImage(const GrayImage& grayImage, const ImageTransformation& xform) { - ImageTransformation xform150dpi(xform); - xform150dpi.preScaleToDpi(Dpi(150, 150)); - - if (xform150dpi.resultingRect().toRect().isEmpty()) { - return; - } - - QImage gray150(transformToGray(grayImage, xform150dpi.transform(), xform150dpi.resultingRect().toRect(), - OutsidePixels::assumeColor(Qt::white))); - - m_contentImage = binarizeWolf(gray150, QSize(51, 51), 50); - - PolygonRasterizer::fillExcept(m_contentImage, WHITE, xform150dpi.resultingPreCropArea(), Qt::WindingFill); - - Despeckle::despeckleInPlace(m_contentImage, Dpi(150, 150), Despeckle::NORMAL, NullTaskStatus()); - - m_originalToContentImage = xform150dpi.transform(); - m_contentImageToOriginal = m_originalToContentImage.inverted(); -} - -QRect ImageView::findContentInArea(const QRect& area) const { - const uint32_t* imageLine = m_contentImage.data(); - const int imageStride = m_contentImage.wordsPerLine(); - const uint32_t msb = uint32_t(1) << 31; - - int top = std::numeric_limits::max(); - int left = std::numeric_limits::max(); - int bottom = std::numeric_limits::min(); - int right = std::numeric_limits::min(); - - imageLine += area.top() * imageStride; - for (int y = area.top(); y <= area.bottom(); ++y) { - for (int x = area.left(); x <= area.right(); ++x) { - if (imageLine[x >> 5] & (msb >> (x & 31))) { - top = std::min(top, y); - left = std::min(left, x); - bottom = std::max(bottom, y); - right = std::max(right, x); - } - } - imageLine += imageStride; - } - - if (top > bottom) { - return QRect(); - } - - QRect foundArea = QRect(left, top, right - left + 1, bottom - top + 1); - foundArea.adjust(-1, -1, 1, 1); - return foundArea; -} - void ImageView::onMouseDoubleClickEvent(QMouseEvent* event, InteractionState& interaction) { if (event->button() == Qt::LeftButton) { if (!m_alignment.isNull() && !m_guides.empty()) { @@ -1002,18 +945,12 @@ void ImageView::onMouseDoubleClickEvent(QMouseEvent* event, InteractionState& in } void ImageView::attachContentToNearestGuide(const QPointF& pos, const Qt::KeyboardModifiers mask) { - const QTransform widgetToContentImage(widgetToImage() * m_originalToContentImage); - const QTransform contentImageToVirtual(m_contentImageToOriginal * imageToVirtual()); + const QTransform widgetToContentImage(widgetToImage() * m_contentMask.originalToContentXform()); + const QTransform contentImageToVirtual(m_contentMask.contentToOriginalXform() * imageToVirtual()); const QPointF contentPos = widgetToContentImage.map(pos); - QRect findingArea((contentPos - QPointF(15, 15)).toPoint(), QSize(30, 30)); - findingArea = findingArea.intersected(m_contentImage.rect()); - if (findingArea.isEmpty()) { - return; - } - - QRect foundArea = findContentInArea(findingArea); + QRect foundArea = m_contentMask.findContentInArea(findingArea); if (foundArea.isEmpty()) { return; } @@ -1138,4 +1075,4 @@ void ImageView::enableMiddleRectInteraction(const bool state) { bool ImageView::isShowingMiddleRectEnabled() const { return (!m_nullContentRect && m_settings->isShowingMiddleRectEnabled()) || m_alignment.isNull(); } -} // namespace page_layout \ No newline at end of file +} // namespace page_layout diff --git a/src/core/filters/page_layout/ImageView.h b/src/core/filters/page_layout/ImageView.h index 1f9a736c8..6059942f9 100644 --- a/src/core/filters/page_layout/ImageView.h +++ b/src/core/filters/page_layout/ImageView.h @@ -4,7 +4,7 @@ #ifndef SCANTAILOR_PAGE_LAYOUT_IMAGEVIEW_H_ #define SCANTAILOR_PAGE_LAYOUT_IMAGEVIEW_H_ -#include +#include #include #include @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "Alignment.h" @@ -25,14 +26,9 @@ #include "ObjectDragHandler.h" #include "PageId.h" #include "ZoomHandler.h" -#include "intrusive_ptr.h" class Margins; -namespace imageproc { -class GrayImage; -} - namespace page_layout { class OptionsWidget; class Settings; @@ -40,11 +36,11 @@ class Settings; class ImageView : public ImageViewBase, private InteractionHandler { Q_OBJECT public: - ImageView(const intrusive_ptr& settings, + ImageView(const std::shared_ptr& settings, const PageId& pageId, const QImage& image, const QImage& downscaledImage, - const imageproc::GrayImage& grayImage, + const ContentMask& contentMask, const ImageTransformation& xform, const QRectF& adaptedContentRect, const OptionsWidget& optWidget); @@ -181,12 +177,8 @@ class ImageView : public ImageViewBase, private InteractionHandler { void innerRectMoveRequest(const QPointF& mousePos, Qt::KeyboardModifiers mask = Qt::NoModifier); - void buildContentImage(const imageproc::GrayImage& grayImage, const ImageTransformation& xform); - void attachContentToNearestGuide(const QPointF& pos, Qt::KeyboardModifiers mask = Qt::NoModifier); - QRect findContentInArea(const QRect& area) const; - void enableMiddleRectInteraction(bool state); bool isShowingMiddleRectEnabled() const; @@ -205,7 +197,7 @@ class ImageView : public ImageViewBase, private InteractionHandler { DragHandler m_dragHandler; ZoomHandler m_zoomHandler; - intrusive_ptr m_settings; + std::shared_ptr m_settings; const PageId m_pageId; @@ -296,11 +288,9 @@ class ImageView : public ImageViewBase, private InteractionHandler { Qt::KeyboardModifier m_innerRectVerticalDragModifier; Qt::KeyboardModifier m_innerRectHorizontalDragModifier; - imageproc::BinaryImage m_contentImage; - QTransform m_originalToContentImage; - QTransform m_contentImageToOriginal; - const bool m_nullContentRect; + + ContentMask m_contentMask; }; } // namespace page_layout #endif // ifndef SCANTAILOR_PAGE_LAYOUT_IMAGEVIEW_H_ diff --git a/src/core/filters/page_layout/OptionsWidget.cpp b/src/core/filters/page_layout/OptionsWidget.cpp index 5e71a22df..d69453f6e 100644 --- a/src/core/filters/page_layout/OptionsWidget.cpp +++ b/src/core/filters/page_layout/OptionsWidget.cpp @@ -16,7 +16,7 @@ using namespace core; namespace page_layout { -OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) +OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pageSelectionAccessor(pageSelectionAccessor), m_leftRightLinked(true), @@ -45,7 +45,7 @@ OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelecti Utils::mapSetValue(m_alignmentByButton, alignBottomBtn, Alignment(Alignment::BOTTOM, Alignment::HCENTER)); Utils::mapSetValue(m_alignmentByButton, alignBottomRightBtn, Alignment(Alignment::BOTTOM, Alignment::RIGHT)); - m_alignmentButtonGroup = std::make_unique(this); + m_alignmentButtonGroup = new QButtonGroup(this); for (const auto& buttonAndAlignment : m_alignmentByButton) { m_alignmentButtonGroup->addButton(buttonAndAlignment.first); } diff --git a/src/core/filters/page_layout/OptionsWidget.h b/src/core/filters/page_layout/OptionsWidget.h index bad5bff34..24dff2dd3 100644 --- a/src/core/filters/page_layout/OptionsWidget.h +++ b/src/core/filters/page_layout/OptionsWidget.h @@ -5,20 +5,19 @@ #define SCANTAILOR_PAGE_LAYOUT_OPTIONSWIDGET_H_ #include +#include #include #include #include #include #include -#include #include "Alignment.h" #include "FilterOptionsWidget.h" #include "Margins.h" #include "PageId.h" #include "PageSelectionAccessor.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" class QToolButton; @@ -30,7 +29,7 @@ class Settings; class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private Ui::OptionsWidget { Q_OBJECT public: - OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); + OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -113,7 +112,7 @@ class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private void setupIcons(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; PageSelectionAccessor m_pageSelectionAccessor; QIcon m_chainIcon; QIcon m_brokenChainIcon; @@ -124,7 +123,7 @@ class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private Alignment m_alignment; bool m_leftRightLinked; bool m_topBottomLinked; - std::unique_ptr m_alignmentButtonGroup; + QButtonGroup* m_alignmentButtonGroup; ConnectionManager m_connectionManager; }; diff --git a/src/core/filters/page_layout/OptionsWidget.ui b/src/core/filters/page_layout/OptionsWidget.ui index d397b2a5b..df87854ae 100644 --- a/src/core/filters/page_layout/OptionsWidget.ui +++ b/src/core/filters/page_layout/OptionsWidget.ui @@ -84,14 +84,14 @@ - 18 - 46 + 20 + 36 - 18 - 46 + 20 + 36 @@ -122,8 +122,8 @@ QToolButton:pressed { - 10 - 30 + 18 + 24 @@ -153,14 +153,14 @@ QToolButton:pressed { - 18 - 46 + 20 + 36 - 18 - 46 + 20 + 36 @@ -191,8 +191,8 @@ QToolButton:pressed { - 10 - 30 + 18 + 24 @@ -200,8 +200,8 @@ QToolButton:pressed { - - + + 1 @@ -220,8 +220,8 @@ QToolButton:pressed { - - + + 1 @@ -237,8 +237,8 @@ QToolButton:pressed { - - + + 1 @@ -822,7 +822,7 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Right-click</span><span style=" font-size:7pt;"> to create/remove guides from the </span><span style=" font-size:7pt; font-weight:600;">context menu</span><span style=" font-size:7pt;"> called.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Right-click</span><span style=" font-size:7pt;"> on a guide to delete that guide from the </span><span style=" font-size:7pt; font-weight:600;">context menu</span><span style=" font-size:7pt;"> called.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Shift+LMB</span><span style=" font-size:7pt;"> - drag the guide under the cursor.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Ctrl+Alt+LMB</span><span style=" font-size:7pt;"> - drag the guide under the cursor.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Shift/Ctrl+LMB</span><span style=" font-size:7pt;"> on the content rectangle - drag the page content. Hold </span><span style=" font-size:7pt; font-weight:600;">Shift</span><span style=" font-size:7pt;"> pressed to restrict moving along the horizontal axis only or </span><span style=" font-size:7pt; font-weight:600;">Ctrl</span><span style=" font-size:7pt;"> for the vertical one. Hold </span><span style=" font-size:7pt; font-weight:600;">Shift+Ctrl</span><span style=" font-size:7pt;"> for usual dragging.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣ Double-click</span><span style=" font-size:7pt;"> on content - automatically attach that content to the nearest guide. Hold </span><span style=" font-size:7pt; font-weight:600;">Shift</span><span style=" font-size:7pt;"> pressed to select vertical guides only or </span><span style=" font-size:7pt; font-weight:600;">Ctrl</span><span style=" font-size:7pt;"> for horizontal ones. Hold </span><span style=" font-size:7pt; font-weight:600;">Shift+Ctrl</span><span style=" font-size:7pt;"> to attach that to both the nearest vertical and horizontal guides.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; font-weight:600;">‣</span><span style=" font-size:7pt;"> Use the </span><span style=" font-size:7pt; font-weight:600;">context menu</span><span style=" font-size:7pt;"> to enable/disable showing the hard margins rectangle.</span></p></body></html> diff --git a/src/core/filters/page_layout/OrderByHeightProvider.cpp b/src/core/filters/page_layout/OrderByHeightProvider.cpp index 4b5529459..2ce068d0c 100644 --- a/src/core/filters/page_layout/OrderByHeightProvider.cpp +++ b/src/core/filters/page_layout/OrderByHeightProvider.cpp @@ -8,7 +8,7 @@ #include "Params.h" namespace page_layout { -OrderByHeightProvider::OrderByHeightProvider(intrusive_ptr settings) : m_settings(std::move(settings)) {} +OrderByHeightProvider::OrderByHeightProvider(std::shared_ptr settings) : m_settings(std::move(settings)) {} bool OrderByHeightProvider::precedes(const PageId& lhsPage, const bool lhsIncomplete, diff --git a/src/core/filters/page_layout/OrderByHeightProvider.h b/src/core/filters/page_layout/OrderByHeightProvider.h index 0f05d363e..56c0728ef 100644 --- a/src/core/filters/page_layout/OrderByHeightProvider.h +++ b/src/core/filters/page_layout/OrderByHeightProvider.h @@ -4,19 +4,20 @@ #ifndef SCANTAILOR_PAGE_LAYOUT_ORDERBYHEIGHTPROVIDER_H_ #define SCANTAILOR_PAGE_LAYOUT_ORDERBYHEIGHTPROVIDER_H_ +#include + #include "PageOrderProvider.h" #include "Settings.h" -#include "intrusive_ptr.h" namespace page_layout { class OrderByHeightProvider : public PageOrderProvider { public: - explicit OrderByHeightProvider(intrusive_ptr settings); + explicit OrderByHeightProvider(std::shared_ptr settings); bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override; private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace page_layout #endif diff --git a/src/core/filters/page_layout/OrderByWidthProvider.cpp b/src/core/filters/page_layout/OrderByWidthProvider.cpp index 3baa73b8f..9a883f79e 100644 --- a/src/core/filters/page_layout/OrderByWidthProvider.cpp +++ b/src/core/filters/page_layout/OrderByWidthProvider.cpp @@ -8,7 +8,7 @@ #include "Params.h" namespace page_layout { -OrderByWidthProvider::OrderByWidthProvider(intrusive_ptr settings) : m_settings(std::move(settings)) {} +OrderByWidthProvider::OrderByWidthProvider(std::shared_ptr settings) : m_settings(std::move(settings)) {} bool OrderByWidthProvider::precedes(const PageId& lhsPage, const bool lhsIncomplete, diff --git a/src/core/filters/page_layout/OrderByWidthProvider.h b/src/core/filters/page_layout/OrderByWidthProvider.h index c719ca3b7..9f9cafee3 100644 --- a/src/core/filters/page_layout/OrderByWidthProvider.h +++ b/src/core/filters/page_layout/OrderByWidthProvider.h @@ -4,19 +4,20 @@ #ifndef SCANTAILOR_PAGE_LAYOUT_ORDERBYWIDTHPROVIDER_H_ #define SCANTAILOR_PAGE_LAYOUT_ORDERBYWIDTHPROVIDER_H_ +#include + #include "PageOrderProvider.h" #include "Settings.h" -#include "intrusive_ptr.h" namespace page_layout { class OrderByWidthProvider : public PageOrderProvider { public: - explicit OrderByWidthProvider(intrusive_ptr settings); + explicit OrderByWidthProvider(std::shared_ptr settings); bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override; private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace page_layout #endif diff --git a/src/core/filters/page_layout/Params.cpp b/src/core/filters/page_layout/Params.cpp index 2f4ea9cd5..7f7943d01 100644 --- a/src/core/filters/page_layout/Params.cpp +++ b/src/core/filters/page_layout/Params.cpp @@ -40,28 +40,4 @@ QDomElement Params::toXml(QDomDocument& doc, const QString& name) const { el.setAttribute("autoMargins", m_autoMargins ? "1" : "0"); return el; } - -const Margins& Params::hardMarginsMM() const { - return m_hardMarginsMM; -} - -const QRectF& Params::contentRect() const { - return m_contentRect; -} - -const QRectF& Params::pageRect() const { - return m_pageRect; -} - -const QSizeF& Params::contentSizeMM() const { - return m_contentSizeMM; -} - -const Alignment& Params::alignment() const { - return m_alignment; -} - -bool Params::isAutoMarginsEnabled() const { - return m_autoMargins; -} } // namespace page_layout diff --git a/src/core/filters/page_layout/Params.h b/src/core/filters/page_layout/Params.h index 39c8508f9..a9feb70a7 100644 --- a/src/core/filters/page_layout/Params.h +++ b/src/core/filters/page_layout/Params.h @@ -49,5 +49,30 @@ class Params { Alignment m_alignment; bool m_autoMargins; }; + + +inline const Margins& Params::hardMarginsMM() const { + return m_hardMarginsMM; +} + +inline const QRectF& Params::contentRect() const { + return m_contentRect; +} + +inline const QRectF& Params::pageRect() const { + return m_pageRect; +} + +inline const QSizeF& Params::contentSizeMM() const { + return m_contentSizeMM; +} + +inline const Alignment& Params::alignment() const { + return m_alignment; +} + +inline bool Params::isAutoMarginsEnabled() const { + return m_autoMargins; +} } // namespace page_layout #endif // ifndef SCANTAILOR_PAGE_LAYOUT_PARAMS_H_ diff --git a/src/core/filters/page_layout/Settings.cpp b/src/core/filters/page_layout/Settings.cpp index d9bc655be..cf76cb635 100644 --- a/src/core/filters/page_layout/Settings.cpp +++ b/src/core/filters/page_layout/Settings.cpp @@ -204,7 +204,7 @@ class Settings::Impl { /*=============================== Settings ==================================*/ -Settings::Settings() : m_impl(new Impl()) {} +Settings::Settings() : m_impl(std::make_unique()) {} Settings::~Settings() = default; @@ -351,16 +351,14 @@ Settings::Impl::Impl() m_autoMarginsDefault(false), m_showMiddleRect(true) { m_deviationProvider.setComputeValueByKey([this](const PageId& pageId) -> double { - auto it(m_items.find(pageId)); + auto it = m_items.find(pageId); if (it != m_items.end()) { - if (it->alignment.isNull()) { - return std::sqrt(it->hardWidthMM() * it->hardHeightMM() / 4 / 25.4); - } else { - return .0; - } - } else { - return .0; - }; + const Margins& marginsMm = it->hardMarginsMM; + double horHardMargins = marginsMm.left() + marginsMm.right(); + double vertHardMargins = marginsMm.top() + marginsMm.bottom(); + return std::sqrt(std::pow(horHardMargins, 2) + std::pow(vertHardMargins, 2)); + } + return NAN; }); } diff --git a/src/core/filters/page_layout/Settings.h b/src/core/filters/page_layout/Settings.h index 4d1b56b0c..27641193c 100644 --- a/src/core/filters/page_layout/Settings.h +++ b/src/core/filters/page_layout/Settings.h @@ -10,7 +10,6 @@ #include "Margins.h" #include "NonCopyable.h" -#include "ref_countable.h" class PageId; class Margins; @@ -24,7 +23,7 @@ class Params; class Alignment; class Guide; -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) public: @@ -32,7 +31,7 @@ class Settings : public ref_countable { Settings(); - ~Settings() override; + virtual ~Settings(); /** * \brief Removes all stored data. diff --git a/src/core/filters/page_layout/Task.cpp b/src/core/filters/page_layout/Task.cpp index 92e894646..1f25505b2 100644 --- a/src/core/filters/page_layout/Task.cpp +++ b/src/core/filters/page_layout/Task.cpp @@ -3,8 +3,6 @@ #include "Task.h" -#include - #include #include "Dpm.h" @@ -24,27 +22,27 @@ using namespace imageproc; namespace page_layout { class Task::UiUpdater : public FilterResult { public: - UiUpdater(intrusive_ptr filter, - intrusive_ptr settings, + UiUpdater(std::shared_ptr filter, + std::shared_ptr settings, const PageId& pageId, const QImage& image, const ImageTransformation& xform, - const GrayImage& grayImage, + const ContentMask& contentMask, const QRectF& adaptedContentRect, bool aggSizeChanged, bool batch); void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; - intrusive_ptr m_settings; + std::shared_ptr m_filter; + std::shared_ptr m_settings; PageId m_pageId; QImage m_image; QImage m_downscaledImage; - GrayImage m_grayImage; + ContentMask m_contentMask; ImageTransformation m_xform; QRectF m_adaptedContentRect; bool m_aggSizeChanged; @@ -52,9 +50,9 @@ class Task::UiUpdater : public FilterResult { }; -Task::Task(intrusive_ptr filter, - intrusive_ptr nextTask, - intrusive_ptr settings, +Task::Task(std::shared_ptr filter, + std::shared_ptr nextTask, + std::shared_ptr settings, const PageId& pageId, bool batch, bool debug) @@ -94,20 +92,20 @@ FilterResultPtr Task::process(const TaskStatus& status, newXform.setPostCropArea(Utils::shiftToRoundedOrigin(newXform.transform().map(pageRectPhys))); return m_nextTask->process(status, FilterData(data, newXform), contentRectPhys); } else { - return make_intrusive(m_filter, m_settings, m_pageId, data.origImage(), data.xform(), - data.grayImageBlackOnWhite(), adaptedContentRect, - aggHardSizeBefore != aggHardSizeAfter, m_batchProcessing); + return std::make_shared(m_filter, m_settings, m_pageId, data.origImage(), data.xform(), + ContentMask(data.grayImageBlackOnWhite(), data.xform(), status), + adaptedContentRect, aggHardSizeBefore != aggHardSizeAfter, m_batchProcessing); } } /*============================ Task::UiUpdater ==========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, - intrusive_ptr settings, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, + std::shared_ptr settings, const PageId& pageId, const QImage& image, const ImageTransformation& xform, - const GrayImage& grayImage, + const ContentMask& contentMask, const QRectF& adaptedContentRect, const bool aggSizeChanged, const bool batch) @@ -116,7 +114,7 @@ Task::UiUpdater::UiUpdater(intrusive_ptr filter, m_pageId(pageId), m_image(image), m_downscaledImage(ImageView::createDownscaledImage(image)), - m_grayImage(grayImage), + m_contentMask(contentMask), m_xform(xform), m_adaptedContentRect(adaptedContentRect), m_aggSizeChanged(aggSizeChanged), @@ -138,7 +136,7 @@ void Task::UiUpdater::updateUI(FilterUiInterface* ui) { optWidget->postUpdateUI(); ui->setOptionsWidget(optWidget, ui->KEEP_OWNERSHIP); - auto* view = new ImageView(m_settings, m_pageId, m_image, m_downscaledImage, m_grayImage, m_xform, + auto* view = new ImageView(m_settings, m_pageId, m_image, m_downscaledImage, m_contentMask, m_xform, m_adaptedContentRect, *optWidget); ui->setImageWidget(view, ui->TRANSFER_OWNERSHIP); diff --git a/src/core/filters/page_layout/Task.h b/src/core/filters/page_layout/Task.h index a600a5818..319cbda96 100644 --- a/src/core/filters/page_layout/Task.h +++ b/src/core/filters/page_layout/Task.h @@ -9,7 +9,6 @@ #include "FilterResult.h" #include "NonCopyable.h" #include "PageId.h" -#include "ref_countable.h" class TaskStatus; class FilterData; @@ -25,18 +24,18 @@ namespace page_layout { class Filter; class Settings; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: - Task(intrusive_ptr filter, - intrusive_ptr nextTask, - intrusive_ptr settings, + Task(std::shared_ptr filter, + std::shared_ptr nextTask, + std::shared_ptr settings, const PageId& pageId, bool batch, bool debug); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, const FilterData& data, @@ -46,9 +45,9 @@ class Task : public ref_countable { private: class UiUpdater; - intrusive_ptr m_filter; - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; + std::shared_ptr m_filter; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; PageId m_pageId; bool m_batchProcessing; }; diff --git a/src/core/filters/page_layout/Thumbnail.cpp b/src/core/filters/page_layout/Thumbnail.cpp index 6c167bbe4..e6d65add5 100644 --- a/src/core/filters/page_layout/Thumbnail.cpp +++ b/src/core/filters/page_layout/Thumbnail.cpp @@ -13,21 +13,18 @@ using namespace imageproc; namespace page_layout { -Thumbnail::Thumbnail(intrusive_ptr thumbnailCache, +Thumbnail::Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const Params& params, const ImageTransformation& xform, const QPolygonF& physContentRect, - const QRectF& displayArea, bool deviant) - : ThumbnailBase(std::move(thumbnailCache), maxSize, imageId, xform, displayArea), + : ThumbnailBase(std::move(thumbnailCache), maxSize, imageId, xform, xform.resultingRect()), m_params(params), m_virtContentRect(xform.transform().map(physContentRect).boundingRect()), - m_virtOuterRect(displayArea), - m_deviant(deviant) { - setExtendedClipArea(true); -} + m_virtOuterRect(xform.resultingRect()), + m_deviant(deviant) {} void Thumbnail::paintOverImage(QPainter& painter, const QTransform& imageToDisplay, const QTransform& thumbToDisplay) { // We work in display coordinates because we want to be @@ -94,6 +91,7 @@ void Thumbnail::paintOverImage(QPainter& painter, const QTransform& imageToDispl painter.drawRect(outerRect); if (m_deviant) { + painter.setWorldTransform(thumbToDisplay); paintDeviant(painter); } } // Thumbnail::paintOverImage diff --git a/src/core/filters/page_layout/Thumbnail.h b/src/core/filters/page_layout/Thumbnail.h index c916f71ac..f4d44780a 100644 --- a/src/core/filters/page_layout/Thumbnail.h +++ b/src/core/filters/page_layout/Thumbnail.h @@ -6,11 +6,11 @@ #include #include +#include #include "ImageTransformation.h" #include "Params.h" #include "ThumbnailBase.h" -#include "intrusive_ptr.h" class ThumbnailPixmapCache; class ImageId; @@ -18,13 +18,12 @@ class ImageId; namespace page_layout { class Thumbnail : public ThumbnailBase { public: - Thumbnail(intrusive_ptr thumbnailCache, + Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const Params& params, const ImageTransformation& xform, const QPolygonF& physContentRect, - const QRectF& displayArea, bool deviant); void paintOverImage(QPainter& painter, const QTransform& imageToDisplay, const QTransform& thumbToDisplay) override; diff --git a/src/core/filters/page_layout/Utils.cpp b/src/core/filters/page_layout/Utils.cpp index 17242c984..0db20aece 100644 --- a/src/core/filters/page_layout/Utils.cpp +++ b/src/core/filters/page_layout/Utils.cpp @@ -4,6 +4,8 @@ #include "Utils.h" #include +#include +#include #include #include @@ -229,4 +231,22 @@ QPolygonF Utils::shiftToRoundedOrigin(const QPolygonF& poly) { const double shiftValueY = -(y - std::round(y)); return poly.translated(shiftValueX, shiftValueY); } + +Params Utils::buildDefaultParams(const Dpi& dpi) { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::PageLayoutParams& pageLayoutParams = defaultParams.getPageLayoutParams(); + + const UnitsConverter unitsConverter(dpi); + + const Margins& margins = pageLayoutParams.getHardMargins(); + double leftMargin = margins.left(); + double topMargin = margins.top(); + double rightMargin = margins.right(); + double bottomMargin = margins.bottom(); + unitsConverter.convert(leftMargin, topMargin, defaultParams.getUnits(), MILLIMETRES); + unitsConverter.convert(rightMargin, bottomMargin, defaultParams.getUnits(), MILLIMETRES); + + return Params(Margins(leftMargin, topMargin, rightMargin, bottomMargin), QRectF(), QRectF(), QSizeF(), + pageLayoutParams.getAlignment(), pageLayoutParams.isAutoMargins()); +} } // namespace page_layout \ No newline at end of file diff --git a/src/core/filters/page_layout/Utils.h b/src/core/filters/page_layout/Utils.h index 6eea307bc..33f00e7a1 100644 --- a/src/core/filters/page_layout/Utils.h +++ b/src/core/filters/page_layout/Utils.h @@ -10,6 +10,7 @@ class QSizeF; class QRectF; class Margins; class ImageTransformation; +class Dpi; namespace page_layout { class Alignment; @@ -17,6 +18,8 @@ class Params; class Utils { public: + Utils() = delete; + /** * \brief Replace an empty content rectangle with a tiny centered one. * @@ -76,6 +79,8 @@ class Utils { static QPolygonF shiftToRoundedOrigin(const QPolygonF& poly); + static Params buildDefaultParams(const Dpi& dpi); + private: static QPointF getRightUnitVector(const QPolygonF& polyRect); diff --git a/src/core/filters/page_split/CMakeLists.txt b/src/core/filters/page_split/CMakeLists.txt index 26e9d22b2..4341fe324 100644 --- a/src/core/filters/page_split/CMakeLists.txt +++ b/src/core/filters/page_split/CMakeLists.txt @@ -22,7 +22,8 @@ set(sources LayoutType.cpp LayoutType.h UnremoveButton.cpp UnremoveButton.h OrderBySplitTypeProvider.cpp OrderBySplitTypeProvider.h - PageLayoutAdapter.cpp PageLayoutAdapter.h) + PageLayoutAdapter.cpp PageLayoutAdapter.h + Utils.cpp Utils.h) add_library(page_split STATIC ${sources} ${ui_files}) target_link_libraries(page_split PUBLIC core) diff --git a/src/core/filters/page_split/CacheDrivenTask.cpp b/src/core/filters/page_split/CacheDrivenTask.cpp index 58536ff94..85c016f62 100644 --- a/src/core/filters/page_split/CacheDrivenTask.cpp +++ b/src/core/filters/page_split/CacheDrivenTask.cpp @@ -16,9 +16,9 @@ #include "filters/deskew/CacheDrivenTask.h" namespace page_split { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr settings, - intrusive_ptr projectPages, - intrusive_ptr nextTask) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr settings, + std::shared_ptr projectPages, + std::shared_ptr nextTask) : m_nextTask(std::move(nextTask)), m_settings(std::move(settings)), m_projectPages(std::move(projectPages)) {} CacheDrivenTask::~CacheDrivenTask() = default; diff --git a/src/core/filters/page_split/CacheDrivenTask.h b/src/core/filters/page_split/CacheDrivenTask.h index 1948efa07..315c38474 100644 --- a/src/core/filters/page_split/CacheDrivenTask.h +++ b/src/core/filters/page_split/CacheDrivenTask.h @@ -4,9 +4,9 @@ #ifndef SCANTAILOR_PAGE_SPLIT_CACHEDRIVENTASK_H_ #define SCANTAILOR_PAGE_SPLIT_CACHEDRIVENTASK_H_ +#include + #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QSizeF; class PageInfo; @@ -21,22 +21,22 @@ class CacheDrivenTask; namespace page_split { class Settings; -class CacheDrivenTask : public ref_countable { +class CacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr settings, - intrusive_ptr projectPages, - intrusive_ptr nextTask); + CacheDrivenTask(std::shared_ptr settings, + std::shared_ptr projectPages, + std::shared_ptr nextTask); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector, const ImageTransformation& xform); private: - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; - intrusive_ptr m_projectPages; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; + std::shared_ptr m_projectPages; }; } // namespace page_split #endif // ifndef SCANTAILOR_PAGE_SPLIT_CACHEDRIVENTASK_H_ diff --git a/src/core/filters/page_split/Dependencies.cpp b/src/core/filters/page_split/Dependencies.cpp index a46da0d76..33b830f69 100644 --- a/src/core/filters/page_split/Dependencies.cpp +++ b/src/core/filters/page_split/Dependencies.cpp @@ -61,12 +61,4 @@ QDomElement Dependencies::toXml(QDomDocument& doc, const QString& tagName) const bool Dependencies::isNull() const { return m_imageSize.isNull(); } - -const OrthogonalRotation& Dependencies::orientation() const { - return m_rotation; -} - -void Dependencies::setLayoutType(LayoutType type) { - m_layoutType = type; -} } // namespace page_split \ No newline at end of file diff --git a/src/core/filters/page_split/Dependencies.h b/src/core/filters/page_split/Dependencies.h index fc413b9e7..af39e32c0 100644 --- a/src/core/filters/page_split/Dependencies.h +++ b/src/core/filters/page_split/Dependencies.h @@ -45,5 +45,14 @@ class Dependencies { OrthogonalRotation m_rotation; LayoutType m_layoutType; }; + + +inline const OrthogonalRotation& Dependencies::orientation() const { + return m_rotation; +} + +inline void Dependencies::setLayoutType(LayoutType type) { + m_layoutType = type; +} } // namespace page_split #endif // ifndef SCANTAILOR_PAGE_SPLIT_DEPENDENCIES_H_ diff --git a/src/core/filters/page_split/Filter.cpp b/src/core/filters/page_split/Filter.cpp index 89da6f82f..186f4e3d9 100644 --- a/src/core/filters/page_split/Filter.cpp +++ b/src/core/filters/page_split/Filter.cpp @@ -3,13 +3,9 @@ #include "Filter.h" -#include -#include #include #include -#include -#include #include #include "CacheDrivenTask.h" @@ -21,14 +17,15 @@ #include "ProjectWriter.h" #include "Settings.h" #include "Task.h" +#include "Utils.h" namespace page_split { -Filter::Filter(intrusive_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor) - : m_pages(std::move(pageSequence)), m_settings(new Settings), m_selectedPageOrder(0) { +Filter::Filter(std::shared_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor) + : m_pages(std::move(pageSequence)), m_settings(std::make_shared()), m_selectedPageOrder(0) { m_optionsWidget.reset(new OptionsWidget(m_settings, m_pages, pageSelectionAccessor)); const PageOrderOption::ProviderPtr defaultOrder; - const auto orderBySplitType = make_intrusive(m_settings); + const auto orderBySplitType = std::make_shared(m_settings); m_pageOrderOptions.emplace_back(tr("Natural order"), defaultOrder); m_pageOrderOptions.emplace_back(tr("Order by split type"), orderBySplitType); } @@ -142,16 +139,16 @@ void Filter::writeImageSettings(QDomDocument& doc, } } -intrusive_ptr Filter::createTask(const PageInfo& pageInfo, - intrusive_ptr nextTask, - const bool batchProcessing, - const bool debug) { - return make_intrusive(intrusive_ptr(this), m_settings, m_pages, std::move(nextTask), pageInfo, - batchProcessing, debug); +std::shared_ptr Filter::createTask(const PageInfo& pageInfo, + std::shared_ptr nextTask, + const bool batchProcessing, + const bool debug) { + return std::make_shared(std::static_pointer_cast(shared_from_this()), m_settings, m_pages, + std::move(nextTask), pageInfo, batchProcessing, debug); } -intrusive_ptr Filter::createCacheDrivenTask(intrusive_ptr nextTask) { - return make_intrusive(m_settings, m_pages, std::move(nextTask)); +std::shared_ptr Filter::createCacheDrivenTask(std::shared_ptr nextTask) { + return std::make_shared(m_settings, m_pages, std::move(nextTask)); } std::vector Filter::pageOrderOptions() const { @@ -168,15 +165,10 @@ void Filter::selectPageOrder(int option) { } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->getPageRecord(pageInfo.id().imageId()).isNull()) { + if (!m_settings->getPageRecord(pageInfo.id().imageId()).isNull()) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::PageSplitParams& pageSplitParams = defaultParams.getPageSplitParams(); - Settings::UpdateAction update; - update.setLayoutType(pageSplitParams.getLayoutType()); - m_settings->updatePage(pageInfo.id().imageId(), update); + m_settings->updatePage(pageInfo.id().imageId(), Utils::buildDefaultUpdateAction()); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/page_split/Filter.h b/src/core/filters/page_split/Filter.h index d40b8996c..09fe288da 100644 --- a/src/core/filters/page_split/Filter.h +++ b/src/core/filters/page_split/Filter.h @@ -5,6 +5,7 @@ #define SCANTAILOR_PAGE_SPLIT_FILTER_H_ #include +#include #include #include "AbstractFilter.h" @@ -13,7 +14,6 @@ #include "PageOrderOption.h" #include "PageView.h" #include "SafeDeletingQObjectPtr.h" -#include "intrusive_ptr.h" class ImageId; class PageInfo; @@ -39,7 +39,7 @@ class Filter : public AbstractFilter { Q_DECLARE_TR_FUNCTIONS(page_split::Filter) public: - Filter(intrusive_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor); + Filter(std::shared_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor); ~Filter() override; @@ -57,12 +57,12 @@ class Filter : public AbstractFilter { void loadDefaultSettings(const PageInfo& pageInfo) override; - intrusive_ptr createTask(const PageInfo& pageInfo, - intrusive_ptr nextTask, - bool batchProcessing, - bool debug); + std::shared_ptr createTask(const PageInfo& pageInfo, + std::shared_ptr nextTask, + bool batchProcessing, + bool debug); - intrusive_ptr createCacheDrivenTask(intrusive_ptr nextTask); + std::shared_ptr createCacheDrivenTask(std::shared_ptr nextTask); OptionsWidget* optionsWidget(); @@ -77,8 +77,8 @@ class Filter : public AbstractFilter { private: void writeImageSettings(QDomDocument& doc, QDomElement& filterEl, const ImageId& imageId, int numericId) const; - intrusive_ptr m_pages; - intrusive_ptr m_settings; + std::shared_ptr m_pages; + std::shared_ptr m_settings; SafeDeletingQObjectPtr m_optionsWidget; std::vector m_pageOrderOptions; int m_selectedPageOrder; diff --git a/src/core/filters/page_split/ImageView.cpp b/src/core/filters/page_split/ImageView.cpp index 38575792c..a8d76885e 100644 --- a/src/core/filters/page_split/ImageView.cpp +++ b/src/core/filters/page_split/ImageView.cpp @@ -20,7 +20,7 @@ ImageView::ImageView(const QImage& image, const QImage& downscaledImage, const ImageTransformation& xform, const PageLayout& layout, - intrusive_ptr pages, + std::shared_ptr pages, const ImageId& imageId, bool leftHalfRemoved, bool rightHalfRemoved) diff --git a/src/core/filters/page_split/ImageView.h b/src/core/filters/page_split/ImageView.h index 11b8a18c4..bddb35ce7 100644 --- a/src/core/filters/page_split/ImageView.h +++ b/src/core/filters/page_split/ImageView.h @@ -5,6 +5,7 @@ #define SCANTAILOR_PAGE_SPLIT_IMAGEVIEW_H_ #include +#include #include "DragHandler.h" #include "DraggableLineSegment.h" @@ -15,7 +16,6 @@ #include "PageLayout.h" #include "UnremoveButton.h" #include "ZoomHandler.h" -#include "intrusive_ptr.h" class ImageTransformation; class ProjectPages; @@ -32,7 +32,7 @@ class ImageView : public ImageViewBase, private InteractionHandler { const QImage& downscaledImage, const ImageTransformation& xform, const PageLayout& layout, - intrusive_ptr pages, + std::shared_ptr pages, const ImageId& imageId, bool leftHalfRemoved, bool rightHalfRemoved); @@ -103,7 +103,7 @@ class ImageView : public ImageViewBase, private InteractionHandler { static QLineF customInscribedCutterLine(const QLineF& line, const QRectF& rect); - intrusive_ptr m_pages; + std::shared_ptr m_pages; ImageId m_imageId; DraggablePoint m_handles[2][2]; ObjectDragHandler m_handleInteractors[2][2]; diff --git a/src/core/filters/page_split/OptionsWidget.cpp b/src/core/filters/page_split/OptionsWidget.cpp index 15e41ffac..9e732f1f9 100644 --- a/src/core/filters/page_split/OptionsWidget.cpp +++ b/src/core/filters/page_split/OptionsWidget.cpp @@ -16,8 +16,8 @@ #include "SplitModeDialog.h" namespace page_split { -OptionsWidget::OptionsWidget(intrusive_ptr settings, - intrusive_ptr pageSequence, +OptionsWidget::OptionsWidget(std::shared_ptr settings, + std::shared_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pages(std::move(pageSequence)), @@ -296,36 +296,4 @@ void OptionsWidget::setupIcons() { OptionsWidget::UiData::UiData() : m_splitLineMode(MODE_AUTO), m_layoutTypeAutoDetected(false) {} OptionsWidget::UiData::~UiData() = default; - -void OptionsWidget::UiData::setPageLayout(const PageLayout& layout) { - m_pageLayout = layout; -} - -const PageLayout& OptionsWidget::UiData::pageLayout() const { - return m_pageLayout; -} - -void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { - m_deps = deps; -} - -const Dependencies& OptionsWidget::UiData::dependencies() const { - return m_deps; -} - -void OptionsWidget::UiData::setSplitLineMode(const AutoManualMode mode) { - m_splitLineMode = mode; -} - -AutoManualMode OptionsWidget::UiData::splitLineMode() const { - return m_splitLineMode; -} - -bool OptionsWidget::UiData::layoutTypeAutoDetected() const { - return m_layoutTypeAutoDetected; -} - -void OptionsWidget::UiData::setLayoutTypeAutoDetected(const bool val) { - m_layoutTypeAutoDetected = val; -} } // namespace page_split \ No newline at end of file diff --git a/src/core/filters/page_split/OptionsWidget.h b/src/core/filters/page_split/OptionsWidget.h index 63595dc3a..33ee9db9f 100644 --- a/src/core/filters/page_split/OptionsWidget.h +++ b/src/core/filters/page_split/OptionsWidget.h @@ -4,9 +4,11 @@ #ifndef SCANTAILOR_PAGE_SPLIT_OPTIONSWIDGET_H_ #define SCANTAILOR_PAGE_SPLIT_OPTIONSWIDGET_H_ +#include + #include +#include #include -#include #include "AutoManualMode.h" #include "Dependencies.h" @@ -16,7 +18,6 @@ #include "PageId.h" #include "PageLayout.h" #include "PageSelectionAccessor.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" class ProjectPages; @@ -58,8 +59,8 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { }; - OptionsWidget(intrusive_ptr settings, - intrusive_ptr pageSequence, + OptionsWidget(std::shared_ptr settings, + std::shared_ptr pageSequence, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -93,13 +94,46 @@ class OptionsWidget : public FilterOptionsWidget, private Ui::OptionsWidget { void setupIcons(); - intrusive_ptr m_settings; - intrusive_ptr m_pages; + std::shared_ptr m_settings; + std::shared_ptr m_pages; PageSelectionAccessor m_pageSelectionAccessor; PageId m_pageId; UiData m_uiData; ConnectionManager m_connectionManager; }; + + +inline void OptionsWidget::UiData::setPageLayout(const PageLayout& layout) { + m_pageLayout = layout; +} + +inline const PageLayout& OptionsWidget::UiData::pageLayout() const { + return m_pageLayout; +} + +inline void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { + m_deps = deps; +} + +inline const Dependencies& OptionsWidget::UiData::dependencies() const { + return m_deps; +} + +inline void OptionsWidget::UiData::setSplitLineMode(const AutoManualMode mode) { + m_splitLineMode = mode; +} + +inline AutoManualMode OptionsWidget::UiData::splitLineMode() const { + return m_splitLineMode; +} + +inline bool OptionsWidget::UiData::layoutTypeAutoDetected() const { + return m_layoutTypeAutoDetected; +} + +inline void OptionsWidget::UiData::setLayoutTypeAutoDetected(const bool val) { + m_layoutTypeAutoDetected = val; +} } // namespace page_split #endif // ifndef SCANTAILOR_PAGE_SPLIT_OPTIONSWIDGET_H_ diff --git a/src/core/filters/page_split/OptionsWidget.ui b/src/core/filters/page_split/OptionsWidget.ui index 97601452d..7b6626e3f 100644 --- a/src/core/filters/page_split/OptionsWidget.ui +++ b/src/core/filters/page_split/OptionsWidget.ui @@ -51,8 +51,7 @@ - :/icons/single_page_uncut.svg - :/icons/single_page_uncut_selected.svg:/icons/single_page_uncut.svg + :/icons/single_page_uncut.svg:/icons/single_page_uncut.svg @@ -75,8 +74,7 @@ - :/icons/right_page_plus_offcut.svg - :/icons/right_page_plus_offcut_selected.svg:/icons/right_page_plus_offcut.svg + :/icons/right_page_plus_offcut.svg:/icons/right_page_plus_offcut.svg @@ -99,8 +97,7 @@ - :/icons/two_pages.svg - :/icons/two_pages_selected.svg:/icons/two_pages.svg + :/icons/two_pages.svg:/icons/two_pages.svg diff --git a/src/core/filters/page_split/OrderBySplitTypeProvider.cpp b/src/core/filters/page_split/OrderBySplitTypeProvider.cpp index 073602b40..295b66a1d 100644 --- a/src/core/filters/page_split/OrderBySplitTypeProvider.cpp +++ b/src/core/filters/page_split/OrderBySplitTypeProvider.cpp @@ -7,7 +7,7 @@ #include namespace page_split { -OrderBySplitTypeProvider::OrderBySplitTypeProvider(intrusive_ptr settings) +OrderBySplitTypeProvider::OrderBySplitTypeProvider(std::shared_ptr settings) : m_settings(std::move(settings)) {} bool OrderBySplitTypeProvider::precedes(const PageId& lhsPage, diff --git a/src/core/filters/page_split/OrderBySplitTypeProvider.h b/src/core/filters/page_split/OrderBySplitTypeProvider.h index 75de587cb..a434c724f 100644 --- a/src/core/filters/page_split/OrderBySplitTypeProvider.h +++ b/src/core/filters/page_split/OrderBySplitTypeProvider.h @@ -4,19 +4,20 @@ #ifndef SCANTAILOR_PAGE_SPLIT_ORDERBYSPLITTYPEPROVIDER_H_ #define SCANTAILOR_PAGE_SPLIT_ORDERBYSPLITTYPEPROVIDER_H_ +#include + #include "PageOrderProvider.h" #include "Settings.h" -#include "intrusive_ptr.h" namespace page_split { class OrderBySplitTypeProvider : public PageOrderProvider { public: - explicit OrderBySplitTypeProvider(intrusive_ptr settings); + explicit OrderBySplitTypeProvider(std::shared_ptr settings); bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override; private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace page_split diff --git a/src/core/filters/page_split/PageLayout.cpp b/src/core/filters/page_split/PageLayout.cpp index 99c973e17..2b7c35a38 100644 --- a/src/core/filters/page_split/PageLayout.cpp +++ b/src/core/filters/page_split/PageLayout.cpp @@ -92,10 +92,6 @@ int PageLayout::numCutters() const { return 0; } -int PageLayout::numSubPages() const { - return m_type == TWO_PAGES ? 2 : 1; -} - QLineF PageLayout::inscribedCutterLine(int idx) const { assert(idx >= 0 && idx < numCutters()); @@ -364,12 +360,4 @@ void PageLayout::maybeAddIntersectionPoint(QPolygonF& poly, const QLineF& line1, bool PageLayout::isNull() const { return m_uncutOutline.isEmpty(); } - -PageLayout::Type PageLayout::type() const { - return m_type; -} - -const QPolygonF& PageLayout::uncutOutline() const { - return m_uncutOutline; -} } // namespace page_split \ No newline at end of file diff --git a/src/core/filters/page_split/PageLayout.h b/src/core/filters/page_split/PageLayout.h index 622680afe..1b03abc31 100644 --- a/src/core/filters/page_split/PageLayout.h +++ b/src/core/filters/page_split/PageLayout.h @@ -177,5 +177,18 @@ class PageLayout { Type m_type; }; + + +inline int PageLayout::numSubPages() const { + return m_type == TWO_PAGES ? 2 : 1; +} + +inline PageLayout::Type PageLayout::type() const { + return m_type; +} + +inline const QPolygonF& PageLayout::uncutOutline() const { + return m_uncutOutline; +} } // namespace page_split #endif // ifndef SCANTAILOR_PAGE_SPLIT_PAGELAYOUT_H_ diff --git a/src/core/filters/page_split/Params.cpp b/src/core/filters/page_split/Params.cpp index 8dfae4883..37aaf617b 100644 --- a/src/core/filters/page_split/Params.cpp +++ b/src/core/filters/page_split/Params.cpp @@ -23,28 +23,4 @@ QDomElement Params::toXml(QDomDocument& doc, const QString& name) const { el.appendChild(m_deps.toXml(doc, "dependencies")); return el; } - -const PageLayout& Params::pageLayout() const { - return m_layout; -} - -void Params::setPageLayout(const PageLayout& layout) { - m_layout = layout; -} - -const Dependencies& Params::dependencies() const { - return m_deps; -} - -void Params::setDependencies(const Dependencies& deps) { - m_deps = deps; -} - -AutoManualMode Params::splitLineMode() const { - return m_splitLineMode; -} - -void Params::setSplitLineMode(AutoManualMode mode) { - m_splitLineMode = mode; -} } // namespace page_split \ No newline at end of file diff --git a/src/core/filters/page_split/Params.h b/src/core/filters/page_split/Params.h index b4af78142..efd442019 100644 --- a/src/core/filters/page_split/Params.h +++ b/src/core/filters/page_split/Params.h @@ -44,5 +44,30 @@ class Params { Dependencies m_deps; AutoManualMode m_splitLineMode; }; + + +inline const PageLayout& Params::pageLayout() const { + return m_layout; +} + +inline void Params::setPageLayout(const PageLayout& layout) { + m_layout = layout; +} + +inline const Dependencies& Params::dependencies() const { + return m_deps; +} + +inline void Params::setDependencies(const Dependencies& deps) { + m_deps = deps; +} + +inline AutoManualMode Params::splitLineMode() const { + return m_splitLineMode; +} + +inline void Params::setSplitLineMode(AutoManualMode mode) { + m_splitLineMode = mode; +} } // namespace page_split #endif // ifndef SCANTAILOR_PAGE_SPLIT_PARAMS_H_ diff --git a/src/core/filters/page_split/Settings.h b/src/core/filters/page_split/Settings.h index 64caa79e8..b6d1bfe3a 100644 --- a/src/core/filters/page_split/Settings.h +++ b/src/core/filters/page_split/Settings.h @@ -15,12 +15,11 @@ #include "PageId.h" #include "PageLayout.h" #include "Params.h" -#include "ref_countable.h" class AbstractRelinker; namespace page_split { -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) private: @@ -110,7 +109,7 @@ class Settings : public ref_countable { Settings(); - ~Settings() override; + virtual ~Settings(); /** * \brief Reset all settings to their initial state. diff --git a/src/core/filters/page_split/SplitModeDialog.h b/src/core/filters/page_split/SplitModeDialog.h index c5560b2e8..f1098d5d1 100644 --- a/src/core/filters/page_split/SplitModeDialog.h +++ b/src/core/filters/page_split/SplitModeDialog.h @@ -6,13 +6,13 @@ #include #include +#include #include #include "LayoutType.h" #include "PageId.h" #include "PageLayout.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_SplitModeDialog.h" class ProjectPages; diff --git a/src/core/filters/page_split/Task.cpp b/src/core/filters/page_split/Task.cpp index b298655cd..92ad736cf 100644 --- a/src/core/filters/page_split/Task.cpp +++ b/src/core/filters/page_split/Task.cpp @@ -26,8 +26,8 @@ using imageproc::BinaryThreshold; class Task::UiUpdater : public FilterResult { public: - UiUpdater(intrusive_ptr filter, - intrusive_ptr pages, + UiUpdater(std::shared_ptr filter, + std::shared_ptr pages, std::unique_ptr dbgImg, const QImage& image, const PageInfo& pageInfo, @@ -37,11 +37,11 @@ class Task::UiUpdater : public FilterResult { void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; - intrusive_ptr m_pages; + std::shared_ptr m_filter; + std::shared_ptr m_pages; std::unique_ptr m_dbg; QImage m_image; QImage m_downscaledImage; @@ -65,10 +65,10 @@ static ProjectPages::LayoutType toPageLayoutType(const PageLayout& layout) { return ProjectPages::ONE_PAGE_LAYOUT; } -Task::Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr pages, - intrusive_ptr nextTask, +Task::Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr pages, + std::shared_ptr nextTask, const PageInfo& pageInfo, const bool batchProcessing, const bool debug) @@ -170,14 +170,14 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data) newXform.setPreCropArea(layout.pageOutline(m_pageInfo.id().subPage()).toPolygon()); return m_nextTask->process(status, FilterData(data, newXform)); } - return make_intrusive(m_filter, m_pages, std::move(m_dbg), data.origImage(), m_pageInfo, data.xform(), - uiData, m_batchProcessing); + return std::make_shared(m_filter, m_pages, std::move(m_dbg), data.origImage(), m_pageInfo, data.xform(), + uiData, m_batchProcessing); } // Task::process /*============================ Task::UiUpdater =========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, - intrusive_ptr pages, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, + std::shared_ptr pages, std::unique_ptr dbgImg, const QImage& image, const PageInfo& pageInfo, diff --git a/src/core/filters/page_split/Task.h b/src/core/filters/page_split/Task.h index ff451c5b2..5210063a0 100644 --- a/src/core/filters/page_split/Task.h +++ b/src/core/filters/page_split/Task.h @@ -9,8 +9,6 @@ #include "FilterResult.h" #include "NonCopyable.h" #include "PageInfo.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class TaskStatus; class FilterData; @@ -28,29 +26,29 @@ class Settings; class PageLayout; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: - Task(intrusive_ptr filter, - intrusive_ptr settings, - intrusive_ptr pages, - intrusive_ptr nextTask, + Task(std::shared_ptr filter, + std::shared_ptr settings, + std::shared_ptr pages, + std::shared_ptr nextTask, const PageInfo& pageInfo, bool batchProcessing, bool debug); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, const FilterData& data); private: class UiUpdater; - intrusive_ptr m_filter; - intrusive_ptr m_settings; - intrusive_ptr m_pages; - intrusive_ptr m_nextTask; + std::shared_ptr m_filter; + std::shared_ptr m_settings; + std::shared_ptr m_pages; + std::shared_ptr m_nextTask; std::unique_ptr m_dbg; PageInfo m_pageInfo; bool m_batchProcessing; diff --git a/src/core/filters/page_split/Thumbnail.cpp b/src/core/filters/page_split/Thumbnail.cpp index 24a36e572..51f439f75 100644 --- a/src/core/filters/page_split/Thumbnail.cpp +++ b/src/core/filters/page_split/Thumbnail.cpp @@ -9,7 +9,7 @@ #include namespace page_split { -Thumbnail::Thumbnail(intrusive_ptr thumbnailCache, +Thumbnail::Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/page_split/Thumbnail.h b/src/core/filters/page_split/Thumbnail.h index 0da486cda..09f11330c 100644 --- a/src/core/filters/page_split/Thumbnail.h +++ b/src/core/filters/page_split/Thumbnail.h @@ -5,10 +5,10 @@ #define SCANTAILOR_PAGE_SPLIT_THUMBNAIL_H_ #include +#include #include "PageLayout.h" #include "ThumbnailBase.h" -#include "intrusive_ptr.h" class QPointF; class QSizeF; @@ -20,7 +20,7 @@ class ImageTransformation; namespace page_split { class Thumbnail : public ThumbnailBase { public: - Thumbnail(intrusive_ptr thumbnailCache, + Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/page_split/Utils.cpp b/src/core/filters/page_split/Utils.cpp new file mode 100644 index 000000000..2e6c9a175 --- /dev/null +++ b/src/core/filters/page_split/Utils.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "Utils.h" + +#include +#include + +using namespace page_split; + +Settings::UpdateAction Utils::buildDefaultUpdateAction() { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::PageSplitParams& pageSplitParams = defaultParams.getPageSplitParams(); + + Settings::UpdateAction update; + update.setLayoutType(pageSplitParams.getLayoutType()); + + return update; +} diff --git a/src/core/filters/page_split/Utils.h b/src/core/filters/page_split/Utils.h new file mode 100644 index 000000000..1db9a2135 --- /dev/null +++ b/src/core/filters/page_split/Utils.h @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_PAGE_SPLIT_UTILS_H_ +#define SCANTAILOR_PAGE_SPLIT_UTILS_H_ + +#include "Settings.h" + +namespace page_split { +class Utils { + public: + Utils() = delete; + + static Settings::UpdateAction buildDefaultUpdateAction(); +}; +} // namespace page_split + +#endif // SCANTAILOR_PAGE_SPLIT_UTILS_H_ diff --git a/src/core/filters/select_content/ApplyDialog.h b/src/core/filters/select_content/ApplyDialog.h index 81b0d7182..b495412aa 100644 --- a/src/core/filters/select_content/ApplyDialog.h +++ b/src/core/filters/select_content/ApplyDialog.h @@ -6,13 +6,13 @@ #include #include +#include #include #include #include "PageId.h" #include "PageRange.h" #include "PageSequence.h" -#include "intrusive_ptr.h" #include "ui_ApplyDialog.h" class PageSelectionAccessor; diff --git a/src/core/filters/select_content/CMakeLists.txt b/src/core/filters/select_content/CMakeLists.txt index b0b51368a..6ab9bcc66 100644 --- a/src/core/filters/select_content/CMakeLists.txt +++ b/src/core/filters/select_content/CMakeLists.txt @@ -19,7 +19,8 @@ set(sources Thumbnail.cpp Thumbnail.h PhysSizeCalc.cpp PhysSizeCalc.h OrderByWidthProvider.cpp OrderByWidthProvider.h - OrderByHeightProvider.cpp OrderByHeightProvider.h) + OrderByHeightProvider.cpp OrderByHeightProvider.h + Utils.cpp Utils.h) add_library(select_content STATIC ${sources} ${ui_files}) target_link_libraries(select_content PUBLIC core) diff --git a/src/core/filters/select_content/CacheDrivenTask.cpp b/src/core/filters/select_content/CacheDrivenTask.cpp index 492d22c8e..2196440ee 100644 --- a/src/core/filters/select_content/CacheDrivenTask.cpp +++ b/src/core/filters/select_content/CacheDrivenTask.cpp @@ -18,7 +18,8 @@ #include "filters/page_layout/CacheDrivenTask.h" namespace select_content { -CacheDrivenTask::CacheDrivenTask(intrusive_ptr settings, intrusive_ptr nextTask) +CacheDrivenTask::CacheDrivenTask(std::shared_ptr settings, + std::shared_ptr nextTask) : m_settings(std::move(settings)), m_nextTask(std::move(nextTask)) {} CacheDrivenTask::~CacheDrivenTask() = default; @@ -53,10 +54,10 @@ void CacheDrivenTask::process(const PageInfo& pageInfo, const double deviationThreshold = settings.getSelectContentDeviationThreshold(); if (auto* thumbCol = dynamic_cast(collector)) { - thumbCol->processThumbnail(std::unique_ptr( - new Thumbnail(thumbCol->thumbnailCache(), thumbCol->maxLogicalThumbSize(), pageInfo.imageId(), xform, - params->contentRect(), params->pageRect(), params->pageDetectionMode() != MODE_DISABLED, - m_settings->deviationProvider().isDeviant(pageInfo.id(), deviationCoef, deviationThreshold)))); + thumbCol->processThumbnail(std::unique_ptr(new Thumbnail( + thumbCol->thumbnailCache(), thumbCol->maxLogicalThumbSize(), pageInfo.imageId(), xform, params->contentRect(), + params->pageRect(), params->pageDetectionMode() != MODE_DISABLED, + m_settings->deviationProvider().isDeviant(pageInfo.id(), deviationCoef, deviationThreshold, true)))); } } // CacheDrivenTask::process } // namespace select_content \ No newline at end of file diff --git a/src/core/filters/select_content/CacheDrivenTask.h b/src/core/filters/select_content/CacheDrivenTask.h index b09f64cd3..3f3561863 100644 --- a/src/core/filters/select_content/CacheDrivenTask.h +++ b/src/core/filters/select_content/CacheDrivenTask.h @@ -4,9 +4,9 @@ #ifndef SCANTAILOR_SELECT_CONTENT_CACHEDRIVENTASK_H_ #define SCANTAILOR_SELECT_CONTENT_CACHEDRIVENTASK_H_ +#include + #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class QSizeF; class PageInfo; @@ -20,19 +20,19 @@ class CacheDrivenTask; namespace select_content { class Settings; -class CacheDrivenTask : public ref_countable { +class CacheDrivenTask { DECLARE_NON_COPYABLE(CacheDrivenTask) public: - CacheDrivenTask(intrusive_ptr settings, intrusive_ptr nextTask); + CacheDrivenTask(std::shared_ptr settings, std::shared_ptr nextTask); - ~CacheDrivenTask() override; + virtual ~CacheDrivenTask(); void process(const PageInfo& pageInfo, AbstractFilterDataCollector* collector, const ImageTransformation& xform); private: - intrusive_ptr m_settings; - intrusive_ptr m_nextTask; + std::shared_ptr m_settings; + std::shared_ptr m_nextTask; }; } // namespace select_content #endif // ifndef SCANTAILOR_SELECT_CONTENT_CACHEDRIVENTASK_H_ diff --git a/src/core/filters/select_content/ContentBoxFinder.cpp b/src/core/filters/select_content/ContentBoxFinder.cpp index 8b6fea758..2e1f8dcb2 100644 --- a/src/core/filters/select_content/ContentBoxFinder.cpp +++ b/src/core/filters/select_content/ContentBoxFinder.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -1327,4 +1328,4 @@ const SEDM& ContentBoxFinder::Garbage::sedm() { } return m_sedm; } -} // namespace select_content \ No newline at end of file +} // namespace select_content diff --git a/src/core/filters/select_content/Filter.cpp b/src/core/filters/select_content/Filter.cpp index 0580d6203..0b9cd6db7 100644 --- a/src/core/filters/select_content/Filter.cpp +++ b/src/core/filters/select_content/Filter.cpp @@ -3,18 +3,13 @@ #include "Filter.h" -#include -#include #include -#include #include #include #include #include #include -#include -#include #include #include "CacheDrivenTask.h" @@ -25,17 +20,19 @@ #include "ProjectReader.h" #include "ProjectWriter.h" #include "Task.h" +#include "Utils.h" using namespace foundation; namespace select_content { -Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) : m_settings(new Settings), m_selectedPageOrder(0) { +Filter::Filter(const PageSelectionAccessor& pageSelectionAccessor) + : m_settings(std::make_shared()), m_selectedPageOrder(0) { m_optionsWidget.reset(new OptionsWidget(m_settings, pageSelectionAccessor)); const PageOrderOption::ProviderPtr defaultOrder; - const auto orderByWidth = make_intrusive(m_settings); - const auto orderByHeight = make_intrusive(m_settings); - const auto orderByDeviation = make_intrusive(m_settings->deviationProvider()); + const auto orderByWidth = std::make_shared(m_settings); + const auto orderByHeight = std::make_shared(m_settings); + const auto orderByDeviation = std::make_shared(m_settings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), defaultOrder); m_pageOrderOptions.emplace_back(tr("Order by increasing width"), orderByWidth); m_pageOrderOptions.emplace_back(tr("Order by increasing height"), orderByHeight); @@ -78,7 +75,8 @@ QDomElement Filter::saveSettings(const ProjectWriter& writer, QDomDocument& doc) QDomElement filterEl(doc.createElement("select-content")); filterEl.appendChild(XmlMarshaller(doc).sizeF(m_settings->pageDetectionBox(), "page-detection-box")); - filterEl.setAttribute("pageDetectionTolerance", Utils::doubleToString(m_settings->pageDetectionTolerance())); + filterEl.setAttribute("pageDetectionTolerance", + foundation::Utils::doubleToString(m_settings->pageDetectionTolerance())); writer.enumPages( [&](const PageId& pageId, int numericId) { this->writePageSettings(doc, filterEl, pageId, numericId); }); @@ -138,35 +136,23 @@ void Filter::loadSettings(const ProjectReader& reader, const QDomElement& filter } } // Filter::loadSettings -intrusive_ptr Filter::createTask(const PageId& pageId, - intrusive_ptr nextTask, - bool batch, - bool debug) { - return make_intrusive(intrusive_ptr(this), std::move(nextTask), m_settings, pageId, batch, debug); +std::shared_ptr Filter::createTask(const PageId& pageId, + std::shared_ptr nextTask, + bool batch, + bool debug) { + return std::make_shared(std::static_pointer_cast(shared_from_this()), std::move(nextTask), m_settings, + pageId, batch, debug); } -intrusive_ptr Filter::createCacheDrivenTask(intrusive_ptr nextTask) { - return make_intrusive(m_settings, std::move(nextTask)); +std::shared_ptr Filter::createCacheDrivenTask(std::shared_ptr nextTask) { + return std::make_shared(m_settings, std::move(nextTask)); } void Filter::loadDefaultSettings(const PageInfo& pageInfo) { - if (!m_settings->isParamsNull(pageInfo.id())) { + if (!m_settings->isParamsNull(pageInfo.id())) return; - } - const DefaultParams defaultParams = DefaultParamsProvider::getInstance().getParams(); - const DefaultParams::SelectContentParams& selectContentParams = defaultParams.getSelectContentParams(); - - const UnitsConverter unitsConverter(pageInfo.metadata().dpi()); - - const QSizeF& pageRectSize = selectContentParams.getPageRectSize(); - double pageRectWidth = pageRectSize.width(); - double pageRectHeight = pageRectSize.height(); - unitsConverter.convert(pageRectWidth, pageRectHeight, defaultParams.getUnits(), PIXELS); - m_settings->setPageParams( - pageInfo.id(), Params(QRectF(), QSizeF(), QRectF(QPointF(0, 0), QSizeF(pageRectWidth, pageRectHeight)), - Dependencies(), selectContentParams.isContentDetectEnabled() ? MODE_AUTO : MODE_DISABLED, - selectContentParams.getPageDetectMode(), selectContentParams.isFineTuneCorners())); + m_settings->setPageParams(pageInfo.id(), select_content::Utils::buildDefaultParams(pageInfo.metadata().dpi())); } OptionsWidget* Filter::optionsWidget() { diff --git a/src/core/filters/select_content/Filter.h b/src/core/filters/select_content/Filter.h index 3a1c6299a..c9a284433 100644 --- a/src/core/filters/select_content/Filter.h +++ b/src/core/filters/select_content/Filter.h @@ -5,6 +5,7 @@ #define SCANTAILOR_SELECT_CONTENT_FILTER_H_ #include +#include #include #include "AbstractFilter.h" @@ -14,7 +15,6 @@ #include "PageView.h" #include "SafeDeletingQObjectPtr.h" #include "Settings.h" -#include "intrusive_ptr.h" class PageSelectionAccessor; class QString; @@ -59,12 +59,12 @@ class Filter : public AbstractFilter { void loadDefaultSettings(const PageInfo& pageInfo) override; - intrusive_ptr createTask(const PageId& pageId, - intrusive_ptr nextTask, - bool batch, - bool debug); + std::shared_ptr createTask(const PageId& pageId, + std::shared_ptr nextTask, + bool batch, + bool debug); - intrusive_ptr createCacheDrivenTask(intrusive_ptr nextTask); + std::shared_ptr createCacheDrivenTask(std::shared_ptr nextTask); OptionsWidget* optionsWidget(); @@ -72,7 +72,7 @@ class Filter : public AbstractFilter { void writePageSettings(QDomDocument& doc, QDomElement& filterEl, const PageId& pageId, int numericId) const; - intrusive_ptr m_settings; + std::shared_ptr m_settings; SafeDeletingQObjectPtr m_optionsWidget; std::vector m_pageOrderOptions; int m_selectedPageOrder; diff --git a/src/core/filters/select_content/ImageView.cpp b/src/core/filters/select_content/ImageView.cpp index bed0f6327..14e557784 100644 --- a/src/core/filters/select_content/ImageView.cpp +++ b/src/core/filters/select_content/ImageView.cpp @@ -3,13 +3,7 @@ #include "ImageView.h" -#include -#include #include -#include -#include -#include -#include #include #include @@ -27,7 +21,7 @@ using namespace imageproc; namespace select_content { ImageView::ImageView(const QImage& image, const QImage& downscaledImage, - const GrayImage& grayImage, + const ContentMask& contentMask, const ImageTransformation& xform, const QRectF& contentRect, const QRectF& pageRect, @@ -42,6 +36,7 @@ ImageView::ImageView(const QImage& image, m_pageRectEnabled(pageRectEnabled), m_pageRectReloadRequested(false), m_minBoxSize(10.0, 10.0), + m_contentMask(contentMask), m_adjustmentVerticalModifier(Qt::ControlModifier), m_adjustmentHorizontalModifier(Qt::ShiftModifier) { setMouseTracking(true); @@ -159,8 +154,6 @@ ImageView::ImageView(const QImage& image, addAction(remove); connect(create, SIGNAL(triggered(bool)), this, SLOT(createContentBox())); connect(remove, SIGNAL(triggered(bool)), this, SLOT(removeContentBox())); - - buildContentImage(grayImage, xform); } ImageView::~ImageView() = default; @@ -486,48 +479,21 @@ void ImageView::pageRectSetExternally(const QRectF& pageRect) { update(); } -void ImageView::buildContentImage(const GrayImage& grayImage, const ImageTransformation& xform) { - ImageTransformation xform150dpi(xform); - xform150dpi.preScaleToDpi(Dpi(150, 150)); - - if (xform150dpi.resultingRect().toRect().isEmpty()) { - return; - } - - QImage gray150(transformToGray(grayImage, xform150dpi.transform(), xform150dpi.resultingRect().toRect(), - OutsidePixels::assumeColor(Qt::white))); - - m_contentImage = binarizeWolf(gray150, QSize(51, 51), 50); - - PolygonRasterizer::fillExcept(m_contentImage, WHITE, xform150dpi.resultingPreCropArea(), Qt::WindingFill); - - Despeckle::despeckleInPlace(m_contentImage, Dpi(150, 150), Despeckle::NORMAL, NullTaskStatus()); - - m_originalToContentImage = xform150dpi.transform(); - m_contentImageToOriginal = m_originalToContentImage.inverted(); -} - void ImageView::onMouseDoubleClickEvent(QMouseEvent* event, InteractionState& interaction) { if (event->button() == Qt::LeftButton) { - if (!m_contentRect.isEmpty() && !m_contentImage.isNull()) { + if (!m_contentRect.isEmpty() && !m_contentMask.isNull()) { correctContentBox(QPointF(0.5, 0.5) + event->pos(), event->modifiers()); } } } void ImageView::correctContentBox(const QPointF& pos, const Qt::KeyboardModifiers mask) { - const QTransform widgetToContentImage(widgetToImage() * m_originalToContentImage); - const QTransform contentImageToVirtual(m_contentImageToOriginal * imageToVirtual()); + const QTransform widgetToContentImage(widgetToImage() * m_contentMask.originalToContentXform()); + const QTransform contentImageToVirtual(m_contentMask.contentToOriginalXform() * imageToVirtual()); const QPointF contentPos = widgetToContentImage.map(pos); - QRect findingArea((contentPos - QPointF(15, 15)).toPoint(), QSize(30, 30)); - findingArea = findingArea.intersected(m_contentImage.rect()); - if (findingArea.isEmpty()) { - return; - } - - QRect foundArea = findContentInArea(findingArea); + QRect foundArea = m_contentMask.findContentInArea(findingArea); if (foundArea.isEmpty()) { return; } @@ -588,38 +554,6 @@ void ImageView::correctContentBox(const QPointF& pos, const Qt::KeyboardModifier contentRectDragFinished(); } -QRect ImageView::findContentInArea(const QRect& area) const { - const uint32_t* imageLine = m_contentImage.data(); - const int imageStride = m_contentImage.wordsPerLine(); - const uint32_t msb = uint32_t(1) << 31; - - int top = std::numeric_limits::max(); - int left = std::numeric_limits::max(); - int bottom = std::numeric_limits::min(); - int right = std::numeric_limits::min(); - - imageLine += area.top() * imageStride; - for (int y = area.top(); y <= area.bottom(); ++y) { - for (int x = area.left(); x <= area.right(); ++x) { - if (imageLine[x >> 5] & (msb >> (x & 31))) { - top = std::min(top, y); - left = std::min(left, x); - bottom = std::max(bottom, y); - right = std::max(right, x); - } - } - imageLine += imageStride; - } - - if (top > bottom) { - return QRect(); - } - - QRect foundArea = QRect(left, top, right - left + 1, bottom - top + 1); - foundArea.adjust(-1, -1, 1, 1); - return foundArea; -} - void ImageView::setPageRectEnabled(const bool state) { m_pageRectEnabled = state; enablePageRectInteraction(state); diff --git a/src/core/filters/select_content/ImageView.h b/src/core/filters/select_content/ImageView.h index be715994c..f6459b3fa 100644 --- a/src/core/filters/select_content/ImageView.h +++ b/src/core/filters/select_content/ImageView.h @@ -4,7 +4,7 @@ #ifndef SCANTAILOR_SELECT_CONTENT_IMAGEVIEW_H_ #define SCANTAILOR_SELECT_CONTENT_IMAGEVIEW_H_ -#include +#include #include #include @@ -21,10 +21,6 @@ class ImageTransformation; class QMenu; -namespace imageproc { -class GrayImage; -} - namespace select_content { class ImageView : public ImageViewBase, private InteractionHandler { Q_OBJECT @@ -34,7 +30,7 @@ class ImageView : public ImageViewBase, private InteractionHandler { */ ImageView(const QImage& image, const QImage& downscaledImage, - const imageproc::GrayImage& grayImage, + const ContentMask& contentMask, const ImageTransformation& xform, const QRectF& contentRect, const QRectF& pageRect, @@ -103,12 +99,8 @@ class ImageView : public ImageViewBase, private InteractionHandler { void pageRectMoveRequest(const QPolygonF& polyMoved); - void buildContentImage(const imageproc::GrayImage& grayImage, const ImageTransformation& xform); - void correctContentBox(const QPointF& pos, Qt::KeyboardModifiers mask = Qt::NoModifier); - QRect findContentInArea(const QRect& area) const; - void enableContentRectInteraction(bool state); void enablePageRectInteraction(bool state); @@ -156,9 +148,7 @@ class ImageView : public ImageViewBase, private InteractionHandler { QSizeF m_minBoxSize; - imageproc::BinaryImage m_contentImage; - QTransform m_originalToContentImage; - QTransform m_contentImageToOriginal; + ContentMask m_contentMask; Qt::KeyboardModifier m_adjustmentVerticalModifier; Qt::KeyboardModifier m_adjustmentHorizontalModifier; diff --git a/src/core/filters/select_content/OptionsWidget.cpp b/src/core/filters/select_content/OptionsWidget.cpp index 496806ee7..150d3d1ba 100644 --- a/src/core/filters/select_content/OptionsWidget.cpp +++ b/src/core/filters/select_content/OptionsWidget.cpp @@ -12,7 +12,7 @@ #include "Settings.h" namespace select_content { -OptionsWidget::OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) +OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor) : m_settings(std::move(settings)), m_pageSelectionAccessor(pageSelectionAccessor), m_connectionManager(std::bind(&OptionsWidget::setupUiConnections, this)) { @@ -312,59 +312,4 @@ OptionsWidget::UiData::UiData() : m_contentDetectionMode(MODE_AUTO), m_pageDetectionMode(MODE_DISABLED), m_fineTuneCornersEnabled(false) {} OptionsWidget::UiData::~UiData() = default; - -void OptionsWidget::UiData::setSizeCalc(const PhysSizeCalc& calc) { - m_sizeCalc = calc; -} - -void OptionsWidget::UiData::setContentRect(const QRectF& contentRect) { - m_contentRect = contentRect; -} - -const QRectF& OptionsWidget::UiData::contentRect() const { - return m_contentRect; -} - -void OptionsWidget::UiData::setPageRect(const QRectF& pageRect) { - m_pageRect = pageRect; -} - -const QRectF& OptionsWidget::UiData::pageRect() const { - return m_pageRect; -} - -QSizeF OptionsWidget::UiData::contentSizeMM() const { - return m_sizeCalc.sizeMM(m_contentRect); -} - -void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { - m_deps = deps; -} - -const Dependencies& OptionsWidget::UiData::dependencies() const { - return m_deps; -} - -void OptionsWidget::UiData::setContentDetectionMode(AutoManualMode mode) { - m_contentDetectionMode = mode; -} - -AutoManualMode OptionsWidget::UiData::contentDetectionMode() const { - return m_contentDetectionMode; -} - -void OptionsWidget::UiData::setPageDetectionMode(AutoManualMode mode) { - m_pageDetectionMode = mode; -} - -AutoManualMode OptionsWidget::UiData::pageDetectionMode() const { - return m_pageDetectionMode; -} -void OptionsWidget::UiData::setFineTuneCornersEnabled(bool fineTune) { - m_fineTuneCornersEnabled = fineTune; -} - -bool OptionsWidget::UiData::isFineTuningCornersEnabled() const { - return m_fineTuneCornersEnabled; -} } // namespace select_content \ No newline at end of file diff --git a/src/core/filters/select_content/OptionsWidget.h b/src/core/filters/select_content/OptionsWidget.h index 96498beec..ff326d3e3 100644 --- a/src/core/filters/select_content/OptionsWidget.h +++ b/src/core/filters/select_content/OptionsWidget.h @@ -19,7 +19,6 @@ #include "PageSelectionAccessor.h" #include "Params.h" #include "PhysSizeCalc.h" -#include "intrusive_ptr.h" #include "ui_OptionsWidget.h" namespace select_content { @@ -74,7 +73,7 @@ class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private }; - OptionsWidget(intrusive_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); + OptionsWidget(std::shared_ptr settings, const PageSelectionAccessor& pageSelectionAccessor); ~OptionsWidget() override; @@ -125,7 +124,7 @@ class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private void setupUiConnections(); - intrusive_ptr m_settings; + std::shared_ptr m_settings; UiData m_uiData; PageSelectionAccessor m_pageSelectionAccessor; PageId m_pageId; @@ -133,5 +132,61 @@ class OptionsWidget : public FilterOptionsWidget, public UnitsListener, private ConnectionManager m_connectionManager; }; + + +inline void OptionsWidget::UiData::setSizeCalc(const PhysSizeCalc& calc) { + m_sizeCalc = calc; +} + +inline void OptionsWidget::UiData::setContentRect(const QRectF& contentRect) { + m_contentRect = contentRect; +} + +inline const QRectF& OptionsWidget::UiData::contentRect() const { + return m_contentRect; +} + +inline void OptionsWidget::UiData::setPageRect(const QRectF& pageRect) { + m_pageRect = pageRect; +} + +inline const QRectF& OptionsWidget::UiData::pageRect() const { + return m_pageRect; +} + +inline QSizeF OptionsWidget::UiData::contentSizeMM() const { + return m_sizeCalc.sizeMM(m_contentRect); +} + +inline void OptionsWidget::UiData::setDependencies(const Dependencies& deps) { + m_deps = deps; +} + +inline const Dependencies& OptionsWidget::UiData::dependencies() const { + return m_deps; +} + +inline void OptionsWidget::UiData::setContentDetectionMode(AutoManualMode mode) { + m_contentDetectionMode = mode; +} + +inline AutoManualMode OptionsWidget::UiData::contentDetectionMode() const { + return m_contentDetectionMode; +} + +inline void OptionsWidget::UiData::setPageDetectionMode(AutoManualMode mode) { + m_pageDetectionMode = mode; +} + +inline AutoManualMode OptionsWidget::UiData::pageDetectionMode() const { + return m_pageDetectionMode; +} +inline void OptionsWidget::UiData::setFineTuneCornersEnabled(bool fineTune) { + m_fineTuneCornersEnabled = fineTune; +} + +inline bool OptionsWidget::UiData::isFineTuningCornersEnabled() const { + return m_fineTuneCornersEnabled; +} } // namespace select_content #endif // ifndef SCANTAILOR_SELECT_CONTENT_OPTIONSWIDGET_H_ diff --git a/src/core/filters/select_content/OrderByHeightProvider.cpp b/src/core/filters/select_content/OrderByHeightProvider.cpp index 1f3e1d784..918f9a46f 100644 --- a/src/core/filters/select_content/OrderByHeightProvider.cpp +++ b/src/core/filters/select_content/OrderByHeightProvider.cpp @@ -6,7 +6,7 @@ #include namespace select_content { -OrderByHeightProvider::OrderByHeightProvider(intrusive_ptr settings) : m_settings(std::move(settings)) {} +OrderByHeightProvider::OrderByHeightProvider(std::shared_ptr settings) : m_settings(std::move(settings)) {} bool OrderByHeightProvider::precedes(const PageId& lhsPage, const bool lhsIncomplete, diff --git a/src/core/filters/select_content/OrderByHeightProvider.h b/src/core/filters/select_content/OrderByHeightProvider.h index d2d0e71a5..35c82ecba 100644 --- a/src/core/filters/select_content/OrderByHeightProvider.h +++ b/src/core/filters/select_content/OrderByHeightProvider.h @@ -4,19 +4,20 @@ #ifndef SCANTAILOR_SELECT_CONTENT_ORDERBYHEIGHTPROVIDER_H_ #define SCANTAILOR_SELECT_CONTENT_ORDERBYHEIGHTPROVIDER_H_ +#include + #include "PageOrderProvider.h" #include "Settings.h" -#include "intrusive_ptr.h" namespace select_content { class OrderByHeightProvider : public PageOrderProvider { public: - explicit OrderByHeightProvider(intrusive_ptr settings); + explicit OrderByHeightProvider(std::shared_ptr settings); bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override; private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace select_content #endif diff --git a/src/core/filters/select_content/OrderByWidthProvider.cpp b/src/core/filters/select_content/OrderByWidthProvider.cpp index 618499aca..a0ddd7b60 100644 --- a/src/core/filters/select_content/OrderByWidthProvider.cpp +++ b/src/core/filters/select_content/OrderByWidthProvider.cpp @@ -6,7 +6,7 @@ #include namespace select_content { -OrderByWidthProvider::OrderByWidthProvider(intrusive_ptr settings) : m_settings(std::move(settings)) {} +OrderByWidthProvider::OrderByWidthProvider(std::shared_ptr settings) : m_settings(std::move(settings)) {} bool OrderByWidthProvider::precedes(const PageId& lhsPage, const bool lhsIncomplete, diff --git a/src/core/filters/select_content/OrderByWidthProvider.h b/src/core/filters/select_content/OrderByWidthProvider.h index 8adf797d2..190a7d644 100644 --- a/src/core/filters/select_content/OrderByWidthProvider.h +++ b/src/core/filters/select_content/OrderByWidthProvider.h @@ -4,19 +4,20 @@ #ifndef SCANTAILOR_SELECT_CONTENT_ORDERBYWIDTHPROVIDER_H_ #define SCANTAILOR_SELECT_CONTENT_ORDERBYWIDTHPROVIDER_H_ +#include + #include "PageOrderProvider.h" #include "Settings.h" -#include "intrusive_ptr.h" namespace select_content { class OrderByWidthProvider : public PageOrderProvider { public: - explicit OrderByWidthProvider(intrusive_ptr settings); + explicit OrderByWidthProvider(std::shared_ptr settings); bool precedes(const PageId& lhsPage, bool lhsIncomplete, const PageId& rhsPage, bool rhsIncomplete) const override; private: - intrusive_ptr m_settings; + std::shared_ptr m_settings; }; } // namespace select_content #endif diff --git a/src/core/filters/select_content/Params.cpp b/src/core/filters/select_content/Params.cpp index be4ea5101..1f0a4c757 100644 --- a/src/core/filters/select_content/Params.cpp +++ b/src/core/filters/select_content/Params.cpp @@ -49,60 +49,4 @@ QDomElement Params::toXml(QDomDocument& doc, const QString& name) const { el.appendChild(m_deps.toXml(doc, "dependencies")); return el; } - -const QRectF& Params::contentRect() const { - return m_contentRect; -} - -const QRectF& Params::pageRect() const { - return m_pageRect; -} - -const QSizeF& Params::contentSizeMM() const { - return m_contentSizeMM; -} - -const Dependencies& Params::dependencies() const { - return m_deps; -} - -AutoManualMode Params::contentDetectionMode() const { - return m_contentDetectionMode; -} - -AutoManualMode Params::pageDetectionMode() const { - return m_pageDetectionMode; -} - -bool Params::isFineTuningEnabled() const { - return m_fineTuneCorners; -} - -void Params::setContentDetectionMode(const AutoManualMode mode) { - m_contentDetectionMode = mode; -} - -void Params::setPageDetectionMode(const AutoManualMode mode) { - m_pageDetectionMode = mode; -} - -void Params::setContentRect(const QRectF& rect) { - m_contentRect = rect; -} - -void Params::setPageRect(const QRectF& rect) { - m_pageRect = rect; -} - -void Params::setContentSizeMM(const QSizeF& size) { - m_contentSizeMM = size; -} - -void Params::setDependencies(const Dependencies& deps) { - m_deps = deps; -} - -void Params::setFineTuneCornersEnabled(bool fineTuneCorners) { - m_fineTuneCorners = fineTuneCorners; -} } // namespace select_content diff --git a/src/core/filters/select_content/Params.h b/src/core/filters/select_content/Params.h index fe634dd2a..eeda2b9e9 100644 --- a/src/core/filters/select_content/Params.h +++ b/src/core/filters/select_content/Params.h @@ -75,5 +75,62 @@ class Params { AutoManualMode m_pageDetectionMode; bool m_fineTuneCorners; }; + + +inline const QRectF& Params::contentRect() const { + return m_contentRect; +} + +inline const QRectF& Params::pageRect() const { + return m_pageRect; +} + +inline const QSizeF& Params::contentSizeMM() const { + return m_contentSizeMM; +} + +inline const Dependencies& Params::dependencies() const { + return m_deps; +} + +inline AutoManualMode Params::contentDetectionMode() const { + return m_contentDetectionMode; +} + +inline AutoManualMode Params::pageDetectionMode() const { + return m_pageDetectionMode; +} + +inline bool Params::isFineTuningEnabled() const { + return m_fineTuneCorners; +} + +inline void Params::setContentDetectionMode(const AutoManualMode mode) { + m_contentDetectionMode = mode; +} + +inline void Params::setPageDetectionMode(const AutoManualMode mode) { + m_pageDetectionMode = mode; +} + +inline void Params::setContentRect(const QRectF& rect) { + m_contentRect = rect; +} + +inline void Params::setPageRect(const QRectF& rect) { + m_pageRect = rect; +} + +inline void Params::setContentSizeMM(const QSizeF& size) { + m_contentSizeMM = size; +} + +inline void Params::setDependencies(const Dependencies& deps) { + m_deps = deps; +} + +inline void Params::setFineTuneCornersEnabled(bool fineTuneCorners) { + m_fineTuneCorners = fineTuneCorners; +} } // namespace select_content #endif // ifndef SCANTAILOR_SELECT_CONTENT_PARAMS_H_ diff --git a/src/core/filters/select_content/Settings.cpp b/src/core/filters/select_content/Settings.cpp index bdeb99647..5098f8fe7 100644 --- a/src/core/filters/select_content/Settings.cpp +++ b/src/core/filters/select_content/Settings.cpp @@ -18,10 +18,10 @@ Settings::Settings() : m_pageDetectionBox(0.0, 0.0), m_pageDetectionTolerance(0. if (it != m_pageParams.end()) { const Params& params = it->second; const QSizeF& contentSizeMM = params.contentSizeMM(); - return std::sqrt(contentSizeMM.width() * contentSizeMM.height() / 4 / 25.4); - } else { - return .0; - }; + if (!contentSizeMM.toSize().isEmpty()) + return std::sqrt(std::pow(contentSizeMM.width(), 2) + std::pow(contentSizeMM.height(), 2)); + } + return NAN; }); } diff --git a/src/core/filters/select_content/Settings.h b/src/core/filters/select_content/Settings.h index 421d6edca..6a4d344be 100644 --- a/src/core/filters/select_content/Settings.h +++ b/src/core/filters/select_content/Settings.h @@ -13,18 +13,17 @@ #include "NonCopyable.h" #include "PageId.h" #include "Params.h" -#include "ref_countable.h" class AbstractRelinker; namespace select_content { -class Settings : public ref_countable { +class Settings { DECLARE_NON_COPYABLE(Settings) public: Settings(); - ~Settings() override; + virtual ~Settings(); void clear(); diff --git a/src/core/filters/select_content/Task.cpp b/src/core/filters/select_content/Task.cpp index 51f2e9ad1..15d4c92a2 100644 --- a/src/core/filters/select_content/Task.cpp +++ b/src/core/filters/select_content/Task.cpp @@ -25,35 +25,35 @@ using namespace imageproc; namespace select_content { class Task::UiUpdater : public FilterResult { public: - UiUpdater(intrusive_ptr filter, + UiUpdater(std::shared_ptr filter, const PageId& pageId, std::unique_ptr dbg, const QImage& image, const ImageTransformation& xform, - const GrayImage& grayImage, + const ContentMask& contentMask, const OptionsWidget::UiData& uiData, bool batch); void updateUI(FilterUiInterface* ui) override; - intrusive_ptr filter() override { return m_filter; } + std::shared_ptr filter() override { return m_filter; } private: - intrusive_ptr m_filter; + std::shared_ptr m_filter; PageId m_pageId; std::unique_ptr m_dbg; QImage m_image; QImage m_downscaledImage; - GrayImage m_grayImage; + ContentMask m_contentMask; ImageTransformation m_xform; OptionsWidget::UiData m_uiData; bool m_batchProcessing; }; -Task::Task(intrusive_ptr filter, - intrusive_ptr nextTask, - intrusive_ptr settings, +Task::Task(std::shared_ptr filter, + std::shared_ptr nextTask, + std::shared_ptr settings, const PageId& pageId, const bool batch, const bool debug) @@ -145,19 +145,20 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data) if (m_nextTask) { return m_nextTask->process(status, FilterData(data, data.xform()), uiData.pageRect(), uiData.contentRect()); } else { - return make_intrusive(m_filter, m_pageId, std::move(m_dbg), data.origImage(), data.xform(), - data.grayImageBlackOnWhite(), uiData, m_batchProcessing); + return std::make_shared(m_filter, m_pageId, std::move(m_dbg), data.origImage(), data.xform(), + ContentMask(data.grayImageBlackOnWhite(), data.xform(), status), uiData, + m_batchProcessing); } } // Task::process /*============================ Task::UiUpdater ==========================*/ -Task::UiUpdater::UiUpdater(intrusive_ptr filter, +Task::UiUpdater::UiUpdater(std::shared_ptr filter, const PageId& pageId, std::unique_ptr dbg, const QImage& image, const ImageTransformation& xform, - const GrayImage& grayImage, + const ContentMask& contentMask, const OptionsWidget::UiData& uiData, const bool batch) : m_filter(std::move(filter)), @@ -165,7 +166,7 @@ Task::UiUpdater::UiUpdater(intrusive_ptr filter, m_dbg(std::move(dbg)), m_image(image), m_downscaledImage(ImageView::createDownscaledImage(image)), - m_grayImage(grayImage), + m_contentMask(contentMask), m_xform(xform), m_uiData(uiData), m_batchProcessing(batch) {} @@ -182,7 +183,7 @@ void Task::UiUpdater::updateUI(FilterUiInterface* ui) { optWidget->postUpdateUI(m_uiData); ui->setOptionsWidget(optWidget, ui->KEEP_OWNERSHIP); - auto* view = new ImageView(m_image, m_downscaledImage, m_grayImage, m_xform, m_uiData.contentRect(), + auto* view = new ImageView(m_image, m_downscaledImage, m_contentMask, m_xform, m_uiData.contentRect(), m_uiData.pageRect(), m_uiData.pageDetectionMode() != MODE_DISABLED); ui->setImageWidget(view, ui->TRANSFER_OWNERSHIP, m_dbg.get()); diff --git a/src/core/filters/select_content/Task.h b/src/core/filters/select_content/Task.h index 2abb9451e..f0d6dcb76 100644 --- a/src/core/filters/select_content/Task.h +++ b/src/core/filters/select_content/Task.h @@ -11,7 +11,6 @@ #include "FilterResult.h" #include "NonCopyable.h" #include "PageId.h" -#include "ref_countable.h" class TaskStatus; class FilterData; @@ -27,27 +26,27 @@ namespace select_content { class Filter; class Settings; -class Task : public ref_countable { +class Task { DECLARE_NON_COPYABLE(Task) public: - Task(intrusive_ptr filter, - intrusive_ptr nextTask, - intrusive_ptr settings, + Task(std::shared_ptr filter, + std::shared_ptr nextTask, + std::shared_ptr settings, const PageId& pageId, bool batch, bool debug); - ~Task() override; + virtual ~Task(); FilterResultPtr process(const TaskStatus& status, const FilterData& data); private: class UiUpdater; - intrusive_ptr m_filter; - intrusive_ptr m_nextTask; - intrusive_ptr m_settings; + std::shared_ptr m_filter; + std::shared_ptr m_nextTask; + std::shared_ptr m_settings; std::unique_ptr m_dbg; PageId m_pageId; bool m_batchProcessing; diff --git a/src/core/filters/select_content/Thumbnail.cpp b/src/core/filters/select_content/Thumbnail.cpp index 7ed7df3bb..ae53b1b3a 100644 --- a/src/core/filters/select_content/Thumbnail.cpp +++ b/src/core/filters/select_content/Thumbnail.cpp @@ -7,7 +7,7 @@ #include namespace select_content { -Thumbnail::Thumbnail(intrusive_ptr thumbnailCache, +Thumbnail::Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/select_content/Thumbnail.h b/src/core/filters/select_content/Thumbnail.h index da68ffa60..f2fbdadf1 100644 --- a/src/core/filters/select_content/Thumbnail.h +++ b/src/core/filters/select_content/Thumbnail.h @@ -16,7 +16,7 @@ class ImageTransformation; namespace select_content { class Thumbnail : public ThumbnailBase { public: - Thumbnail(intrusive_ptr thumbnailCache, + Thumbnail(std::shared_ptr thumbnailCache, const QSizeF& maxSize, const ImageId& imageId, const ImageTransformation& xform, diff --git a/src/core/filters/select_content/Utils.cpp b/src/core/filters/select_content/Utils.cpp new file mode 100644 index 000000000..6ab7ca64c --- /dev/null +++ b/src/core/filters/select_content/Utils.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#include "Utils.h" + +#include +#include +#include + +#include "Params.h" + +using namespace select_content; + +Params Utils::buildDefaultParams(const Dpi& dpi) { + const DefaultParams& defaultParams = DefaultParamsProvider::getInstance().getParams(); + const DefaultParams::SelectContentParams& selectContentParams = defaultParams.getSelectContentParams(); + + const UnitsConverter unitsConverter(dpi); + + const QSizeF& pageRectSize = selectContentParams.getPageRectSize(); + double pageRectWidth = pageRectSize.width(); + double pageRectHeight = pageRectSize.height(); + unitsConverter.convert(pageRectWidth, pageRectHeight, defaultParams.getUnits(), PIXELS); + + return Params(QRectF(), QSizeF(), QRectF(QPointF(0, 0), QSizeF(pageRectWidth, pageRectHeight)), Dependencies(), + selectContentParams.isContentDetectEnabled() ? MODE_AUTO : MODE_DISABLED, + selectContentParams.getPageDetectMode(), selectContentParams.isFineTuneCorners()); +} diff --git a/src/core/filters/select_content/Utils.h b/src/core/filters/select_content/Utils.h new file mode 100644 index 000000000..43093bbcd --- /dev/null +++ b/src/core/filters/select_content/Utils.h @@ -0,0 +1,20 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_SELECT_CONTENT_UTILS_H_ +#define SCANTAILOR_SELECT_CONTENT_UTILS_H_ + +class Dpi; + +namespace select_content { +class Params; + +class Utils { + public: + Utils() = delete; + + static Params buildDefaultParams(const Dpi& dpi); +}; +} // namespace select_content + +#endif // SCANTAILOR_SELECT_CONTENT_UTILS_H_ diff --git a/src/core/interaction/InteractionHandler.cpp b/src/core/interaction/InteractionHandler.cpp index 27098bf9e..43f3099d4 100644 --- a/src/core/interaction/InteractionHandler.cpp +++ b/src/core/interaction/InteractionHandler.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "InteractionState.h" @@ -53,7 +52,8 @@ ScopedClearAcceptance::~ScopedClearAcceptance() { } } // anonymous namespace -InteractionHandler::InteractionHandler() : m_preceeders(new HandlerList), m_followers(new HandlerList) {} +InteractionHandler::InteractionHandler() + : m_preceeders(std::make_shared()), m_followers(std::make_shared()) {} InteractionHandler::~InteractionHandler() { using namespace boost::lambda; @@ -63,8 +63,8 @@ InteractionHandler::~InteractionHandler() { void InteractionHandler::paint(QPainter& painter, const InteractionState& interaction) { // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, paint(painter, interaction)); painter.save(); @@ -75,8 +75,8 @@ void InteractionHandler::paint(QPainter& painter, const InteractionState& intera void InteractionHandler::proximityUpdate(const QPointF& screenMousePos, InteractionState& interaction) { // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, proximityUpdate(screenMousePos, interaction)); onProximityUpdate(screenMousePos, interaction); @@ -88,8 +88,8 @@ void InteractionHandler::keyPressEvent(QKeyEvent* event, InteractionState& inter RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, keyPressEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -101,8 +101,8 @@ void InteractionHandler::keyPressEvent(QKeyEvent* event, InteractionState& inter void InteractionHandler::keyReleaseEvent(QKeyEvent* event, InteractionState& interaction) { RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, keyReleaseEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -115,8 +115,8 @@ void InteractionHandler::mousePressEvent(QMouseEvent* event, InteractionState& i RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, mousePressEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -128,8 +128,8 @@ void InteractionHandler::mousePressEvent(QMouseEvent* event, InteractionState& i void InteractionHandler::mouseReleaseEvent(QMouseEvent* event, InteractionState& interaction) { RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, mouseReleaseEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -141,8 +141,8 @@ void InteractionHandler::mouseReleaseEvent(QMouseEvent* event, InteractionState& void InteractionHandler::mouseDoubleClickEvent(QMouseEvent* event, InteractionState& interaction) { RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, mouseDoubleClickEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -155,8 +155,8 @@ void InteractionHandler::mouseMoveEvent(QMouseEvent* event, InteractionState& in RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, mouseMoveEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -169,8 +169,8 @@ void InteractionHandler::wheelEvent(QWheelEvent* event, InteractionState& intera RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, wheelEvent(event, interaction)); RETURN_IF_ACCEPTED(event); @@ -182,8 +182,8 @@ void InteractionHandler::wheelEvent(QWheelEvent* event, InteractionState& intera void InteractionHandler::contextMenuEvent(QContextMenuEvent* event, InteractionState& interaction) { RETURN_IF_ACCEPTED(event); // Keep them alive in case this object gets destroyed. - intrusive_ptr preceeders(m_preceeders); - intrusive_ptr followers(m_followers); + std::shared_ptr preceeders(m_preceeders); + std::shared_ptr followers(m_followers); DISPATCH(preceeders, contextMenuEvent(event, interaction)); RETURN_IF_ACCEPTED(event); diff --git a/src/core/interaction/InteractionHandler.h b/src/core/interaction/InteractionHandler.h index 298c39917..4ab35dcb9 100644 --- a/src/core/interaction/InteractionHandler.h +++ b/src/core/interaction/InteractionHandler.h @@ -5,10 +5,9 @@ #define SCANTAILOR_INTERACTION_INTERACTIONHANDLER_H_ #include +#include #include "NonCopyable.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class InteractionState; class QPainter; @@ -83,12 +82,11 @@ class InteractionHandler static bool defaultInteractionPermitter(const InteractionState& interaction); private: - class HandlerList : public ref_countable, - public boost::intrusive::list> {}; + class HandlerList : public boost::intrusive::list> {}; - intrusive_ptr m_preceeders; - intrusive_ptr m_followers; + std::shared_ptr m_preceeders; + std::shared_ptr m_followers; }; diff --git a/src/core/interaction/InteractiveXSpline.cpp b/src/core/interaction/InteractiveXSpline.cpp index 2c10e94d3..551ea649f 100644 --- a/src/core/interaction/InteractiveXSpline.cpp +++ b/src/core/interaction/InteractiveXSpline.cpp @@ -3,10 +3,10 @@ #include "InteractiveXSpline.h" -#include +#include + #include #include -#include #include "MatrixCalc.h" #include "Proximity.h" @@ -26,8 +26,9 @@ struct InteractiveXSpline::IdentTransform { QPointF operator()(const QPointF& pt) const { return pt; } }; -InteractiveXSpline::InteractiveXSpline() - : m_modifiedCallback(NoOp()), +InteractiveXSpline::InteractiveXSpline(ImageViewBase& imageView) + : m_imageView(imageView), + m_modifiedCallback(NoOp()), m_dragFinishedCallback(NoOp()), m_fromStorage(IdentTransform()), m_toStorage(IdentTransform()), @@ -56,7 +57,7 @@ void InteractiveXSpline::setSpline(const XSpline& spline) { newControlPoints[i].handler.setProximityStatusTip( tr("This point can be dragged. Hold Ctrl or Shift to drag along axes.")); } else { - newControlPoints[i].handler.setProximityStatusTip(tr("Drag this point or delete it by pressing Del or D.")); + newControlPoints[i].handler.setProximityStatusTip(tr("Drag this point or delete it by pressing D key.")); } newControlPoints[i].handler.setInteractionCursor(Qt::BlankCursor); newControlPoints[i].handler.setObject(&newControlPoints[i].point); @@ -135,26 +136,22 @@ void InteractiveXSpline::onMousePressEvent(QMouseEvent* event, InteractionState& } } -void InteractiveXSpline::onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) { +void InteractiveXSpline::removeControlPointUnderMouse() { + InteractionState& interaction = m_imageView.interactionState(); if (interaction.captured()) { return; } - switch (event->key()) { - case Qt::Key_Delete: - case Qt::Key_D: - const int numControlPoints = m_spline.numControlPoints(); - // Check if one of our control points is a proximity leader. - // Note that we don't consider the endpoints. - for (int i = 1; i < numControlPoints - 1; ++i) { - if (m_controlPoints[i].handler.proximityLeader(interaction)) { - m_spline.eraseControlPoint(i); - setSpline(m_spline); - interaction.setRedrawRequested(true); - event->accept(); - break; - } - } + const int numControlPoints = m_spline.numControlPoints(); + // Check if one of our control points is a proximity leader. + // Note that we don't consider the endpoints. + for (int i = 1; i < numControlPoints - 1; ++i) { + if (m_controlPoints[i].handler.proximityLeader(interaction)) { + m_spline.eraseControlPoint(i); + setSpline(m_spline); + interaction.setRedrawRequested(true); + break; + } } } diff --git a/src/core/interaction/InteractiveXSpline.h b/src/core/interaction/InteractiveXSpline.h index 9a52b7a2c..624e332fe 100644 --- a/src/core/interaction/InteractiveXSpline.h +++ b/src/core/interaction/InteractiveXSpline.h @@ -16,6 +16,9 @@ #include "VecNT.h" #include "XSpline.h" +class ImageViewBase; +class QShortcut; + class InteractiveXSpline : public InteractionHandler { Q_DECLARE_TR_FUNCTIONS(InteractiveXSpline) public: @@ -23,7 +26,7 @@ class InteractiveXSpline : public InteractionHandler { using ModifiedCallback = boost::function; using DragFinishedCallback = boost::function; - InteractiveXSpline(); + explicit InteractiveXSpline(ImageViewBase& imageView); void setSpline(const XSpline& spline); @@ -48,6 +51,8 @@ class InteractiveXSpline : public InteractionHandler { */ bool curveIsProximityLeader(const InteractionState& state, QPointF* pt = nullptr, double* t = nullptr) const; + void removeControlPointUnderMouse(); + protected: void onProximityUpdate(const QPointF& screenMousePos, InteractionState& interaction) override; @@ -55,8 +60,6 @@ class InteractiveXSpline : public InteractionHandler { void onMousePressEvent(QMouseEvent* event, InteractionState& interaction) override; - void onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) override; - private: struct NoOp; struct IdentTransform; @@ -76,6 +79,7 @@ class InteractiveXSpline : public InteractionHandler { static Vec4d rotationAndScale(const QPointF& from, const QPointF& to); + ImageViewBase& m_imageView; ModifiedCallback m_modifiedCallback; DragFinishedCallback m_dragFinishedCallback; Transform m_fromStorage; diff --git a/src/core/interaction/ZoomHandler.cpp b/src/core/interaction/ZoomHandler.cpp index 540096e62..dd6bca39e 100644 --- a/src/core/interaction/ZoomHandler.cpp +++ b/src/core/interaction/ZoomHandler.cpp @@ -4,17 +4,26 @@ #include "ZoomHandler.h" #include +#include +#include #include "ImageViewBase.h" ZoomHandler::ZoomHandler(ImageViewBase& imageView) - : m_imageView(imageView), - m_interactionPermitter(&InteractionHandler::defaultInteractionPermitter), - m_focus(CURSOR) {} + : ZoomHandler(imageView, &InteractionHandler::defaultInteractionPermitter) {} ZoomHandler::ZoomHandler(ImageViewBase& imageView, const boost::function& explicitInteractionPermitter) - : m_imageView(imageView), m_interactionPermitter(explicitInteractionPermitter), m_focus(CURSOR) {} + : m_imageView(imageView), m_interactionPermitter(explicitInteractionPermitter), m_focus(CURSOR) { + m_magnifyShortcut = std::make_unique(Qt::Key_Plus, &m_imageView); + m_diminishShortcut = std::make_unique(Qt::Key_Minus, &m_imageView); + QObject::connect(m_magnifyShortcut.get(), &QShortcut::activated, &m_imageView, + std::bind(&ZoomHandler::zoom, this, std::pow(2, 1.0 / 6))); + QObject::connect(m_diminishShortcut.get(), &QShortcut::activated, &m_imageView, + std::bind(&ZoomHandler::zoom, this, std::pow(2, -1.0 / 6))); +} + +ZoomHandler::~ZoomHandler() = default; void ZoomHandler::onWheelEvent(QWheelEvent* event, InteractionState& interaction) { if (event->orientation() != Qt::Vertical) { @@ -28,18 +37,14 @@ void ZoomHandler::onWheelEvent(QWheelEvent* event, InteractionState& interaction event->accept(); double zoom = m_imageView.zoomLevel(); - if ((zoom == 1.0) && (event->delta() < 0)) { - // Alredy zoomed out and trying to zoom out more. - + // Already zoomed out and trying to zoom out more. // Scroll amount in terms of typical mouse wheel "clicks". const double deltaClicks = event->delta() / 120; - const double dist = -deltaClicks * 30; // 30px per "click" m_imageView.moveTowardsIdealPosition(dist); return; } - const double degrees = event->delta() / 8.0; zoom *= std::pow(2.0, degrees / 60.0); // 2 times zoom for every 60 degrees if (zoom < 1.0) { @@ -59,26 +64,34 @@ void ZoomHandler::onWheelEvent(QWheelEvent* event, InteractionState& interaction m_imageView.setZoomLevel(zoom); // this will call update() } // ZoomHandler::onWheelEvent -void ZoomHandler::onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) { - if (!m_interactionPermitter(interaction)) { +void ZoomHandler::zoom(double factor) { + if (!m_interactionPermitter(m_imageView.interactionState())) { return; } double zoom = m_imageView.zoomLevel(); + if ((zoom == 1.0) && (factor < 1)) { + // Already zoomed out and trying to zoom out more. + m_imageView.moveTowardsIdealPosition(20); + return; + } + zoom *= factor; + if (zoom < 1.0) + zoom = 1.0; - switch (event->key()) { - case Qt::Key_Plus: - zoom *= 1.12246205; // == 2^( 1/6); + QPointF focusPoint; + switch (m_focus) { + case CENTER: + focusPoint = QRectF(m_imageView.rect()).center(); break; - case Qt::Key_Minus: - zoom *= 0.89089872; // == 2^(-1/6); + case CURSOR: + focusPoint = m_virtualMousePos; break; - default: - return; } - - QPointF focusPoint = QRectF(m_imageView.rect()).center(); - m_imageView.setWidgetFocalPointWithoutMoving(focusPoint); m_imageView.setZoomLevel(zoom); // this will call update() } + +void ZoomHandler::onMouseMoveEvent(QMouseEvent* event, InteractionState&) { + m_virtualMousePos = event->pos() + QPointF(0.5, 0.5); +} diff --git a/src/core/interaction/ZoomHandler.h b/src/core/interaction/ZoomHandler.h index 592d3dc0a..9dde4671e 100644 --- a/src/core/interaction/ZoomHandler.h +++ b/src/core/interaction/ZoomHandler.h @@ -12,6 +12,7 @@ #include "InteractionState.h" class ImageViewBase; +class QShortcut; class ZoomHandler : public InteractionHandler { Q_DECLARE_TR_FUNCTIONS(ZoomHandler) @@ -23,20 +24,27 @@ class ZoomHandler : public InteractionHandler { ZoomHandler(ImageViewBase& imageView, const boost::function& explicitInteractionPermitter); + ~ZoomHandler() override; + Focus focus() const { return m_focus; } void setFocus(Focus focus) { m_focus = focus; } protected: - void onWheelEvent(QWheelEvent* event, InteractionState& interaction) override; + void onMouseMoveEvent(QMouseEvent* event, InteractionState& interaction) override; - void onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) override; + void onWheelEvent(QWheelEvent* event, InteractionState& interaction) override; private: + void zoom(double factor); + ImageViewBase& m_imageView; boost::function m_interactionPermitter; InteractionState::Captor m_interaction; Focus m_focus; + QPointF m_virtualMousePos; + std::unique_ptr m_magnifyShortcut; + std::unique_ptr m_diminishShortcut; }; diff --git a/src/core/zones/CMakeLists.txt b/src/core/zones/CMakeLists.txt index a85d5ea62..eb13117bb 100644 --- a/src/core/zones/CMakeLists.txt +++ b/src/core/zones/CMakeLists.txt @@ -13,7 +13,8 @@ set(sources ZoneVertexDragInteraction.cpp ZoneVertexDragInteraction.h ZoneContextMenuInteraction.cpp ZoneContextMenuInteraction.h ZoneContextMenuItem.h - ZoneDragInteraction.cpp ZoneDragInteraction.h) + ZoneDragInteraction.cpp ZoneDragInteraction.h + ZoneCreationMode.h) add_library(zones STATIC ${sources}) target_link_libraries(zones PUBLIC interaction) diff --git a/src/core/zones/EditableSpline.cpp b/src/core/zones/EditableSpline.cpp index 74ca4d36c..f2d86220e 100644 --- a/src/core/zones/EditableSpline.cpp +++ b/src/core/zones/EditableSpline.cpp @@ -5,9 +5,13 @@ #include "SerializableSpline.h" -EditableSpline::EditableSpline() = default; +EditableSpline::EditableSpline() { + m_sentinel->init(); +} EditableSpline::EditableSpline(const SerializableSpline& spline) { + m_sentinel->init(); + for (const QPointF& pt : spline.toPolygon()) { appendVertex(pt); } @@ -20,8 +24,12 @@ EditableSpline::EditableSpline(const SerializableSpline& spline) { setBridged(true); } +EditableSpline::~EditableSpline() { + m_sentinel->finalize(); +} + void EditableSpline::appendVertex(const QPointF& pt) { - m_sentinel.insertBefore(pt); + m_sentinel->insertBefore(pt); } bool EditableSpline::hasAtLeastSegments(int num) const { diff --git a/src/core/zones/EditableSpline.h b/src/core/zones/EditableSpline.h index d9de68671..0377455bd 100644 --- a/src/core/zones/EditableSpline.h +++ b/src/core/zones/EditableSpline.h @@ -5,17 +5,16 @@ #define SCANTAILOR_ZONES_EDITABLESPLINE_H_ #include +#include #include "SplineSegment.h" #include "SplineVertex.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class SerializableSpline; -class EditableSpline : public ref_countable { +class EditableSpline { public: - using Ptr = intrusive_ptr; + using Ptr = std::shared_ptr; class SegmentIterator { public: @@ -29,27 +28,28 @@ class EditableSpline : public ref_countable { SplineVertex::Ptr m_nextVertex; }; - EditableSpline(); EditableSpline(const SerializableSpline& spline); + virtual ~EditableSpline(); + void appendVertex(const QPointF& pt); - SplineVertex::Ptr firstVertex() const { return m_sentinel.firstVertex(); } + SplineVertex::Ptr firstVertex() const { return m_sentinel->firstVertex(); } - SplineVertex::Ptr lastVertex() const { return m_sentinel.lastVertex(); } + SplineVertex::Ptr lastVertex() const { return m_sentinel->lastVertex(); } bool hasAtLeastSegments(int num) const; - bool bridged() const { return m_sentinel.bridged(); } + bool bridged() const { return m_sentinel->bridged(); } - void setBridged(bool bridged) { m_sentinel.setBridged(true); } + void setBridged(bool bridged) { m_sentinel->setBridged(true); } QPolygonF toPolygon() const; private: - SentinelSplineVertex m_sentinel; + std::shared_ptr m_sentinel = std::make_shared(); }; diff --git a/src/core/zones/EditableZoneSet.cpp b/src/core/zones/EditableZoneSet.cpp index 64048a15f..9bc8e114d 100644 --- a/src/core/zones/EditableZoneSet.cpp +++ b/src/core/zones/EditableZoneSet.cpp @@ -10,12 +10,12 @@ void EditableZoneSet::setDefaultProperties(const PropertySet& props) { } void EditableZoneSet::addZone(const EditableSpline::Ptr& spline) { - auto newProps = make_intrusive(m_defaultProps); + auto newProps = std::make_shared(m_defaultProps); m_zoneItems.insert(ZoneItem(spline, newProps)); } void EditableZoneSet::addZone(const EditableSpline::Ptr& spline, const PropertySet& props) { - auto newProps = make_intrusive(props); + auto newProps = std::make_shared(props); m_zoneItems.insert(ZoneItem(spline, newProps)); } @@ -27,7 +27,7 @@ void EditableZoneSet::commit() { emit committed(); } -intrusive_ptr EditableZoneSet::propertiesFor(const EditableSpline::Ptr& spline) { +std::shared_ptr EditableZoneSet::propertiesFor(const EditableSpline::Ptr& spline) { auto it(m_zoneItems.find(spline)); if (it != m_zoneItems.end()) { return it->second; @@ -36,7 +36,7 @@ intrusive_ptr EditableZoneSet::propertiesFor(const EditableSpline:: } } -intrusive_ptr EditableZoneSet::propertiesFor(const EditableSpline::Ptr& spline) const { +std::shared_ptr EditableZoneSet::propertiesFor(const EditableSpline::Ptr& spline) const { auto it(m_zoneItems.find(spline)); if (it != m_zoneItems.end()) { return it->second; diff --git a/src/core/zones/EditableZoneSet.h b/src/core/zones/EditableZoneSet.h index b7636cbba..3b2d029e9 100644 --- a/src/core/zones/EditableZoneSet.h +++ b/src/core/zones/EditableZoneSet.h @@ -12,15 +12,15 @@ #include #include #include +#include #include "EditableSpline.h" #include "PropertySet.h" -#include "intrusive_ptr.h" class EditableZoneSet : public QObject { Q_OBJECT private: - using ZoneItem = std::pair>; + using ZoneItem = std::pair>; class ZoneItemOrderedTag; @@ -28,7 +28,7 @@ class EditableZoneSet : public QObject { ZoneItem, boost::multi_index::indexed_by< boost::multi_index::hashed_unique, - EditableSpline::Ptr::hash>, + std::hash>>, boost::multi_index::sequenced>>>; using ZoneItemsInOrder = ZoneItems::index::type; @@ -44,7 +44,7 @@ class EditableZoneSet : public QObject { const EditableSpline::Ptr& spline() const { return m_iter->first; } - const intrusive_ptr& properties() const { return m_iter->second; } + const std::shared_ptr& properties() const { return m_iter->second; } private: explicit Zone(ZoneItemsInOrder::const_iterator it) : m_iter(it) {} @@ -93,9 +93,9 @@ class EditableZoneSet : public QObject { void commit(); - intrusive_ptr propertiesFor(const EditableSpline::Ptr& spline); + std::shared_ptr propertiesFor(const EditableSpline::Ptr& spline); - intrusive_ptr propertiesFor(const EditableSpline::Ptr& spline) const; + std::shared_ptr propertiesFor(const EditableSpline::Ptr& spline) const; signals: diff --git a/src/core/zones/SplineVertex.cpp b/src/core/zones/SplineVertex.cpp index 4f0d428f4..7ccdda6ed 100644 --- a/src/core/zones/SplineVertex.cpp +++ b/src/core/zones/SplineVertex.cpp @@ -4,22 +4,25 @@ #include "SplineVertex.h" #include +#include /*============================= SplineVertex ============================*/ -SplineVertex::SplineVertex(SplineVertex* prev, SplineVertex* next) : m_prev(prev), m_next(next) {} +SplineVertex::SplineVertex() : m_prev(nullptr), m_next(nullptr) {} + +SplineVertex::SplineVertex(SplineVertex* prev, SplineVertex* next) : m_prev(prev), m_next(next->shared_from_this()) {} void SplineVertex::remove() { // Be very careful here - don't let this object // be destroyed before we've finished working with it. + if (m_next) + m_next->m_prev = m_prev; + if (m_prev) + m_prev->m_next.swap(m_next); + assert(!m_next || (m_next.get() == this)); - m_prev->m_next.swap(m_next); - assert(m_next.get() == this); - - m_prev->m_next->m_prev = m_prev; m_prev = nullptr; - // This may or may not destroy this object, // depending on if there are other references to it. m_next.reset(); @@ -27,7 +30,7 @@ void SplineVertex::remove() { bool SplineVertex::hasAtLeastSiblings(const int num) { int todo = num; - for (SplineVertex::Ptr node(this); (node = node->next(LOOP)).get() != this;) { + for (SplineVertex::Ptr node = shared_from_this(); (node = node->next(LOOP)).get() != this;) { if (--todo == 0) { return true; } @@ -44,36 +47,41 @@ SplineVertex::Ptr SplineVertex::next(const Loop loop) { } SplineVertex::Ptr SplineVertex::insertBefore(const QPointF& pt) { - auto newVertex = make_intrusive(pt, m_prev, this); + auto newVertex = std::make_shared(pt, m_prev, this); m_prev->m_next = newVertex; m_prev = newVertex.get(); return newVertex; } SplineVertex::Ptr SplineVertex::insertAfter(const QPointF& pt) { - auto newVertex = make_intrusive(pt, this, m_next.get()); + auto newVertex = std::make_shared(pt, this, m_next.get()); m_next->m_prev = newVertex.get(); m_next = newVertex; return newVertex; } +void SplineVertex::unlinkWithPrevious() { + m_prev->m_next.reset(); + m_prev = nullptr; +} + /*========================= SentinelSplineVertex =======================*/ -SentinelSplineVertex::SentinelSplineVertex() : SplineVertex(this, this), m_bridged(false) {} +SentinelSplineVertex::SentinelSplineVertex() : m_bridged(false) {} SentinelSplineVertex::~SentinelSplineVertex() { // Just releasing m_next is not enough, because in case some external - // object holds a reference to a vertix of this spline, that vertex will + // object holds a reference to a vertex of this spline, that vertex will // still (possibly indirectly) reference us through a chain of m_next - // smart pointers. Therefore, we explicitly unlink each node. - while (m_next.get() != this) { + // smart pointers. Therefore, we explicitly unlink each node. + while (m_next) { m_next->remove(); } } SplineVertex::Ptr SentinelSplineVertex::thisOrPrevReal(const Loop loop) { if ((loop == LOOP) || ((loop == LOOP_IF_BRIDGED) && m_bridged)) { - return SplineVertex::Ptr(m_prev); + return m_prev->shared_from_this(); } else { return nullptr; } @@ -87,17 +95,16 @@ SplineVertex::Ptr SentinelSplineVertex::thisOrNextReal(const Loop loop) { } } -const QPointF SentinelSplineVertex::point() const { - assert(!"Illegal call to SentinelSplineVertex::point()"); - return QPointF(); +const QPointF& SentinelSplineVertex::point() const { + throw std::logic_error("Illegal call to SentinelSplineVertex::point()"); } -void SentinelSplineVertex::setPoint(const QPointF& pt) { - assert(!"Illegal call to SentinelSplineVertex::setPoint()"); +void SentinelSplineVertex::setPoint(const QPointF&) { + throw std::logic_error("Illegal call to SentinelSplineVertex::setPoint()"); } void SentinelSplineVertex::remove() { - assert(!"Illegal call to SentinelSplineVertex::remove()"); + throw std::logic_error("Illegal call to SentinelSplineVertex::remove()"); } SplineVertex::Ptr SentinelSplineVertex::firstVertex() const { @@ -112,34 +119,35 @@ SplineVertex::Ptr SentinelSplineVertex::lastVertex() const { if (m_prev == this) { return nullptr; } else { - return SplineVertex::Ptr(m_prev); + return m_prev->shared_from_this(); } } -/*============================== RealSplineVertex ============================*/ - -RealSplineVertex::RealSplineVertex(const QPointF& pt, SplineVertex* prev, SplineVertex* next) - : SplineVertex(prev, next), m_point(pt), m_counter(0) {} - -void RealSplineVertex::ref() const { - ++m_counter; +void SentinelSplineVertex::finalize() { + SplineVertex::unlinkWithPrevious(); } -void RealSplineVertex::unref() const { - if (--m_counter == 0) { - delete this; +void SentinelSplineVertex::init() { + if (!m_next && !m_prev) { + m_next = shared_from_this(); + m_prev = this; } } +/*============================== RealSplineVertex ============================*/ + +RealSplineVertex::RealSplineVertex(const QPointF& pt, SplineVertex* prev, SplineVertex* next) + : SplineVertex(prev, next), m_point(pt) {} + SplineVertex::Ptr RealSplineVertex::thisOrPrevReal(Loop) { - return SplineVertex::Ptr(this); + return shared_from_this(); } -SplineVertex::Ptr RealSplineVertex::thisOrNextReal(Loop loop) { - return SplineVertex::Ptr(this); +SplineVertex::Ptr RealSplineVertex::thisOrNextReal(Loop) { + return shared_from_this(); } -const QPointF RealSplineVertex::point() const { +const QPointF& RealSplineVertex::point() const { return m_point; } diff --git a/src/core/zones/SplineVertex.h b/src/core/zones/SplineVertex.h index 54a0c746b..54104a7ec 100644 --- a/src/core/zones/SplineVertex.h +++ b/src/core/zones/SplineVertex.h @@ -5,35 +5,24 @@ #define SCANTAILOR_ZONES_SPLINEVERTEX_H_ #include +#include #include "NonCopyable.h" -#include "intrusive_ptr.h" -class SplineVertex { +class SplineVertex : public std::enable_shared_from_this { public: enum Loop { LOOP, NO_LOOP, LOOP_IF_BRIDGED }; - using Ptr = intrusive_ptr; + using Ptr = std::shared_ptr; + + SplineVertex(); SplineVertex(SplineVertex* prev, SplineVertex* next); virtual ~SplineVertex() = default; /** - * We don't want reference counting for sentinel vertices, - * but we can't make ref() and unref() abstract here, because - * in case of sentinel vertices these function may actually - * be called from this class constructor. - */ - virtual void ref() const {} - - /** - * \see ref() - */ - virtual void unref() const {} - - /** - * \return Smart pointer to this vertex, unless it's a sentiel vertex, + * \return Smart pointer to this vertex, unless it's a sentinel vertex, * in which case the previous non-sentinel vertex is returned. * If there are no non-sentinel vertices, a null smart pointer * is returned. @@ -41,14 +30,14 @@ class SplineVertex { virtual SplineVertex::Ptr thisOrPrevReal(Loop loop) = 0; /** - * \return Smart pointer to this vertex, unless it's a sentiel vertex, + * \return Smart pointer to this vertex, unless it's a sentinel vertex, * in which case the next non-sentinel vertex is returned. * If there are no non-sentinel vertices, a null smart pointer * is returned. */ virtual SplineVertex::Ptr thisOrNextReal(Loop loop) = 0; - virtual const QPointF point() const = 0; + virtual const QPointF& point() const = 0; virtual void setPoint(const QPointF& pt) = 0; @@ -66,10 +55,15 @@ class SplineVertex { protected: /** - * The reason m_prev is an ordinary pointer rather than a smart pointer - * is that we don't want pairs of vertices holding smart pointers to each - * other. Note that we don't have a loop of smart pointers, because - * sentinel vertices aren't reference counted. + * Usually we have circular dependency of m_next pointers here + * so we unlink a vertex from the previous one to have + * that pointer loop broken to be able to destruct this spline. + */ + void unlinkWithPrevious(); + + /** + * m_prev have to be an ordinary pointer or weak_ptr in order + * to avoid circular dependencies. */ SplineVertex* m_prev; SplineVertex::Ptr m_next; @@ -78,7 +72,6 @@ class SplineVertex { class SentinelSplineVertex : public SplineVertex { DECLARE_NON_COPYABLE(SentinelSplineVertex) - public: SentinelSplineVertex(); @@ -88,7 +81,7 @@ class SentinelSplineVertex : public SplineVertex { SplineVertex::Ptr thisOrNextReal(Loop loop) override; - const QPointF point() const override; + const QPointF& point() const override; void setPoint(const QPointF& pt) override; @@ -98,6 +91,20 @@ class SentinelSplineVertex : public SplineVertex { SplineVertex::Ptr lastVertex() const; + /** + * Making this sentinel be ready for operation. + * This method must usually be called in a constructor + * of the class that have the ownership of this sentinel. + */ + void init(); + + /** + * Preparing this sentinel to be destroyed. + * This method must usually be called in the destructor + * of the class that have the ownership of this sentinel. + */ + void finalize(); + bool bridged() const { return m_bridged; } void setBridged(bool bridged) { m_bridged = bridged; } @@ -109,25 +116,19 @@ class SentinelSplineVertex : public SplineVertex { class RealSplineVertex : public SplineVertex { DECLARE_NON_COPYABLE(RealSplineVertex) - public: RealSplineVertex(const QPointF& pt, SplineVertex* prev, SplineVertex* next); - void ref() const override; - - void unref() const override; - SplineVertex::Ptr thisOrPrevReal(Loop loop) override; SplineVertex::Ptr thisOrNextReal(Loop loop) override; - const QPointF point() const override; + const QPointF& point() const override; void setPoint(const QPointF& pt) override; private: QPointF m_point; - mutable int m_counter; }; diff --git a/src/core/zones/Zone.cpp b/src/core/zones/Zone.cpp index 0f2693e32..43de9b8e2 100644 --- a/src/core/zones/Zone.cpp +++ b/src/core/zones/Zone.cpp @@ -34,15 +34,3 @@ bool Zone::isValid() const { return true; } } - -const SerializableSpline& Zone::spline() const { - return m_spline; -} - -PropertySet& Zone::properties() { - return m_props; -} - -const PropertySet& Zone::properties() const { - return m_props; -} diff --git a/src/core/zones/Zone.h b/src/core/zones/Zone.h index d97043654..586c996f7 100644 --- a/src/core/zones/Zone.h +++ b/src/core/zones/Zone.h @@ -36,4 +36,16 @@ class Zone { }; +inline const SerializableSpline& Zone::spline() const { + return m_spline; +} + +inline PropertySet& Zone::properties() { + return m_props; +} + +inline const PropertySet& Zone::properties() const { + return m_props; +} + #endif // ifndef SCANTAILOR_ZONES_ZONE_H_ diff --git a/src/core/zones/ZoneContextMenuInteraction.cpp b/src/core/zones/ZoneContextMenuInteraction.cpp index 7fcccc8bc..a36cc0b9e 100644 --- a/src/core/zones/ZoneContextMenuInteraction.cpp +++ b/src/core/zones/ZoneContextMenuInteraction.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "ImageViewBase.h" @@ -64,7 +65,7 @@ ZoneContextMenuInteraction::ZoneContextMenuInteraction(ZoneInteractionContext& c const MenuCustomizer& menuCustomizer, std::vector& selectableZones) : m_context(context), - m_menu(new QMenu(&context.imageView())), + m_menu(std::make_unique(&context.imageView())), m_highlightedZoneIdx(-1), m_menuItemTriggered(false) { #ifdef Q_OS_MAC diff --git a/src/core/zones/ZoneContextMenuInteraction.h b/src/core/zones/ZoneContextMenuInteraction.h index 3adc3bc52..3c1a2824c 100644 --- a/src/core/zones/ZoneContextMenuInteraction.h +++ b/src/core/zones/ZoneContextMenuInteraction.h @@ -19,7 +19,6 @@ #include "InteractionState.h" #include "PropertySet.h" #include "ZoneContextMenuItem.h" -#include "intrusive_ptr.h" class ZoneInteractionContext; class QPainter; diff --git a/src/core/zones/ZoneCreationInteraction.cpp b/src/core/zones/ZoneCreationInteraction.cpp index 113786358..aa7732205 100644 --- a/src/core/zones/ZoneCreationInteraction.cpp +++ b/src/core/zones/ZoneCreationInteraction.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,17 +18,15 @@ ZoneCreationInteraction::ZoneCreationInteraction(ZoneInteractionContext& context m_dragHandler(context.imageView(), boost::bind(&ZoneCreationInteraction::isDragHandlerPermitted, this, _1)), m_dragWatcher(m_dragHandler), m_zoomHandler(context.imageView(), boost::lambda::constant(true)), - m_spline(new EditableSpline), - m_lassoModeModifiers(Qt::ShiftModifier | Qt::AltModifier) { + m_spline(std::make_shared()), + m_initialZoneCreationMode(context.getZoneCreationMode()), + m_leftMouseButtonPressed(m_initialZoneCreationMode == ZoneCreationMode::LASSO) { const QPointF screenMousePos(m_context.imageView().mapFromGlobal(QCursor::pos()) + QPointF(0.5, 0.5)); const QTransform fromScreen(m_context.imageView().widgetToImage()); m_nextVertexImagePos = fromScreen.map(screenMousePos); m_nextVertexImagePos_mid1 = m_nextVertexImagePos; m_nextVertexImagePos_mid2 = m_nextVertexImagePos; - m_rectangularZoneType = false; - - m_lassoMode = false; makeLastFollower(m_dragHandler); m_dragHandler.makeFirstFollower(m_dragWatcher); @@ -38,6 +37,11 @@ ZoneCreationInteraction::ZoneCreationInteraction(ZoneInteractionContext& context m_spline->appendVertex(m_nextVertexImagePos); updateStatusTip(); + + m_cancelShortcut = std::make_unique(Qt::Key_Escape, &m_context.imageView()); + m_cancelShortcut->setAutoRepeat(false); + QObject::connect(m_cancelShortcut.get(), &QShortcut::activated, &m_context.imageView(), + std::bind(&ZoneCreationInteraction::cancel, this)); } void ZoneCreationInteraction::onPaint(QPainter& painter, const InteractionState& interaction) { @@ -82,7 +86,7 @@ void ZoneCreationInteraction::onPaint(QPainter& painter, const InteractionState& gradientMid2.setColorAt(0.0, midColor); gradientMid2.setColorAt(1.0, stopColor); - if (m_rectangularZoneType) { + if (currentZoneCreationMode() == ZoneCreationMode::RECTANGULAR) { if (m_nextVertexImagePos != m_spline->firstVertex()->point()) { m_visualizer.drawVertex(painter, toScreen.map(m_nextVertexImagePos_mid1), m_visualizer.highlightBrightColor()); m_visualizer.drawVertex(painter, toScreen.map(m_nextVertexImagePos_mid2), m_visualizer.highlightBrightColor()); @@ -143,24 +147,18 @@ void ZoneCreationInteraction::onPaint(QPainter& painter, const InteractionState& m_visualizer.drawVertex(painter, toScreen.map(m_nextVertexImagePos), m_visualizer.highlightBrightColor()); } // ZoneCreationInteraction::onPaint -void ZoneCreationInteraction::onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) { - if (event->key() == Qt::Key_Escape) { - makePeerPreceeder(*m_context.createDefaultInteraction()); - m_context.imageView().update(); - delete this; - event->accept(); - } +void ZoneCreationInteraction::cancel() { + makePeerPreceeder(*m_context.createDefaultInteraction()); + m_context.imageView().update(); + delete this; } void ZoneCreationInteraction::onMousePressEvent(QMouseEvent* event, InteractionState& interaction) { if (event->button() != Qt::LeftButton) { return; } - - if (!m_rectangularZoneType && (event->modifiers() == m_lassoModeModifiers)) { - m_lassoMode = true; - } - + m_leftMouseButtonPressed = true; + m_mouseButtonModifiers = event->modifiers(); event->accept(); } @@ -168,17 +166,19 @@ void ZoneCreationInteraction::onMouseReleaseEvent(QMouseEvent* event, Interactio if (event->button() != Qt::LeftButton) { return; } - if (m_dragWatcher.haveSignificantDrag() && !m_lassoMode) { + m_leftMouseButtonPressed = false; + + ZoneCreationMode currentCreationMode = currentZoneCreationMode(); + if (m_dragWatcher.haveSignificantDrag()) { return; } - m_lassoMode = false; const QTransform toScreen(m_context.imageView().imageToWidget()); const QTransform fromScreen(m_context.imageView().widgetToImage()); const QPointF screenMousePos(event->pos() + QPointF(0.5, 0.5)); const QPointF imageMousePos(fromScreen.map(screenMousePos)); - if (m_rectangularZoneType) { + if (currentCreationMode == ZoneCreationMode::RECTANGULAR) { if (m_nextVertexImagePos != m_spline->firstVertex()->point()) { QPointF firstPoint = m_spline->firstVertex()->point(); @@ -239,26 +239,19 @@ void ZoneCreationInteraction::onMouseMoveEvent(QMouseEvent* event, InteractionSt const QPointF first(toScreen.map(m_spline->firstVertex()->point())); const QPointF last(toScreen.map(m_spline->lastVertex()->point())); - if (!m_rectangularZoneType) { - if (event->modifiers() == Qt::ControlModifier) { - m_rectangularZoneType = true; - m_lassoMode = false; - updateStatusTip(); - } else if (!m_lassoMode && (event->modifiers() == m_lassoModeModifiers) && (event->buttons() & Qt::LeftButton)) { - m_lassoMode = true; - } - } + ZoneCreationMode currentCreationMode = currentZoneCreationMode(); if (Proximity(last, screenMousePos) <= interaction.proximityThreshold()) { m_nextVertexImagePos = m_spline->lastVertex()->point(); - } else if (m_spline->hasAtLeastSegments(2) || m_rectangularZoneType) { + } else if (m_spline->hasAtLeastSegments(2) || (currentCreationMode == ZoneCreationMode::RECTANGULAR)) { if (Proximity(first, screenMousePos) <= interaction.proximityThreshold()) { m_nextVertexImagePos = m_spline->firstVertex()->point(); updateStatusTip(); } } - if (m_rectangularZoneType && (m_nextVertexImagePos != m_spline->firstVertex()->point())) { + if ((currentCreationMode == ZoneCreationMode::RECTANGULAR) + && (m_nextVertexImagePos != m_spline->firstVertex()->point())) { QPointF screenMousePosMid1; screenMousePosMid1.setX(first.x()); screenMousePosMid1.setY(screenMousePos.y()); @@ -279,10 +272,21 @@ void ZoneCreationInteraction::onMouseMoveEvent(QMouseEvent* event, InteractionSt } } - if (m_lassoMode) { - Proximity minDistance = Proximity::fromDist(10); + if ((currentCreationMode == ZoneCreationMode::LASSO) && m_leftMouseButtonPressed + && (m_mouseButtonModifiers == Qt::NoModifier)) { + Proximity minDistance = interaction.proximityThreshold(); if ((Proximity(last, screenMousePos) > minDistance) && (Proximity(first, screenMousePos) > minDistance)) { m_spline->appendVertex(m_nextVertexImagePos); + } else if (m_spline->hasAtLeastSegments(2) && (m_nextVertexImagePos == m_spline->firstVertex()->point())) { + // Finishing the spline. Bridging the first and the last points + // will create another segment. + m_spline->setBridged(true); + m_context.zones().addZone(m_spline); + m_context.zones().commit(); + + makePeerPreceeder(*m_context.createDefaultInteraction()); + m_context.imageView().update(); + delete this; } } @@ -292,7 +296,9 @@ void ZoneCreationInteraction::onMouseMoveEvent(QMouseEvent* event, InteractionSt void ZoneCreationInteraction::updateStatusTip() { QString tip; - if (m_rectangularZoneType) { + ZoneCreationMode currentCreationMode = currentZoneCreationMode(); + + if (currentCreationMode == ZoneCreationMode::RECTANGULAR) { if (m_nextVertexImagePos != m_spline->firstVertex()->point()) { tip = tr("Click to finish this rectangular zone. ESC to cancel."); } @@ -304,13 +310,32 @@ void ZoneCreationInteraction::updateStatusTip() { tip = tr("Connect first and last points to finish this zone. ESC to cancel."); } } else { - tip = tr("Hold Ctrl to create a rectangular zone or Shift+Alt+LMB to use lasso mode. ESC to cancel."); + tip = tr("Use Z and X keys to switch zone creation mode. ESC to cancel."); } } m_interaction.setInteractionStatusTip(tip); } -bool ZoneCreationInteraction::isDragHandlerPermitted(const InteractionState& interaction) const { - return !m_lassoMode; +bool ZoneCreationInteraction::isDragHandlerPermitted(const InteractionState&) const { + return !((currentZoneCreationMode() == ZoneCreationMode::LASSO) && m_leftMouseButtonPressed + && (m_mouseButtonModifiers == Qt::NoModifier)); +} + +ZoneCreationMode ZoneCreationInteraction::currentZoneCreationMode() const { + switch (m_initialZoneCreationMode) { + case ZoneCreationMode::RECTANGULAR: + return ZoneCreationMode::RECTANGULAR; + case ZoneCreationMode::POLYGONAL: + case ZoneCreationMode::LASSO: + switch (m_context.getZoneCreationMode()) { + case ZoneCreationMode::POLYGONAL: + return ZoneCreationMode::POLYGONAL; + case ZoneCreationMode::LASSO: + return ZoneCreationMode::LASSO; + default: + break; + } + } + return ZoneCreationMode::POLYGONAL; } diff --git a/src/core/zones/ZoneCreationInteraction.h b/src/core/zones/ZoneCreationInteraction.h index bba751488..e4a687df3 100644 --- a/src/core/zones/ZoneCreationInteraction.h +++ b/src/core/zones/ZoneCreationInteraction.h @@ -14,9 +14,11 @@ #include "EditableSpline.h" #include "InteractionHandler.h" #include "InteractionState.h" +#include "ZoneCreationMode.h" #include "ZoomHandler.h" class ZoneInteractionContext; +class QShortcut; class ZoneCreationInteraction : public InteractionHandler { Q_DECLARE_TR_FUNCTIONS(ZoneCreationInteraction) @@ -28,8 +30,6 @@ class ZoneCreationInteraction : public InteractionHandler { void onPaint(QPainter& painter, const InteractionState& interaction) override; - void onKeyPressEvent(QKeyEvent* event, InteractionState& interaction) override; - void onMousePressEvent(QMouseEvent* event, InteractionState& interaction) override; void onMouseReleaseEvent(QMouseEvent* event, InteractionState& interaction) override; @@ -41,6 +41,10 @@ class ZoneCreationInteraction : public InteractionHandler { bool isDragHandlerPermitted(const InteractionState& interaction) const; + ZoneCreationMode currentZoneCreationMode() const; + + void cancel(); + ZoneInteractionContext& m_context; /** @@ -68,11 +72,12 @@ class ZoneCreationInteraction : public InteractionHandler { InteractionState::Captor m_interaction; EditableSpline::Ptr m_spline; QPointF m_nextVertexImagePos; - bool m_rectangularZoneType; QPointF m_nextVertexImagePos_mid1; QPointF m_nextVertexImagePos_mid2; - bool m_lassoMode; - Qt::KeyboardModifiers m_lassoModeModifiers; + ZoneCreationMode m_initialZoneCreationMode; + bool m_leftMouseButtonPressed; + Qt::KeyboardModifiers m_mouseButtonModifiers; + std::unique_ptr m_cancelShortcut; }; diff --git a/src/core/zones/ZoneCreationMode.h b/src/core/zones/ZoneCreationMode.h new file mode 100644 index 000000000..3beab3a53 --- /dev/null +++ b/src/core/zones/ZoneCreationMode.h @@ -0,0 +1,9 @@ +// Copyright (C) 2020 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> +// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. + +#ifndef SCANTAILOR_ZONES_ZONECREATIONMODE_H_ +#define SCANTAILOR_ZONES_ZONECREATIONMODE_H_ + +enum class ZoneCreationMode { POLYGONAL, RECTANGULAR, LASSO }; + +#endif // SCANTAILOR_ZONES_ZONECREATIONMODE_H_ diff --git a/src/core/zones/ZoneDefaultInteraction.cpp b/src/core/zones/ZoneDefaultInteraction.cpp index 5cb5657cb..68e015d62 100644 --- a/src/core/zones/ZoneDefaultInteraction.cpp +++ b/src/core/zones/ZoneDefaultInteraction.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "ImageViewBase.h" #include "SerializableSpline.h" @@ -15,7 +16,8 @@ ZoneDefaultInteraction::ZoneDefaultInteraction(ZoneInteractionContext& context) makeLastFollower(m_dragHandler); m_dragHandler.makeFirstFollower(m_dragWatcher); - m_vertexProximity.setProximityStatusTip(tr("Drag the vertex. Hold Ctrl to make the vertex angle right.")); + m_vertexProximity.setProximityStatusTip( + tr("Drag the vertex. Hold Ctrl to make the vertex angle right. Press D to delete the vertex.")); m_segmentProximity.setProximityStatusTip(tr("Click to create a new vertex here.")); m_zoneAreaProximity.setProximityStatusTip( tr("Right click to edit zone properties. Hold Shift to drag the zone or " @@ -25,7 +27,15 @@ ZoneDefaultInteraction::ZoneDefaultInteraction(ZoneInteractionContext& context) m_zoneAreaDragCopyProximity.setProximityStatusTip(tr("Hold left mouse button to copy and drag the zone.")); m_zoneAreaDragCopyProximity.setProximityCursor(Qt::DragCopyCursor); m_context.imageView().interactionState().setDefaultStatusTip( - tr("Click to start creating a new zone. Use Ctrl+Alt+Click to copy the latest created zone.")); + tr("Click to start creating a new zone. Ctrl+Alt+Click to copy the latest created zone. Use Z, X and C keys to " + "switch zone creation mode.")); + + m_removeZoneShortcut = std::make_unique(Qt::Key_Delete, &m_context.imageView()); + m_removeVertexShortcut = std::make_unique(Qt::Key_D, &m_context.imageView()); + QObject::connect(m_removeZoneShortcut.get(), &QShortcut::activated, &m_context.imageView(), + std::bind(&ZoneDefaultInteraction::removeZoneUnderMouse, this)); + QObject::connect(m_removeVertexShortcut.get(), &QShortcut::activated, &m_context.imageView(), + std::bind(&ZoneDefaultInteraction::removeVertexUnderMouse, this)); } void ZoneDefaultInteraction::onPaint(QPainter& painter, const InteractionState& interaction) { @@ -87,7 +97,7 @@ void ZoneDefaultInteraction::onPaint(QPainter& painter, const InteractionState& m_visualizer.drawVertex(painter, screenVertex, m_visualizer.highlightBrightColor()); } else if (interaction.proximityLeader(m_segmentProximity)) { const QLineF line(toScreen.map(m_nearestSegment.toLine())); - // Draw the highglighed edge in orange. + // Draw the highlighted edge in orange. QPen pen(painter.pen()); pen.setColor(m_visualizer.highlightDarkColor()); painter.setPen(pen); @@ -110,25 +120,16 @@ void ZoneDefaultInteraction::onProximityUpdate(const QPointF& mousePos, Interact m_nearestVertexSpline.reset(); m_nearestSegment = SplineSegment(); m_nearestSegmentSpline.reset(); - m_underCursorSpline.reset(); + m_splineUnderMouse.reset(); Proximity bestVertexProximity; Proximity bestSegmentProximity; - bool hasZoneUnderMouse = false; - for (const EditableZoneSet::Zone& zone : m_context.zones()) { const EditableSpline::Ptr& spline = zone.spline(); - { - QPainterPath path; - path.setFillRule(Qt::WindingFill); - path.addPolygon(spline->toPolygon()); - if (path.contains(imageMousePos)) { - m_underCursorSpline = spline; - - hasZoneUnderMouse = true; - } + if (spline->toPolygon().containsPoint(imageMousePos, Qt::WindingFill)) { + m_splineUnderMouse = spline; } // Process vertices. @@ -158,7 +159,7 @@ void ZoneDefaultInteraction::onProximityUpdate(const QPointF& mousePos, Interact interaction.updateProximity(m_vertexProximity, bestVertexProximity, 2); interaction.updateProximity(m_segmentProximity, bestSegmentProximity, 1); - if (hasZoneUnderMouse) { + if (m_splineUnderMouse) { const Proximity zoneAreaProximity(std::min(bestVertexProximity, bestSegmentProximity)); interaction.updateProximity(m_zoneAreaProximity, zoneAreaProximity, -1, zoneAreaProximity); if (m_activeKeyboardModifiers == Qt::ShiftModifier) { @@ -188,15 +189,19 @@ void ZoneDefaultInteraction::onMousePressEvent(QMouseEvent* event, InteractionSt delete this; event->accept(); } else if (interaction.proximityLeader(m_zoneAreaDragProximity)) { - makePeerPreceeder(*m_context.createZoneDragInteraction(interaction, m_underCursorSpline)); + makePeerPreceeder(*m_context.createZoneDragInteraction(interaction, m_splineUnderMouse)); delete this; event->accept(); } else if (interaction.proximityLeader(m_zoneAreaDragCopyProximity)) { - auto newSpline = make_intrusive(SerializableSpline(*m_underCursorSpline)); - m_context.zones().addZone(newSpline, *m_context.zones().propertiesFor(m_underCursorSpline)); + auto newSpline = std::make_shared(SerializableSpline(*m_splineUnderMouse)); + m_context.zones().addZone(newSpline, *m_context.zones().propertiesFor(m_splineUnderMouse)); makePeerPreceeder(*m_context.createZoneDragInteraction(interaction, newSpline)); delete this; event->accept(); + } else if ((m_context.getZoneCreationMode() == ZoneCreationMode::LASSO) && (event->modifiers() == Qt::NoModifier)) { + makePeerPreceeder(*m_context.createZoneCreationInteraction(interaction)); + delete this; + event->accept(); } } @@ -215,9 +220,9 @@ void ZoneDefaultInteraction::onMouseReleaseEvent(QMouseEvent* event, Interaction if (m_activeKeyboardModifiers == (Qt::ControlModifier | Qt::AltModifier)) { const QTransform fromScreen(m_context.imageView().widgetToImage()); - EditableZoneSet::const_iterator latest_zone = --m_context.zones().end(); - if (latest_zone != m_context.zones().end()) { - SerializableSpline serializableSpline(*(*latest_zone).spline()); + EditableZoneSet::const_iterator latestZone = --m_context.zones().end(); + if (latestZone != m_context.zones().end()) { + SerializableSpline serializableSpline(*(*latestZone).spline()); const QPointF oldCenter = serializableSpline.toPolygon().boundingRect().center(); const QPointF newCenter = fromScreen.map(event->pos() + QPointF(0.5, 0.5)); @@ -225,8 +230,8 @@ void ZoneDefaultInteraction::onMouseReleaseEvent(QMouseEvent* event, Interaction serializableSpline = serializableSpline.transformed(QTransform().translate(shift.x(), shift.y())); - auto newSpline = make_intrusive(serializableSpline); - m_context.zones().addZone(newSpline, *(*latest_zone).properties()); + auto newSpline = std::make_shared(serializableSpline); + m_context.zones().addZone(newSpline, *(*latestZone).properties()); m_context.zones().commit(); } @@ -252,15 +257,6 @@ void ZoneDefaultInteraction::onKeyPressEvent(QKeyEvent* event, InteractionState& void ZoneDefaultInteraction::onKeyReleaseEvent(QKeyEvent* event, InteractionState& interaction) { m_activeKeyboardModifiers = event->modifiers(); - - if (event->key() == Qt::Key_Delete) { - if (m_underCursorSpline != nullptr) { - m_context.zones().removeZone(m_underCursorSpline); - m_context.zones().commit(); - } - - m_context.imageView().update(); - } } void ZoneDefaultInteraction::onContextMenuEvent(QContextMenuEvent* event, InteractionState& interaction) { @@ -274,3 +270,20 @@ void ZoneDefaultInteraction::onContextMenuEvent(QContextMenuEvent* event, Intera makePeerPreceeder(*cmInteraction); delete this; } + +void ZoneDefaultInteraction::removeZoneUnderMouse() { + if (m_splineUnderMouse) { + m_context.zones().removeZone(m_splineUnderMouse); + m_context.zones().commit(); + m_context.imageView().update(); + } +} + +void ZoneDefaultInteraction::removeVertexUnderMouse() { + if ((m_nearestVertex && m_nearestVertexSpline) && m_nearestVertexSpline->hasAtLeastSegments(4) + && m_context.imageView().interactionState().proximityLeader(m_vertexProximity)) { + m_nearestVertex->remove(); + m_context.zones().commit(); + m_context.imageView().update(); + } +} diff --git a/src/core/zones/ZoneDefaultInteraction.h b/src/core/zones/ZoneDefaultInteraction.h index eaff81465..aa7fd1bfa 100644 --- a/src/core/zones/ZoneDefaultInteraction.h +++ b/src/core/zones/ZoneDefaultInteraction.h @@ -16,6 +16,7 @@ #include "SplineSegment.h" #include "SplineVertex.h" +class QShortcut; class ZoneInteractionContext; class ZoneDefaultInteraction : public InteractionHandler { @@ -43,6 +44,10 @@ class ZoneDefaultInteraction : public InteractionHandler { void onContextMenuEvent(QContextMenuEvent* event, InteractionState& interaction) override; private: + void removeZoneUnderMouse(); + + void removeVertexUnderMouse(); + ZoneInteractionContext& m_context; BasicSplineVisualizer m_visualizer; InteractionState::Captor m_vertexProximity; @@ -75,7 +80,10 @@ class ZoneDefaultInteraction : public InteractionHandler { SplineSegment m_nearestSegment; EditableSpline::Ptr m_nearestSegmentSpline; QPointF m_screenPointOnSegment; - EditableSpline::Ptr m_underCursorSpline; + EditableSpline::Ptr m_splineUnderMouse; + + std::unique_ptr m_removeZoneShortcut; + std::unique_ptr m_removeVertexShortcut; }; diff --git a/src/core/zones/ZoneInteractionContext.cpp b/src/core/zones/ZoneInteractionContext.cpp index 293b145e8..1f04b37ec 100644 --- a/src/core/zones/ZoneInteractionContext.cpp +++ b/src/core/zones/ZoneInteractionContext.cpp @@ -21,7 +21,8 @@ ZoneInteractionContext::ZoneInteractionContext(ImageViewBase& imageView, Editabl boost::bind(&ZoneInteractionContext::createStdVertexDragInteraction, this, _1, _2, _3)), m_zoneDragInteractionCreator(boost::bind(&ZoneInteractionContext::createStdZoneDragInteraction, this, _1, _2)), m_contextMenuInteractionCreator(boost::bind(&ZoneInteractionContext::createStdContextMenuInteraction, this, _1)), - m_showPropertiesCommand(&ZoneInteractionContext::showPropertiesStub) {} + m_showPropertiesCommand(&ZoneInteractionContext::showPropertiesStub), + m_zoneCreationMode(ZoneCreationMode::POLYGONAL) {} ZoneInteractionContext::~ZoneInteractionContext() = default; diff --git a/src/core/zones/ZoneInteractionContext.h b/src/core/zones/ZoneInteractionContext.h index a12fb869b..205ee1621 100644 --- a/src/core/zones/ZoneInteractionContext.h +++ b/src/core/zones/ZoneInteractionContext.h @@ -9,6 +9,7 @@ #include "EditableSpline.h" #include "EditableZoneSet.h" #include "SplineVertex.h" +#include "ZoneCreationMode.h" class InteractionHandler; class InteractionState; @@ -86,6 +87,10 @@ class ZoneInteractionContext { void setShowPropertiesCommand(const ShowPropertiesCommand& command) { m_showPropertiesCommand = command; } + ZoneCreationMode getZoneCreationMode() const { return m_zoneCreationMode; } + + void setZoneCreationMode(ZoneCreationMode zoneCreationMode) { m_zoneCreationMode = zoneCreationMode; } + private: /** * Creates an instance of ZoneDefaultInteraction. @@ -124,6 +129,7 @@ class ZoneInteractionContext { ZoneDragInteractionCreator m_zoneDragInteractionCreator; ContextMenuInteractionCreator m_contextMenuInteractionCreator; ShowPropertiesCommand m_showPropertiesCommand; + ZoneCreationMode m_zoneCreationMode; }; diff --git a/src/foundation/CMakeLists.txt b/src/foundation/CMakeLists.txt index 8cdbe8ee2..fc130b2aa 100644 --- a/src/foundation/CMakeLists.txt +++ b/src/foundation/CMakeLists.txt @@ -1,6 +1,6 @@ set(sources Constants.h Constants.cpp - NonCopyable.h intrusive_ptr.h ref_countable.h + NonCopyable.h AlignedArray.h FastQueue.h SafeDeletingQObjectPtr.h diff --git a/src/foundation/Property.h b/src/foundation/Property.h index 2aa473243..f9cf0d72b 100644 --- a/src/foundation/Property.h +++ b/src/foundation/Property.h @@ -4,15 +4,17 @@ #ifndef SCANTAILOR_FOUNDATION_PROPERTY_H_ #define SCANTAILOR_FOUNDATION_PROPERTY_H_ -#include "intrusive_ptr.h" -#include "ref_countable.h" +#include class QDomDocument; class QDomElement; +class QString; -class Property : public ref_countable { +class Property { public: - virtual intrusive_ptr clone() const = 0; + virtual ~Property() = default; + + virtual std::shared_ptr clone() const = 0; virtual QDomElement toXml(QDomDocument& doc, const QString& name) const = 0; }; diff --git a/src/foundation/PropertyFactory.cpp b/src/foundation/PropertyFactory.cpp index 4f105c8a9..b6668abe6 100644 --- a/src/foundation/PropertyFactory.cpp +++ b/src/foundation/PropertyFactory.cpp @@ -9,7 +9,7 @@ void PropertyFactory::registerProperty(const QString& property, PropertyConstruc m_registry[property] = constructor; } -intrusive_ptr PropertyFactory::construct(const QDomElement& el) const { +std::shared_ptr PropertyFactory::construct(const QDomElement& el) const { auto it(m_registry.find(el.attribute("type"))); if (it != m_registry.end()) { return (*it->second)(el); diff --git a/src/foundation/PropertyFactory.h b/src/foundation/PropertyFactory.h index e61d7ed8d..85363b044 100644 --- a/src/foundation/PropertyFactory.h +++ b/src/foundation/PropertyFactory.h @@ -5,11 +5,11 @@ #define SCANTAILOR_FOUNDATION_PROPERTYFACTORY_H_ #include +#include #include #include "Hashes.h" #include "Property.h" -#include "intrusive_ptr.h" class QDomElement; @@ -18,11 +18,11 @@ class PropertyFactory { public: virtual ~PropertyFactory() = default; - using PropertyConstructor = intrusive_ptr (*)(const QDomElement& el); + using PropertyConstructor = std::shared_ptr (*)(const QDomElement& el); void registerProperty(const QString& property, PropertyConstructor constructor); - intrusive_ptr construct(const QDomElement& el) const; + std::shared_ptr construct(const QDomElement& el) const; private: using Registry = std::unordered_map>; diff --git a/src/foundation/PropertySet.cpp b/src/foundation/PropertySet.cpp index 465b6f6a2..6e8561117 100644 --- a/src/foundation/PropertySet.cpp +++ b/src/foundation/PropertySet.cpp @@ -20,14 +20,14 @@ PropertySet::PropertySet(const QDomElement& el, const PropertyFactory& factory) } QDomElement propEl(node.toElement()); - intrusive_ptr prop = factory.construct(propEl); + std::shared_ptr prop = factory.construct(propEl); if (prop) { m_props[typeid(*prop)] = prop; } } } -PropertySet::PropertySet(const PropertySet& other) : ref_countable(other) { +PropertySet::PropertySet(const PropertySet& other) { m_props.reserve(other.m_props.size()); for (const auto& [type, prop] : other.m_props) { m_props[type] = prop->clone(); @@ -39,10 +39,6 @@ PropertySet& PropertySet::operator=(const PropertySet& other) { return *this; } -void PropertySet::swap(PropertySet& other) { - m_props.swap(other.m_props); -} - QDomElement PropertySet::toXml(QDomDocument& doc, const QString& name) const { const QString propertyStr("property"); QDomElement propsEl(doc.createElement(name)); diff --git a/src/foundation/PropertySet.h b/src/foundation/PropertySet.h index ce4c79500..358a86ca4 100644 --- a/src/foundation/PropertySet.h +++ b/src/foundation/PropertySet.h @@ -4,20 +4,19 @@ #ifndef SCANTAILOR_FOUNDATION_PROPERTYSET_H_ #define SCANTAILOR_FOUNDATION_PROPERTYSET_H_ +#include #include #include #include #include "Property.h" -#include "intrusive_ptr.h" -#include "ref_countable.h" class PropertyFactory; class QDomDocument; class QDomElement; class QString; -class PropertySet : public ref_countable { +class PropertySet { public: PropertySet() = default; @@ -28,6 +27,8 @@ class PropertySet : public ref_countable { PropertySet(const QDomElement& el, const PropertyFactory& factory); + virtual ~PropertySet() = default; + /** * \brief Makes a deep copy of another property set. */ @@ -45,20 +46,20 @@ class PropertySet : public ref_countable { * type is found, or returns a null smart pointer otherwise. */ template > - intrusive_ptr locate(); + std::shared_ptr locate(); template > - intrusive_ptr locate() const; + std::shared_ptr locate() const; /** * Returns a property stored in this set, if one having a suitable * type is found, or returns a default constructed object otherwise. */ template > - intrusive_ptr locateOrDefault(); + std::shared_ptr locateOrDefault(); template > - intrusive_ptr locateOrDefault() const; + std::shared_ptr locateOrDefault() const; /** * Returns a property stored in this set, if one having a suitable @@ -66,53 +67,57 @@ class PropertySet : public ref_countable { * to the set and then returned. */ template > - intrusive_ptr locateOrCreate(); + std::shared_ptr locateOrCreate(); private: - using PropertyMap = std::unordered_map>; + using PropertyMap = std::unordered_map>; PropertyMap m_props; }; template -intrusive_ptr PropertySet::locate() { +std::shared_ptr PropertySet::locate() { auto it(m_props.find(typeid(T))); if (it != m_props.end()) { - return static_pointer_cast(it->second); + return std::static_pointer_cast(it->second); } else { return nullptr; } } template -intrusive_ptr PropertySet::locate() const { +std::shared_ptr PropertySet::locate() const { return const_cast(this)->locate(); } template -intrusive_ptr PropertySet::locateOrDefault() { - intrusive_ptr prop = locate(); +std::shared_ptr PropertySet::locateOrDefault() { + std::shared_ptr prop = locate(); if (!prop) { - return make_intrusive(); + return std::make_shared(); } return prop; } template -intrusive_ptr PropertySet::locateOrDefault() const { +std::shared_ptr PropertySet::locateOrDefault() const { return const_cast(this)->locateOrDefault(); } template -intrusive_ptr PropertySet::locateOrCreate() { - intrusive_ptr prop = locate(); +std::shared_ptr PropertySet::locateOrCreate() { + std::shared_ptr prop = locate(); if (!prop) { - prop = make_intrusive(); + prop = std::make_shared(); m_props[typeid(T)] = prop; } return prop; } +inline void PropertySet::swap(PropertySet& other) { + m_props.swap(other.m_props); +} + inline void swap(PropertySet& o1, PropertySet& o2) { o1.swap(o2); } diff --git a/src/foundation/intrusive_ptr.h b/src/foundation/intrusive_ptr.h deleted file mode 100644 index 0cd918ea8..000000000 --- a/src/foundation/intrusive_ptr.h +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (C) 2019 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> -// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. - -#ifndef SCANTAILOR_FOUNDATION_INTRUSIVE_PTR_H_ -#define SCANTAILOR_FOUNDATION_INTRUSIVE_PTR_H_ - -#include -#include - -template -class intrusive_ptr { - template - friend class intrusive_ptr; - - public: - struct hash; - - using pointer = T*; - - template - using enable_if_convertible = - typename std::enable_if::pointer, pointer>::value>::type; - - public: - constexpr intrusive_ptr(std::nullptr_t = nullptr) noexcept; - - explicit intrusive_ptr(T* obj) noexcept; - - intrusive_ptr(const intrusive_ptr& other) noexcept; - - intrusive_ptr(intrusive_ptr&& other) noexcept; - - template > - intrusive_ptr(const intrusive_ptr& other) noexcept; - - template > - intrusive_ptr(intrusive_ptr&& other) noexcept; - - ~intrusive_ptr() noexcept; - - intrusive_ptr& operator=(std::nullptr_t) noexcept; - - intrusive_ptr& operator=(const intrusive_ptr& rhs) noexcept; - - intrusive_ptr& operator=(intrusive_ptr&& rhs) noexcept; - - template > - intrusive_ptr& operator=(const intrusive_ptr& rhs) noexcept; - - template > - intrusive_ptr& operator=(intrusive_ptr&& rhs) noexcept; - - T& operator*() const; - - T* operator->() const noexcept; - - T* get() const noexcept; - - T* release() noexcept; - - void reset(std::nullptr_t = nullptr) noexcept; - - void reset(T* obj) noexcept; - - void swap(intrusive_ptr& other) noexcept; - - explicit operator bool() const noexcept; - - private: - T* fork() const noexcept; - - void intrusive_ref(const T& obj) const noexcept; - - void intrusive_unref(const T& obj) const noexcept; - - - T* m_obj; -}; - -/** - * \brief Default implementation of intrusive referencing. - * - * May be specialized or overloaded. - */ -template -inline void intrusive_ptr::intrusive_ref(const T& obj) const noexcept { - obj.ref(); -} - -/** - * \brief Default implementation of intrusive unreferencing. - * - * May be specialized or overloaded. - */ -template -inline void intrusive_ptr::intrusive_unref(const T& obj) const noexcept { - obj.unref(); -} - -template -constexpr inline intrusive_ptr::intrusive_ptr(std::nullptr_t) noexcept : m_obj(nullptr) {} - -template -inline intrusive_ptr::intrusive_ptr(T* obj) noexcept : m_obj(obj) { - if (obj) { - intrusive_ref(*obj); - } -} - -template -inline intrusive_ptr::intrusive_ptr(const intrusive_ptr& other) noexcept : m_obj(other.fork()) {} - -template -inline intrusive_ptr::intrusive_ptr(intrusive_ptr&& other) noexcept : m_obj(other.release()) {} - -template -template -inline intrusive_ptr::intrusive_ptr(const intrusive_ptr& other) noexcept : m_obj(other.fork()) {} - -template -template -inline intrusive_ptr::intrusive_ptr(intrusive_ptr&& other) noexcept : m_obj(other.release()) {} - -template -inline intrusive_ptr::~intrusive_ptr() noexcept { - if (m_obj) { - intrusive_unref(*m_obj); - } -} - -template -inline intrusive_ptr& intrusive_ptr::operator=(std::nullptr_t) noexcept { - reset(); - return *this; -} - -template -inline intrusive_ptr& intrusive_ptr::operator=(const intrusive_ptr& rhs) noexcept { - intrusive_ptr(rhs).swap(*this); - return *this; -} - -template -inline intrusive_ptr& intrusive_ptr::operator=(intrusive_ptr&& rhs) noexcept { - intrusive_ptr(std::move(rhs)).swap(*this); - return *this; -} - -template -template -inline intrusive_ptr& intrusive_ptr::operator=(const intrusive_ptr& rhs) noexcept { - intrusive_ptr(rhs).swap(*this); - return *this; -} - -template -template -inline intrusive_ptr& intrusive_ptr::operator=(intrusive_ptr&& rhs) noexcept { - intrusive_ptr(std::move(rhs)).swap(*this); - return *this; -} - -template -inline T& intrusive_ptr::operator*() const { - return *get(); -} - -template -inline T* intrusive_ptr::operator->() const noexcept { - return get(); -} - -template -inline T* intrusive_ptr::get() const noexcept { - return m_obj; -} - -template -inline T* intrusive_ptr::release() noexcept { - T* obj = m_obj; - m_obj = nullptr; - return obj; -} - -template -inline void intrusive_ptr::reset(std::nullptr_t) noexcept { - intrusive_ptr().swap(*this); -} - -template -inline void intrusive_ptr::reset(T* obj) noexcept { - intrusive_ptr(obj).swap(*this); -} - -template -inline void intrusive_ptr::swap(intrusive_ptr& other) noexcept { - T* obj = other.m_obj; - other.m_obj = m_obj; - m_obj = obj; -} - -template -inline intrusive_ptr::operator bool() const noexcept { - return (get() != nullptr); -} - -template -inline T* intrusive_ptr::fork() const noexcept { - T* obj = m_obj; - if (obj) { - intrusive_ref(*obj); - } - return obj; -} - -template -inline intrusive_ptr make_intrusive(Args&&... args) { - return intrusive_ptr(new T(std::forward(args)...)); -} - -template -struct intrusive_ptr::hash { - std::size_t operator()(const intrusive_ptr& __p) const noexcept { - return reinterpret_cast(__p.get()); - } -}; - - -#define INTRUSIVE_PTR_OP(op) \ - template \ - inline bool operator op(const intrusive_ptr& lhs, const intrusive_ptr& rhs) { \ - return (lhs.get() op rhs.get()); \ - } \ - \ - template \ - inline bool operator op(const intrusive_ptr& lhs, const intrusive_ptr& rhs) { \ - return (lhs.get() op rhs.get()); \ - } \ - \ - template \ - inline bool operator op(std::nullptr_t, const intrusive_ptr& rhs) { \ - return (nullptr op rhs.get()); \ - } \ - \ - template \ - inline bool operator op(const intrusive_ptr& lhs, std::nullptr_t) { \ - return (lhs.get() op nullptr); \ - } - -INTRUSIVE_PTR_OP(==) - -INTRUSIVE_PTR_OP(!=) - -INTRUSIVE_PTR_OP(<) - -INTRUSIVE_PTR_OP(>) - -INTRUSIVE_PTR_OP(<=) - -INTRUSIVE_PTR_OP(>=) - -template -inline void swap(intrusive_ptr& lhs, intrusive_ptr& rhs) { - lhs.swap(rhs); -} - -template -inline intrusive_ptr static_pointer_cast(const intrusive_ptr& r) noexcept { - return intrusive_ptr(static_cast::pointer>(r.get())); -} - -template -inline intrusive_ptr const_pointer_cast(const intrusive_ptr& r) noexcept { - return intrusive_ptr(const_cast::pointer>(r.get())); -} - -template -inline intrusive_ptr dynamic_pointer_cast(const intrusive_ptr& r) noexcept { - if (auto* p = dynamic_cast::pointer>(r.get())) { - return intrusive_ptr(p); - } - return intrusive_ptr(); -} - -template -inline intrusive_ptr reinterpret_pointer_cast(const intrusive_ptr& r) noexcept { - return intrusive_ptr(reinterpret_cast::pointer>(r.get())); -} - -#endif // ifndef SCANTAILOR_FOUNDATION_INTRUSIVE_PTR_H_ diff --git a/src/foundation/ref_countable.h b/src/foundation/ref_countable.h deleted file mode 100644 index 323fb8fc7..000000000 --- a/src/foundation/ref_countable.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2019 Joseph Artsimovich , 4lex4 <4lex49@zoho.com> -// Use of this source code is governed by the GNU GPLv3 license that can be found in the LICENSE file. - -#ifndef SCANTAILOR_FOUNDATION_REF_COUNTABLE_H_ -#define SCANTAILOR_FOUNDATION_REF_COUNTABLE_H_ - -#include - -class ref_countable { - public: - ref_countable() = default; - - ref_countable(const ref_countable&) {} - - ref_countable& operator=(const ref_countable&) { return *this; } - - void ref() const { m_counter.fetchAndAddRelaxed(1); } - - void unref() const { - if (m_counter.fetchAndAddRelease(-1) == 1) { - delete this; - } - } - - protected: - virtual ~ref_countable() = default; - - private: - mutable QAtomicInt m_counter = 0; -}; - - -#endif // ifndef SCANTAILOR_FOUNDATION_REF_COUNTABLE_H_ diff --git a/src/imageproc/Dpi.cpp b/src/imageproc/Dpi.cpp index d34ca3db9..7d9adfcf1 100644 --- a/src/imageproc/Dpi.cpp +++ b/src/imageproc/Dpi.cpp @@ -44,15 +44,3 @@ QDomElement Dpi::toXml(QDomDocument& doc, const QString& name) const { el.setAttribute("vertical", m_yDpi); return el; } - -int Dpi::horizontal() const { - return m_xDpi; -} - -int Dpi::vertical() const { - return m_yDpi; -} - -bool Dpi::isNull() const { - return m_xDpi <= 1 || m_yDpi <= 1; -} diff --git a/src/imageproc/Dpi.h b/src/imageproc/Dpi.h index 40ffc104f..07b9ec3fe 100644 --- a/src/imageproc/Dpi.h +++ b/src/imageproc/Dpi.h @@ -45,4 +45,16 @@ class Dpi { }; +inline int Dpi::horizontal() const { + return m_xDpi; +} + +inline int Dpi::vertical() const { + return m_yDpi; +} + +inline bool Dpi::isNull() const { + return m_xDpi <= 1 || m_yDpi <= 1; +} + #endif // ifndef SCANTAILOR_IMAGEPROC_DPI_H_ diff --git a/src/imageproc/MaxWhitespaceFinder.cpp b/src/imageproc/MaxWhitespaceFinder.cpp index d6061c373..2c20df7af 100644 --- a/src/imageproc/MaxWhitespaceFinder.cpp +++ b/src/imageproc/MaxWhitespaceFinder.cpp @@ -22,7 +22,7 @@ class AreaCompare { MaxWhitespaceFinder::MaxWhitespaceFinder(const BinaryImage& img, QSize minSize) : m_integralImg(img.size()), - m_queuedRegions(new PriorityStorageImpl(AreaCompare())), + m_queuedRegions(std::make_unique>(AreaCompare())), m_minSize(minSize) { init(img); } diff --git a/src/imageproc/MaxWhitespaceFinder.h b/src/imageproc/MaxWhitespaceFinder.h index 4dd6cc5b2..3cab3c664 100644 --- a/src/imageproc/MaxWhitespaceFinder.h +++ b/src/imageproc/MaxWhitespaceFinder.h @@ -294,7 +294,7 @@ void PriorityStorageImpl::popHeap(const std::deque::iter template MaxWhitespaceFinder::MaxWhitespaceFinder(const QualityCompare comp, const BinaryImage& img, const QSize minSize) : m_integralImg(img.size()), - m_queuedRegions(new max_whitespace_finder::PriorityStorageImpl(comp)), + m_queuedRegions(std::make_unique>(comp)), m_minSize(minSize) { init(img); } diff --git a/src/imageproc/Transform.cpp b/src/imageproc/Transform.cpp index 02e6d537d..a0be0ff90 100644 --- a/src/imageproc/Transform.cpp +++ b/src/imageproc/Transform.cpp @@ -282,8 +282,10 @@ static void transformGeneric(const StorageUnit* const srcData, template void fixDpiInPlace(ImageT& dst, const QImage& src, const QTransform& xform) { - dst.setDotsPerMeterX(qRound(src.dotsPerMeterX() * xform.m11())); - dst.setDotsPerMeterY(qRound(src.dotsPerMeterY() * xform.m22())); + QLineF horLine(0, 0, src.dotsPerMeterX(), 0); + QLineF verLine(0, 0, 0, src.dotsPerMeterY()); + dst.setDotsPerMeterX(qRound(xform.map(horLine).length())); + dst.setDotsPerMeterY(qRound(xform.map(verLine).length())); } } // namespace diff --git a/src/resources/dark_scheme/stylesheet/stylesheet.qss b/src/resources/dark_scheme/stylesheet/stylesheet.qss index f9898f9ce..309694aa9 100644 --- a/src/resources/dark_scheme/stylesheet/stylesheet.qss +++ b/src/resources/dark_scheme/stylesheet/stylesheet.qss @@ -78,7 +78,7 @@ QCheckBox::indicator:unchecked, QTreeView::indicator:unchecked, QTableView::indi border-radius: 2.75px; } -QMenu::indicator:non-exclusive:unchecked { +QMenu::indicator:non-exclusive:unchecked, QMenu::indicator:non-exclusive:unchecked:selected { border: 1px solid #666666; margin: 0px 0px 0px 2px; background-color: palette(base); @@ -163,7 +163,7 @@ QRadioButton::indicator:unchecked { border-radius: 7.75px; } -QMenu::indicator:exclusive:unchecked { +QMenu::indicator:exclusive:unchecked, QMenu::indicator:exclusive:unchecked:selected { border: 1px solid #666666; margin: 0px 0px 0px 2px; background-color: palette(base); @@ -432,23 +432,12 @@ QScrollBar::up-arrow:vertical { image: url(:/dark_scheme/icons/scroll_bar_up_arrow.svg); } -QTabWidget > QWidget { - qproperty-drawBase:0; -} - -QTabWidget::pane { - background-color: palette(window); - background-color: #424242; - qproperty-drawBase:0; -} - QTabWidget::tab-bar { top: 1px; } -QTabBar { - background-color: transparent; - border: none; +QTabBar, QTabWidget::pane { + qproperty-drawBase:0; } QTabBar::tab { diff --git a/src/resources/icons.xml b/src/resources/icons.xml index b7ec273d1..ec601848a 100644 --- a/src/resources/icons.xml +++ b/src/resources/icons.xml @@ -167,5 +167,28 @@ :/icons/multi-column-view.svg :/icons/single-column-view.svg - + + + :icons/ascending_sorting_order.svg + :icons/descending_sorting_order.svg + + + :icons/lasso-zone-mode.svg + + + :icons/polygonal-zone-mode.svg + + + :icons/rectangular-zone-mode.svg + + + :icons/six-spoked-asterisk-disabled.svg + :icons/six-spoked-asterisk.svg + + + :icons/diminishing-glass.svg + + + :icons/magnifying-glass.svg + \ No newline at end of file diff --git a/src/resources/icons/ascending_sorting_order.svg b/src/resources/icons/ascending_sorting_order.svg new file mode 100644 index 000000000..ab08f12ea --- /dev/null +++ b/src/resources/icons/ascending_sorting_order.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/src/resources/icons/check-mark-disabled.svg b/src/resources/icons/check-mark-disabled.svg index 16d7f12a5..c26fa83a7 100644 --- a/src/resources/icons/check-mark-disabled.svg +++ b/src/resources/icons/check-mark-disabled.svg @@ -2,18 +2,18 @@ - - - - + + + + diff --git a/src/resources/icons/descending_sorting_order.svg b/src/resources/icons/descending_sorting_order.svg new file mode 100644 index 000000000..4d640ce64 --- /dev/null +++ b/src/resources/icons/descending_sorting_order.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/src/resources/icons/diminishing-glass.svg b/src/resources/icons/diminishing-glass.svg new file mode 100644 index 000000000..f8b788087 --- /dev/null +++ b/src/resources/icons/diminishing-glass.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/src/resources/icons/eye-disabled.svg b/src/resources/icons/eye-disabled.svg index c04815ebb..8c987e9d9 100644 --- a/src/resources/icons/eye-disabled.svg +++ b/src/resources/icons/eye-disabled.svg @@ -2,20 +2,20 @@ - - - - + + + + diff --git a/src/resources/icons/lasso-zone-mode.svg b/src/resources/icons/lasso-zone-mode.svg new file mode 100644 index 000000000..093435447 --- /dev/null +++ b/src/resources/icons/lasso-zone-mode.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/src/resources/icons/magnifying-glass.svg b/src/resources/icons/magnifying-glass.svg new file mode 100644 index 000000000..e2d92c983 --- /dev/null +++ b/src/resources/icons/magnifying-glass.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/src/resources/icons/polygonal-zone-mode.svg b/src/resources/icons/polygonal-zone-mode.svg new file mode 100644 index 000000000..ad338a99d --- /dev/null +++ b/src/resources/icons/polygonal-zone-mode.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/src/resources/icons/rectangular-zone-mode.svg b/src/resources/icons/rectangular-zone-mode.svg new file mode 100644 index 000000000..5685c2db1 --- /dev/null +++ b/src/resources/icons/rectangular-zone-mode.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/src/resources/icons/six-spoked-asterisk-disabled.svg b/src/resources/icons/six-spoked-asterisk-disabled.svg new file mode 100644 index 000000000..1e13ddf71 --- /dev/null +++ b/src/resources/icons/six-spoked-asterisk-disabled.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/src/resources/icons/six-spoked-asterisk.svg b/src/resources/icons/six-spoked-asterisk.svg new file mode 100644 index 000000000..e8b43e9e3 --- /dev/null +++ b/src/resources/icons/six-spoked-asterisk.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/resources/icons/stock-vchain-broken.svg b/src/resources/icons/stock-vchain-broken.svg index f1ec54f32..f098be769 100644 --- a/src/resources/icons/stock-vchain-broken.svg +++ b/src/resources/icons/stock-vchain-broken.svg @@ -1,22 +1,18 @@ - - - - - + viewBox="0 0 18 24" style="enable-background:new 0 0 18 24;" xml:space="preserve"> + + + + + diff --git a/src/resources/icons/stock-vchain.svg b/src/resources/icons/stock-vchain.svg index 8200626e4..b10e32e48 100644 --- a/src/resources/icons/stock-vchain.svg +++ b/src/resources/icons/stock-vchain.svg @@ -1,20 +1,20 @@ - - - + viewBox="0 0 18 24" style="enable-background:new 0 0 18 24;" xml:space="preserve"> + + + diff --git a/src/resources/light_scheme/stylesheet/stylesheet.qss b/src/resources/light_scheme/stylesheet/stylesheet.qss index b7d334045..d2da5eab7 100644 --- a/src/resources/light_scheme/stylesheet/stylesheet.qss +++ b/src/resources/light_scheme/stylesheet/stylesheet.qss @@ -78,7 +78,7 @@ QCheckBox::indicator:unchecked, QTreeView::indicator:unchecked, QTableView::indi border-radius: 2.75px; } -QMenu::indicator:non-exclusive:unchecked { +QMenu::indicator:non-exclusive:unchecked, QMenu::indicator:non-exclusive:unchecked:selected { border: 1px solid #cccccc; margin: 0px 0px 0px 2px; background-color: palette(base); @@ -163,7 +163,7 @@ QRadioButton::indicator:unchecked { border-radius: 7.75px; } -QMenu::indicator:exclusive:unchecked { +QMenu::indicator:exclusive:unchecked, QMenu::indicator:exclusive:unchecked:selected { border: 1px solid #cccccc; margin: 0px 0px 0px 2px; background-color: palette(base); @@ -433,23 +433,12 @@ QScrollBar::up-arrow:vertical { image: url(:/light_scheme/icons/scroll_bar_up_arrow.svg); } -QTabWidget > QWidget { - qproperty-drawBase:0; -} - -QTabWidget::pane { - background-color: palette(window); - border: 1px solid #cccccc; - qproperty-drawBase:0; -} - QTabWidget::tab-bar { top: 1px; } -QTabBar { - background-color: transparent; - border: none; +QTabBar, QTabWidget::pane { + qproperty-drawBase:0; } QTabBar::tab { diff --git a/src/resources/resources.qrc b/src/resources/resources.qrc index 8d9a92d1e..6c5a41b82 100644 --- a/src/resources/resources.qrc +++ b/src/resources/resources.qrc @@ -57,6 +57,15 @@ icons/right-pointing.svg icons/multi-column-view.svg icons/single-column-view.svg + icons/ascending_sorting_order.svg + icons/descending_sorting_order.svg + icons/lasso-zone-mode.svg + icons/polygonal-zone-mode.svg + icons/rectangular-zone-mode.svg + icons/six-spoked-asterisk.svg + icons/six-spoked-asterisk-disabled.svg + icons/diminishing-glass.svg + icons/magnifying-glass.svg icons.xml font-icons.xml GPLv3.html diff --git a/version.h.in b/version.h.in index 7a9f9ecb7..8dd4cd621 100644 --- a/version.h.in +++ b/version.h.in @@ -1,20 +1,4 @@ -/* - Scan Tailor - Interactive post-processing tool for scanned pages. - Copyright (C) Joseph Artsimovich - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ +/* This file is a template for version.h, for use with CMake. */ #ifndef SCANTAILOR_VERSION_H_ #define SCANTAILOR_VERSION_H_