void MainWindow::createMenus() { QAction* action; QString name; QMenu* menu; QMenu* subMenu; // ----- File Menu ----- menu = menuBar()->addMenu("File"); name = "About"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(showAbout())); name = "New Molecule"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(newMoleculeMenu())); action->setShortcut(QKeySequence::New); name = "New Viewer"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(newViewer())); name = "Open"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(openFile())); action->setShortcut(QKeySequence::Open); name = "Open Recent"; m_recentFilesMenu = menu->addMenu(name); updateRecentFilesMenu(); menu->addSeparator(); /* name = "Parse Test File"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(parseFile())); menu->addSeparator(); */ name = "Close Viewer"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(close())); action->setShortcut(QKeySequence::Close); name = "Save"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(saveAll())); action->setShortcut(QKeySequence::Save); name = "Save As"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(saveAs())); action->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_S); menu->addSeparator(); name = "Save Picture"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewer, SLOT(saveSnapshot())); action->setShortcut(Qt::CTRL + Qt::Key_P); name = "Record Animation"; action = menu->addAction(name); action->setCheckable(true); action->setChecked(false); connect(action, SIGNAL(triggered()), this, SLOT(toggleRecordingActive())); action->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_P); m_recordAnimationAction = action; name = "Show Message Log"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(showLogMessages())); action->setShortcut(Qt::CTRL + Qt::Key_L); name = "Quit"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(quit())); action->setShortcut(Qt::CTRL + Qt::Key_Q); // ----- Edit Menu ----- menu = menuBar()->addMenu("Edit"); name = "Undo"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_undoStack, SLOT(undo())); action->setShortcut(QKeySequence::Undo); connect(&m_undoStack, SIGNAL(canUndoChanged(bool)), action, SLOT(setEnabled(bool))); name = "Redo"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_undoStack, SLOT(redo())); action->setShortcut(QKeySequence::Redo); connect(&m_undoStack, SIGNAL(canRedoChanged(bool)), action, SLOT(setEnabled(bool))); menu->addSeparator(); name = "Cut"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(cutSelection())); action->setShortcut(Qt::CTRL + Qt::Key_X); name = "Copy"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(copySelectionToClipboard())); action->setShortcut(Qt::CTRL + Qt::Key_C); name = "Paste"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(pasteSelectionFromClipboard())); action->setShortcut(Qt::CTRL + Qt::Key_V); menu->addSeparator(); name = "Select All"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(selectAll())); action->setShortcut(Qt::CTRL + Qt::Key_A); name = "Select None"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SIGNAL(clearSelection())); action->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_A); name = "Invert Selection"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(invertSelection())); action->setShortcut(Qt::CTRL + Qt::Key_I); menu->addSeparator(); name = "Reindex Atoms"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(reindexAtoms())); menu->addSeparator(); name = "Preferences"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(showPreferences())); // ----- Display Menu ----- menu = menuBar()->addMenu("Display"); name = "Full Screen"; action = menu->addAction(name); action->setCheckable(true); action->setChecked(false); connect(action, SIGNAL(triggered()), this, SLOT(fullScreen())); action->setShortcut(Qt::CTRL + Qt::Key_0); m_fullScreenAction = action; name = "Reset View"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewer, SLOT(resetView())); action->setShortcut(Qt::CTRL + Qt::Key_R); name = "Show Axes"; action = menu->addAction(name); action->setCheckable(true); action->setChecked(false); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(toggleAxes())); connect(&m_viewerModel, SIGNAL(axesOn(bool)), action, SLOT(setChecked(bool))); action->setShortcut(Qt::Key_A); menu->addSeparator(); name = "Atom Labels"; subMenu = menu->addMenu(name); name = "Element"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::Element); action->setShortcut(Qt::Key_E); action->setCheckable(true); m_labelActions << action; name = "Index"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::Index); action->setShortcut(Qt::Key_I); action->setCheckable(true); m_labelActions << action; name = "Mass"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::Mass); action->setShortcut(Qt::Key_M); action->setCheckable(true); m_labelActions << action; /* name = "NMR Shifts"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::NmrShifts); action->setShortcut(Qt::Key_N); action->setCheckable(true); m_labelActions << action; */ name = "Partial Charge"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::Charge); action->setShortcut(Qt::Key_Q); action->setCheckable(true); m_labelActions << action; name = "Spin Densities"; action = subMenu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setLabel())); action->setData(Layer::Atom::Spin); action->setShortcut(Qt::Key_S); action->setCheckable(true); m_labelActions << action; menu->addSeparator(); name = "Configure Appearance"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(configureAppearance())); // These are not working correctly at the moment. /* name = "Partial Charge Type"; QActionGroup* partialChargeGroup = new QActionGroup(this); subMenu = menu->addMenu(name); QString pc("Gasteiger"); action = subMenu->addAction(pc); action->setCheckable(true); action->setChecked(true); action->setData(pc); partialChargeGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setPartialChargeType())); pc = "Sanderson"; action = subMenu->addAction(pc); action->setCheckable(true); action->setData(pc); partialChargeGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setPartialChargeType())); pc = "Mulliken"; action = subMenu->addAction(pc); action->setCheckable(true); action->setData(pc); partialChargeGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setPartialChargeType())); */ // ----- Build Menu ----- menu = menuBar()->addMenu("Build"); name = "Fill Valencies With Hydrogens"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(addHydrogens())); action->setShortcut(Qt::CTRL + Qt::Key_F); name = "Reperceive Bonds"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(reperceiveBonds())); menu->addSeparator(); name = "Set Constraint"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(setConstraint())); action->setShortcut(Qt::CTRL + Qt::Key_K); name = "Minimize Structure"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(minimizeEnergy())); action->setShortcut(Qt::CTRL + Qt::Key_M); name = "Select Force Field"; QActionGroup* forceFieldGroup = new QActionGroup(this); subMenu = menu->addMenu(name); QString ff("MMFF94"); action = subMenu->addAction(ff); action->setCheckable(true); action->setData(ff); forceFieldGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setForceField())); if (Preferences::DefaultForceField() == ff) action->setChecked(true); ff = "MMFF94s"; action = subMenu->addAction(ff); action->setCheckable(true); action->setData(ff); forceFieldGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setForceField())); if (Preferences::DefaultForceField() == ff) action->setChecked(true); ff = "UFF"; action = subMenu->addAction(ff); action->setCheckable(true); action->setData(ff); forceFieldGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setForceField())); if (Preferences::DefaultForceField() == ff) action->setChecked(true); ff = "Ghemical"; action = subMenu->addAction(ff); action->setCheckable(true); action->setData(ff); forceFieldGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setForceField())); if (Preferences::DefaultForceField() == ff) action->setChecked(true); ff = "Gaff"; action = subMenu->addAction(ff); action->setCheckable(true); action->setData(ff); forceFieldGroup->addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(setForceField())); if (Preferences::DefaultForceField() == ff) action->setChecked(true); menu->addSeparator(); name = "Translate To Center"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(translateToCenter())); action->setShortcut(Qt::CTRL + Qt::Key_T ); name = "Symmetrize Molecule"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(symmetrize())); action->setShortcut(Qt::CTRL + Qt::Key_Y ); name = "Set Symmetry Tolerance"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(adjustSymmetryTolerance())); name = "Auto-detect Symmetry"; action = menu->addAction(name); action->setCheckable(true); action->setChecked(false); connect(action, SIGNAL(triggered()), &m_viewerModel, SLOT(toggleAutoDetectSymmetry())); // ----- Calculation Menu ----- menu = menuBar()->addMenu("Calculation"); name = "Q-Chem Setup"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(openQChemUI())); action->setShortcut(Qt::CTRL + Qt::Key_U ); m_qchemSetupAction = action; name = "Job Monitor"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(showProcessMonitor())); action->setShortcut(Qt::CTRL + Qt::Key_J ); menu->addSeparator(); name = "Edit Servers"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(editServers())); name = "Remove All Processes"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), &(ProcessMonitor::instance()), SLOT(clearProcessList())); name = "Reset Password Vault Key"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(setVaultPassword())); // ----- Help Menu ----- menu = menuBar()->addMenu("Help"); name = "Show Help"; action = menu->addAction(name); connect(action, SIGNAL(triggered()), this, SLOT(showHelp())); }
void KisDuplicateOp::paintAt(const KisPaintInformation& info) { if (!painter()) return; if (!m_duplicateStartIsSet) { m_duplicateStartIsSet = true; m_duplicateStart = info.pos(); } bool heal = settings->healing(); if (!source()) return; KisBrushSP brush = m_brush; if (!brush) return; if (! brush->canPaintFor(info)) return; double scale = KisPaintOp::scaleForPressure(info.pressure()); QPointF hotSpot = brush->hotSpot(scale, scale); QPointF pt = info.pos() - hotSpot; // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x; double xFraction; qint32 y; double yFraction; splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); xFraction = yFraction = 0.0; QPointF srcPointF = pt - settings->offset(); QPoint srcPoint = QPoint(x - static_cast<qint32>(settings->offset().x()), y - static_cast<qint32>(settings->offset().y())); qint32 sw = brush->maskWidth(scale, 0.0); qint32 sh = brush->maskHeight(scale, 0.0); if (srcPoint.x() < 0) srcPoint.setX(0); if (srcPoint.y() < 0) srcPoint.setY(0); if (!(m_srcdev && !(*m_srcdev->colorSpace() == *source()->colorSpace()))) { m_srcdev = new KisPaintDevice(source()->colorSpace()); } Q_CHECK_PTR(m_srcdev); // Perspective correction ? KisPainter copyPainter(m_srcdev); KisImageSP image = settings->m_image; if (settings->perspectiveCorrection() && image && image->perspectiveGrid()->countSubGrids() == 1) { Matrix3qreal startM = Matrix3qreal::Identity(); Matrix3qreal endM = Matrix3qreal::Identity(); // First look for the grid corresponding to the start point KisSubPerspectiveGrid* subGridStart = *image->perspectiveGrid()->begin(); QRect r = QRect(0, 0, image->width(), image->height()); #if 1 if (subGridStart) { startM = KisPerspectiveMath::computeMatrixTransfoFromPerspective(r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight()); } #endif #if 1 // Second look for the grid corresponding to the end point KisSubPerspectiveGrid* subGridEnd = *image->perspectiveGrid()->begin(); if (subGridEnd) { endM = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r); } #endif // Compute the translation in the perspective transformation space: QPointF positionStartPaintingT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart)); QPointF duplicateStartPositionT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart) - QPointF(settings->offset())); QPointF translat = duplicateStartPositionT - positionStartPaintingT; KisRectIteratorPixel dstIt = m_srcdev->createRectIterator(0, 0, sw, sh); KisRandomSubAccessorPixel srcAcc = source()->createRandomSubAccessor(); //Action while (!dstIt.isDone()) { if (dstIt.isSelected()) { QPointF p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, QPointF(dstIt.x() + x, dstIt.y() + y)) + translat); srcAcc.moveTo(p); srcAcc.sampledOldRawData(dstIt.rawData()); } ++dstIt; } } else { // Or, copy the source data on the temporary device: copyPainter.setCompositeOp(COMPOSITE_COPY); copyPainter.bitBlt(0, 0, source(), srcPoint.x(), srcPoint.y(), sw, sh); copyPainter.end(); } // heal ? if (heal) { quint16 dataDevice[4]; quint16 dataSrcDev[4]; double* matrix = new double[ 3 * sw * sh ]; // First divide const KoColorSpace* deviceCs = source()->colorSpace(); KisHLineConstIteratorPixel deviceIt = source()->createHLineConstIterator(x, y, sw); KisHLineIteratorPixel srcDevIt = m_srcdev->createHLineIterator(0, 0, sw); double* matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; !srcDevIt.isDone(); i++) { deviceCs->toLabA16(deviceIt.rawData(), (quint8*)dataDevice, 1); deviceCs->toLabA16(srcDevIt.rawData(), (quint8*)dataSrcDev, 1); // Division for (int k = 0; k < 3; k++) { matrixIt[k] = dataDevice[k] / (double)qMax((int)dataSrcDev [k], 1); } ++deviceIt; ++srcDevIt; matrixIt += 3; } deviceIt.nextRow(); srcDevIt.nextRow(); } // Minimize energy { int iter = 0; double err; double* solution = new double [ 3 * sw * sh ]; do { err = minimizeEnergy(&matrix[0], &solution[0], sw, sh); memcpy(&matrix[0], &solution[0], sw * sh * 3 * sizeof(double)); iter++; } while (err < 0.00001 && iter < 100); delete [] solution; } // Finaly multiply deviceIt = source()->createHLineIterator(x, y, sw); srcDevIt = m_srcdev->createHLineIterator(0, 0, sw); matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; !srcDevIt.isDone(); i++) { deviceCs->toLabA16(deviceIt.rawData(), (quint8*)dataDevice, 1); deviceCs->toLabA16(srcDevIt.rawData(), (quint8*)dataSrcDev, 1); // Multiplication for (int k = 0; k < 3; k++) { dataSrcDev[k] = (int)CLAMP(matrixIt[k] * qMax((int) dataSrcDev[k], 1), 0, 65535); } deviceCs->fromLabA16((quint8*)dataSrcDev, srcDevIt.rawData(), 1); ++deviceIt; ++srcDevIt; matrixIt += 3; } deviceIt.nextRow(); srcDevIt.nextRow(); } delete [] matrix; } KisFixedPaintDeviceSP fixedDab = new KisFixedPaintDevice(m_srcdev->colorSpace()); fixedDab->setRect(QRect(0, 0, sw, sh)); fixedDab->initialize(); m_srcdev->readBytes(fixedDab->data(), fixedDab->bounds()); brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction); m_srcdev->writeBytes(fixedDab->data(), fixedDab->bounds()); QRect dabRect = QRect(0, 0, brush->maskWidth(scale, 0.0), brush->maskHeight(scale, 0.0)); QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); if (painter()->bounds().isValid()) { dstRect &= painter()->bounds(); } if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; qint32 sx = dstRect.x() - x; qint32 sy = dstRect.y() - y; sw = dstRect.width(); sh = dstRect.height(); painter()->bitBlt(dstRect.x(), dstRect.y(), m_srcdev, sx, sy, sw, sh); }
void MainWindow::createConnections() { connect(&m_toolBar, SIGNAL(newMolecule()), &m_viewerModel, SLOT(newMoleculeMenu())); connect(&m_toolBar, SIGNAL(open()), this, SLOT(openFile())); connect(&m_toolBar, SIGNAL(save()), &m_viewerModel, SLOT(saveAll())); connect(&m_toolBar, SIGNAL(addHydrogens()), &m_viewerModel, SLOT(addHydrogens())); connect(&m_toolBar, SIGNAL(minimizeEnergy()), &m_viewerModel, SLOT(minimizeEnergy())); connect(&m_toolBar, SIGNAL(deleteSelection()), &m_viewerModel, SLOT(deleteSelection())); connect(&m_toolBar, SIGNAL(takeSnapshot()), &m_viewer, SLOT(saveSnapshot())); connect(&m_toolBar, SIGNAL(record(bool)), this, SLOT(setRecordingActive(bool))); connect(this, SIGNAL(recordingActive(bool)), &m_toolBar, SLOT(setRecordAnimationButtonChecked(bool))); connect(this, SIGNAL(recordingActive(bool)), &m_viewer, SLOT(setRecordingActive(bool))); connect(&m_viewer, SIGNAL(recordingCancelled()), this, SLOT(recordingCancelled())); connect(&m_toolBar, SIGNAL(fullScreen()), this, SLOT(fullScreen())); connect(&m_toolBar, SIGNAL(showHelp()), this, SLOT(showHelp())); connect(&m_toolBar, SIGNAL(viewerModeChanged(Viewer::Mode const)), &m_viewer, SLOT(setActiveViewerMode(Viewer::Mode const))); connect(&m_toolBar, SIGNAL(buildElementSelected(unsigned int)), &m_viewer, SLOT(setDefaultBuildElement(unsigned int))); connect(&m_toolBar, SIGNAL(buildFragmentSelected(QString const&, Viewer::Mode const)), &m_viewer, SLOT(setDefaultBuildFragment(QString const&, Viewer::Mode const))); // ViewerModel connect(&m_viewerModel, SIGNAL(updated()), &m_viewer, SLOT(updateGL())); connect(&m_viewerView, SIGNAL(doubleClicked(QModelIndex const&)), &m_viewerModel, SLOT(itemDoubleClicked(QModelIndex const&))); connect(&m_viewerView, SIGNAL(expanded(QModelIndex const&)), &m_viewerModel, SLOT(itemExpanded(QModelIndex const&))); connect(&m_viewerModel, SIGNAL(sceneRadiusChanged(double const)), &m_viewer, SLOT(setSceneRadius(double const))); connect(&m_viewerModel, SIGNAL(changeActiveViewerMode(Viewer::Mode const)), &m_viewer, SLOT(setActiveViewerMode(Viewer::Mode const))); connect(&m_viewerModel, SIGNAL(displayMessage(QString const&)), &m_viewer, SLOT(displayMessage(QString const&))); connect(&m_viewerModel, SIGNAL(postCommand(QUndoCommand*)), this, SLOT(addCommand(QUndoCommand*))); connect(&m_viewerModel, SIGNAL(foregroundColorChanged(QColor const&)), &m_viewer, SLOT(setForegroundColor(QColor const&))); connect(&(ProcessMonitor::instance()), SIGNAL(resultsAvailable(JobInfo*)), &m_viewerModel, SLOT(openCalculationResults(JobInfo*))); // Viewer connect(&m_viewer, SIGNAL(enableUpdate(bool const)), &m_viewerModel, SLOT(enableUpdate(bool const))); connect(&m_viewerModel, SIGNAL(pushAnimators(AnimatorList const&)), &m_viewer, SLOT(pushAnimators(AnimatorList const&))); connect(&m_viewerModel, SIGNAL(popAnimators(AnimatorList const&)), &m_viewer, SLOT(popAnimators(AnimatorList const&))); connect(&m_viewer, SIGNAL(postCommand(QUndoCommand*)), this, SLOT(addCommand(QUndoCommand*))); connect(&m_viewer, SIGNAL(openFileFromDrop(QString const&)), this, SLOT(openFile(QString const&))); connect(&m_viewer, SIGNAL(activeViewerModeChanged(Viewer::Mode const)), &m_toolBar, SLOT(setToolBarMode(Viewer::Mode const))); connect(&m_viewer, SIGNAL(escapeFullScreen()), this, SLOT(fullScreen())); connect(&m_viewer, SIGNAL(animationStep()), &m_viewerModel, SLOT(reperceiveBondsForAnimation())); // Selection connect(&m_viewerSelectionModel, SIGNAL(selectionChanged(QItemSelection const&, QItemSelection const&)), &m_viewerModel, SLOT(selectionChanged(QItemSelection const&, QItemSelection const&)) ); connect(&m_viewerModel, SIGNAL(selectionChanged(QItemSelection const&, QItemSelectionModel::SelectionFlags)), &m_viewerSelectionModel, SLOT(select(QItemSelection const&, QItemSelectionModel::SelectionFlags)) ); connect(&m_viewerModel, SIGNAL(clearSelection()), &m_viewerSelectionModel, SLOT(clearSelection())); connect(&m_viewer, SIGNAL(clearSelection()), &m_viewerSelectionModel, SLOT(clearSelection())); connect(&m_viewer, SIGNAL(select(QModelIndex const&, QItemSelectionModel::SelectionFlags)), &m_viewerSelectionModel, SLOT(select(QModelIndex const&, QItemSelectionModel::SelectionFlags))); connect(&m_viewerModel, SIGNAL(select(QModelIndex const&, QItemSelectionModel::SelectionFlags)), &m_viewerSelectionModel, SLOT(select(QModelIndex const&, QItemSelectionModel::SelectionFlags))); }
KisSpacingInformation KisDuplicateOp::paintAt(const KisPaintInformation& info) { if (!painter()->device()) return 1.0; KisBrushSP brush = m_brush; if (!brush) return 1.0; if (!brush->canPaintFor(info)) return 1.0; if (!m_duplicateStartIsSet) { m_duplicateStartIsSet = true; m_duplicateStart = info.pos(); } KisPaintDeviceSP realSourceDevice = settings->node()->paintDevice(); qreal scale = m_sizeOption.apply(info); if (checkSizeTooSmall(scale)) return KisSpacingInformation(); QPointF hotSpot = brush->hotSpot(scale, scale, 0, info); QPointF pt = info.pos() - hotSpot; setCurrentScale(scale); // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x, y; qreal xFraction, yFraction; // will not be used splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); QPoint srcPoint; if(m_moveSourcePoint) { srcPoint = QPoint(x - static_cast<qint32>(settings->offset().x()), y - static_cast<qint32>(settings->offset().y())); } else { srcPoint = QPoint(static_cast<qint32>(settings->position().x() - hotSpot.x()), static_cast<qint32>(settings->position().y() - hotSpot.y())); } qint32 sw = brush->maskWidth(scale, 0.0, xFraction, yFraction, info); qint32 sh = brush->maskHeight(scale, 0.0, xFraction, yFraction, info); if (srcPoint.x() < 0) srcPoint.setX(0); if (srcPoint.y() < 0) srcPoint.setY(0); // Perspective correction ? KisImageWSP image = settings->m_image; if (m_perspectiveCorrection && image && image->perspectiveGrid()->countSubGrids() == 1) { Matrix3qreal startM = Matrix3qreal::Identity(); Matrix3qreal endM = Matrix3qreal::Identity(); // First look for the grid corresponding to the start point KisSubPerspectiveGrid* subGridStart = *image->perspectiveGrid()->begin(); QRect r = QRect(0, 0, image->width(), image->height()); #if 1 if (subGridStart) { startM = KisPerspectiveMath::computeMatrixTransfoFromPerspective(r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight()); } #endif #if 1 // Second look for the grid corresponding to the end point KisSubPerspectiveGrid* subGridEnd = *image->perspectiveGrid()->begin(); if (subGridEnd) { endM = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r); } #endif // Compute the translation in the perspective transformation space: QPointF positionStartPaintingT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart)); QPointF duplicateStartPositionT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart) - QPointF(settings->offset())); QPointF translat = duplicateStartPositionT - positionStartPaintingT; KisRectIteratorSP dstIt = m_srcdev->createRectIteratorNG(0, 0, sw, sh); KisRandomSubAccessorSP srcAcc = realSourceDevice->createRandomSubAccessor(); //Action do { QPointF p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, QPointF(dstIt->x() + x, dstIt->y() + y)) + translat); srcAcc->moveTo(p); srcAcc->sampledOldRawData(dstIt->rawData()); } while (dstIt->nextPixel()); } else { KisPainter copyPainter(m_srcdev); copyPainter.setCompositeOp(COMPOSITE_COPY); copyPainter.bitBltOldData(0, 0, realSourceDevice, srcPoint.x(), srcPoint.y(), sw, sh); copyPainter.end(); } // heal ? if (m_healing) { quint16 srcData[4]; quint16 tmpData[4]; qreal* matrix = new qreal[ 3 * sw * sh ]; // First divide const KoColorSpace* srcCs = realSourceDevice->colorSpace(); const KoColorSpace* tmpCs = m_srcdev->colorSpace(); KisHLineConstIteratorSP srcIt = realSourceDevice->createHLineConstIteratorNG(x, y, sw); KisHLineIteratorSP tmpIt = m_srcdev->createHLineIteratorNG(0, 0, sw); qreal* matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; i < sw; i++) { srcCs->toLabA16(srcIt->oldRawData(), (quint8*)srcData, 1); tmpCs->toLabA16(tmpIt->rawData(), (quint8*)tmpData, 1); // Division for (int k = 0; k < 3; k++) { matrixIt[k] = srcData[k] / (qreal)qMax((int)tmpData [k], 1); } srcIt->nextPixel(); tmpIt->nextPixel(); matrixIt += 3; } srcIt->nextRow(); tmpIt->nextRow(); } // Minimize energy { int iter = 0; qreal err; qreal* solution = new qreal [ 3 * sw * sh ]; do { err = minimizeEnergy(&matrix[0], &solution[0], sw, sh); // swap pointers qreal *tmp = matrix; matrix = solution; solution = tmp; iter++; } while (err > 0.00001 && iter < 100); delete [] solution; } // Finaly multiply KisHLineIteratorSP srcIt2 = realSourceDevice->createHLineIteratorNG(x, y, sw); KisHLineIteratorSP tmpIt2 = m_srcdev->createHLineIteratorNG(0, 0, sw); matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; i < sw; i++) { srcCs->toLabA16(srcIt2->rawData(), (quint8*)srcData, 1); tmpCs->toLabA16(tmpIt2->rawData(), (quint8*)tmpData, 1); // Multiplication for (int k = 0; k < 3; k++) { tmpData[k] = (int)CLAMP(matrixIt[k] * qMax((int) tmpData[k], 1), 0, 65535); } tmpCs->fromLabA16((quint8*)tmpData, tmpIt2->rawData(), 1); srcIt2->nextPixel(); tmpIt2->nextPixel(); matrixIt += 3; } srcIt2->nextRow(); tmpIt2->nextRow(); } delete [] matrix; } static const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8(); static KoColor color(Qt::black, cs); KisFixedPaintDeviceSP dab = m_dabCache->fetchDab(cs, color, scale, scale, 0.0, info); QRect dstRect = QRect(x, y, dab->bounds().width(), dab->bounds().height()); if (dstRect.isEmpty()) return 1.0; painter()->bitBltWithFixedSelection(dstRect.x(), dstRect.y(), m_srcdev, dab, dstRect.width(), dstRect.height()); painter()->renderMirrorMaskSafe(dstRect, m_srcdev, 0, 0, dab, !m_dabCache->needSeparateOriginal()); return effectiveSpacing(dstRect.width(), dstRect.height()); }