From 685d0ee84bfa53b414be4d72627eca5600c6f954 Mon Sep 17 00:00:00 2001 From: Joshua-cla <75090936+Joshua-cla@users.noreply.github.com> Date: Tue, 20 Dec 2022 18:54:31 +0100 Subject: [PATCH] Snap to grid (#3016) * Add widget to side panel * Draw grid * snap tool to grid * Update french translation * Format code with clang-format Co-authored-by: joshua --- data/translations/Internationalization_fr.ts | 741 +++++++++---------- src/widgets/capture/capturewidget.cpp | 65 +- src/widgets/capture/capturewidget.h | 8 + src/widgets/panel/sidepanelwidget.cpp | 22 + src/widgets/panel/sidepanelwidget.h | 5 + 5 files changed, 455 insertions(+), 386 deletions(-) diff --git a/data/translations/Internationalization_fr.ts b/data/translations/Internationalization_fr.ts index 6b88ecb6..750a1a33 100644 --- a/data/translations/Internationalization_fr.ts +++ b/data/translations/Internationalization_fr.ts @@ -4,24 +4,20 @@ AbstractWidgetList - Add New - Ajouter nouveau + Ajouter nouveau - Move Up - Déplacer vers le haut + Déplacer vers le haut - Move Down - Déplacer vers le bas + Déplacer vers le bas - Remove - Enlever + Enlever @@ -53,33 +49,33 @@ AppLauncherWidget - + Open With Ouvrir avec - + Launch in terminal Lancer dans le terminal - + Keep open after selection Maintenir ouvert après la sélection - - + + Error Erreur - + Unable to write in Impossible d'écrire dessus - + Unable to launch in terminal. Impossible de lancer dans le terminal. @@ -141,66 +137,42 @@ - - - seconds secondes - - - Take new screenshot Prendre une nouvelle capture - - - Area: Zone : - - - Capture Launcher Lanceur de capture - - - TextLabel Étiquette de texte - - - Capture Mode Mode de capture - - - Delay: Retard : - - - WxH+x+y WxH+x+y @@ -208,62 +180,62 @@ CaptureWidget - + Unable to capture screen Impossible de capturer l'écran - + Mouse Souris - + Select screenshot area Sélectionner la zone de capture d'écran - + Mouse Wheel Molette de la souris - + Change tool size Changer la taille de l'outil - + Right Click Clic droit - + Show color picker Afficher la palette des couleurs - + Open side panel Ouvrir le panneau latéral - + Esc Échap - + Exit Quitter - + Flameshot has lost focus. Keyboard shortcuts won't work until you click somewhere. Flameshot a perdu focus. Les raccourcis clavier ne fonctionneront pas sans avoir cliquer quelque part. - + Configuration error resolved. Launch `flameshot gui` again to apply it. Erreur de configuration résolue. Lancer `flameshot gui` à nouveau. @@ -280,7 +252,7 @@ Utiliser la molette de la souris pour changer l'épaisseur de l'outil. Appuyer sur Espace pour ouvrir le panneau latéral. - + Tool Settings Réglages des outils @@ -314,76 +286,40 @@ Appuyer sur Espace pour ouvrir le panneau latéral. ColorDialog - - - - Select Color - Sélectionner Couleur + Sélectionner Couleur - - - - Saturation - Saturation + Saturation - - - - Hue - Teinte + Teinte - - - - Hex - Hex + Hex - - - - Blue - Bleu + Bleu - - - - Value - Valeur + Valeur - - - - Green - Vert + Vert - - - - Alpha - Alpha + Alpha - - - - Red - Rouge + Rouge @@ -517,45 +453,45 @@ Appuyer sur Espace pour ouvrir le panneau latéral. ConfigHandler - + Unrecognized setting: '%1' Préférence inconnue : '%1' - + Unrecognized shortcut name: '%1'. Nom de raccourcis inconnu : '%1'. - + Shortcut conflict: '%1' and '%2' have the same shortcut: %3 Conflit de raccourcis : '%1' et '%2' ont le même raccourci : %3 - + Bad value in '%1'. Expected: %2 Mauvaise valeur dans '%1'. Attendu : %2 - + You have successfully resolved the configuration error. Vous avez résolu l'erreur de configuration. - + The configuration contains an error. Open configuration to resolve. Cette configuration contient une erreur. Ouvrez la configuration pour la résoudre. - + Bad config key '%1' in ConfigHandler. Please report this as a bug. Bad config key '%1' in ConfigHandler. Please report this as a bug. @@ -806,17 +742,17 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Flameshot - + Error Erreur - + Unable to close active modal widgets Impossible de fermer les widgets modales actifs - + URL copied to clipboard. URL copied to clipboard. @@ -824,22 +760,22 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. FlameshotDaemon - + New version %1 is available La nouvelle version %1 est disponible - + You have the latest version Vous avez la dernière version - + Failed to get information about the latest version. Impossible d'obtenir des informations sur la dernière version. - + Unable to connect via DBus Impossible de se connecter via DBus @@ -926,47 +862,47 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. GeneralConf - - + + Import Importer - - - + + + Error Erreur - + Unable to read file. Impossible de lire le fichier. - - + + Unable to write file. Impossible d'écrire le fichier. - + Save File Sauvegarder le fichier - + Confirm Reset Confirmer la réinitialisation - + Are you sure you want to reset the configuration? Êtes-vous sûr(e) de vouloir réinitialiser la configuration ? - + Show help message Afficher le message d'aide @@ -975,7 +911,7 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Afficher le message d'aide au lancement du mode capture. - + Show the side panel button Afficher le bouton du panneau principal @@ -984,12 +920,12 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Afficher le bouton de basculement du panneau latéral en mode capture. - + Show desktop notifications Afficher les notifications du bureau - + Show tray icon Afficher les icônes de la barre d'état @@ -998,62 +934,59 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Afficher l'icône dans la barre de tâches - + Confirmation required to delete screenshot from the latest uploads Confirmation requise pour supprimer la capture d'écran des derniers téléchargements - + Configuration File Fichier de configuration - + Export Exporter - + Reset Réinitialiser - + Automatic check for updates Contrôle automatique des mises à jour - + Allow multiple flameshot GUI instances simultaneously Autoriser plusieurs instances simultanées de flameshot GUI - - Automatically close daemon when it is not needed - Clore automatiquement le démon lorsqu'il n'est plus nécessaire + Clore automatiquement le démon lorsqu'il n'est plus nécessaire - Launch at startup - Lancer au démarrage + Lancer au démarrage Launch Flameshot Démarrer Flameshot - + Show welcome message on launch Afficher le message de bienvenue au démarrage - + Use large predefined color palette Utiliser une large palette de couleurs prédéfinies - + Copy URL after upload Copier l'URL après le téléchargement @@ -1062,7 +995,7 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Copier l'URL et fermer la fenêtre après le téléchargement - + Save image after copy Enregistrer l'image après la copie @@ -1071,182 +1004,263 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Enregistrer le fichier image après l'avoir copiée - + Show the help message at the beginning in the capture mode Afficher un message d'aide au début du mode de capture - + Use last region Use last region - + Uses the last region as the default selection for the next screenshot Uses the last region as the default selection for the next screenshot - + Show the side panel toggle button in the capture mode Afficher le bouton pour activer le panneau du côté en mode capture - + Enable desktop notifications Activer les notifications sur le bureau - + Show icon in the system tray Afficher une icône dans la barre de tâches - + Ask for confirmation to delete screenshot from the latest uploads Demander la confirmation avant de supprimer les captures d'écran précédemment envoyées - + Check for updates automatically Vérifier automatiquement les mises à jour - + This allows you to take screenshots of Flameshot itself for example Cela permet par exemple de prendre des captures d'écran de Flameshot - Launch Flameshot daemon when computer is booted - Lancer le démon de Flameshot quand l'ordinateur démarre + Lancer le démon de Flameshot quand l'ordinateur démarre - + Show the welcome message box in the middle of the screen while taking a screenshot Afficher la boite de message de bienvenue à milieu de l'écran à la prise d'une capture d'écran - + Use a large predefined color palette Utiliser une vaste palette de couleurs prédéfinie - + Copy on double click Copy on double click - Enable Copy on Double Click - Enable Copy on Double Click + Enable Copy on Double Click - Copy URL and close window after uploading was successful - Copier l'URL puis fermer la fenêtre au succès de l'envoi + Copier l'URL puis fermer la fenêtre au succès de l'envoi - + + Automatically unload from memory when it is not needed + + + + + Automatically close daemon (background process) when it is not needed + + + + + Launch in background at startup + + + + + Launch Flameshot daemon (background process) when computer is booted + + + + + Enable Copy to clipboard on Double Click + + + + + Copy URL after uploading was successful + + + + After copying the screenshot, save it to a file as well Après la copie de la capture d'écran, l'enregistrée aussi dans un fichier - + Save Path Enregistrer le chemin - + Change... modifier... - + Use fixed path for screenshots to save Utiliser un emplacement spécifique pour l'enregistrement des captures d'écran - + Preferred save file extension: Extension de fichier préférée pour l'enregistrement : - + Latest Uploads Max Size Derniers téléchargements, taille maximale - + Imgur Application Client ID Imgur Application Client ID - + Undo limit Annuler la limite - - + Use JPG format for clipboard (PNG default) Utiliser le format JPG pour le presse-papiers (PNG par défaut) - + + Use lossy JPG format for clipboard (lossless PNG default) + + + + Copy file path after save Copier le chemin du fichier après l'enregistrement - + Copy the file path to clipboard after the file is saved Copier le chemin vers le fichier dans le presse-papier quand il a été enregistré - + Anti-aliasing image when zoom the pinned image Anticrénelage de l'image lors du zoom de l'image épinglée - + After zooming the pinned image, should the image get smoothened or stay pixelated Après avoir zoomé sur l'image épinglée, l'image doit-elle être lissée ou rester pixelisée ? - - + + Upload image without confirmation Uploader image sans confirmation - + Choose a Folder Choisir un dossier - + Unable to write to directory. Impossible d'écrire dans le répertoire. - + Show magnifier Afficher la loupe - + Enable a magnifier while selecting the screenshot area Activer la loupe lors de la sélection de l'aire de capture d'écran - + Square shaped magnifier Loupe carrée - + Make the magnifier to be square-shaped Affiche la loupe avec une forme carrée + + + Milliseconds before geometry display hides; 0 means do not hide + + + + + Set geometry display timeout (ms) + + + + + Selection Geometry Display + + + + + Display Location + + + + + None + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + Center + + HistoryWidget @@ -1352,57 +1366,57 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Upload image - + Uploading Image Envoi de l'image - + Copy URL Copier l'URL - + Open URL Ouvrir l'URL - + Delete image Effacer l'image - + Image to Clipboard. Copier l'image dans le presse-papiers. - + Save image Enregistrer l'image - + Unable to open the URL. Impossible d'ouvrir l'URL. - + URL copied to clipboard. URL copiée dans le presse-papiers. - + Screenshot copied to clipboard. Capture d'écran copiée dans le presse-papier. - + Unable to save the screenshot to disk. Impossible d'enregistrer la capture d'écran sur le disque. - + Screenshot saved. Capture d'écran enregistrée. @@ -1475,65 +1489,41 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. InfoWindow - - - About À propos - - - Icon Icône - - - License Licence - - - GPLv3+ GPLv3+ - - - Version Version - - - Flameshot v Flameshot v - - - OS Info Infos SE - - - Copy Info Copier infos @@ -1683,20 +1673,45 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. PinWidget - + Context menu Context menu - + Copy to clipboard Copier dans le presse-papier - + Save to file Save to file + + + Rotate Right + Pivoter à droite + + + + Rotate Left + Pivoter à gauche + + + + Increase Opacity + Augmenter l'opacité + + + + Decrease Opacity + Diminuer l'opacité + + + + Close + Fermer + PixelateTool @@ -1714,14 +1729,12 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. QHotkey - Failed to register %1. Error: %2 - Échec de l'enregistrement %1. Erreur : %2 + Échec de l'enregistrement %1. Erreur : %2 - Failed to unregister %1. Error: %2 - Échec de la désinscription %1. Erreur : %2 + Échec de la désinscription %1. Erreur : %2 @@ -1781,42 +1794,42 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Capture enregistrée et copiée dans le presse-papier - + Unable to connect via DBus Impossible de se connecter via DBus - + Powerful yet simple to use screenshot software. Logiciel de capture d'écran puissant mais simple à utiliser. - + See Voir - + Capture the entire desktop. Capturer l'écran entier. - + Open the capture launcher. Ouvrir le menu de capture. - + Start a manual capture in GUI mode. Démarre une capture manuelle en mode graphique. - + Configure Configurer - + Capture a single screen. Capturer un écran seul. @@ -1825,107 +1838,107 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Chemin où la capture sera enregistrée - + Existing directory or new file to save to Dossier existant ou nouveau fichier à sauvegarder dans - + Save the capture to the clipboard Enregistrer la capture dans le presse-papier - + Pin the capture to the screen Pin the capture to the screen - + Upload screenshot Upload screenshot - + Delay time in milliseconds Délai en millisecondes - + Repeat screenshot with previously selected region Repeat screenshot with previously selected region - + Screenshot region to select Zone de capture d'écran à sélectionner - + Set the filename pattern Définir le modèle de nom de fichier - + Accept capture as soon as a selection is made Accepter la capture d'écran dès qu'une sélection est faite - + Enable or disable the trayicon Activer ou désactiver l'icone de la barre des tâches - + Enable or disable run at startup Activer ou désactiver le lancement au démarrage - + Check the configuration for errors Vérifiez l'absence d'erreurs dans la configuration - + Show the help message in the capture mode Afficher le message d'aide dans le mode capture - + Define the main UI color Définir la couleur de base de l'interface - + Define the contrast UI color Définir le contraste de l'interface utilisateur - + Print raw PNG capture Print raw PNG capture - + Print geometry of the selection in the format WxH+X+Y. Does nothing if raw is specified Print geometry of the selection in the format WxH+X+Y. Does nothing if raw is specified - + Define the screen to capture (starting from 0) Define the screen to capture (starting from 0) - + Invalid delay, it must be a number greater than 0 Délai invalide, il doit être supérieur à 0 - + Invalid region, use 'WxH+X+Y' or 'all' or 'screen0/screen1/...'. Invalid region, use 'WxH+X+Y' or 'all' or 'screen0/screen1/...'. - + Invalid path, must be an existing directory or a new file in an existing directory Invalid path, must be an existing directory or a new file in an existing directory @@ -1934,17 +1947,17 @@ Veuillez résoudre ce problème manuellement depuis le fichier de configuration. Définir l'écran à capturer - + default: screen containing the cursor Par défaut : Ecran contenant le curseur - + Screen number Numéro d'écran - + Invalid color, this flag supports the following formats: - #RGB (each of R, G, and B is a single hex digit) - #RRGGBB @@ -1965,7 +1978,7 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Délai non valable, il doit être plus élevé que 0 - + Invalid screen number, it must be non negative Numéro d'écran non-valable, il ne doit pas être négatif @@ -1974,7 +1987,7 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Chemin non-valable, il doit indiquer un chemin existant du système - + Invalid value, it must be defined as 'true' or 'false' Valeur non-valable, elle doit être définie comme 'true' ou 'false' @@ -1989,12 +2002,12 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Impossible d'écrire par dessus - + Requested screen exceeds screen count Requested screen exceeds screen count - + Full screen screenshot pinned to screen Full screen screenshot pinned to screen @@ -2082,27 +2095,27 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Effacer l'outil actuel - + Quit capture Quitter la capture d'écran - + Screenshot history Historique des captures d'écran - + Capture screen Capturer l'écran - + Show color picker Afficher la palette de couleurs - + Change the tool's size Change the tool's size @@ -2157,17 +2170,21 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< ScreenGrabber - Unable to detect desktop environment (GNOME? KDE? Sway? ...) - Impossible de détecter l’environnement de bureau (GNOME ? KDE ? Sway ? ...) + Impossible de détecter l’environnement de bureau (GNOME ? KDE ? Sway ? ...) - + + Unable to detect desktop environment (GNOME? KDE? Qile? Sway? ...) + Impossible de détecter l'environnement de bureau (GNOME ? KDE ? Qile ? Sway ?...) + + + Hint: try setting the XDG_CURRENT_DESKTOP environment variable. Conseil : essayez de définir la variable d’environnement XDG_CURRENT_DESKTOP. - + Unable to capture screen Impossible de capturer l'écran @@ -2266,47 +2283,67 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Redimensionner la sélection de 1px vers le bas - + + Symmetrically decrease width by 2px + Diminuer symétriquement la largeur de 2px + + + + Symmetrically increase width by 2px + Augmenter symétriquement la largeur de 2px + + + + Symmetrically increase height by 2px + Augmenter symétriquement la hauteur de 2px + + + + Symmetrically decrease height by 2px + Diminuer symétriquement la hauteur de 2px + + + Select entire screen Sélectionner l'écran en entier - + Move selection left 1px Déplacer la sélection de 1px vers la gauche - + Move selection right 1px Déplacer la sélection de 1px vers la droite - + Move selection up 1px Déplacer la sélection de 1px vers le haut - + Move selection down 1px Déplacer la sélection de 1px vers le bas - + Commit text in text area Insérer du texte dans la zone de texte - + Delete current tool Effacer l'outil actuel - + Capture screen Capturer l'écran - + Screenshot history Historique des captures d'écran @@ -2322,20 +2359,25 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< Appuyer sur Échap pour annuler - + Active tool size: Taille de l’outil actif : - + Active Color: Couleur active : - + Grab Color Saisir la couleur + + + Display grid + Afficher la grille + Active thickness: Épaisseur sélectionnée: @@ -2370,14 +2412,12 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< SizeIndicatorTool - Selection Size Indicator - Indicateur de la taille de la sélection + Indicateur de la taille de la sélection - Show X and Y dimensions of the selection - Show X and Y dimensions of the selection + Show X and Y dimensions of the selection Show the dimensions of the selection (X Y) @@ -2554,42 +2594,42 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< TrayIcon - + &Take Screenshot &Capturer l'écran - + &Open Launcher &Ouvrir le lanceur - + &Configuration &Configuration - + &About &À propos - + Check for updates Vérifier les mises à jour - + New version %1 is available La nouvelle version %1 est disponible - + &Quit &Quitter - + &Latest Uploads &Derniers téléversements @@ -2671,9 +2711,6 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< UploadHistory - - - Upload History Historique d'envois @@ -2687,33 +2724,21 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< UploadLineItem - - - Form Formulaire - - - TextLabel étiquette de texte - - - Copy URL Copier l'URL - - - Open In Browser Ouvrir dans le navigateur @@ -2772,176 +2797,124 @@ Vous devrez probablement remplacer le signe '#' par '\#FFF'< color_widgets::ColorDialog - Pick - Pick + Pick color_widgets::ColorPalette - Unnamed - Unnamed + Unnamed color_widgets::ColorPaletteModel - Unnamed - Unnamed + Unnamed - %1 (%2 colors) - %1 (%2 colors) + %1 (%2 colors) color_widgets::ColorPaletteWidget - - - - Open a new palette from file - Open a new palette from file + Open a new palette from file - - - - Create a new palette - Create a new palette + Create a new palette - - - - Duplicate the current palette - Duplicate the current palette + Duplicate the current palette - - - - Delete the current palette - Delete the current palette + Delete the current palette - - - - Revert changes to the current palette - Revert changes to the current palette + Revert changes to the current palette - - - - Save changes to the current palette - Save changes to the current palette + Save changes to the current palette - - - - Add a color to the palette - Add a color to the palette + Add a color to the palette - - - - Remove the selected color from the palette - Remove the selected color from the palette + Remove the selected color from the palette - - New Palette - New Palette + New Palette - - Name - Name + Name - GIMP Palettes (*.gpl) - GIMP Palettes (*.gpl) + GIMP Palettes (*.gpl) - Palette Image (%1) - Palette Image (%1) + Palette Image (%1) - All Files (*) - All Files (*) + All Files (*) - - Open Palette - Open Palette + Open Palette - Failed to load the palette file %1 - Failed to load the palette file + Failed to load the palette file %1 color_widgets::GradientEditor - Add Color - Add Color + Add Color - Remove Color - Remove Color + Remove Color - Edit Color... - Edit Color... + Edit Color... color_widgets::GradientListModel - %1 (%2 colors) - %1 (%2 colors) + %1 (%2 colors) color_widgets::Swatch - Clear Color - Clear Color + Clear Color - %1 (%2) - %1 (%2) + %1 (%2) diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index 796bdc55..c12f03b0 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -393,6 +393,18 @@ void CaptureWidget::xywhTick() repaint(); } +void CaptureWidget::onDisplayGridChanged(bool display) +{ + m_displayGrid = display; + repaint(); +} + +void CaptureWidget::onGridSizeChanged(int size) +{ + m_gridSize = size; + repaint(); +} + void CaptureWidget::showxywh(bool show) { int timeout = @@ -605,6 +617,31 @@ void CaptureWidget::paintEvent(QPaintEvent* paintEvent) xy); } + if (m_displayGrid) { + painter.save(); + QColor uicolor = ConfigHandler().uiColor(); + uicolor.setAlpha(100); + painter.setPen(uicolor); + painter.setBrush(QBrush(uicolor)); + + auto topLeft = mapToGlobal(m_context.selection.topLeft()); + topLeft.rx() -= topLeft.x() % m_gridSize; + topLeft.ry() -= topLeft.y() % m_gridSize; + topLeft = mapFromGlobal(topLeft); + + const auto scale{ m_context.screenshot.devicePixelRatio() }; + const auto step{ m_gridSize * scale }; + const auto radius{ 1 * scale }; + + for (int y = topLeft.y(); y < m_context.selection.bottom(); y += step) { + for (int x = topLeft.x(); x < m_context.selection.right(); + x += step) { + painter.drawEllipse(x, y, radius, radius); + } + } + painter.restore(); + } + if (m_activeTool && m_mouseIsClicked) { m_activeTool->process(painter, m_context.screenshot); } else if (m_previewEnabled && activeButtonTool() && @@ -671,7 +708,8 @@ bool CaptureWidget::startDrawObjectTool(const QPoint& pos) &CaptureTool::requestAction, this, &CaptureWidget::handleToolSignal); - m_context.mousePos = pos; + + m_context.mousePos = m_displayGrid ? snapToGrid(pos) : pos; m_activeTool->drawStart(m_context); // TODO this is the wrong place to do this @@ -847,7 +885,8 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e) if (m_adjustmentButtonPressed) { m_activeTool->drawMoveWithAdjustment(e->pos()); } else { - m_activeTool->drawMove(e->pos()); + m_activeTool->drawMove(m_displayGrid ? snapToGrid(e->pos()) + : e->pos()); } // update drawing object updateTool(m_activeTool); @@ -1126,6 +1165,14 @@ void CaptureWidget::initPanel() &SidePanelWidget::togglePanel, m_panel, &UtilityPanel::toggle); + connect(m_sidePanel, + &SidePanelWidget::displayGridChanged, + this, + &CaptureWidget::onDisplayGridChanged); + connect(m_sidePanel, + &SidePanelWidget::gridSizeChanged, + this, + &CaptureWidget::onGridSizeChanged); // TODO replace with a CaptureWidget signal emit m_sidePanel->colorChanged(m_context.color); emit toolSizeChanged(m_context.toolSize); @@ -1721,6 +1768,20 @@ CaptureTool::Type CaptureWidget::activeButtonToolType() const return activeTool->type(); } +QPoint CaptureWidget::snapToGrid(const QPoint& point) const +{ + QPoint snapPoint = mapToGlobal(point); + + const auto scale{ m_context.screenshot.devicePixelRatio() }; + + snapPoint.setX((qRound(snapPoint.x() / double(m_gridSize)) * m_gridSize) * + scale); + snapPoint.setY((qRound(snapPoint.y() / double(m_gridSize)) * m_gridSize) * + scale); + + return mapFromGlobal(snapPoint); +} + QPointer CaptureWidget::activeToolObject() { return m_captureToolObjects.at(m_panel->activeLayerIndex()); diff --git a/src/widgets/capture/capturewidget.h b/src/widgets/capture/capturewidget.h index ece0047c..d728174a 100644 --- a/src/widgets/capture/capturewidget.h +++ b/src/widgets/capture/capturewidget.h @@ -87,6 +87,8 @@ private slots: void onMoveCaptureToolDown(int captureToolIndex); void selectAll(); void xywhTick(); + void onDisplayGridChanged(bool display); + void onGridSizeChanged(int size); public: void removeToolObject(int index = -1); @@ -147,6 +149,8 @@ private: CaptureTool* activeButtonTool() const; CaptureTool::Type activeButtonToolType() const; + QPoint snapToGrid(const QPoint& point) const; + //////////////////////////////////////// // Class members @@ -214,4 +218,8 @@ private: // For start moving after more than X offset QPoint m_startMovePos; bool m_startMove; + + // Grid + bool m_displayGrid{ false }; + int m_gridSize{ 10 }; }; diff --git a/src/widgets/panel/sidepanelwidget.cpp b/src/widgets/panel/sidepanelwidget.cpp index 6764e3cc..2d156a48 100644 --- a/src/widgets/panel/sidepanelwidget.cpp +++ b/src/widgets/panel/sidepanelwidget.cpp @@ -8,6 +8,7 @@ #include "src/utils/pathinfo.h" #include "utilitypanel.h" #include +#include #include #include #include @@ -80,6 +81,18 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent) m_layout->addWidget(m_colorWheel); m_layout->addWidget(m_colorHex); + QHBoxLayout* gridHBoxLayout = new QHBoxLayout(this); + m_gridCheck = new QCheckBox(tr("Display grid"), this); + m_gridSizeSpin = new QSpinBox(this); + m_gridSizeSpin->setRange(5, 50); + m_gridSizeSpin->setSingleStep(5); + m_gridSizeSpin->setValue(10); + m_gridSizeSpin->setDisabled(true); + m_gridSizeSpin->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + gridHBoxLayout->addWidget(m_gridCheck); + gridHBoxLayout->addWidget(m_gridSizeSpin); + m_layout->addLayout(gridHBoxLayout); + // tool size sigslots connect(m_toolSizeSpin, static_cast(&QSpinBox::valueChanged), @@ -112,6 +125,15 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent) &color_widgets::ColorWheel::colorSelected, this, &SidePanelWidget::colorChanged); + // Grid feature + connect(m_gridCheck, &QCheckBox::clicked, this, [=](bool b) { + this->m_gridSizeSpin->setEnabled(b); + emit this->displayGridChanged(b); + }); + connect(m_gridSizeSpin, + qOverload(&QSpinBox::valueChanged), + this, + &SidePanelWidget::gridSizeChanged); } void SidePanelWidget::onColorChanged(const QColor& color) diff --git a/src/widgets/panel/sidepanelwidget.h b/src/widgets/panel/sidepanelwidget.h index 770ad839..198607ae 100644 --- a/src/widgets/panel/sidepanelwidget.h +++ b/src/widgets/panel/sidepanelwidget.h @@ -14,6 +14,7 @@ class QLineEdit; class ColorGrabWidget; class QColorPickingEventFilter; class QSlider; +class QCheckBox; constexpr int maxToolSize = 50; constexpr int minSliderWidth = 100; @@ -31,6 +32,8 @@ signals: void colorChanged(const QColor& color); void toolSizeChanged(int size); void togglePanel(); + void displayGridChanged(bool display); + void gridSizeChanged(int size); public slots: void onToolSizeChanged(int tool); @@ -61,4 +64,6 @@ private: QSpinBox* m_toolSizeSpin; QSlider* m_toolSizeSlider; int m_toolSize{}; + QCheckBox* m_gridCheck{ nullptr }; + QSpinBox* m_gridSizeSpin{ nullptr }; };