diff --git a/src/musredit_qt6/musredit/PReplaceDialog.cpp b/src/musredit_qt6/musredit/PReplaceDialog.cpp index fa89c089a..5b49bdb63 100644 --- a/src/musredit_qt6/musredit/PReplaceDialog.cpp +++ b/src/musredit_qt6/musredit/PReplaceDialog.cpp @@ -27,6 +27,19 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +/** + * @file PReplaceDialog.cpp + * @brief Implementation of the find and replace dialog for musredit. + * + * @details Provides the implementation of PReplaceDialog class methods for + * managing find-and-replace operations in the musredit text editor. The + * dialog handles initialization of UI controls from saved parameters, + * validation of user input, and collection of search/replace settings. + * + * @author Andreas Suter + * @date 2009-2025 + */ + #include #include #include @@ -35,12 +48,89 @@ //---------------------------------------------------------------------------------------------------- /** - *

Constructor. + * @brief Constructor - Initializes the find and replace dialog. * - * \param data find/replace data structure - * \param selection if true, find/replace only of the selection - * \param parent pointer to the parent object - * \param f qt windows flag + * @details Sets up the find-and-replace dialog with comprehensive search + * options and replacement controls. The dialog is initialized from existing + * search parameters and configured based on current editor state. + * + * **Initialization Process:** + * + * 1. **Base Class Initialization**: Calls QDialog constructor with parent + * and stores pointer to data structure + * + * 2. **UI Setup**: Loads dialog layout from Qt Designer UI file including: + * - Find text combo box with history + * - Replace text combo box with history + * - Search option checkboxes + * - Replace, Replace All, and Close buttons + * + * 3. **Modal Configuration**: Sets dialog as modal to ensure focused interaction + * + * 4. **Replace Button Validation**: Disables Replace button if find text is + * empty, preventing invalid search operations from being initiated + * + * 5. **Selection State Handling**: If no text is selected in the editor: + * - Unchecks "Selected text only" checkbox + * - Disables the checkbox to prevent invalid configuration + * This provides clear visual feedback about available search scope + * + * 6. **Parameter Loading**: Populates all UI controls from PFindReplaceData: + * - **Find text**: Loaded into combo box item 0 (maintains history) + * - **Replace text**: Loaded into combo box item 0 (maintains history) + * - **Case sensitive**: Checkbox reflects previous setting + * - **Whole words only**: Checkbox reflects previous setting + * - **From cursor**: Checkbox reflects previous setting + * - **Find backwards**: Checkbox reflects previous setting + * - **Prompt on replace**: Checkbox reflects previous setting + * - **Selected text**: Checkbox reflects previous setting (if selection exists) + * + * **State-Based Behavior:** + * + * The dialog adapts its initial state based on editor context: + * - Empty find text → Replace button disabled + * - Non-empty find text → Replace button enabled + * - No selection → Selected text checkbox disabled and unchecked + * - Has selection → Selected text checkbox enabled, state from data + * + * **Combo Box History:** + * The combo boxes use item 0 for the current/default text. Additional items + * (if present) maintain search/replace history, allowing users to quickly + * reuse previous patterns. + * + * @param data Pointer to PFindReplaceData structure containing: + * - Previous find/replace text strings + * - All search option flags + * - Scope settings + * This structure is both read from (initialization) and written + * to (via getData()) during the dialog's lifetime. Must not be + * nullptr. + * + * @param selection Indicates whether text is currently selected in the editor: + * - true: Selected text checkbox is enabled and state loaded + * from data parameter, allowing search within selection + * - false: Selected text checkbox is disabled and unchecked, + * forcing full-document scope + * + * @param parent Pointer to the parent widget (typically the main musredit + * window). The parent relationship provides: + * - Automatic dialog centering over parent + * - Proper z-order (dialog appears on top) + * - Consistent theme and styling + * - Automatic cleanup when parent is destroyed + * + * @note The dialog is created but not displayed by the constructor. The + * caller must invoke exec() to show it modally. + * @note The Replace button's enabled state is managed dynamically through + * the onFindTextAvailable() slot as the user types. + * @note Combo box item 0 is used for current text; additional items could + * provide search history functionality. + * @note The selected text checkbox is handled specially: only checked if + * selection exists AND the data parameter indicates it should be used. + * + * @see PFindReplaceData For the complete parameter structure + * @see getData() Retrieves updated parameters after dialog use + * @see onFindTextAvailable() Manages Replace button state dynamically */ PReplaceDialog::PReplaceDialog(PFindReplaceData *data, const bool selection, QWidget *parent) : QDialog(parent), fData(data) @@ -75,7 +165,80 @@ PReplaceDialog::PReplaceDialog(PFindReplaceData *data, const bool selection, QWi //---------------------------------------------------------------------------------------------------- /** - *

returns the pointer to the find/replace data structure which is updated from the GUI content. + * @brief Retrieves updated find/replace parameters from the dialog. + * + * @details Collects all current settings from the dialog's UI controls and + * updates the internal PFindReplaceData structure. This method provides a + * complete snapshot of the user's search and replace configuration. + * + * **Retrieved Parameters:** + * + * **Text Strings:** + * - **findText**: Current text in the find combo box (what to search for) + * - **replaceText**: Current text in the replace combo box (replacement string) + * + * Both strings are retrieved using currentText(), which returns the text + * visible in the combo box (either from item selection or direct user input). + * + * **Search Options (Boolean Flags):** + * - **caseSensitive**: true = match case exactly, false = ignore case + * - Example: "THEORY" vs "theory" are different when true + * - **wholeWordsOnly**: true = match complete words only, false = allow partial + * - Example: searching "fit" won't match "musrfit" when true + * - **fromCursor**: true = start from current cursor position, false = from beginning + * - Affects where the search operation begins + * - **findBackwards**: true = search upward, false = search downward + * - Controls search direction through the document + * + * **Scope Options:** + * - **selectedText**: true = limit search to selection, false = entire document + * - **Conditional update**: Only updated if checkbox is enabled + * - If checkbox is disabled (no selection), this flag is not modified + * - Prevents setting invalid scope when no selection exists + * + * **Replacement Behavior:** + * - **promptOnReplace**: true = confirm each replacement, false = replace automatically + * - When true, PReplaceConfirmationDialog appears for each match + * - When false, replacements occur immediately (for "Replace All") + * + * **Conditional Logic:** + * + * The selectedText flag has special handling: + * @code + * if (fSelectedText_checkBox->isEnabled()) + * fData->selectedText = fSelectedText_checkBox->isChecked(); + * @endcode + * + * This ensures that when no selection exists (checkbox disabled), the flag + * retains its previous value rather than being forced to false. This prevents + * unintended changes to the data structure for subsequent operations where + * a selection might exist. + * + * **Usage Pattern:** + * + * This method is typically called by the main editor after the dialog is + * accepted: + * 1. User clicks Replace or Replace All button + * 2. Dialog is accepted (exec() returns) + * 3. Calling code invokes getData() + * 4. Updated parameters are used to perform find/replace operation + * 5. Search/replace engine uses settings from returned structure + * + * @return PFindReplaceData* Pointer to the updated parameter structure. + * This is the same pointer passed to the constructor, now with all + * fields updated from current dialog state. The caller owns this + * structure and is responsible for its lifetime management. + * + * @note The returned pointer is never nullptr (it's the constructor parameter). + * @note The selectedText flag is only updated when the checkbox is enabled. + * @note Current combo box text is used, not necessarily a selected item, + * allowing users to enter new search patterns. + * @note This method does not validate the parameters; validation should be + * performed by the calling code if needed. + * + * @see PFindReplaceData For the complete parameter structure definition + * @see PReplaceDialog::PReplaceDialog() Where the data pointer is stored + * @see PReplaceConfirmationDialog Used when promptOnReplace is true */ PFindReplaceData* PReplaceDialog::getData() { @@ -94,7 +257,67 @@ PFindReplaceData* PReplaceDialog::getData() //---------------------------------------------------------------------------------------------------- /** - *

SLOT: called on find text available. + * @brief Slot: Handles changes to the find text input. + * + * @details Called whenever the find text combo box content changes. This slot + * provides dynamic validation and user feedback by managing the Replace button's + * enabled state based on whether valid search text is present. + * + * **Validation Logic:** + * + * The method implements a simple but effective validation rule: + * - **Non-empty find text**: Enable Replace button + * - Allows user to proceed with find/replace operation + * - Indicates that a valid search can be performed + * - **Empty find text**: Disable Replace button + * - Prevents execution of meaningless search operations + * - Provides immediate visual feedback that input is required + * + * **User Experience Benefits:** + * + * 1. **Immediate Feedback**: Button state updates as user types, providing + * instant indication of whether the configuration is valid + * + * 2. **Error Prevention**: Disabling the button prevents users from attempting + * to search for empty strings, which would either produce errors or + * meaningless results + * + * 3. **Clear Affordance**: The disabled state clearly communicates that the + * find text field requires input before proceeding + * + * 4. **Consistent Behavior**: Works in tandem with constructor initialization, + * maintaining consistent button state throughout dialog lifetime + * + * **Signal Connection:** + * + * This slot is typically connected to one of these combo box signals: + * - editTextChanged(QString): Emitted when user types or edits text + * - currentTextChanged(QString): Emitted when displayed text changes + * + * The connection is likely established in the UI file or during dialog setup. + * + * **Implementation Note:** + * + * The method receives a QString parameter (the new text) from Qt's signal-slot + * mechanism, but the current implementation queries the combo box directly via + * currentText() rather than using the parameter. This approach: + * - Ensures consistency with actual combo box state + * - Avoids potential timing issues with signal delivery + * - Simplifies the logic by using a single data source + * + * @param str The new text content from the combo box. Currently unused in the + * implementation as the method queries the combo box directly. + * Parameter present to match expected slot signature for Qt signals. + * + * @note This validation is purely UI-related; the actual find/replace engine + * may perform additional validation when the operation is executed. + * @note The method only affects the Replace button; the Replace All button + * (if different) might have separate validation logic. + * @note Empty string check uses QString's default comparison; whitespace-only + * strings are considered non-empty. + * + * @see PReplaceDialog::PReplaceDialog() Where initial button state is set + * @see QComboBox::currentText() Method used to query combo box state */ void PReplaceDialog::onFindTextAvailable(const QString&) { diff --git a/src/musredit_qt6/musredit/PReplaceDialog.h b/src/musredit_qt6/musredit/PReplaceDialog.h index 31f85594c..e1b369889 100644 --- a/src/musredit_qt6/musredit/PReplaceDialog.h +++ b/src/musredit_qt6/musredit/PReplaceDialog.h @@ -27,27 +27,191 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +/** + * @file PReplaceDialog.h + * @brief Find and replace dialog for the musredit text editor. + * + * @details This header defines the PReplaceDialog class which provides a + * comprehensive find-and-replace interface for the musredit editor. The + * dialog supports both searching and replacing text with various options + * for search direction, case sensitivity, whole word matching, and scope + * (selection or entire document). + * + * @author Andreas Suter + * @date 2010-2025 + * @copyright Copyright (C) 2010-2025 by Andreas Suter + * @license GNU General Public License v2 or later + * + * @see PFindReplaceData Data structure for find/replace parameters + * @see PReplaceConfirmationDialog For interactive replacement confirmation + * @see musredit Main editor application + */ + #ifndef _PREPLACEDIALOG_H_ #define _PREPLACEDIALOG_H_ #include "musredit.h" #include "ui_PReplaceDialog.h" +/** + * @class PReplaceDialog + * @brief Find and replace dialog for text editing operations. + * + * @details This dialog provides a comprehensive interface for finding and + * replacing text within the musredit editor. It supports various search + * options and replacement modes to accommodate different user workflows. + * + * @par Search Options: + * The dialog offers several options to refine search behavior: + * - **Case sensitive**: Match text case exactly vs. ignore case + * - **Whole words only**: Match complete words vs. partial matches + * - **From cursor**: Start from current position vs. from document beginning + * - **Find backwards**: Search upward vs. downward + * - **Selected text only**: Limit search to selection vs. entire document + * + * @par Replacement Modes: + * Users can choose how replacements are performed: + * - **Replace**: Find and replace one occurrence at a time + * - **Replace All**: Replace all occurrences without confirmation + * - **Prompt on replace**: Ask for confirmation before each replacement + * (launches PReplaceConfirmationDialog for interactive control) + * + * @par Text Input Features: + * - Combo boxes for find/replace text maintain search history + * - Previous searches are accessible via dropdown + * - Empty find text disables replace button to prevent errors + * + * @par Scope Control: + * - **Selected text checkbox**: Enabled only when text is selected in editor + * - When enabled, restricts operations to selection boundaries + * - When disabled/unchecked, operates on entire document + * + * @par State Management: + * The dialog uses PFindReplaceData structure to: + * - Initialize dialog controls from previous search parameters + * - Store current dialog settings for use by calling code + * - Maintain search state across multiple find/replace operations + * - Preserve user preferences between dialog invocations + * + * @par Dialog Workflow: + * 1. User opens dialog (Edit → Replace or Ctrl+H) + * 2. Dialog loads previous search parameters from PFindReplaceData + * 3. User enters find text and replacement text + * 4. User configures search options via checkboxes + * 5. User clicks Replace, Replace All, or Close + * 6. Dialog updates PFindReplaceData with current settings + * 7. Calling code executes requested operation using updated data + * + * @par Button State Management: + * - Replace button is enabled only when find text is non-empty + * - Button state updates dynamically as user types + * - Prevents execution of invalid search operations + * + * @note The dialog is modal, requiring user interaction before continuing. + * @note Changes to settings are only applied when user clicks Replace/Replace All. + * @note The dialog maintains search history through combo box items. + * + * @see PFindReplaceData Structure defining all find/replace parameters + * @see PReplaceConfirmationDialog For per-replacement confirmation + * @see musredit For the main editor with text manipulation capabilities + */ class PReplaceDialog : public QDialog, private Ui::PReplaceDialog { Q_OBJECT public: + /** + * @brief Constructs the find and replace dialog. + * + * @details Initializes the dialog with existing find/replace parameters + * and configures UI controls based on current editor state. The dialog + * is configured as modal and populates all fields from the provided + * data structure. + * + * @param data Pointer to PFindReplaceData structure containing previous + * search parameters and settings. The dialog reads from this + * structure to initialize controls and writes to it when + * getData() is called. Must not be nullptr. + * @param selection true if text is currently selected in the editor, + * false otherwise. Controls the enabled state of the + * "Selected text only" checkbox. When false, the + * checkbox is disabled and unchecked. + * @param parent Pointer to the parent widget (typically the main editor + * window). If nullptr, the dialog has no parent. Parent + * relationship ensures proper centering and cleanup. + * + * @see PFindReplaceData For the parameter structure definition + * @see getData() Retrieves updated parameters after dialog use + */ PReplaceDialog(PFindReplaceData *data, const bool selection, QWidget *parent = nullptr); + + /** + * @brief Virtual destructor. + * + * @details Default destructor implementation. Qt's parent-child ownership + * system automatically handles cleanup of UI elements. + * + * @note Declared virtual to ensure proper cleanup in inheritance hierarchies. + */ virtual ~PReplaceDialog() {} + /** + * @brief Retrieves updated find/replace parameters from the dialog. + * + * @details Collects all current settings from dialog UI controls and + * updates the internal PFindReplaceData structure. This method should + * be called after the dialog is accepted to obtain the user's search + * and replace configuration. + * + * The retrieved data includes: + * - Find text string (from combo box current text) + * - Replacement text string (from combo box current text) + * - Case sensitive flag + * - Whole words only flag + * - From cursor flag (search starting point) + * - Find backwards flag (search direction) + * - Selected text only flag (if checkbox enabled) + * - Prompt on replace flag (confirmation mode) + * + * @return PFindReplaceData* Pointer to the updated parameter structure. + * This is the same pointer passed to the constructor, with all + * fields updated from current dialog state. + * + * @note The selected text flag is only updated if the checkbox is enabled. + * @note This method is typically called by the main editor after the + * dialog is accepted via Replace or Replace All buttons. + * + * @see PFindReplaceData For the complete parameter structure definition + */ virtual PFindReplaceData *getData(); protected slots: + /** + * @brief Slot: Handles changes to the find text input. + * + * @details Called when the find text combo box content changes. Updates + * the enabled state of the Replace button based on whether the find text + * is empty. This prevents users from initiating invalid search operations. + * + * Button state logic: + * - If find text is non-empty: Enable Replace button + * - If find text is empty: Disable Replace button + * + * This provides immediate visual feedback about whether the current + * configuration is valid for replacement operations. + * + * @param str The new text content (parameter not currently used in + * implementation, as the method queries the combo box directly). + * + * @note This slot is typically connected to the combo box's + * editTextChanged() or currentTextChanged() signal. + * @note The parameter is provided by Qt's signal-slot mechanism but + * is not used in the current implementation. + */ virtual void onFindTextAvailable(const QString&); private: - PFindReplaceData *fData; ///< pointer to the find/replace data + PFindReplaceData *fData; ///< Pointer to find/replace parameter structure storing all settings. }; #endif // _PREPLACEDIALOG_H_