From 8b78a8791bc539bcffe7159f9d9714d577cb3d7d Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 23 May 2021 20:48:35 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- kspread/CHANGES | 2 +- kspread/DESIGN.html | 6 +- kspread/Doxyfile | 3 +- kspread/KSpreadAppIface.cc | 83 - kspread/KSpreadAppIface.cpp | 83 + kspread/KSpreadCellIface.cc | 1238 --- kspread/KSpreadCellIface.cpp | 1238 +++ kspread/KSpreadColumnIface.cc | 65 - kspread/KSpreadColumnIface.cpp | 65 + kspread/KSpreadDocIface.cc | 221 - kspread/KSpreadDocIface.cpp | 221 + kspread/KSpreadLayoutIface.cc | 415 - kspread/KSpreadLayoutIface.cpp | 415 + kspread/KSpreadMapIface.cc | 125 - kspread/KSpreadMapIface.cpp | 125 + kspread/KSpreadRowIface.cc | 63 - kspread/KSpreadRowIface.cpp | 63 + kspread/KSpreadTableIface.cc | 434 - kspread/KSpreadTableIface.cpp | 434 + kspread/KSpreadViewIface.cc | 459 -- kspread/KSpreadViewIface.cpp | 459 ++ kspread/Makefile.am | 46 +- kspread/TODO | 2 +- kspread/commands.cc | 946 --- kspread/commands.cpp | 946 +++ kspread/damages.cc | 83 - kspread/damages.cpp | 83 + kspread/dependencies.cc | 682 -- kspread/dependencies.cpp | 682 ++ kspread/dialogs/Makefile.am | 60 +- kspread/dialogs/kspread_dlg_angle.cc | 86 - kspread/dialogs/kspread_dlg_angle.cpp | 86 + kspread/dialogs/kspread_dlg_area.cc | 101 - kspread/dialogs/kspread_dlg_area.cpp | 101 + kspread/dialogs/kspread_dlg_comment.cc | 83 - kspread/dialogs/kspread_dlg_comment.cpp | 83 + kspread/dialogs/kspread_dlg_conditional.cc | 679 -- kspread/dialogs/kspread_dlg_conditional.cpp | 679 ++ kspread/dialogs/kspread_dlg_cons.cc | 687 -- kspread/dialogs/kspread_dlg_cons.cpp | 687 ++ kspread/dialogs/kspread_dlg_csv.cc | 735 -- kspread/dialogs/kspread_dlg_csv.cpp | 735 ++ kspread/dialogs/kspread_dlg_database.cc | 1179 --- kspread/dialogs/kspread_dlg_database.cpp | 1179 +++ kspread/dialogs/kspread_dlg_find.cc | 167 - kspread/dialogs/kspread_dlg_find.cpp | 167 + kspread/dialogs/kspread_dlg_format.cc | 352 - kspread/dialogs/kspread_dlg_format.cpp | 352 + kspread/dialogs/kspread_dlg_formula.cc | 763 -- kspread/dialogs/kspread_dlg_formula.cpp | 763 ++ kspread/dialogs/kspread_dlg_goalseek.cc | 486 -- kspread/dialogs/kspread_dlg_goalseek.cpp | 486 ++ kspread/dialogs/kspread_dlg_goto.cc | 87 - kspread/dialogs/kspread_dlg_goto.cpp | 87 + kspread/dialogs/kspread_dlg_insert.cc | 148 - kspread/dialogs/kspread_dlg_insert.cpp | 148 + kspread/dialogs/kspread_dlg_layout.cc | 3928 --------- kspread/dialogs/kspread_dlg_layout.cpp | 3928 +++++++++ kspread/dialogs/kspread_dlg_list.cc | 321 - kspread/dialogs/kspread_dlg_list.cpp | 321 + kspread/dialogs/kspread_dlg_paperlayout.cc | 554 -- kspread/dialogs/kspread_dlg_paperlayout.cpp | 554 ++ kspread/dialogs/kspread_dlg_pasteinsert.cc | 77 - kspread/dialogs/kspread_dlg_pasteinsert.cpp | 77 + kspread/dialogs/kspread_dlg_preference.cc | 1042 --- kspread/dialogs/kspread_dlg_preference.cpp | 1042 +++ kspread/dialogs/kspread_dlg_reference.cc | 368 - kspread/dialogs/kspread_dlg_reference.cpp | 368 + kspread/dialogs/kspread_dlg_resize2.cc | 183 - kspread/dialogs/kspread_dlg_resize2.cpp | 183 + kspread/dialogs/kspread_dlg_series.cc | 213 - kspread/dialogs/kspread_dlg_series.cpp | 213 + kspread/dialogs/kspread_dlg_show.cc | 112 - kspread/dialogs/kspread_dlg_show.cpp | 112 + kspread/dialogs/kspread_dlg_showColRow.cc | 152 - kspread/dialogs/kspread_dlg_showColRow.cpp | 152 + kspread/dialogs/kspread_dlg_sort.cc | 748 -- kspread/dialogs/kspread_dlg_sort.cpp | 748 ++ kspread/dialogs/kspread_dlg_special.cc | 135 - kspread/dialogs/kspread_dlg_special.cpp | 135 + kspread/dialogs/kspread_dlg_styles.cc | 332 - kspread/dialogs/kspread_dlg_styles.cpp | 332 + kspread/dialogs/kspread_dlg_subtotal.cc | 321 - kspread/dialogs/kspread_dlg_subtotal.cpp | 321 + kspread/dialogs/kspread_dlg_validity.cc | 814 -- kspread/dialogs/kspread_dlg_validity.cpp | 814 ++ kspread/dialogs/link.cc | 288 - kspread/dialogs/link.cpp | 288 + kspread/dialogs/sheet_properties.cc | 192 - kspread/dialogs/sheet_properties.cpp | 192 + kspread/digest.cc | 853 -- kspread/digest.cpp | 853 ++ kspread/formula.cc | 1535 ---- kspread/formula.cpp | 1535 ++++ kspread/functions.cc | 526 -- kspread/functions.cpp | 526 ++ kspread/kspread_autofill.cc | 1217 --- kspread/kspread_autofill.cpp | 1217 +++ kspread/kspread_brush.cc | 270 - kspread/kspread_brush.cpp | 270 + kspread/kspread_canvas.cc | 6167 -------------- kspread/kspread_canvas.cpp | 6167 ++++++++++++++ kspread/kspread_cell.cc | 7348 ----------------- kspread/kspread_cell.cpp | 7348 +++++++++++++++++ kspread/kspread_cluster.cc | 1449 ---- kspread/kspread_cluster.cpp | 1449 ++++ kspread/kspread_condition.cc | 670 -- kspread/kspread_condition.cpp | 670 ++ kspread/kspread_doc.cc | 2462 ------ kspread/kspread_doc.cpp | 2462 ++++++ kspread/kspread_editors.cc | 1589 ---- kspread/kspread_editors.cpp | 1589 ++++ kspread/kspread_events.cc | 19 - kspread/kspread_events.cpp | 19 + kspread/kspread_factory.cc | 101 - kspread/kspread_factory.cpp | 101 + kspread/kspread_factory_init.cc | 23 - kspread/kspread_factory_init.cpp | 23 + kspread/kspread_format.cc | 3581 -------- kspread/kspread_format.cpp | 3581 ++++++++ kspread/kspread_functions_conversion.cc | 266 - kspread/kspread_functions_conversion.cpp | 266 + kspread/kspread_functions_database.cc | 537 -- kspread/kspread_functions_database.cpp | 537 ++ kspread/kspread_functions_datetime.cc | 650 -- kspread/kspread_functions_datetime.cpp | 650 ++ kspread/kspread_functions_engineering.cc | 1256 --- kspread/kspread_functions_engineering.cpp | 1256 +++ kspread/kspread_functions_financial.cc | 907 --- kspread/kspread_functions_financial.cpp | 907 +++ kspread/kspread_functions_helper.cc | 135 - kspread/kspread_functions_helper.cpp | 135 + kspread/kspread_functions_information.cc | 285 - kspread/kspread_functions_information.cpp | 285 + kspread/kspread_functions_logic.cc | 183 - kspread/kspread_functions_logic.cpp | 183 + kspread/kspread_functions_math.cc | 1144 --- kspread/kspread_functions_math.cpp | 1144 +++ kspread/kspread_functions_reference.cc | 342 - kspread/kspread_functions_reference.cpp | 342 + kspread/kspread_functions_statistical.cc | 1243 --- kspread/kspread_functions_statistical.cpp | 1243 +++ kspread/kspread_functions_text.cc | 636 -- kspread/kspread_functions_text.cpp | 636 ++ kspread/kspread_functions_trig.cc | 194 - kspread/kspread_functions_trig.cpp | 194 + kspread/kspread_genvalidationstyle.cc | 401 - kspread/kspread_genvalidationstyle.cpp | 401 + kspread/kspread_handler.cc | 194 - kspread/kspread_handler.cpp | 194 + kspread/kspread_locale.cc | 106 - kspread/kspread_locale.cpp | 106 + kspread/kspread_map.cc | 524 -- kspread/kspread_map.cpp | 524 ++ kspread/kspread_numformat.cc | 1634 ---- kspread/kspread_numformat.cpp | 1634 ++++ kspread/kspread_object.cc | 1621 ---- kspread/kspread_object.cpp | 1621 ++++ kspread/kspread_pen.cc | 69 - kspread/kspread_pen.cpp | 69 + kspread/kspread_sheet.cc | 8577 -------------------- kspread/kspread_sheet.cpp | 8577 ++++++++++++++++++++ kspread/kspread_sheet.h | 4 +- kspread/kspread_sheetprint.cc | 1807 ----- kspread/kspread_sheetprint.cpp | 1807 +++++ kspread/kspread_style.cc | 3214 -------- kspread/kspread_style.cpp | 3214 ++++++++ kspread/kspread_style_manager.cc | 396 - kspread/kspread_style_manager.cpp | 396 + kspread/kspread_toolbox.cc | 232 - kspread/kspread_toolbox.cpp | 232 + kspread/kspread_undo.cc | 3001 ------- kspread/kspread_undo.cpp | 3001 +++++++ kspread/kspread_util.cc | 1218 --- kspread/kspread_util.cpp | 1218 +++ kspread/kspread_value.cc | 970 --- kspread/kspread_value.cpp | 970 +++ kspread/kspread_view.cc | 7541 ----------------- kspread/kspread_view.cpp | 7541 +++++++++++++++++ kspread/main.cc | 46 - kspread/main.cpp | 46 + kspread/manipulator.cc | 1723 ---- kspread/manipulator.cpp | 1723 ++++ kspread/manipulator_data.cc | 197 - kspread/manipulator_data.cpp | 197 + kspread/plugins/insertcalendar/Makefile.am | 6 +- .../insertcalendar/kspread_insertcalendardialog.cc | 150 - .../kspread_insertcalendardialog.cpp | 150 + .../insertcalendar/kspread_plugininsertcalendar.cc | 280 - .../kspread_plugininsertcalendar.cpp | 280 + kspread/plugins/scripting/Makefile.am | 2 +- kspread/plugins/scripting/scripting.cc | 84 - kspread/plugins/scripting/scripting.cpp | 84 + kspread/region.cc | 956 --- kspread/region.cpp | 956 +++ kspread/selection.cc | 1009 --- kspread/selection.cpp | 1009 +++ kspread/tests/Makefile.am | 12 +- kspread/tests/formula_tester.cc | 448 - kspread/tests/formula_tester.cpp | 448 + kspread/tests/inspector.cc | 261 - kspread/tests/inspector.cpp | 261 + kspread/tests/test_formula.cc | 60 - kspread/tests/test_formula.cpp | 60 + kspread/tests/tester.cc | 54 - kspread/tests/tester.cpp | 54 + kspread/tests/testrunner.cc | 132 - kspread/tests/testrunner.cpp | 132 + kspread/tests/value_tester.cc | 307 - kspread/tests/value_tester.cpp | 307 + kspread/valuecalc.cc | 1992 ----- kspread/valuecalc.cpp | 1992 +++++ kspread/valueconverter.cc | 342 - kspread/valueconverter.cpp | 342 + kspread/valueformatter.cc | 649 -- kspread/valueformatter.cpp | 649 ++ kspread/valueparser.cc | 631 -- kspread/valueparser.cpp | 631 ++ 218 files changed, 96632 insertions(+), 96633 deletions(-) delete mode 100644 kspread/KSpreadAppIface.cc create mode 100644 kspread/KSpreadAppIface.cpp delete mode 100644 kspread/KSpreadCellIface.cc create mode 100644 kspread/KSpreadCellIface.cpp delete mode 100644 kspread/KSpreadColumnIface.cc create mode 100644 kspread/KSpreadColumnIface.cpp delete mode 100644 kspread/KSpreadDocIface.cc create mode 100644 kspread/KSpreadDocIface.cpp delete mode 100644 kspread/KSpreadLayoutIface.cc create mode 100644 kspread/KSpreadLayoutIface.cpp delete mode 100644 kspread/KSpreadMapIface.cc create mode 100644 kspread/KSpreadMapIface.cpp delete mode 100644 kspread/KSpreadRowIface.cc create mode 100644 kspread/KSpreadRowIface.cpp delete mode 100644 kspread/KSpreadTableIface.cc create mode 100644 kspread/KSpreadTableIface.cpp delete mode 100644 kspread/KSpreadViewIface.cc create mode 100644 kspread/KSpreadViewIface.cpp delete mode 100644 kspread/commands.cc create mode 100644 kspread/commands.cpp delete mode 100644 kspread/damages.cc create mode 100644 kspread/damages.cpp delete mode 100644 kspread/dependencies.cc create mode 100644 kspread/dependencies.cpp delete mode 100644 kspread/dialogs/kspread_dlg_angle.cc create mode 100644 kspread/dialogs/kspread_dlg_angle.cpp delete mode 100644 kspread/dialogs/kspread_dlg_area.cc create mode 100644 kspread/dialogs/kspread_dlg_area.cpp delete mode 100644 kspread/dialogs/kspread_dlg_comment.cc create mode 100644 kspread/dialogs/kspread_dlg_comment.cpp delete mode 100644 kspread/dialogs/kspread_dlg_conditional.cc create mode 100644 kspread/dialogs/kspread_dlg_conditional.cpp delete mode 100644 kspread/dialogs/kspread_dlg_cons.cc create mode 100644 kspread/dialogs/kspread_dlg_cons.cpp delete mode 100644 kspread/dialogs/kspread_dlg_csv.cc create mode 100644 kspread/dialogs/kspread_dlg_csv.cpp delete mode 100644 kspread/dialogs/kspread_dlg_database.cc create mode 100644 kspread/dialogs/kspread_dlg_database.cpp delete mode 100644 kspread/dialogs/kspread_dlg_find.cc create mode 100644 kspread/dialogs/kspread_dlg_find.cpp delete mode 100644 kspread/dialogs/kspread_dlg_format.cc create mode 100644 kspread/dialogs/kspread_dlg_format.cpp delete mode 100644 kspread/dialogs/kspread_dlg_formula.cc create mode 100644 kspread/dialogs/kspread_dlg_formula.cpp delete mode 100644 kspread/dialogs/kspread_dlg_goalseek.cc create mode 100644 kspread/dialogs/kspread_dlg_goalseek.cpp delete mode 100644 kspread/dialogs/kspread_dlg_goto.cc create mode 100644 kspread/dialogs/kspread_dlg_goto.cpp delete mode 100644 kspread/dialogs/kspread_dlg_insert.cc create mode 100644 kspread/dialogs/kspread_dlg_insert.cpp delete mode 100644 kspread/dialogs/kspread_dlg_layout.cc create mode 100644 kspread/dialogs/kspread_dlg_layout.cpp delete mode 100644 kspread/dialogs/kspread_dlg_list.cc create mode 100644 kspread/dialogs/kspread_dlg_list.cpp delete mode 100644 kspread/dialogs/kspread_dlg_paperlayout.cc create mode 100644 kspread/dialogs/kspread_dlg_paperlayout.cpp delete mode 100644 kspread/dialogs/kspread_dlg_pasteinsert.cc create mode 100644 kspread/dialogs/kspread_dlg_pasteinsert.cpp delete mode 100644 kspread/dialogs/kspread_dlg_preference.cc create mode 100644 kspread/dialogs/kspread_dlg_preference.cpp delete mode 100644 kspread/dialogs/kspread_dlg_reference.cc create mode 100644 kspread/dialogs/kspread_dlg_reference.cpp delete mode 100644 kspread/dialogs/kspread_dlg_resize2.cc create mode 100644 kspread/dialogs/kspread_dlg_resize2.cpp delete mode 100644 kspread/dialogs/kspread_dlg_series.cc create mode 100644 kspread/dialogs/kspread_dlg_series.cpp delete mode 100644 kspread/dialogs/kspread_dlg_show.cc create mode 100644 kspread/dialogs/kspread_dlg_show.cpp delete mode 100644 kspread/dialogs/kspread_dlg_showColRow.cc create mode 100644 kspread/dialogs/kspread_dlg_showColRow.cpp delete mode 100644 kspread/dialogs/kspread_dlg_sort.cc create mode 100644 kspread/dialogs/kspread_dlg_sort.cpp delete mode 100644 kspread/dialogs/kspread_dlg_special.cc create mode 100644 kspread/dialogs/kspread_dlg_special.cpp delete mode 100644 kspread/dialogs/kspread_dlg_styles.cc create mode 100644 kspread/dialogs/kspread_dlg_styles.cpp delete mode 100644 kspread/dialogs/kspread_dlg_subtotal.cc create mode 100644 kspread/dialogs/kspread_dlg_subtotal.cpp delete mode 100644 kspread/dialogs/kspread_dlg_validity.cc create mode 100644 kspread/dialogs/kspread_dlg_validity.cpp delete mode 100644 kspread/dialogs/link.cc create mode 100644 kspread/dialogs/link.cpp delete mode 100644 kspread/dialogs/sheet_properties.cc create mode 100644 kspread/dialogs/sheet_properties.cpp delete mode 100644 kspread/digest.cc create mode 100644 kspread/digest.cpp delete mode 100644 kspread/formula.cc create mode 100644 kspread/formula.cpp delete mode 100644 kspread/functions.cc create mode 100644 kspread/functions.cpp delete mode 100644 kspread/kspread_autofill.cc create mode 100644 kspread/kspread_autofill.cpp delete mode 100644 kspread/kspread_brush.cc create mode 100644 kspread/kspread_brush.cpp delete mode 100644 kspread/kspread_canvas.cc create mode 100644 kspread/kspread_canvas.cpp delete mode 100644 kspread/kspread_cell.cc create mode 100644 kspread/kspread_cell.cpp delete mode 100644 kspread/kspread_cluster.cc create mode 100644 kspread/kspread_cluster.cpp delete mode 100644 kspread/kspread_condition.cc create mode 100644 kspread/kspread_condition.cpp delete mode 100644 kspread/kspread_doc.cc create mode 100644 kspread/kspread_doc.cpp delete mode 100644 kspread/kspread_editors.cc create mode 100644 kspread/kspread_editors.cpp delete mode 100644 kspread/kspread_events.cc create mode 100644 kspread/kspread_events.cpp delete mode 100644 kspread/kspread_factory.cc create mode 100644 kspread/kspread_factory.cpp delete mode 100644 kspread/kspread_factory_init.cc create mode 100644 kspread/kspread_factory_init.cpp delete mode 100644 kspread/kspread_format.cc create mode 100644 kspread/kspread_format.cpp delete mode 100644 kspread/kspread_functions_conversion.cc create mode 100644 kspread/kspread_functions_conversion.cpp delete mode 100644 kspread/kspread_functions_database.cc create mode 100644 kspread/kspread_functions_database.cpp delete mode 100644 kspread/kspread_functions_datetime.cc create mode 100644 kspread/kspread_functions_datetime.cpp delete mode 100644 kspread/kspread_functions_engineering.cc create mode 100644 kspread/kspread_functions_engineering.cpp delete mode 100644 kspread/kspread_functions_financial.cc create mode 100644 kspread/kspread_functions_financial.cpp delete mode 100644 kspread/kspread_functions_helper.cc create mode 100644 kspread/kspread_functions_helper.cpp delete mode 100644 kspread/kspread_functions_information.cc create mode 100644 kspread/kspread_functions_information.cpp delete mode 100644 kspread/kspread_functions_logic.cc create mode 100644 kspread/kspread_functions_logic.cpp delete mode 100644 kspread/kspread_functions_math.cc create mode 100644 kspread/kspread_functions_math.cpp delete mode 100644 kspread/kspread_functions_reference.cc create mode 100644 kspread/kspread_functions_reference.cpp delete mode 100644 kspread/kspread_functions_statistical.cc create mode 100644 kspread/kspread_functions_statistical.cpp delete mode 100644 kspread/kspread_functions_text.cc create mode 100644 kspread/kspread_functions_text.cpp delete mode 100644 kspread/kspread_functions_trig.cc create mode 100644 kspread/kspread_functions_trig.cpp delete mode 100644 kspread/kspread_genvalidationstyle.cc create mode 100644 kspread/kspread_genvalidationstyle.cpp delete mode 100644 kspread/kspread_handler.cc create mode 100644 kspread/kspread_handler.cpp delete mode 100644 kspread/kspread_locale.cc create mode 100644 kspread/kspread_locale.cpp delete mode 100644 kspread/kspread_map.cc create mode 100644 kspread/kspread_map.cpp delete mode 100644 kspread/kspread_numformat.cc create mode 100644 kspread/kspread_numformat.cpp delete mode 100644 kspread/kspread_object.cc create mode 100644 kspread/kspread_object.cpp delete mode 100644 kspread/kspread_pen.cc create mode 100644 kspread/kspread_pen.cpp delete mode 100644 kspread/kspread_sheet.cc create mode 100644 kspread/kspread_sheet.cpp delete mode 100644 kspread/kspread_sheetprint.cc create mode 100644 kspread/kspread_sheetprint.cpp delete mode 100644 kspread/kspread_style.cc create mode 100644 kspread/kspread_style.cpp delete mode 100644 kspread/kspread_style_manager.cc create mode 100644 kspread/kspread_style_manager.cpp delete mode 100644 kspread/kspread_toolbox.cc create mode 100644 kspread/kspread_toolbox.cpp delete mode 100644 kspread/kspread_undo.cc create mode 100644 kspread/kspread_undo.cpp delete mode 100644 kspread/kspread_util.cc create mode 100644 kspread/kspread_util.cpp delete mode 100644 kspread/kspread_value.cc create mode 100644 kspread/kspread_value.cpp delete mode 100644 kspread/kspread_view.cc create mode 100644 kspread/kspread_view.cpp delete mode 100644 kspread/main.cc create mode 100644 kspread/main.cpp delete mode 100644 kspread/manipulator.cc create mode 100644 kspread/manipulator.cpp delete mode 100644 kspread/manipulator_data.cc create mode 100644 kspread/manipulator_data.cpp delete mode 100644 kspread/plugins/insertcalendar/kspread_insertcalendardialog.cc create mode 100644 kspread/plugins/insertcalendar/kspread_insertcalendardialog.cpp delete mode 100644 kspread/plugins/insertcalendar/kspread_plugininsertcalendar.cc create mode 100644 kspread/plugins/insertcalendar/kspread_plugininsertcalendar.cpp delete mode 100644 kspread/plugins/scripting/scripting.cc create mode 100644 kspread/plugins/scripting/scripting.cpp delete mode 100644 kspread/region.cc create mode 100644 kspread/region.cpp delete mode 100644 kspread/selection.cc create mode 100644 kspread/selection.cpp delete mode 100644 kspread/tests/formula_tester.cc create mode 100644 kspread/tests/formula_tester.cpp delete mode 100644 kspread/tests/inspector.cc create mode 100644 kspread/tests/inspector.cpp delete mode 100644 kspread/tests/test_formula.cc create mode 100644 kspread/tests/test_formula.cpp delete mode 100644 kspread/tests/tester.cc create mode 100644 kspread/tests/tester.cpp delete mode 100644 kspread/tests/testrunner.cc create mode 100644 kspread/tests/testrunner.cpp delete mode 100644 kspread/tests/value_tester.cc create mode 100644 kspread/tests/value_tester.cpp delete mode 100644 kspread/valuecalc.cc create mode 100644 kspread/valuecalc.cpp delete mode 100644 kspread/valueconverter.cc create mode 100644 kspread/valueconverter.cpp delete mode 100644 kspread/valueformatter.cc create mode 100644 kspread/valueformatter.cpp delete mode 100644 kspread/valueparser.cc create mode 100644 kspread/valueparser.cpp (limited to 'kspread') diff --git a/kspread/CHANGES b/kspread/CHANGES index 9b9b654e..514e7bf8 100644 --- a/kspread/CHANGES +++ b/kspread/CHANGES @@ -386,7 +386,7 @@ Until beta1: - many new built-in functions (see detailed list below) - function name is now case-insensitive - "Related Function" in formula editor -- move functions in kspread_interpreter into several kspread_functions_*.cc +- move functions in kspread_interpreter into several kspread_functions_*.cpp New functions added: conversion: diff --git a/kspread/DESIGN.html b/kspread/DESIGN.html index 3cd509e2..f1aef8cf 100644 --- a/kspread/DESIGN.html +++ b/kspread/DESIGN.html @@ -684,7 +684,7 @@ existing tester and modify it. Basically, it must be a subclass of class Tester (see koffice/kspread/tests/tester.h). Just reimplement the virtual function run() and it is ready. In order to make it possible to run the new tester, add an instance of the class in TestRunner -(for details, see koffice/kspread/tests/testrunner.cc).

+(for details, see koffice/kspread/tests/testrunner.cpp).

A tester must be self-contained, it should not use any test data from current document. If necessary, it must create (or hard code) the data by @@ -739,7 +739,7 @@ would not cause tons of recompile.

When creating a new class, use namespace KSpread. Do not use KSpread prefix anymore. Example: use KSpread::Foo instead of KSpreadFoo. Also source file name should not contain kspread prefix anymore, i.e. -foo.h and foo.cc (but not kspread_foo.h and -kspread_foo.cc) for the above example.

+foo.h and foo.cpp (but not kspread_foo.h and +kspread_foo.cpp) for the above example.

diff --git a/kspread/Doxyfile b/kspread/Doxyfile index 38131dfb..bb39c7ba 100644 --- a/kspread/Doxyfile +++ b/kspread/Doxyfile @@ -397,12 +397,11 @@ INPUT = # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.c *.cpp *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc FILE_PATTERNS = *.h \ *.cpp \ - *.cc \ *.hpp \ *.dox \ *.c++ \ diff --git a/kspread/KSpreadAppIface.cc b/kspread/KSpreadAppIface.cc deleted file mode 100644 index 6f0c8362..00000000 --- a/kspread/KSpreadAppIface.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2004 Ariya Hidayat - Copyright 2003 David Faure - Copyright 2001 Philipp Mueller - Copyright 2001 Laurent Montel - Copyright 2002 Werner Trobin - Copyright 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - -*/ - -#include "KSpreadAppIface.h" - -#include "kspread_doc.h" - -#include -#include - -using namespace KSpread; - -AppIface::AppIface() - : DCOPObject( "Application" ) -{ -} - -DCOPRef AppIface::createDoc() -{ - Doc* doc = new Doc(); - doc->initDoc(KoDocument::InitDocFileNew); - - return DCOPRef( kapp->dcopClient()->appId(), doc->dcopObject()->objId() ); -} - -DCOPRef AppIface::createDoc( const TQString& name ) -{ - // ######### Torben: Check for duplicate names here - Doc* doc = new Doc( 0, name.latin1() ); - doc->initDoc( KoDocument::InitDocEmpty, 0 ); - - return DCOPRef( kapp->dcopClient()->appId(), doc->dcopObject()->objId() ); -} - -TQMap AppIface::documents() -{ - TQMap map; - - TQValueList lst = Doc::documents(); - TQValueListIterator it = lst.begin(); - for( ; it != lst.end(); ++it ) - { - map[ TQString( (*it)->name() ) ] = - DCOPRef( kapp->dcopClient()->appId(), (*it)->dcopObject()->objId() ); - } - - return map; -} - -DCOPRef AppIface::document( const TQString& name ) -{ - TQValueList lst = Doc::documents(); - TQValueListIterator it = lst.begin(); - for( ; it != lst.end(); ++it ) - if ( name == (*it)->name() ) - return DCOPRef( kapp->dcopClient()->appId(), (*it)->dcopObject()->objId() ); - - return DCOPRef(); -} - diff --git a/kspread/KSpreadAppIface.cpp b/kspread/KSpreadAppIface.cpp new file mode 100644 index 00000000..6f0c8362 --- /dev/null +++ b/kspread/KSpreadAppIface.cpp @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + + Copyright 2004 Ariya Hidayat + Copyright 2003 David Faure + Copyright 2001 Philipp Mueller + Copyright 2001 Laurent Montel + Copyright 2002 Werner Trobin + Copyright 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + +*/ + +#include "KSpreadAppIface.h" + +#include "kspread_doc.h" + +#include +#include + +using namespace KSpread; + +AppIface::AppIface() + : DCOPObject( "Application" ) +{ +} + +DCOPRef AppIface::createDoc() +{ + Doc* doc = new Doc(); + doc->initDoc(KoDocument::InitDocFileNew); + + return DCOPRef( kapp->dcopClient()->appId(), doc->dcopObject()->objId() ); +} + +DCOPRef AppIface::createDoc( const TQString& name ) +{ + // ######### Torben: Check for duplicate names here + Doc* doc = new Doc( 0, name.latin1() ); + doc->initDoc( KoDocument::InitDocEmpty, 0 ); + + return DCOPRef( kapp->dcopClient()->appId(), doc->dcopObject()->objId() ); +} + +TQMap AppIface::documents() +{ + TQMap map; + + TQValueList lst = Doc::documents(); + TQValueListIterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + { + map[ TQString( (*it)->name() ) ] = + DCOPRef( kapp->dcopClient()->appId(), (*it)->dcopObject()->objId() ); + } + + return map; +} + +DCOPRef AppIface::document( const TQString& name ) +{ + TQValueList lst = Doc::documents(); + TQValueListIterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + if ( name == (*it)->name() ) + return DCOPRef( kapp->dcopClient()->appId(), (*it)->dcopObject()->objId() ); + + return DCOPRef(); +} + diff --git a/kspread/KSpreadCellIface.cc b/kspread/KSpreadCellIface.cc deleted file mode 100644 index 4188a1e4..00000000 --- a/kspread/KSpreadCellIface.cc +++ /dev/null @@ -1,1238 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2002-2004 Ariya Hidayat - Copyright 2002-2003 Philipp Mueller - Copyright 2002-2003 Norbert Andres - Copyright 2002-2003 Joseph Wenninger - Copyright 2002 John Dailey - Copyright 1999-2002 Laurent Montel - Copyright 2000-2001 David Faure - Copyright 1999-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - -*/ - -#include "KSpreadCellIface.h" - -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_value.h" -#include "valueconverter.h" - -using namespace KSpread; - -CellIface::CellIface() - : m_point( 0, 0 ), m_sheet( 0 ) -{ -} - -void CellIface::setCell( Sheet* sheet, const TQPoint& point ) -{ - m_sheet = sheet; - m_point = point; -} - -bool CellIface::isDefault() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->cellAt( m_point ); - return cell->isDefault(); -} - -bool CellIface::isEmpty() const -{ - if (!m_sheet) return true; - Cell *cell=m_sheet->cellAt(m_point); - return cell->isEmpty(); -} - -TQString CellIface::text() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return m_sheet->doc()->converter()->asString (cell->value()).asString(); -} - -void CellIface::setText( const TQString& text ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->setCellText( text ); -} - -TQString CellIface::visibleContentAsString() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if (cell->isEmpty()) return TQString(); - TQString ret; - ret=cell->value().asString(); - - if (ret.isEmpty()) - { - ret=TQString::number(cell->value().asFloat()); - } - return ret; -} - -TQString CellIface::comment() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->comment(m_point.x(), m_point.y()); -} - -void CellIface::setComment( const TQString& comment ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setComment( comment); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setValue( int value ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->setValue( (double)value ); -} - -void CellIface::setValue( double value ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->setValue( value ); -} - -double CellIface::value() const -{ - if( !m_sheet ) return 0.0; - Cell* cell = m_sheet->cellAt( m_point ); - return m_sheet->doc()->converter()->asFloat (cell->value()).asFloat(); -} - -void CellIface::setBgColor(const TQString& _c) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(_c); - cell->format()->setBgColor(c); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setBgColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setBgColor(c); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::bgColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->bgColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::textColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->textColor( m_point.x(), m_point.y() ).name(); -} - -void CellIface::setTextColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setTextColor(c); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setTextColor(const TQString& _c) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(_c); - cell->format()->setTextColor(c); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setAngle(int angle) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setAngle(angle); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::angle() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->getAngle(m_point.x(), m_point.y()); -} - -void CellIface::setVerticalText(bool _vertical) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setVerticalText(_vertical); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::verticalText() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->verticalText( m_point.x(), m_point.y() ); -} - - -void CellIface::setMultiRow(bool _multi) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setMultiRow( _multi ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::multiRow() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->multiRow( m_point.x(), m_point.y() ); -} - -void CellIface::setAlign( const TQString& _Align ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - Format::Align Align; - if(_Align=="Left") - Align=Format::Left; - else if(_Align=="Right") - Align=Format::Right; - else if(_Align=="Center") - Align=Format::Center; - else - Align=Format::Undefined; - cell->format()->setAlign( Align); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::align() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQString alignString; - switch( cell->format()->align( m_point.x(), m_point.y() ) ) - { - case Format::Left : - alignString="Left"; - break; - case Format::Right : - alignString="Right"; - break; - case Format::Center : - alignString="Center"; - break; - case Format::Undefined : - alignString="Undefined"; - break; - } - return alignString; -} - -void CellIface::setAlignY( const TQString& _AlignY ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - Format::AlignY AlignY; - if(_AlignY=="Top") - AlignY=Format::Top; - else if(_AlignY=="Middle") - AlignY=Format::Middle; - else if(_AlignY=="Bottom") - AlignY=Format::Bottom; - else - AlignY=Format::Middle; - cell->format()->setAlignY( AlignY); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::alignY() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQString alignString; - switch( cell->format()->alignY( m_point.x(), m_point.y() ) ) - { - case Format::Top : - alignString="Top"; - break; - case Format::Middle : - alignString="Middle"; - break; - case Format::Bottom : - alignString="Bottom"; - break; - case Format::UndefinedY : - alignString="UndefinedY"; - break; - } - return alignString; -} - -void CellIface::setPostfix(const TQString &_postfix) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setPostfix( _postfix ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::prefix() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->prefix( m_point.x(), m_point.y() ); -} - -void CellIface::setPrefix(const TQString &_prefix) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setPrefix( _prefix ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::postfix() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->postfix( m_point.x(), m_point.y() ); -} - -void CellIface::setFormatType(const TQString &_formatType) -{ - if( !m_sheet ) return; - - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - FormatType format; - cell->format()->setPrecision(2); - if (_formatType=="Generic") - format = Generic_format; - else if(_formatType=="Number") - format=Number_format; - else if (_formatType=="Text") - format=Text_format; - else if(_formatType=="Money") - format=Money_format; - else if(_formatType=="Percentage") - format=Percentage_format; - else if(_formatType=="Scientific") - format=Scientific_format; - else if(_formatType=="ShortDate") - format=ShortDate_format; - else if(_formatType=="TextDate") - format=TextDate_format; - else if(_formatType=="Time") - format=Time_format; - else if(_formatType=="SecondeTime") - format=SecondeTime_format; - else if(_formatType=="fraction_half") - format=fraction_half; - else if(_formatType=="fraction_quarter") - format=fraction_quarter; - else if(_formatType=="fraction_eighth") - format=fraction_eighth; - else if(_formatType=="fraction_sixteenth") - format=fraction_sixteenth; - else if(_formatType=="fraction_tenth") - format=fraction_tenth; - else if(_formatType=="fraction_hundredth") - format=fraction_hundredth; - else if(_formatType=="fraction_one_digit") - format=fraction_one_digit; - else if(_formatType=="fraction_two_digits") - format=fraction_two_digits; - else if(_formatType=="fraction_three_digits") - format=fraction_three_digits; - else - format=Generic_format; - cell->format()->setFormatType( format); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::getFormatType() const -{ - if( !m_sheet ) return TQString(); - - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQString stringFormat; - switch( cell->format()->getFormatType(m_point.x(), m_point.y())) - { - case Text_format: - stringFormat="Text"; - break; - case Number_format: - stringFormat="Number"; - break; - case Money_format: - stringFormat="Money"; - break; - case Percentage_format: - stringFormat="Percentage"; - break; - case Scientific_format: - stringFormat="Scientific"; - break; - case ShortDate_format: - stringFormat="ShortDate"; - break; - case TextDate_format: - stringFormat="TextDate"; - break; - case date_format1: - case date_format2: - case date_format3: - case date_format4: - case date_format5: - case date_format6: - case date_format7: - case date_format8: - case date_format9: - case date_format10: - case date_format11: - case date_format12: - case date_format13: - case date_format14: - case date_format15: - case date_format16: - case date_format17: - case date_format18: - case date_format19: - case date_format20: - case date_format21: - case date_format22: - case date_format23: - case date_format24: - case date_format25: - case date_format26: - stringFormat="date format"; - break; - case Time_format: - stringFormat="Time"; - break; - case SecondeTime_format: - stringFormat="SecondeTime"; - break; - case Time_format1: - case Time_format2: - case Time_format3: - case Time_format4: - case Time_format5: - case Time_format6: - case Time_format7: - case Time_format8: - stringFormat="time format"; - break; - case fraction_half: - stringFormat="fraction_half"; - break; - case fraction_quarter: - stringFormat="fraction_quarter"; - break; - case fraction_eighth: - stringFormat="fraction_eighth"; - break; - case fraction_sixteenth: - stringFormat="fraction_sixteenth"; - break; - case fraction_tenth: - stringFormat="fraction_tenth"; - break; - case fraction_hundredth: - stringFormat="fraction_hundredth"; - break; - case fraction_one_digit: - stringFormat="fraction_one_digit"; - break; - case fraction_two_digits: - stringFormat="fraction_two_digits"; - break; - case fraction_three_digits: - stringFormat="fraction_three_digits"; - break; - default: - break; - } - return stringFormat; -} - -void CellIface::setPrecision(int _p) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setPrecision( _p ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::precision() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->precision( m_point.x(), m_point.y() ); -} - -void CellIface::setTextFontBold(bool _b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontBold( _b ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::textFontBold() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontBold( m_point.x(), m_point.y() ); -} - -void CellIface::setTextFontItalic(bool _b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontItalic( _b ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::textFontItalic() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontItalic( m_point.x(), m_point.y() ); -} - - -void CellIface::setTextFontUnderline(bool _b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontUnderline( _b ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::textFontUnderline() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontUnderline( m_point.x(), m_point.y() ); -} - -void CellIface::setTextFontStrike(bool _b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontStrike( _b ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -bool CellIface::textFontStrike() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontStrike( m_point.x(), m_point.y() ); -} - -void CellIface::setTextFontSize( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontSize( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::textFontSize() const -{ - if( !m_sheet ) return 10; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontSize( m_point.x(), m_point.y() ); -} - -void CellIface::setTextFontFamily( const TQString& _font ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTextFontFamily( _font ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -TQString CellIface::textFontFamily() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->textFontFamily( m_point.x(), m_point.y() ); -} - -//border left -void CellIface::setLeftBorderStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setLeftBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setLeftBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setLeftBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setLeftBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setLeftBorderStyle(Qt::SolidLine); - else - cell->format()->setLeftBorderStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setLeftBorderColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setLeftBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setLeftBorderColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setLeftBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setLeftBorderWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setLeftBorderWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - - -int CellIface::leftBorderWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->leftBorderWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::leftBorderColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->leftBorderColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::leftBorderStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->leftBorderStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - -//border right -void CellIface::setRightBorderStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setRightBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setRightBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setRightBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setRightBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setRightBorderStyle(Qt::SolidLine); - else - cell->format()->setRightBorderStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setRightBorderColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setRightBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} -void CellIface::setRightBorderColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setRightBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setRightBorderWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setRightBorderWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -int CellIface::rightBorderWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->rightBorderWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::rightBorderColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->rightBorderColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::rightBorderStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->rightBorderStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - -//border top -void CellIface::setTopBorderStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setTopBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setTopBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setTopBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setTopBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setTopBorderStyle(Qt::SolidLine); - else - cell->format()->setTopBorderStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setTopBorderColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTopBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} -void CellIface::setTopBorderColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setTopBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setTopBorderWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setTopBorderWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::topBorderWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->topBorderWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::topBorderColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->topBorderColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::topBorderStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->topBorderStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - -//border bottom -void CellIface::setBottomBorderStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setBottomBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setBottomBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setBottomBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setBottomBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setBottomBorderStyle(Qt::SolidLine); - else - cell->format()->setBottomBorderStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setBottomBorderColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setBottomBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} -void CellIface::setBottomBorderColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setBottomBorderColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setBottomBorderWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setBottomBorderWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::bottomBorderWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->bottomBorderWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::bottomBorderColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->bottomBorderColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::bottomBorderStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->bottomBorderStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - -//fall back diagonal -void CellIface::setFallDiagonalStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setFallDiagonalStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setFallDiagonalStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setFallDiagonalStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setFallDiagonalStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setFallDiagonalStyle(Qt::SolidLine); - else - cell->format()->setFallDiagonalStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setFallDiagonalColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setFallDiagonalColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} -void CellIface::setFallDiagonalColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setFallDiagonalColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setFallDiagonalWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setFallDiagonalWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::fallDiagonalWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->fallDiagonalWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::fallDiagonalColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->fallDiagonalColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::fallDiagonalStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->fallDiagonalStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - - -//GoUpDiagonal -void CellIface::setGoUpDiagonalStyle( const TQString& _style ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if(_style=="DotLine") - cell->format()->setGoUpDiagonalStyle(Qt::DotLine); - else if(_style=="DashLine") - cell->format()->setGoUpDiagonalStyle(Qt::DashLine); - else if(_style=="DashDotLine") - cell->format()->setGoUpDiagonalStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - cell->format()->setGoUpDiagonalStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - cell->format()->setGoUpDiagonalStyle(Qt::SolidLine); - else - cell->format()->setGoUpDiagonalStyle(Qt::SolidLine); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} - -void CellIface::setGoUpDiagonalColor(const TQString& _c) -{ - if( !m_sheet ) return; - TQColor c(_c); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setGoUpDiagonalColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); - -} -void CellIface::setGoUpDiagonalColor(int r,int g,int b) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - TQColor c(r,g,b); - cell->format()->setGoUpDiagonalColor(c ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -void CellIface::setGoUpDiagonalWidth( int _size ) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setGoUpDiagonalWidth( _size ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -int CellIface::goUpDiagonalWidth() const -{ - if( !m_sheet ) return 0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->goUpDiagonalWidth(m_point.x(), m_point.y()); -} - -TQString CellIface::goUpDiagonalColor() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - return cell->format()->goUpDiagonalColor( m_point.x(), m_point.y() ).name(); -} - -TQString CellIface::goUpDiagonalStyle() const -{ - if( !m_sheet ) return TQString(); - Cell* cell = m_sheet->cellAt( m_point ); - Qt::PenStyle penStyle=cell->format()->goUpDiagonalStyle( m_point.x(), m_point.y() ); - TQString tmp; - if( penStyle==TQt::DotLine) - tmp="DotLine"; - else if( penStyle==TQt::DashLine) - tmp="DashLine"; - else if( penStyle==TQt::DashDotLine) - tmp="DashDotLine"; - else if( penStyle==TQt::DashDotDotLine) - tmp="DashDotDotLine"; - else if( penStyle==TQt::SolidLine) - tmp="SolidLine"; - else - tmp="SolidLine"; - return tmp; -} - -void CellIface::setIndent(double indent) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if( indent >= 0.0 ) - cell->format()->setIndent( indent ); - else - cell->format()->setIndent( 0.0 ); - m_sheet->setRegionPaintDirty(cell->cellRect()); -} - -double CellIface::getIndent() const -{ - if( !m_sheet ) return 0.0; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->getIndent( m_point.x(), m_point.y() ); -} - -void CellIface::setDontPrintText ( bool _print) -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->format()->setDontPrintText ( _print); -} - -bool CellIface::getDontprintText() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - return cell->format()->getDontprintText(m_point.x(), m_point.y()); -} - -bool CellIface::hasValidation() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - return true; - else - return false; -} - -TQString CellIface::validationTitle() const -{ - if( !m_sheet ) return ""; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->title; - } - else - return ""; -} - -TQString CellIface::validationMessage() const -{ - if( !m_sheet ) return ""; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->message; - } - else - return ""; -} - -TQStringList CellIface::listValidation() const -{ - if( !m_sheet ) return TQStringList(); - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->listValidity; - } - else - return TQStringList(); -} - - -TQString CellIface::validationTitleInfo() const -{ - if( !m_sheet ) return ""; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->titleInfo; - } - else - return ""; -} - -TQString CellIface::validationMessageInfo() const -{ - if( !m_sheet ) return ""; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->messageInfo; - } - else - return ""; -} - - -bool CellIface::displayValidationInformation() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->displayValidationInformation; - } - else - return false; -} - -bool CellIface::displayValidationMessage() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->displayMessage; - } - else - return false; -} - -bool CellIface::validationAllowEmptyCell() const -{ - if( !m_sheet ) return false; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - if ( cell->getValidity( 0 ) ) - { - return cell->getValidity( 0 )->allowEmptyCell; - } - else - return false; -} - -void CellIface::removeValidity() -{ - if( !m_sheet ) return; - Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); - cell->removeValidity(); -} diff --git a/kspread/KSpreadCellIface.cpp b/kspread/KSpreadCellIface.cpp new file mode 100644 index 00000000..4188a1e4 --- /dev/null +++ b/kspread/KSpreadCellIface.cpp @@ -0,0 +1,1238 @@ +/* This file is part of the KDE project + + Copyright 2002-2004 Ariya Hidayat + Copyright 2002-2003 Philipp Mueller + Copyright 2002-2003 Norbert Andres + Copyright 2002-2003 Joseph Wenninger + Copyright 2002 John Dailey + Copyright 1999-2002 Laurent Montel + Copyright 2000-2001 David Faure + Copyright 1999-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + +*/ + +#include "KSpreadCellIface.h" + +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_value.h" +#include "valueconverter.h" + +using namespace KSpread; + +CellIface::CellIface() + : m_point( 0, 0 ), m_sheet( 0 ) +{ +} + +void CellIface::setCell( Sheet* sheet, const TQPoint& point ) +{ + m_sheet = sheet; + m_point = point; +} + +bool CellIface::isDefault() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->cellAt( m_point ); + return cell->isDefault(); +} + +bool CellIface::isEmpty() const +{ + if (!m_sheet) return true; + Cell *cell=m_sheet->cellAt(m_point); + return cell->isEmpty(); +} + +TQString CellIface::text() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return m_sheet->doc()->converter()->asString (cell->value()).asString(); +} + +void CellIface::setText( const TQString& text ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->setCellText( text ); +} + +TQString CellIface::visibleContentAsString() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if (cell->isEmpty()) return TQString(); + TQString ret; + ret=cell->value().asString(); + + if (ret.isEmpty()) + { + ret=TQString::number(cell->value().asFloat()); + } + return ret; +} + +TQString CellIface::comment() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->comment(m_point.x(), m_point.y()); +} + +void CellIface::setComment( const TQString& comment ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setComment( comment); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setValue( int value ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->setValue( (double)value ); +} + +void CellIface::setValue( double value ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->setValue( value ); +} + +double CellIface::value() const +{ + if( !m_sheet ) return 0.0; + Cell* cell = m_sheet->cellAt( m_point ); + return m_sheet->doc()->converter()->asFloat (cell->value()).asFloat(); +} + +void CellIface::setBgColor(const TQString& _c) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(_c); + cell->format()->setBgColor(c); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setBgColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setBgColor(c); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::bgColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->bgColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::textColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->textColor( m_point.x(), m_point.y() ).name(); +} + +void CellIface::setTextColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setTextColor(c); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setTextColor(const TQString& _c) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(_c); + cell->format()->setTextColor(c); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setAngle(int angle) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setAngle(angle); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::angle() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->getAngle(m_point.x(), m_point.y()); +} + +void CellIface::setVerticalText(bool _vertical) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setVerticalText(_vertical); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::verticalText() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->verticalText( m_point.x(), m_point.y() ); +} + + +void CellIface::setMultiRow(bool _multi) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setMultiRow( _multi ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::multiRow() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->multiRow( m_point.x(), m_point.y() ); +} + +void CellIface::setAlign( const TQString& _Align ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + Format::Align Align; + if(_Align=="Left") + Align=Format::Left; + else if(_Align=="Right") + Align=Format::Right; + else if(_Align=="Center") + Align=Format::Center; + else + Align=Format::Undefined; + cell->format()->setAlign( Align); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::align() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQString alignString; + switch( cell->format()->align( m_point.x(), m_point.y() ) ) + { + case Format::Left : + alignString="Left"; + break; + case Format::Right : + alignString="Right"; + break; + case Format::Center : + alignString="Center"; + break; + case Format::Undefined : + alignString="Undefined"; + break; + } + return alignString; +} + +void CellIface::setAlignY( const TQString& _AlignY ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + Format::AlignY AlignY; + if(_AlignY=="Top") + AlignY=Format::Top; + else if(_AlignY=="Middle") + AlignY=Format::Middle; + else if(_AlignY=="Bottom") + AlignY=Format::Bottom; + else + AlignY=Format::Middle; + cell->format()->setAlignY( AlignY); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::alignY() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQString alignString; + switch( cell->format()->alignY( m_point.x(), m_point.y() ) ) + { + case Format::Top : + alignString="Top"; + break; + case Format::Middle : + alignString="Middle"; + break; + case Format::Bottom : + alignString="Bottom"; + break; + case Format::UndefinedY : + alignString="UndefinedY"; + break; + } + return alignString; +} + +void CellIface::setPostfix(const TQString &_postfix) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setPostfix( _postfix ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::prefix() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->prefix( m_point.x(), m_point.y() ); +} + +void CellIface::setPrefix(const TQString &_prefix) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setPrefix( _prefix ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::postfix() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->postfix( m_point.x(), m_point.y() ); +} + +void CellIface::setFormatType(const TQString &_formatType) +{ + if( !m_sheet ) return; + + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + FormatType format; + cell->format()->setPrecision(2); + if (_formatType=="Generic") + format = Generic_format; + else if(_formatType=="Number") + format=Number_format; + else if (_formatType=="Text") + format=Text_format; + else if(_formatType=="Money") + format=Money_format; + else if(_formatType=="Percentage") + format=Percentage_format; + else if(_formatType=="Scientific") + format=Scientific_format; + else if(_formatType=="ShortDate") + format=ShortDate_format; + else if(_formatType=="TextDate") + format=TextDate_format; + else if(_formatType=="Time") + format=Time_format; + else if(_formatType=="SecondeTime") + format=SecondeTime_format; + else if(_formatType=="fraction_half") + format=fraction_half; + else if(_formatType=="fraction_quarter") + format=fraction_quarter; + else if(_formatType=="fraction_eighth") + format=fraction_eighth; + else if(_formatType=="fraction_sixteenth") + format=fraction_sixteenth; + else if(_formatType=="fraction_tenth") + format=fraction_tenth; + else if(_formatType=="fraction_hundredth") + format=fraction_hundredth; + else if(_formatType=="fraction_one_digit") + format=fraction_one_digit; + else if(_formatType=="fraction_two_digits") + format=fraction_two_digits; + else if(_formatType=="fraction_three_digits") + format=fraction_three_digits; + else + format=Generic_format; + cell->format()->setFormatType( format); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::getFormatType() const +{ + if( !m_sheet ) return TQString(); + + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQString stringFormat; + switch( cell->format()->getFormatType(m_point.x(), m_point.y())) + { + case Text_format: + stringFormat="Text"; + break; + case Number_format: + stringFormat="Number"; + break; + case Money_format: + stringFormat="Money"; + break; + case Percentage_format: + stringFormat="Percentage"; + break; + case Scientific_format: + stringFormat="Scientific"; + break; + case ShortDate_format: + stringFormat="ShortDate"; + break; + case TextDate_format: + stringFormat="TextDate"; + break; + case date_format1: + case date_format2: + case date_format3: + case date_format4: + case date_format5: + case date_format6: + case date_format7: + case date_format8: + case date_format9: + case date_format10: + case date_format11: + case date_format12: + case date_format13: + case date_format14: + case date_format15: + case date_format16: + case date_format17: + case date_format18: + case date_format19: + case date_format20: + case date_format21: + case date_format22: + case date_format23: + case date_format24: + case date_format25: + case date_format26: + stringFormat="date format"; + break; + case Time_format: + stringFormat="Time"; + break; + case SecondeTime_format: + stringFormat="SecondeTime"; + break; + case Time_format1: + case Time_format2: + case Time_format3: + case Time_format4: + case Time_format5: + case Time_format6: + case Time_format7: + case Time_format8: + stringFormat="time format"; + break; + case fraction_half: + stringFormat="fraction_half"; + break; + case fraction_quarter: + stringFormat="fraction_quarter"; + break; + case fraction_eighth: + stringFormat="fraction_eighth"; + break; + case fraction_sixteenth: + stringFormat="fraction_sixteenth"; + break; + case fraction_tenth: + stringFormat="fraction_tenth"; + break; + case fraction_hundredth: + stringFormat="fraction_hundredth"; + break; + case fraction_one_digit: + stringFormat="fraction_one_digit"; + break; + case fraction_two_digits: + stringFormat="fraction_two_digits"; + break; + case fraction_three_digits: + stringFormat="fraction_three_digits"; + break; + default: + break; + } + return stringFormat; +} + +void CellIface::setPrecision(int _p) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setPrecision( _p ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::precision() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->precision( m_point.x(), m_point.y() ); +} + +void CellIface::setTextFontBold(bool _b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontBold( _b ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::textFontBold() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontBold( m_point.x(), m_point.y() ); +} + +void CellIface::setTextFontItalic(bool _b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontItalic( _b ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::textFontItalic() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontItalic( m_point.x(), m_point.y() ); +} + + +void CellIface::setTextFontUnderline(bool _b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontUnderline( _b ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::textFontUnderline() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontUnderline( m_point.x(), m_point.y() ); +} + +void CellIface::setTextFontStrike(bool _b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontStrike( _b ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +bool CellIface::textFontStrike() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontStrike( m_point.x(), m_point.y() ); +} + +void CellIface::setTextFontSize( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontSize( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::textFontSize() const +{ + if( !m_sheet ) return 10; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontSize( m_point.x(), m_point.y() ); +} + +void CellIface::setTextFontFamily( const TQString& _font ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTextFontFamily( _font ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +TQString CellIface::textFontFamily() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->textFontFamily( m_point.x(), m_point.y() ); +} + +//border left +void CellIface::setLeftBorderStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setLeftBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setLeftBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setLeftBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setLeftBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setLeftBorderStyle(Qt::SolidLine); + else + cell->format()->setLeftBorderStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setLeftBorderColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setLeftBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setLeftBorderColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setLeftBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setLeftBorderWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setLeftBorderWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + + +int CellIface::leftBorderWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->leftBorderWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::leftBorderColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->leftBorderColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::leftBorderStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->leftBorderStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + +//border right +void CellIface::setRightBorderStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setRightBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setRightBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setRightBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setRightBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setRightBorderStyle(Qt::SolidLine); + else + cell->format()->setRightBorderStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setRightBorderColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setRightBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} +void CellIface::setRightBorderColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setRightBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setRightBorderWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setRightBorderWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +int CellIface::rightBorderWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->rightBorderWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::rightBorderColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->rightBorderColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::rightBorderStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->rightBorderStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + +//border top +void CellIface::setTopBorderStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setTopBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setTopBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setTopBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setTopBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setTopBorderStyle(Qt::SolidLine); + else + cell->format()->setTopBorderStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setTopBorderColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTopBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} +void CellIface::setTopBorderColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setTopBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setTopBorderWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setTopBorderWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::topBorderWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->topBorderWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::topBorderColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->topBorderColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::topBorderStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->topBorderStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + +//border bottom +void CellIface::setBottomBorderStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setBottomBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setBottomBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setBottomBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setBottomBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setBottomBorderStyle(Qt::SolidLine); + else + cell->format()->setBottomBorderStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setBottomBorderColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setBottomBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} +void CellIface::setBottomBorderColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setBottomBorderColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setBottomBorderWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setBottomBorderWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::bottomBorderWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->bottomBorderWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::bottomBorderColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->bottomBorderColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::bottomBorderStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->bottomBorderStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + +//fall back diagonal +void CellIface::setFallDiagonalStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setFallDiagonalStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setFallDiagonalStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setFallDiagonalStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setFallDiagonalStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setFallDiagonalStyle(Qt::SolidLine); + else + cell->format()->setFallDiagonalStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setFallDiagonalColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setFallDiagonalColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} +void CellIface::setFallDiagonalColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setFallDiagonalColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setFallDiagonalWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setFallDiagonalWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::fallDiagonalWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->fallDiagonalWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::fallDiagonalColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->fallDiagonalColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::fallDiagonalStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->fallDiagonalStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + + +//GoUpDiagonal +void CellIface::setGoUpDiagonalStyle( const TQString& _style ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if(_style=="DotLine") + cell->format()->setGoUpDiagonalStyle(Qt::DotLine); + else if(_style=="DashLine") + cell->format()->setGoUpDiagonalStyle(Qt::DashLine); + else if(_style=="DashDotLine") + cell->format()->setGoUpDiagonalStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + cell->format()->setGoUpDiagonalStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + cell->format()->setGoUpDiagonalStyle(Qt::SolidLine); + else + cell->format()->setGoUpDiagonalStyle(Qt::SolidLine); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} + +void CellIface::setGoUpDiagonalColor(const TQString& _c) +{ + if( !m_sheet ) return; + TQColor c(_c); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setGoUpDiagonalColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); + +} +void CellIface::setGoUpDiagonalColor(int r,int g,int b) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + TQColor c(r,g,b); + cell->format()->setGoUpDiagonalColor(c ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +void CellIface::setGoUpDiagonalWidth( int _size ) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setGoUpDiagonalWidth( _size ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +int CellIface::goUpDiagonalWidth() const +{ + if( !m_sheet ) return 0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->goUpDiagonalWidth(m_point.x(), m_point.y()); +} + +TQString CellIface::goUpDiagonalColor() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + return cell->format()->goUpDiagonalColor( m_point.x(), m_point.y() ).name(); +} + +TQString CellIface::goUpDiagonalStyle() const +{ + if( !m_sheet ) return TQString(); + Cell* cell = m_sheet->cellAt( m_point ); + Qt::PenStyle penStyle=cell->format()->goUpDiagonalStyle( m_point.x(), m_point.y() ); + TQString tmp; + if( penStyle==TQt::DotLine) + tmp="DotLine"; + else if( penStyle==TQt::DashLine) + tmp="DashLine"; + else if( penStyle==TQt::DashDotLine) + tmp="DashDotLine"; + else if( penStyle==TQt::DashDotDotLine) + tmp="DashDotDotLine"; + else if( penStyle==TQt::SolidLine) + tmp="SolidLine"; + else + tmp="SolidLine"; + return tmp; +} + +void CellIface::setIndent(double indent) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if( indent >= 0.0 ) + cell->format()->setIndent( indent ); + else + cell->format()->setIndent( 0.0 ); + m_sheet->setRegionPaintDirty(cell->cellRect()); +} + +double CellIface::getIndent() const +{ + if( !m_sheet ) return 0.0; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->getIndent( m_point.x(), m_point.y() ); +} + +void CellIface::setDontPrintText ( bool _print) +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->format()->setDontPrintText ( _print); +} + +bool CellIface::getDontprintText() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + return cell->format()->getDontprintText(m_point.x(), m_point.y()); +} + +bool CellIface::hasValidation() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + return true; + else + return false; +} + +TQString CellIface::validationTitle() const +{ + if( !m_sheet ) return ""; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->title; + } + else + return ""; +} + +TQString CellIface::validationMessage() const +{ + if( !m_sheet ) return ""; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->message; + } + else + return ""; +} + +TQStringList CellIface::listValidation() const +{ + if( !m_sheet ) return TQStringList(); + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->listValidity; + } + else + return TQStringList(); +} + + +TQString CellIface::validationTitleInfo() const +{ + if( !m_sheet ) return ""; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->titleInfo; + } + else + return ""; +} + +TQString CellIface::validationMessageInfo() const +{ + if( !m_sheet ) return ""; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->messageInfo; + } + else + return ""; +} + + +bool CellIface::displayValidationInformation() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->displayValidationInformation; + } + else + return false; +} + +bool CellIface::displayValidationMessage() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->displayMessage; + } + else + return false; +} + +bool CellIface::validationAllowEmptyCell() const +{ + if( !m_sheet ) return false; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + if ( cell->getValidity( 0 ) ) + { + return cell->getValidity( 0 )->allowEmptyCell; + } + else + return false; +} + +void CellIface::removeValidity() +{ + if( !m_sheet ) return; + Cell* cell = m_sheet->nonDefaultCell( m_point.x(), m_point.y() ); + cell->removeValidity(); +} diff --git a/kspread/KSpreadColumnIface.cc b/kspread/KSpreadColumnIface.cc deleted file mode 100644 index c0fc813f..00000000 --- a/kspread/KSpreadColumnIface.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2002 Laurent Montel - Copyright 2002 John Dailey - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include "kspread_format.h" -#include "KSpreadLayoutIface.h" - -#include "KSpreadColumnIface.h" - -using namespace KSpread; - -ColumnIface::ColumnIface(ColumnFormat *_lay) - :LayoutIface(_lay) -{ - m_colLayout=_lay; -} - -void ColumnIface::update() -{ - //todo -} - -int ColumnIface::column() -{ - return m_colLayout->column(); -} - -void ColumnIface::setHide(bool _hide) -{ - m_colLayout->setHide(_hide); -} - -bool ColumnIface::isHide()const -{ - return m_colLayout->isHide(); -} - -int ColumnIface::width() const -{ - return m_colLayout->width(); -} - -void ColumnIface::setWidth( int _w ) -{ - m_colLayout->setWidth(_w); -} diff --git a/kspread/KSpreadColumnIface.cpp b/kspread/KSpreadColumnIface.cpp new file mode 100644 index 00000000..c0fc813f --- /dev/null +++ b/kspread/KSpreadColumnIface.cpp @@ -0,0 +1,65 @@ +/* This file is part of the KDE project + + Copyright 2002 Laurent Montel + Copyright 2002 John Dailey + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include "kspread_format.h" +#include "KSpreadLayoutIface.h" + +#include "KSpreadColumnIface.h" + +using namespace KSpread; + +ColumnIface::ColumnIface(ColumnFormat *_lay) + :LayoutIface(_lay) +{ + m_colLayout=_lay; +} + +void ColumnIface::update() +{ + //todo +} + +int ColumnIface::column() +{ + return m_colLayout->column(); +} + +void ColumnIface::setHide(bool _hide) +{ + m_colLayout->setHide(_hide); +} + +bool ColumnIface::isHide()const +{ + return m_colLayout->isHide(); +} + +int ColumnIface::width() const +{ + return m_colLayout->width(); +} + +void ColumnIface::setWidth( int _w ) +{ + m_colLayout->setWidth(_w); +} diff --git a/kspread/KSpreadDocIface.cc b/kspread/KSpreadDocIface.cc deleted file mode 100644 index e8f1df46..00000000 --- a/kspread/KSpreadDocIface.cc +++ /dev/null @@ -1,221 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2004 Ariya Hidayat - Copyright 2003 Norbert Andres - Copyright 2002 Laurent Montel - Copyright 2002 Simon Hausmann - Copyright 2001-2002 Philipp Mueller - Copyright 2000 Stephan Kulow - Copyright 1999-2000 David Faure - Copyright 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "KSpreadDocIface.h" -#include - -#include "kspread_doc.h" -#include "kspread_map.h" - -#include -#include -#include -#include - -using namespace KSpread; - -DocIface::DocIface( Doc* _doc ) - : KoDocumentIface( _doc ) -{ - doc=_doc; -} - -DCOPRef DocIface::map() -{ - return DCOPRef( kapp->dcopClient()->appId(), - doc->map()->dcopObject()->objId() ); -} - -void DocIface::changeDefaultGridPenColor( const TQColor &_col) -{ - doc->setGridColor(_col); -} - -TQColor DocIface::pageBorderColor() const -{ - return doc->pageBorderColor(); -} - -bool DocIface::showFormulaBar()const -{ - return doc->getShowFormulaBar(); -} - -bool DocIface::showStatusBar()const -{ - return doc->getShowStatusBar(); -} - -bool DocIface::showTabBar()const -{ - return doc->getShowTabBar(); -} - -void DocIface::setShowVerticalScrollBar(bool _show) -{ - doc->setShowVerticalScrollBar(_show); - doc->refreshInterface(); -} - -void DocIface::setShowHorizontalScrollBar(bool _show) -{ - doc->setShowHorizontalScrollBar(_show); - doc->refreshInterface(); -} - -void DocIface::setShowColHeader(bool _show) -{ - doc->setShowColHeader(_show); - doc->refreshInterface(); -} - -void DocIface::setShowRowHeader(bool _show) -{ - doc->setShowRowHeader(_show); - doc->refreshInterface(); -} - -void DocIface::setShowTabBar(bool _show) -{ - doc->setShowTabBar(_show); - doc->refreshInterface(); -} - -void DocIface::changePageBorderColor( const TQColor & _color) -{ - doc->changePageBorderColor( _color); - doc->refreshInterface(); -} - -void DocIface::addIgnoreWordAll( const TQString &word) -{ - doc->addIgnoreWordAll( word ); -} - -void DocIface::clearIgnoreWordAll( ) -{ - doc->clearIgnoreWordAll(); -} - -TQStringList DocIface::spellListIgnoreAll() const -{ - return doc->spellListIgnoreAll(); -} - -void DocIface::addStringCompletion(const TQString & stringCompletion) -{ - doc->addStringCompletion( stringCompletion ); -} - -int DocIface::zoom() const -{ - return doc->zoom(); -} - - -TQString DocIface::moveToValue()const -{ - switch(doc->getMoveToValue()) - { - case Bottom: - return TQString("bottom"); - break; - case Left: - return TQString("left"); - break; - case Top: - return TQString("top"); - break; - case Right: - return TQString("right"); - break; - case BottomFirst: - return TQString("bottomFirst"); - break; - } - return TQString(); -} - -void DocIface::setMoveToValue(const TQString & move) -{ - if ( move.lower()=="bottom" ) - doc->setMoveToValue(Bottom); - else if ( move.lower()=="top" ) - doc->setMoveToValue(Top); - else if ( move.lower()=="left" ) - doc->setMoveToValue(Left); - else if ( move.lower()=="right" ) - doc->setMoveToValue(Right); - else if ( move.lower()=="bottomfirst" ) - doc->setMoveToValue(BottomFirst); -} - -void DocIface::setTypeOfCalc( const TQString & calc ) -{ - if ( calc.lower()=="sum") - doc->setTypeOfCalc(SumOfNumber ); - else if ( calc.lower()=="min") - doc->setTypeOfCalc( Min ); - else if ( calc.lower()=="max") - doc->setTypeOfCalc(Max ); - else if ( calc.lower()=="average") - doc->setTypeOfCalc(Average ); - else if ( calc.lower()=="count") - doc->setTypeOfCalc(Count ); - else if ( calc.lower()=="none") - doc->setTypeOfCalc(NoneCalc ); - else - kdDebug()<<"Error in setTypeOfCalc( const TQString & calc ) :"<refreshInterface(); -} - -TQString DocIface::typeOfCalc() const -{ - switch( doc->getTypeOfCalc() ) - { - case SumOfNumber: - return TQString("sum"); - break; - case Min: - return TQString("min"); - break; - case Max: - return TQString("max"); - break; - case Average: - return TQString("average"); - break; - case Count: - return TQString("count"); - break; - case NoneCalc: - default: - return TQString("none"); - break; - } -} - diff --git a/kspread/KSpreadDocIface.cpp b/kspread/KSpreadDocIface.cpp new file mode 100644 index 00000000..e8f1df46 --- /dev/null +++ b/kspread/KSpreadDocIface.cpp @@ -0,0 +1,221 @@ +/* This file is part of the KDE project + + Copyright 2004 Ariya Hidayat + Copyright 2003 Norbert Andres + Copyright 2002 Laurent Montel + Copyright 2002 Simon Hausmann + Copyright 2001-2002 Philipp Mueller + Copyright 2000 Stephan Kulow + Copyright 1999-2000 David Faure + Copyright 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KSpreadDocIface.h" +#include + +#include "kspread_doc.h" +#include "kspread_map.h" + +#include +#include +#include +#include + +using namespace KSpread; + +DocIface::DocIface( Doc* _doc ) + : KoDocumentIface( _doc ) +{ + doc=_doc; +} + +DCOPRef DocIface::map() +{ + return DCOPRef( kapp->dcopClient()->appId(), + doc->map()->dcopObject()->objId() ); +} + +void DocIface::changeDefaultGridPenColor( const TQColor &_col) +{ + doc->setGridColor(_col); +} + +TQColor DocIface::pageBorderColor() const +{ + return doc->pageBorderColor(); +} + +bool DocIface::showFormulaBar()const +{ + return doc->getShowFormulaBar(); +} + +bool DocIface::showStatusBar()const +{ + return doc->getShowStatusBar(); +} + +bool DocIface::showTabBar()const +{ + return doc->getShowTabBar(); +} + +void DocIface::setShowVerticalScrollBar(bool _show) +{ + doc->setShowVerticalScrollBar(_show); + doc->refreshInterface(); +} + +void DocIface::setShowHorizontalScrollBar(bool _show) +{ + doc->setShowHorizontalScrollBar(_show); + doc->refreshInterface(); +} + +void DocIface::setShowColHeader(bool _show) +{ + doc->setShowColHeader(_show); + doc->refreshInterface(); +} + +void DocIface::setShowRowHeader(bool _show) +{ + doc->setShowRowHeader(_show); + doc->refreshInterface(); +} + +void DocIface::setShowTabBar(bool _show) +{ + doc->setShowTabBar(_show); + doc->refreshInterface(); +} + +void DocIface::changePageBorderColor( const TQColor & _color) +{ + doc->changePageBorderColor( _color); + doc->refreshInterface(); +} + +void DocIface::addIgnoreWordAll( const TQString &word) +{ + doc->addIgnoreWordAll( word ); +} + +void DocIface::clearIgnoreWordAll( ) +{ + doc->clearIgnoreWordAll(); +} + +TQStringList DocIface::spellListIgnoreAll() const +{ + return doc->spellListIgnoreAll(); +} + +void DocIface::addStringCompletion(const TQString & stringCompletion) +{ + doc->addStringCompletion( stringCompletion ); +} + +int DocIface::zoom() const +{ + return doc->zoom(); +} + + +TQString DocIface::moveToValue()const +{ + switch(doc->getMoveToValue()) + { + case Bottom: + return TQString("bottom"); + break; + case Left: + return TQString("left"); + break; + case Top: + return TQString("top"); + break; + case Right: + return TQString("right"); + break; + case BottomFirst: + return TQString("bottomFirst"); + break; + } + return TQString(); +} + +void DocIface::setMoveToValue(const TQString & move) +{ + if ( move.lower()=="bottom" ) + doc->setMoveToValue(Bottom); + else if ( move.lower()=="top" ) + doc->setMoveToValue(Top); + else if ( move.lower()=="left" ) + doc->setMoveToValue(Left); + else if ( move.lower()=="right" ) + doc->setMoveToValue(Right); + else if ( move.lower()=="bottomfirst" ) + doc->setMoveToValue(BottomFirst); +} + +void DocIface::setTypeOfCalc( const TQString & calc ) +{ + if ( calc.lower()=="sum") + doc->setTypeOfCalc(SumOfNumber ); + else if ( calc.lower()=="min") + doc->setTypeOfCalc( Min ); + else if ( calc.lower()=="max") + doc->setTypeOfCalc(Max ); + else if ( calc.lower()=="average") + doc->setTypeOfCalc(Average ); + else if ( calc.lower()=="count") + doc->setTypeOfCalc(Count ); + else if ( calc.lower()=="none") + doc->setTypeOfCalc(NoneCalc ); + else + kdDebug()<<"Error in setTypeOfCalc( const TQString & calc ) :"<refreshInterface(); +} + +TQString DocIface::typeOfCalc() const +{ + switch( doc->getTypeOfCalc() ) + { + case SumOfNumber: + return TQString("sum"); + break; + case Min: + return TQString("min"); + break; + case Max: + return TQString("max"); + break; + case Average: + return TQString("average"); + break; + case Count: + return TQString("count"); + break; + case NoneCalc: + default: + return TQString("none"); + break; + } +} + diff --git a/kspread/KSpreadLayoutIface.cc b/kspread/KSpreadLayoutIface.cc deleted file mode 100644 index d3c5e1b7..00000000 --- a/kspread/KSpreadLayoutIface.cc +++ /dev/null @@ -1,415 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2002 Laurent Montel - Copyright 2002 Philipp Mueller - Copyright 2002 John Dailey - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "KSpreadLayoutIface.h" -#include -#include "kspread_format.h" - -using namespace KSpread; - -LayoutIface::LayoutIface(Format *_layout) -{ - layout=_layout; -} - -void LayoutIface::setBgColor(const TQString& _c) -{ - TQColor c(_c); - layout->setBgColor(c); -} - -void LayoutIface::setBgColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setBgColor(c); -} - - -void LayoutIface::setTextColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setTextColor(c); -} - -void LayoutIface::setTextColor(const TQString& _c) -{ - TQColor c(_c); - layout->setTextColor(c); -} - -void LayoutIface::setAngle(int angle) -{ - layout->setAngle(angle); -} - -void LayoutIface::setVerticalText(bool _vertical) -{ - layout->setVerticalText(_vertical); -} - -void LayoutIface::setMultiRow(bool _multi) -{ - layout->setMultiRow( _multi ); -} - -void LayoutIface::setAlign( const TQString& _Align ) -{ - Format::Align Align; - if(_Align=="Left") - Align=Format::Left; - else if(_Align=="Right") - Align=Format::Right; - else if(_Align=="Center") - Align=Format::Center; - else - Align=Format::Undefined; - layout->setAlign( Align); -} - -void LayoutIface::setAlignY( const TQString& _AlignY ) -{ - Format::AlignY AlignY; - if(_AlignY=="Top") - AlignY=Format::Top; - else if(_AlignY=="Middle") - AlignY=Format::Middle; - else if(_AlignY=="Bottom") - AlignY=Format::Bottom; - else - AlignY=Format::Middle; - layout->setAlignY( AlignY); -} - -void LayoutIface::setPostfix(const TQString &_postfix) -{ - layout->setPostfix( _postfix ); -} - -void LayoutIface::setPrefix(const TQString &_prefix) -{ - layout->setPrefix( _prefix ); -} - -void LayoutIface::setFormatType(const TQString &_formatType) -{ - FormatType format; - layout->setPrecision(2); - if (_formatType=="Generic") - format = Generic_format; - else if(_formatType=="Number") - format=Number_format; - else if(_formatType=="Money") - format=Money_format; - else if(_formatType=="Percentage") - format=Percentage_format; - else if(_formatType=="Scientific") - format=Scientific_format; - else if(_formatType=="ShortDate") - format=ShortDate_format; - else if(_formatType=="TextDate") - format=TextDate_format; - else if(_formatType=="Time") - format=Time_format; - else if(_formatType=="SecondeTime") - format=SecondeTime_format; - else if(_formatType=="fraction_half") - format=fraction_half; - else if(_formatType=="fraction_quarter") - format=fraction_quarter; - else if(_formatType=="fraction_eighth") - format=fraction_eighth; - else if(_formatType=="fraction_sixteenth") - format=fraction_sixteenth; - else if(_formatType=="fraction_tenth") - format=fraction_tenth; - else if(_formatType=="fraction_hundredth") - format=fraction_hundredth; - else if(_formatType=="fraction_one_digit") - format=fraction_one_digit; - else if(_formatType=="fraction_two_digits") - format=fraction_two_digits; - else if(_formatType=="fraction_three_digits") - format=fraction_three_digits; - else - format=Generic_format; - layout->setFormatType( format); -} - - -void LayoutIface::setPrecision(int _p) -{ - layout->setPrecision( _p ); -} - -void LayoutIface::setTextFontBold(bool _b) -{ - layout->setTextFontBold( _b ); -} - -void LayoutIface::setTextFontItalic(bool _b) -{ - layout->setTextFontItalic( _b ); -} - -void LayoutIface::setTextFontUnderline(bool _b) -{ - layout->setTextFontUnderline( _b ); -} - -void LayoutIface::setTextFontStrike(bool _b) -{ - layout->setTextFontStrike( _b ); -} - -void LayoutIface::setTextFontSize( int _size ) -{ - layout->setTextFontSize( _size ); -} - -void LayoutIface::setTextFontFamily( const TQString& _font ) -{ - layout->setTextFontFamily( _font ); -} - - -//border left -void LayoutIface::setLeftBorderStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setLeftBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setLeftBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setLeftBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setLeftBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setLeftBorderStyle(Qt::SolidLine); - else - layout->setLeftBorderStyle(Qt::SolidLine); -} - -void LayoutIface::setLeftBorderColor(const TQString& _c) -{ - TQColor c(_c); - layout->setLeftBorderColor(c ); -} - -void LayoutIface::setLeftBorderColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setLeftBorderColor(c ); -} - -void LayoutIface::setLeftBorderWidth( int _size ) -{ - layout->setLeftBorderWidth( _size ); -} - - -//border right -void LayoutIface::setRightBorderStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setRightBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setRightBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setRightBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setRightBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setRightBorderStyle(Qt::SolidLine); - else - layout->setRightBorderStyle(Qt::SolidLine); -} - -void LayoutIface::setRightBorderColor(const TQString& _c) -{ - TQColor c(_c); - layout->setRightBorderColor(c ); -} - -void LayoutIface::setRightBorderColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setRightBorderColor(c ); -} - -void LayoutIface::setRightBorderWidth( int _size ) -{ - layout->setRightBorderWidth( _size ); -} - - -//border top -void LayoutIface::setTopBorderStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setTopBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setTopBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setTopBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setTopBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setTopBorderStyle(Qt::SolidLine); - else - layout->setTopBorderStyle(Qt::SolidLine); -} - -void LayoutIface::setTopBorderColor(const TQString& _c) -{ - TQColor c(_c); - layout->setTopBorderColor(c ); -} - -void LayoutIface::setTopBorderColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setTopBorderColor(c ); -} - -void LayoutIface::setTopBorderWidth( int _size ) -{ - layout->setTopBorderWidth( _size ); -} - - -//border bottom -void LayoutIface::setBottomBorderStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setBottomBorderStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setBottomBorderStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setBottomBorderStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setBottomBorderStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setBottomBorderStyle(Qt::SolidLine); - else - layout->setBottomBorderStyle(Qt::SolidLine); -} - -void LayoutIface::setBottomBorderColor(const TQString& _c) -{ - TQColor c(_c); - layout->setBottomBorderColor(c ); -} -void LayoutIface::setBottomBorderColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setBottomBorderColor(c ); -} - -void LayoutIface::setBottomBorderWidth( int _size ) -{ - layout->setBottomBorderWidth( _size ); -} - - -//fall back diagonal -void LayoutIface::setFallDiagonalStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setFallDiagonalStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setFallDiagonalStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setFallDiagonalStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setFallDiagonalStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setFallDiagonalStyle(Qt::SolidLine); - else - layout->setFallDiagonalStyle(Qt::SolidLine); -} - -void LayoutIface::setFallDiagonalColor(const TQString& _c) -{ - TQColor c(_c); - layout->setFallDiagonalColor(c ); -} -void LayoutIface::setFallDiagonalColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setFallDiagonalColor(c ); -} - -void LayoutIface::setFallDiagonalWidth( int _size ) -{ - layout->setFallDiagonalWidth( _size ); -} - - - -//GoUpDiagonal -void LayoutIface::setGoUpDiagonalStyle( const TQString& _style ) -{ - if(_style=="DotLine") - layout->setGoUpDiagonalStyle(Qt::DotLine); - else if(_style=="DashLine") - layout->setGoUpDiagonalStyle(Qt::DashLine); - else if(_style=="DashDotLine") - layout->setGoUpDiagonalStyle(Qt::DashDotLine); - else if(_style=="DashDotDotLine") - layout->setGoUpDiagonalStyle(Qt::DashDotDotLine); - else if(_style=="SolidLine") - layout->setGoUpDiagonalStyle(Qt::SolidLine); - else - layout->setGoUpDiagonalStyle(Qt::SolidLine); -} - -void LayoutIface::setGoUpDiagonalColor(const TQString& _c) -{ - TQColor c(_c); - layout->setGoUpDiagonalColor(c ); -} -void LayoutIface::setGoUpDiagonalColor(int r,int g,int b) -{ - TQColor c(r,g,b); - layout->setGoUpDiagonalColor(c ); -} - -void LayoutIface::setGoUpDiagonalWidth( int _size ) -{ - layout->setGoUpDiagonalWidth( _size ); -} - - -void LayoutIface::setIndent( double indent ) -{ - if( indent >= 0.0 ) - layout->setIndent( indent ); - else - layout->setIndent( 0.0 ); -} - - -void LayoutIface::setDontPrintText ( bool _print) -{ - layout->setDontPrintText ( _print); -} - diff --git a/kspread/KSpreadLayoutIface.cpp b/kspread/KSpreadLayoutIface.cpp new file mode 100644 index 00000000..d3c5e1b7 --- /dev/null +++ b/kspread/KSpreadLayoutIface.cpp @@ -0,0 +1,415 @@ +/* This file is part of the KDE project + + Copyright 2002 Laurent Montel + Copyright 2002 Philipp Mueller + Copyright 2002 John Dailey + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KSpreadLayoutIface.h" +#include +#include "kspread_format.h" + +using namespace KSpread; + +LayoutIface::LayoutIface(Format *_layout) +{ + layout=_layout; +} + +void LayoutIface::setBgColor(const TQString& _c) +{ + TQColor c(_c); + layout->setBgColor(c); +} + +void LayoutIface::setBgColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setBgColor(c); +} + + +void LayoutIface::setTextColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setTextColor(c); +} + +void LayoutIface::setTextColor(const TQString& _c) +{ + TQColor c(_c); + layout->setTextColor(c); +} + +void LayoutIface::setAngle(int angle) +{ + layout->setAngle(angle); +} + +void LayoutIface::setVerticalText(bool _vertical) +{ + layout->setVerticalText(_vertical); +} + +void LayoutIface::setMultiRow(bool _multi) +{ + layout->setMultiRow( _multi ); +} + +void LayoutIface::setAlign( const TQString& _Align ) +{ + Format::Align Align; + if(_Align=="Left") + Align=Format::Left; + else if(_Align=="Right") + Align=Format::Right; + else if(_Align=="Center") + Align=Format::Center; + else + Align=Format::Undefined; + layout->setAlign( Align); +} + +void LayoutIface::setAlignY( const TQString& _AlignY ) +{ + Format::AlignY AlignY; + if(_AlignY=="Top") + AlignY=Format::Top; + else if(_AlignY=="Middle") + AlignY=Format::Middle; + else if(_AlignY=="Bottom") + AlignY=Format::Bottom; + else + AlignY=Format::Middle; + layout->setAlignY( AlignY); +} + +void LayoutIface::setPostfix(const TQString &_postfix) +{ + layout->setPostfix( _postfix ); +} + +void LayoutIface::setPrefix(const TQString &_prefix) +{ + layout->setPrefix( _prefix ); +} + +void LayoutIface::setFormatType(const TQString &_formatType) +{ + FormatType format; + layout->setPrecision(2); + if (_formatType=="Generic") + format = Generic_format; + else if(_formatType=="Number") + format=Number_format; + else if(_formatType=="Money") + format=Money_format; + else if(_formatType=="Percentage") + format=Percentage_format; + else if(_formatType=="Scientific") + format=Scientific_format; + else if(_formatType=="ShortDate") + format=ShortDate_format; + else if(_formatType=="TextDate") + format=TextDate_format; + else if(_formatType=="Time") + format=Time_format; + else if(_formatType=="SecondeTime") + format=SecondeTime_format; + else if(_formatType=="fraction_half") + format=fraction_half; + else if(_formatType=="fraction_quarter") + format=fraction_quarter; + else if(_formatType=="fraction_eighth") + format=fraction_eighth; + else if(_formatType=="fraction_sixteenth") + format=fraction_sixteenth; + else if(_formatType=="fraction_tenth") + format=fraction_tenth; + else if(_formatType=="fraction_hundredth") + format=fraction_hundredth; + else if(_formatType=="fraction_one_digit") + format=fraction_one_digit; + else if(_formatType=="fraction_two_digits") + format=fraction_two_digits; + else if(_formatType=="fraction_three_digits") + format=fraction_three_digits; + else + format=Generic_format; + layout->setFormatType( format); +} + + +void LayoutIface::setPrecision(int _p) +{ + layout->setPrecision( _p ); +} + +void LayoutIface::setTextFontBold(bool _b) +{ + layout->setTextFontBold( _b ); +} + +void LayoutIface::setTextFontItalic(bool _b) +{ + layout->setTextFontItalic( _b ); +} + +void LayoutIface::setTextFontUnderline(bool _b) +{ + layout->setTextFontUnderline( _b ); +} + +void LayoutIface::setTextFontStrike(bool _b) +{ + layout->setTextFontStrike( _b ); +} + +void LayoutIface::setTextFontSize( int _size ) +{ + layout->setTextFontSize( _size ); +} + +void LayoutIface::setTextFontFamily( const TQString& _font ) +{ + layout->setTextFontFamily( _font ); +} + + +//border left +void LayoutIface::setLeftBorderStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setLeftBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setLeftBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setLeftBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setLeftBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setLeftBorderStyle(Qt::SolidLine); + else + layout->setLeftBorderStyle(Qt::SolidLine); +} + +void LayoutIface::setLeftBorderColor(const TQString& _c) +{ + TQColor c(_c); + layout->setLeftBorderColor(c ); +} + +void LayoutIface::setLeftBorderColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setLeftBorderColor(c ); +} + +void LayoutIface::setLeftBorderWidth( int _size ) +{ + layout->setLeftBorderWidth( _size ); +} + + +//border right +void LayoutIface::setRightBorderStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setRightBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setRightBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setRightBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setRightBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setRightBorderStyle(Qt::SolidLine); + else + layout->setRightBorderStyle(Qt::SolidLine); +} + +void LayoutIface::setRightBorderColor(const TQString& _c) +{ + TQColor c(_c); + layout->setRightBorderColor(c ); +} + +void LayoutIface::setRightBorderColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setRightBorderColor(c ); +} + +void LayoutIface::setRightBorderWidth( int _size ) +{ + layout->setRightBorderWidth( _size ); +} + + +//border top +void LayoutIface::setTopBorderStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setTopBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setTopBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setTopBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setTopBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setTopBorderStyle(Qt::SolidLine); + else + layout->setTopBorderStyle(Qt::SolidLine); +} + +void LayoutIface::setTopBorderColor(const TQString& _c) +{ + TQColor c(_c); + layout->setTopBorderColor(c ); +} + +void LayoutIface::setTopBorderColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setTopBorderColor(c ); +} + +void LayoutIface::setTopBorderWidth( int _size ) +{ + layout->setTopBorderWidth( _size ); +} + + +//border bottom +void LayoutIface::setBottomBorderStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setBottomBorderStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setBottomBorderStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setBottomBorderStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setBottomBorderStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setBottomBorderStyle(Qt::SolidLine); + else + layout->setBottomBorderStyle(Qt::SolidLine); +} + +void LayoutIface::setBottomBorderColor(const TQString& _c) +{ + TQColor c(_c); + layout->setBottomBorderColor(c ); +} +void LayoutIface::setBottomBorderColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setBottomBorderColor(c ); +} + +void LayoutIface::setBottomBorderWidth( int _size ) +{ + layout->setBottomBorderWidth( _size ); +} + + +//fall back diagonal +void LayoutIface::setFallDiagonalStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setFallDiagonalStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setFallDiagonalStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setFallDiagonalStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setFallDiagonalStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setFallDiagonalStyle(Qt::SolidLine); + else + layout->setFallDiagonalStyle(Qt::SolidLine); +} + +void LayoutIface::setFallDiagonalColor(const TQString& _c) +{ + TQColor c(_c); + layout->setFallDiagonalColor(c ); +} +void LayoutIface::setFallDiagonalColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setFallDiagonalColor(c ); +} + +void LayoutIface::setFallDiagonalWidth( int _size ) +{ + layout->setFallDiagonalWidth( _size ); +} + + + +//GoUpDiagonal +void LayoutIface::setGoUpDiagonalStyle( const TQString& _style ) +{ + if(_style=="DotLine") + layout->setGoUpDiagonalStyle(Qt::DotLine); + else if(_style=="DashLine") + layout->setGoUpDiagonalStyle(Qt::DashLine); + else if(_style=="DashDotLine") + layout->setGoUpDiagonalStyle(Qt::DashDotLine); + else if(_style=="DashDotDotLine") + layout->setGoUpDiagonalStyle(Qt::DashDotDotLine); + else if(_style=="SolidLine") + layout->setGoUpDiagonalStyle(Qt::SolidLine); + else + layout->setGoUpDiagonalStyle(Qt::SolidLine); +} + +void LayoutIface::setGoUpDiagonalColor(const TQString& _c) +{ + TQColor c(_c); + layout->setGoUpDiagonalColor(c ); +} +void LayoutIface::setGoUpDiagonalColor(int r,int g,int b) +{ + TQColor c(r,g,b); + layout->setGoUpDiagonalColor(c ); +} + +void LayoutIface::setGoUpDiagonalWidth( int _size ) +{ + layout->setGoUpDiagonalWidth( _size ); +} + + +void LayoutIface::setIndent( double indent ) +{ + if( indent >= 0.0 ) + layout->setIndent( indent ); + else + layout->setIndent( 0.0 ); +} + + +void LayoutIface::setDontPrintText ( bool _print) +{ + layout->setDontPrintText ( _print); +} + diff --git a/kspread/KSpreadMapIface.cc b/kspread/KSpreadMapIface.cc deleted file mode 100644 index ba8071f9..00000000 --- a/kspread/KSpreadMapIface.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2002 Ariya Hidayat - Copyright 2001 Laurent Montel - Copyright 2001 Philipp Mueller - Copyright 2000 Werner Trobin - Copyright 1999-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include "kspread_doc.h" -#include "kspread_map.h" -#include "kspread_sheet.h" - -#include "KSpreadMapIface.h" - -using namespace KSpread; - -MapIface::MapIface( Map* map ) - : DCOPObject( map ) -{ - m_map = map; -} - -DCOPRef MapIface::sheet( const TQString& name ) -{ - Sheet* t = m_map->findSheet( name ); - if ( !t ) - return DCOPRef(); - - return DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); -} - -DCOPRef MapIface::sheetByIndex( int index ) -{ - Sheet* t = m_map->sheetList().at( index ); - if ( !t ) - { - kdDebug(36001) << "+++++ No table found at index " << index << endl; - return DCOPRef(); - } - - kdDebug(36001) << "+++++++ Returning table " << t->TQObject::name() << endl; - - return DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); -} - -int MapIface::sheetCount() const -{ - return m_map->count(); -} - -TQStringList MapIface::sheetNames() const -{ - TQStringList names; - - TQPtrList& lst = m_map->sheetList(); - TQPtrListIterator it( lst ); - for( ; it.current(); ++it ) - names.append( it.current()->name() ); - - return names; -} - -TQValueList MapIface::sheets() -{ - TQValueList t; - - TQPtrList& lst = m_map->sheetList(); - TQPtrListIterator it( lst ); - for( ; it.current(); ++it ) - t.append( DCOPRef( kapp->dcopClient()->appId(), it.current()->dcopObject()->objId() ) ); - - return t; -} - -DCOPRef MapIface::insertSheet( const TQString& name ) -{ - if ( m_map->findSheet( name ) ) - return sheet( name ); - - Sheet* t = m_map->addNewSheet (); - t->setSheetName( name ); - - return sheet( name ); -} - -bool MapIface::processDynamic(const TQCString &fun, const TQByteArray &/*data*/, - TQCString& replyType, TQByteArray &replyData) -{ - // Does the name follow the pattern "foobar()" ? - uint len = fun.length(); - if ( len < 3 ) - return false; - - if ( fun[ len - 1 ] != ')' || fun[ len - 2 ] != '(' ) - return false; - - Sheet* t = m_map->findSheet( fun.left( len - 2 ).data() ); - if ( !t ) - return false; - - replyType = "DCOPRef"; - TQDataStream out( replyData, IO_WriteOnly ); - out << DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); - return true; -} diff --git a/kspread/KSpreadMapIface.cpp b/kspread/KSpreadMapIface.cpp new file mode 100644 index 00000000..ba8071f9 --- /dev/null +++ b/kspread/KSpreadMapIface.cpp @@ -0,0 +1,125 @@ +/* This file is part of the KDE project + + Copyright 2002 Ariya Hidayat + Copyright 2001 Laurent Montel + Copyright 2001 Philipp Mueller + Copyright 2000 Werner Trobin + Copyright 1999-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "kspread_doc.h" +#include "kspread_map.h" +#include "kspread_sheet.h" + +#include "KSpreadMapIface.h" + +using namespace KSpread; + +MapIface::MapIface( Map* map ) + : DCOPObject( map ) +{ + m_map = map; +} + +DCOPRef MapIface::sheet( const TQString& name ) +{ + Sheet* t = m_map->findSheet( name ); + if ( !t ) + return DCOPRef(); + + return DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); +} + +DCOPRef MapIface::sheetByIndex( int index ) +{ + Sheet* t = m_map->sheetList().at( index ); + if ( !t ) + { + kdDebug(36001) << "+++++ No table found at index " << index << endl; + return DCOPRef(); + } + + kdDebug(36001) << "+++++++ Returning table " << t->TQObject::name() << endl; + + return DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); +} + +int MapIface::sheetCount() const +{ + return m_map->count(); +} + +TQStringList MapIface::sheetNames() const +{ + TQStringList names; + + TQPtrList& lst = m_map->sheetList(); + TQPtrListIterator it( lst ); + for( ; it.current(); ++it ) + names.append( it.current()->name() ); + + return names; +} + +TQValueList MapIface::sheets() +{ + TQValueList t; + + TQPtrList& lst = m_map->sheetList(); + TQPtrListIterator it( lst ); + for( ; it.current(); ++it ) + t.append( DCOPRef( kapp->dcopClient()->appId(), it.current()->dcopObject()->objId() ) ); + + return t; +} + +DCOPRef MapIface::insertSheet( const TQString& name ) +{ + if ( m_map->findSheet( name ) ) + return sheet( name ); + + Sheet* t = m_map->addNewSheet (); + t->setSheetName( name ); + + return sheet( name ); +} + +bool MapIface::processDynamic(const TQCString &fun, const TQByteArray &/*data*/, + TQCString& replyType, TQByteArray &replyData) +{ + // Does the name follow the pattern "foobar()" ? + uint len = fun.length(); + if ( len < 3 ) + return false; + + if ( fun[ len - 1 ] != ')' || fun[ len - 2 ] != '(' ) + return false; + + Sheet* t = m_map->findSheet( fun.left( len - 2 ).data() ); + if ( !t ) + return false; + + replyType = "DCOPRef"; + TQDataStream out( replyData, IO_WriteOnly ); + out << DCOPRef( kapp->dcopClient()->appId(), t->dcopObject()->objId() ); + return true; +} diff --git a/kspread/KSpreadRowIface.cc b/kspread/KSpreadRowIface.cc deleted file mode 100644 index 69db292f..00000000 --- a/kspread/KSpreadRowIface.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2002 Laurent Montel - Copyright 2002 John Dailey - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "KSpreadLayoutIface.h" -#include "KSpreadRowIface.h" -#include "kspread_format.h" -#include - -using namespace KSpread; - -RowIface::RowIface(RowFormat *_lay) - :LayoutIface(_lay) -{ - m_rowLayout=_lay; -} - -void RowIface::update() -{ - //todo -} - -int RowIface::row() -{ - return m_rowLayout->row(); -} - -void RowIface::setHide(bool _hide) -{ - m_rowLayout->setHide(_hide); -} - -bool RowIface::isHide()const -{ - return m_rowLayout->isHide(); -} - -void RowIface::setHeight( int _h ) -{ - m_rowLayout->setHeight(_h); -} - -int RowIface::height() -{ - return m_rowLayout->height(); -} diff --git a/kspread/KSpreadRowIface.cpp b/kspread/KSpreadRowIface.cpp new file mode 100644 index 00000000..69db292f --- /dev/null +++ b/kspread/KSpreadRowIface.cpp @@ -0,0 +1,63 @@ +/* This file is part of the KDE project + + Copyright 2002 Laurent Montel + Copyright 2002 John Dailey + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KSpreadLayoutIface.h" +#include "KSpreadRowIface.h" +#include "kspread_format.h" +#include + +using namespace KSpread; + +RowIface::RowIface(RowFormat *_lay) + :LayoutIface(_lay) +{ + m_rowLayout=_lay; +} + +void RowIface::update() +{ + //todo +} + +int RowIface::row() +{ + return m_rowLayout->row(); +} + +void RowIface::setHide(bool _hide) +{ + m_rowLayout->setHide(_hide); +} + +bool RowIface::isHide()const +{ + return m_rowLayout->isHide(); +} + +void RowIface::setHeight( int _h ) +{ + m_rowLayout->setHeight(_h); +} + +int RowIface::height() +{ + return m_rowLayout->height(); +} diff --git a/kspread/KSpreadTableIface.cc b/kspread/KSpreadTableIface.cc deleted file mode 100644 index cbf37f20..00000000 --- a/kspread/KSpreadTableIface.cc +++ /dev/null @@ -1,434 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2003 Lukas Tinkl - Copyright 2000, 2002-2003 Laurent Montel - Copyright 2001-2003 Philipp Mueller - Copyright 2003 Joseph Wenninger - Copyright 2002 Ariya Hidayat - Copyright 2002 Harri Porten - Copyright 2002 John Dailey - Copyright 2001 Simon Hausmann - Copyright 2000 Werner Trobin - Copyright 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include "kspread_util.h" -#include "kspread_doc.h" - -#include -#include -#include - -#include "KSpreadCellIface.h" -#include "region.h" - -#include "KSpreadTableIface.h" - -using namespace KSpread; - -/********************************************* - * - * CellProxy - * - *********************************************/ - -class KSpread::CellProxy : public DCOPObjectProxy -{ -public: - CellProxy( Sheet* sheet, const TQCString& prefix ); - ~CellProxy(); - - virtual bool process( const TQCString& obj, const TQCString& fun, const TQByteArray& data, - TQCString& replyType, TQByteArray &replyData ); - -private: - TQCString m_prefix; - CellIface* m_cell; - Sheet* m_sheet; -}; - -KSpread::CellProxy::CellProxy( Sheet* sheet, const TQCString& prefix ) - : DCOPObjectProxy( kapp->dcopClient() ), m_prefix( prefix ) -{ - m_cell = new CellIface; - m_sheet = sheet; -} - -KSpread::CellProxy::~CellProxy() -{ - delete m_cell; -} - -bool KSpread::CellProxy::process( const TQCString& obj, const TQCString& fun, const TQByteArray& data, - TQCString& replyType, TQByteArray &replyData ) -{ - - kdDebug()<<"CellProxy::process: requested object:"<functions(); - reply<sheetName()+"!"+cellID; - - kdDebug()<<"CellProxy::process: cellID="<setCell( m_sheet, p.pos() ); - return m_cell->process( fun, data, replyType, replyData ); -} - -/************************************************ - * - * SheetIface - * - ************************************************/ - -SheetIface::SheetIface( Sheet* t ) - : DCOPObject() -{ - m_proxy=0; - m_sheet = t; - - sheetNameHasChanged(); - -} - -void SheetIface::sheetNameHasChanged() { - ident.resize(1); - TQObject *currentObj = m_sheet; - while (currentObj != 0L) { - ident.prepend( currentObj->name() ); - ident.prepend("/"); - currentObj = currentObj->parent(); - } - if ( ident[0] == '/' ) - ident = ident.mid(1); - - if (qstrcmp(ident,objId())!=0) { - setObjId(ident); - - delete m_proxy; - TQCString str = objId(); - str += "/"; - kdDebug(36001)<<"SheetIface::tableNameHasChanged(): new DCOP-ID:"<dcopClient()->appId(), str ); -} - -DCOPRef SheetIface::cell( const TQString& name ) -{ - TQCString str = objId(); - str += "/"; - str += name.latin1(); - - return DCOPRef( kapp->dcopClient()->appId(), str ); -} - -DCOPRef SheetIface::column( int _col ) -{ - //First col number = 1 - if(_col <1) - return DCOPRef(); - return DCOPRef( kapp->dcopClient()->appId(), - m_sheet->nonDefaultColumnFormat( _col )->dcopObject()->objId() ); - -} - -DCOPRef SheetIface::row( int _row ) -{ - //First row number = 1 - if(_row <1) - return DCOPRef(); - return DCOPRef( kapp->dcopClient()->appId(), - m_sheet->nonDefaultRowFormat( _row )->dcopObject()->objId() ); -} - - -TQString SheetIface::name() const -{ - return m_sheet->sheetName(); -} - - -int SheetIface::maxColumn() const -{ - return m_sheet->maxColumn(); - -} - -bool SheetIface::areaHasNoContent(TQRect area) const -{ - kdDebug(36001) << "SheetIface::areaHasNoContent("<areaIsEmpty(area); -} - -bool SheetIface::areaHasNoComments(TQRect area) const -{ - return m_sheet->areaIsEmpty(area, Sheet::Comment); -} - -int SheetIface::maxRow() const -{ - return m_sheet->maxRow(); -} - -bool SheetIface::processDynamic( const TQCString& fun, const TQByteArray&/*data*/, - TQCString& replyType, TQByteArray &replyData ) -{ - kdDebug(36001) << "Calling '" << fun.data() << "'" << endl; - // Does the name follow the pattern "foobar()" ? - uint len = fun.length(); - if ( len < 3 ) - return false; - - if ( fun[ len - 1 ] != ')' || fun[ len - 2 ] != '(' ) - return false; - - // Is the function name a valid cell like "B5" ? - Point p( fun.left( len - 2 ).data() ); - if ( !p.isValid() ) - return false; - - TQCString str = objId() + "/" + fun.left( len - 2 ); - - replyType = "DCOPRef"; - TQDataStream out( replyData, IO_WriteOnly ); - out << DCOPRef( kapp->dcopClient()->appId(), str ); - return true; -} - -bool SheetIface::setSheetName( const TQString & name) -{ - return m_sheet->setSheetName( name); -} - -bool SheetIface::insertColumn( int col,int nbCol ) -{ - return m_sheet->insertColumn(col,nbCol); -} - -bool SheetIface::insertRow( int row,int nbRow) -{ - return m_sheet->insertRow(row,nbRow); -} - -void SheetIface::removeColumn( int col,int nbCol ) -{ - m_sheet->removeColumn( col,nbCol ); -} - -void SheetIface::removeRow( int row,int nbRow ) -{ - m_sheet->removeRow( row,nbRow ); -} - - -bool SheetIface::isHidden()const -{ - return m_sheet->isHidden(); -} - - -bool SheetIface::showGrid() const -{ - return m_sheet->getShowGrid(); -} - -bool SheetIface::showFormula() const -{ - return m_sheet->getShowFormula(); -} - -bool SheetIface::lcMode() const -{ - return m_sheet->getLcMode(); -} - -bool SheetIface::autoCalc() const -{ - return m_sheet->getAutoCalc(); -} - -bool SheetIface::showColumnNumber() const -{ - return m_sheet->getShowColumnNumber(); -} - -bool SheetIface::hideZero() const -{ - return m_sheet->getHideZero(); -} - -bool SheetIface::firstLetterUpper() const -{ - return m_sheet->getFirstLetterUpper(); -} - -void SheetIface::setShowPageBorders( bool b ) -{ - m_sheet->setShowPageBorders( b ); - m_sheet->doc()->updateBorderButton(); -} - -float SheetIface::paperHeight()const -{ - return m_sheet->print()->paperHeight(); -} - -float SheetIface::paperWidth()const -{ - return m_sheet->print()->paperWidth(); -} - -float SheetIface::leftBorder()const -{ - return m_sheet->print()->leftBorder(); -} - -float SheetIface::rightBorder()const -{ - return m_sheet->print()->rightBorder(); -} - -float SheetIface::topBorder()const -{ - return m_sheet->print()->topBorder(); -} - -float SheetIface::bottomBorder()const -{ - return m_sheet->print()->bottomBorder(); -} - -TQString SheetIface::paperFormatString() const -{ - return m_sheet->print()->paperFormatString(); -} - -TQString SheetIface::headLeft()const -{ - return m_sheet->print()->headLeft(); -} - -TQString SheetIface::headMid()const -{ - return m_sheet->print()->headMid(); -} - -TQString SheetIface::headRight()const -{ - return m_sheet->print()->headRight(); -} - -TQString SheetIface::footLeft()const -{ - return m_sheet->print()->footLeft(); -} - -TQString SheetIface::footMid()const -{ - return m_sheet->print()->footMid(); -} - -TQString SheetIface::footRight()const -{ - return m_sheet->print()->footRight(); -} - -void SheetIface::setHeaderLeft(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( text, headMid(), headRight(), - footLeft(), footMid(), footRight() ); -} - -void SheetIface::setHeaderMiddle(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( headLeft(), text, headRight(), - footLeft(), footMid(), footRight() ); - -} - -void SheetIface::setHeaderRight(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( headLeft(), headMid(), text, - footLeft(), footMid(), footRight() ); -} - -void SheetIface::setFooterLeft(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), - text, footMid(), footRight() ); -} - -void SheetIface::setFooterMiddle(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), - footLeft(), text, footRight() ); -} - -void SheetIface::setFooterRight(const TQString & text) -{ - m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), - footLeft(), footMid(), text ); -} - -bool SheetIface::isProtected() const -{ - return m_sheet->isProtected(); -} diff --git a/kspread/KSpreadTableIface.cpp b/kspread/KSpreadTableIface.cpp new file mode 100644 index 00000000..cbf37f20 --- /dev/null +++ b/kspread/KSpreadTableIface.cpp @@ -0,0 +1,434 @@ +/* This file is part of the KDE project + + Copyright 2003 Lukas Tinkl + Copyright 2000, 2002-2003 Laurent Montel + Copyright 2001-2003 Philipp Mueller + Copyright 2003 Joseph Wenninger + Copyright 2002 Ariya Hidayat + Copyright 2002 Harri Porten + Copyright 2002 John Dailey + Copyright 2001 Simon Hausmann + Copyright 2000 Werner Trobin + Copyright 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include "kspread_util.h" +#include "kspread_doc.h" + +#include +#include +#include + +#include "KSpreadCellIface.h" +#include "region.h" + +#include "KSpreadTableIface.h" + +using namespace KSpread; + +/********************************************* + * + * CellProxy + * + *********************************************/ + +class KSpread::CellProxy : public DCOPObjectProxy +{ +public: + CellProxy( Sheet* sheet, const TQCString& prefix ); + ~CellProxy(); + + virtual bool process( const TQCString& obj, const TQCString& fun, const TQByteArray& data, + TQCString& replyType, TQByteArray &replyData ); + +private: + TQCString m_prefix; + CellIface* m_cell; + Sheet* m_sheet; +}; + +KSpread::CellProxy::CellProxy( Sheet* sheet, const TQCString& prefix ) + : DCOPObjectProxy( kapp->dcopClient() ), m_prefix( prefix ) +{ + m_cell = new CellIface; + m_sheet = sheet; +} + +KSpread::CellProxy::~CellProxy() +{ + delete m_cell; +} + +bool KSpread::CellProxy::process( const TQCString& obj, const TQCString& fun, const TQByteArray& data, + TQCString& replyType, TQByteArray &replyData ) +{ + + kdDebug()<<"CellProxy::process: requested object:"<functions(); + reply<sheetName()+"!"+cellID; + + kdDebug()<<"CellProxy::process: cellID="<setCell( m_sheet, p.pos() ); + return m_cell->process( fun, data, replyType, replyData ); +} + +/************************************************ + * + * SheetIface + * + ************************************************/ + +SheetIface::SheetIface( Sheet* t ) + : DCOPObject() +{ + m_proxy=0; + m_sheet = t; + + sheetNameHasChanged(); + +} + +void SheetIface::sheetNameHasChanged() { + ident.resize(1); + TQObject *currentObj = m_sheet; + while (currentObj != 0L) { + ident.prepend( currentObj->name() ); + ident.prepend("/"); + currentObj = currentObj->parent(); + } + if ( ident[0] == '/' ) + ident = ident.mid(1); + + if (qstrcmp(ident,objId())!=0) { + setObjId(ident); + + delete m_proxy; + TQCString str = objId(); + str += "/"; + kdDebug(36001)<<"SheetIface::tableNameHasChanged(): new DCOP-ID:"<dcopClient()->appId(), str ); +} + +DCOPRef SheetIface::cell( const TQString& name ) +{ + TQCString str = objId(); + str += "/"; + str += name.latin1(); + + return DCOPRef( kapp->dcopClient()->appId(), str ); +} + +DCOPRef SheetIface::column( int _col ) +{ + //First col number = 1 + if(_col <1) + return DCOPRef(); + return DCOPRef( kapp->dcopClient()->appId(), + m_sheet->nonDefaultColumnFormat( _col )->dcopObject()->objId() ); + +} + +DCOPRef SheetIface::row( int _row ) +{ + //First row number = 1 + if(_row <1) + return DCOPRef(); + return DCOPRef( kapp->dcopClient()->appId(), + m_sheet->nonDefaultRowFormat( _row )->dcopObject()->objId() ); +} + + +TQString SheetIface::name() const +{ + return m_sheet->sheetName(); +} + + +int SheetIface::maxColumn() const +{ + return m_sheet->maxColumn(); + +} + +bool SheetIface::areaHasNoContent(TQRect area) const +{ + kdDebug(36001) << "SheetIface::areaHasNoContent("<areaIsEmpty(area); +} + +bool SheetIface::areaHasNoComments(TQRect area) const +{ + return m_sheet->areaIsEmpty(area, Sheet::Comment); +} + +int SheetIface::maxRow() const +{ + return m_sheet->maxRow(); +} + +bool SheetIface::processDynamic( const TQCString& fun, const TQByteArray&/*data*/, + TQCString& replyType, TQByteArray &replyData ) +{ + kdDebug(36001) << "Calling '" << fun.data() << "'" << endl; + // Does the name follow the pattern "foobar()" ? + uint len = fun.length(); + if ( len < 3 ) + return false; + + if ( fun[ len - 1 ] != ')' || fun[ len - 2 ] != '(' ) + return false; + + // Is the function name a valid cell like "B5" ? + Point p( fun.left( len - 2 ).data() ); + if ( !p.isValid() ) + return false; + + TQCString str = objId() + "/" + fun.left( len - 2 ); + + replyType = "DCOPRef"; + TQDataStream out( replyData, IO_WriteOnly ); + out << DCOPRef( kapp->dcopClient()->appId(), str ); + return true; +} + +bool SheetIface::setSheetName( const TQString & name) +{ + return m_sheet->setSheetName( name); +} + +bool SheetIface::insertColumn( int col,int nbCol ) +{ + return m_sheet->insertColumn(col,nbCol); +} + +bool SheetIface::insertRow( int row,int nbRow) +{ + return m_sheet->insertRow(row,nbRow); +} + +void SheetIface::removeColumn( int col,int nbCol ) +{ + m_sheet->removeColumn( col,nbCol ); +} + +void SheetIface::removeRow( int row,int nbRow ) +{ + m_sheet->removeRow( row,nbRow ); +} + + +bool SheetIface::isHidden()const +{ + return m_sheet->isHidden(); +} + + +bool SheetIface::showGrid() const +{ + return m_sheet->getShowGrid(); +} + +bool SheetIface::showFormula() const +{ + return m_sheet->getShowFormula(); +} + +bool SheetIface::lcMode() const +{ + return m_sheet->getLcMode(); +} + +bool SheetIface::autoCalc() const +{ + return m_sheet->getAutoCalc(); +} + +bool SheetIface::showColumnNumber() const +{ + return m_sheet->getShowColumnNumber(); +} + +bool SheetIface::hideZero() const +{ + return m_sheet->getHideZero(); +} + +bool SheetIface::firstLetterUpper() const +{ + return m_sheet->getFirstLetterUpper(); +} + +void SheetIface::setShowPageBorders( bool b ) +{ + m_sheet->setShowPageBorders( b ); + m_sheet->doc()->updateBorderButton(); +} + +float SheetIface::paperHeight()const +{ + return m_sheet->print()->paperHeight(); +} + +float SheetIface::paperWidth()const +{ + return m_sheet->print()->paperWidth(); +} + +float SheetIface::leftBorder()const +{ + return m_sheet->print()->leftBorder(); +} + +float SheetIface::rightBorder()const +{ + return m_sheet->print()->rightBorder(); +} + +float SheetIface::topBorder()const +{ + return m_sheet->print()->topBorder(); +} + +float SheetIface::bottomBorder()const +{ + return m_sheet->print()->bottomBorder(); +} + +TQString SheetIface::paperFormatString() const +{ + return m_sheet->print()->paperFormatString(); +} + +TQString SheetIface::headLeft()const +{ + return m_sheet->print()->headLeft(); +} + +TQString SheetIface::headMid()const +{ + return m_sheet->print()->headMid(); +} + +TQString SheetIface::headRight()const +{ + return m_sheet->print()->headRight(); +} + +TQString SheetIface::footLeft()const +{ + return m_sheet->print()->footLeft(); +} + +TQString SheetIface::footMid()const +{ + return m_sheet->print()->footMid(); +} + +TQString SheetIface::footRight()const +{ + return m_sheet->print()->footRight(); +} + +void SheetIface::setHeaderLeft(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( text, headMid(), headRight(), + footLeft(), footMid(), footRight() ); +} + +void SheetIface::setHeaderMiddle(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( headLeft(), text, headRight(), + footLeft(), footMid(), footRight() ); + +} + +void SheetIface::setHeaderRight(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( headLeft(), headMid(), text, + footLeft(), footMid(), footRight() ); +} + +void SheetIface::setFooterLeft(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), + text, footMid(), footRight() ); +} + +void SheetIface::setFooterMiddle(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), + footLeft(), text, footRight() ); +} + +void SheetIface::setFooterRight(const TQString & text) +{ + m_sheet->print()->setHeadFootLine( headLeft(), headMid(), headRight(), + footLeft(), footMid(), text ); +} + +bool SheetIface::isProtected() const +{ + return m_sheet->isProtected(); +} diff --git a/kspread/KSpreadViewIface.cc b/kspread/KSpreadViewIface.cc deleted file mode 100644 index 1fb76f46..00000000 --- a/kspread/KSpreadViewIface.cc +++ /dev/null @@ -1,459 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2004 Ariya Hidayat - Copyright 2002-2003 Joseph Wenninger - Copyright 2002 John Dailey - Copyright 2001-2002 Laurent Montel - Copyright 2001 Philipp Mueller - Copyright 2000 Simon Hausmann - Copyright 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include "kspread_doc.h" -#include "kspread_map.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_view.h" - -#include "KSpreadViewIface.h" - -using namespace KSpread; - -/************************************************ - * - * ViewIface - * - ************************************************/ - -ViewIface::ViewIface( View* t ) - : KoViewIface( t ) -{ - m_view = t; -} - -ViewIface::~ViewIface() -{ -} - -DCOPRef ViewIface::doc() const -{ - return DCOPRef( kapp->dcopClient()->appId(), m_view->doc()->dcopObject()->objId() ); -} - -DCOPRef ViewIface::map() const -{ - return DCOPRef( kapp->dcopClient()->appId(), m_view->doc()->map()->dcopObject()->objId() ); -} - -DCOPRef ViewIface::sheet() const -{ - return DCOPRef( kapp->dcopClient()->appId(), m_view->activeSheet()->dcopObject()->objId() ); -} - -void ViewIface::changeNbOfRecentFiles(int _nb) -{ - if(_nb<0) - return; - m_view->changeNbOfRecentFiles(_nb); -} - - -void ViewIface::hide() -{ - m_view->hide(); -} - -void ViewIface::show() -{ - m_view->show(); -} - -void ViewIface::find() -{ - m_view->find(); -} - -void ViewIface::replace() -{ - m_view->replace(); -} - -void ViewIface::conditional() -{ - m_view->conditional(); -} - -void ViewIface::validity() -{ - m_view->validity(); -} - -void ViewIface::insertSeries() -{ - m_view->insertSeries(); -} - -void ViewIface::insertHyperlink() -{ - m_view->insertHyperlink(); -} - -void ViewIface::gotoCell() -{ - m_view->gotoCell(); -} - -void ViewIface::changeAngle() -{ - m_view->changeAngle(); -} - -void ViewIface::preference() -{ - m_view->preference(); -} - -void ViewIface::nextSheet() -{ - m_view->nextSheet(); -} - -bool ViewIface::showSheet(TQString sheetName) -{ - return m_view->showSheet(sheetName); -} - -void ViewIface::previousSheet() -{ - m_view->previousSheet(); -} - -void ViewIface::sortList() -{ - m_view->sortList(); -} - -void ViewIface::setAreaName() -{ - m_view->setAreaName(); -} - -void ViewIface::showAreaName() -{ - m_view->showAreaName(); -} - -void ViewIface::mergeCell() -{ - m_view->mergeCell(); -} - -void ViewIface::dissociateCell() -{ - m_view->dissociateCell(); -} - -void ViewIface::consolidate() -{ - m_view->consolidate(); -} - -void ViewIface::deleteColumn() -{ - m_view->deleteColumn(); -} - -void ViewIface::insertColumn() -{ - m_view->insertColumn(); -} - -void ViewIface::deleteRow() -{ - m_view->deleteRow(); -} - -void ViewIface::insertRow() -{ - m_view->insertRow(); -} - -void ViewIface::hideRow() -{ - m_view->hideRow(); -} - -void ViewIface::showRow() -{ - m_view->showRow(); -} - -void ViewIface::hideColumn() -{ - m_view->hideColumn(); -} - -void ViewIface::showColumn() -{ - m_view->showColumn(); -} - -void ViewIface::upper() -{ - m_view->upper(); -} - -void ViewIface::lower() -{ - m_view->lower(); -} - -void ViewIface::equalizeColumn() -{ - m_view->equalizeColumn(); -} - -void ViewIface::equalizeRow() -{ - m_view->equalizeRow(); -} - -void ViewIface::clearTextSelection() -{ - m_view->clearTextSelection(); -} - -void ViewIface::clearCommentSelection() -{ - m_view->clearCommentSelection(); -} - -void ViewIface::clearValiditySelection() -{ - m_view->clearValiditySelection(); -} - -void ViewIface::clearConditionalSelection() -{ - m_view->clearConditionalSelection(); -} - -void ViewIface::goalSeek() -{ - m_view->goalSeek(); -} - -void ViewIface::insertFromDatabase() -{ - m_view->insertFromDatabase(); -} - -void ViewIface::insertFromTextfile() -{ - m_view->insertFromTextfile(); -} - -void ViewIface::insertFromClipboard() -{ - m_view->insertFromClipboard(); -} - -void ViewIface::textToColumns() -{ - m_view->textToColumns(); -} - -void ViewIface::copyAsText() -{ - m_view->copyAsText(); -} - -void ViewIface::setSelection(TQRect selection) -{ - m_view->selectionInfo()->initialize(selection);//,m_view->activeSheet()); -} - -TQRect ViewIface::selection() -{ - return m_view->selectionInfo()->selection(); -} - -void ViewIface::setSelectionMoneyFormat( bool b ) -{ - m_view->moneyFormat(b); -} - -void ViewIface::setSelectionPrecision( int delta ) -{ - m_view->setSelectionPrecision(delta); -} - -void ViewIface::setSelectionPercent( bool b ) -{ - m_view->percent(b); -} - -void ViewIface::setSelectionMultiRow( bool enable ) -{ - m_view->wrapText(enable); -} - -void ViewIface::setSelectionSize(int size) -{ - m_view->setSelectionFontSize(size); -} - -void ViewIface::setSelectionUpper() -{ - m_view->upper(); -} - -void ViewIface::setSelectionLower() -{ - m_view->lower(); -} - -void ViewIface::setSelectionFirstLetterUpper() -{ - m_view->firstLetterUpper(); -} - -void ViewIface::setSelectionVerticalText(bool enable) -{ - m_view->verticalText(enable); -} - -void ViewIface::setSelectionComment(TQString comment) -{ - m_view->setSelectionComment(comment); -} - -void ViewIface::setSelectionAngle(int value) -{ - m_view->setSelectionAngle(value); -} - -void ViewIface::setSelectionTextColor( TQColor txtColor ) -{ - m_view->setSelectionTextColor(txtColor); -} - -void ViewIface::setSelectionBgColor( TQColor bgColor ) -{ - m_view->setSelectionBackgroundColor(bgColor); -} - -void ViewIface::setSelectionBorderColor( TQColor bdColor ) -{ - m_view->setSelectionBorderColor(bdColor); -} - -void ViewIface::deleteSelection() -{ - m_view->clearTextSelection(); -} - -void ViewIface::copySelection() -{ - m_view->copySelection(); -} - -void ViewIface::cutSelection() -{ - m_view->cutSelection(); -} - -void ViewIface::setLeftBorderColor(TQColor color) -{ - m_view->setSelectionLeftBorderColor(color); -} - -void ViewIface::setTopBorderColor(TQColor color) -{ - m_view->setSelectionTopBorderColor(color); -} - -void ViewIface::setRightBorderColor(TQColor color) -{ - m_view->setSelectionRightBorderColor(color); -} - -void ViewIface::setBottomBorderColor(TQColor color) -{ - m_view->setSelectionBottomBorderColor(color); -} - -void ViewIface::setAllBorderColor(TQColor color) -{ - m_view->setSelectionAllBorderColor(color); -} - -void ViewIface::setOutlineBorderColor(TQColor color) -{ - m_view->setSelectionOutlineBorderColor(color); -} - -void ViewIface::removeBorder() -{ - m_view->borderRemove(); -} - -void ViewIface::increaseIndent() -{ - m_view->increaseIndent(); -} - -void ViewIface::decreaseIndent() -{ - m_view->increaseIndent(); -} - -void ViewIface::subtotals() -{ - m_view->subtotals(); -} - -void ViewIface::sortInc() -{ - m_view->sortInc(); -} - -void ViewIface::sortDec() -{ - m_view->sortDec(); -} - -void ViewIface::layoutDlg() -{ - m_view->layoutDlg(); -} - - -void ViewIface::increaseFontSize() -{ - m_view->increaseFontSize(); -} - -void ViewIface::decreaseFontSize() -{ - m_view->decreaseFontSize(); -} diff --git a/kspread/KSpreadViewIface.cpp b/kspread/KSpreadViewIface.cpp new file mode 100644 index 00000000..1fb76f46 --- /dev/null +++ b/kspread/KSpreadViewIface.cpp @@ -0,0 +1,459 @@ +/* This file is part of the KDE project + + Copyright 2004 Ariya Hidayat + Copyright 2002-2003 Joseph Wenninger + Copyright 2002 John Dailey + Copyright 2001-2002 Laurent Montel + Copyright 2001 Philipp Mueller + Copyright 2000 Simon Hausmann + Copyright 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "kspread_doc.h" +#include "kspread_map.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_view.h" + +#include "KSpreadViewIface.h" + +using namespace KSpread; + +/************************************************ + * + * ViewIface + * + ************************************************/ + +ViewIface::ViewIface( View* t ) + : KoViewIface( t ) +{ + m_view = t; +} + +ViewIface::~ViewIface() +{ +} + +DCOPRef ViewIface::doc() const +{ + return DCOPRef( kapp->dcopClient()->appId(), m_view->doc()->dcopObject()->objId() ); +} + +DCOPRef ViewIface::map() const +{ + return DCOPRef( kapp->dcopClient()->appId(), m_view->doc()->map()->dcopObject()->objId() ); +} + +DCOPRef ViewIface::sheet() const +{ + return DCOPRef( kapp->dcopClient()->appId(), m_view->activeSheet()->dcopObject()->objId() ); +} + +void ViewIface::changeNbOfRecentFiles(int _nb) +{ + if(_nb<0) + return; + m_view->changeNbOfRecentFiles(_nb); +} + + +void ViewIface::hide() +{ + m_view->hide(); +} + +void ViewIface::show() +{ + m_view->show(); +} + +void ViewIface::find() +{ + m_view->find(); +} + +void ViewIface::replace() +{ + m_view->replace(); +} + +void ViewIface::conditional() +{ + m_view->conditional(); +} + +void ViewIface::validity() +{ + m_view->validity(); +} + +void ViewIface::insertSeries() +{ + m_view->insertSeries(); +} + +void ViewIface::insertHyperlink() +{ + m_view->insertHyperlink(); +} + +void ViewIface::gotoCell() +{ + m_view->gotoCell(); +} + +void ViewIface::changeAngle() +{ + m_view->changeAngle(); +} + +void ViewIface::preference() +{ + m_view->preference(); +} + +void ViewIface::nextSheet() +{ + m_view->nextSheet(); +} + +bool ViewIface::showSheet(TQString sheetName) +{ + return m_view->showSheet(sheetName); +} + +void ViewIface::previousSheet() +{ + m_view->previousSheet(); +} + +void ViewIface::sortList() +{ + m_view->sortList(); +} + +void ViewIface::setAreaName() +{ + m_view->setAreaName(); +} + +void ViewIface::showAreaName() +{ + m_view->showAreaName(); +} + +void ViewIface::mergeCell() +{ + m_view->mergeCell(); +} + +void ViewIface::dissociateCell() +{ + m_view->dissociateCell(); +} + +void ViewIface::consolidate() +{ + m_view->consolidate(); +} + +void ViewIface::deleteColumn() +{ + m_view->deleteColumn(); +} + +void ViewIface::insertColumn() +{ + m_view->insertColumn(); +} + +void ViewIface::deleteRow() +{ + m_view->deleteRow(); +} + +void ViewIface::insertRow() +{ + m_view->insertRow(); +} + +void ViewIface::hideRow() +{ + m_view->hideRow(); +} + +void ViewIface::showRow() +{ + m_view->showRow(); +} + +void ViewIface::hideColumn() +{ + m_view->hideColumn(); +} + +void ViewIface::showColumn() +{ + m_view->showColumn(); +} + +void ViewIface::upper() +{ + m_view->upper(); +} + +void ViewIface::lower() +{ + m_view->lower(); +} + +void ViewIface::equalizeColumn() +{ + m_view->equalizeColumn(); +} + +void ViewIface::equalizeRow() +{ + m_view->equalizeRow(); +} + +void ViewIface::clearTextSelection() +{ + m_view->clearTextSelection(); +} + +void ViewIface::clearCommentSelection() +{ + m_view->clearCommentSelection(); +} + +void ViewIface::clearValiditySelection() +{ + m_view->clearValiditySelection(); +} + +void ViewIface::clearConditionalSelection() +{ + m_view->clearConditionalSelection(); +} + +void ViewIface::goalSeek() +{ + m_view->goalSeek(); +} + +void ViewIface::insertFromDatabase() +{ + m_view->insertFromDatabase(); +} + +void ViewIface::insertFromTextfile() +{ + m_view->insertFromTextfile(); +} + +void ViewIface::insertFromClipboard() +{ + m_view->insertFromClipboard(); +} + +void ViewIface::textToColumns() +{ + m_view->textToColumns(); +} + +void ViewIface::copyAsText() +{ + m_view->copyAsText(); +} + +void ViewIface::setSelection(TQRect selection) +{ + m_view->selectionInfo()->initialize(selection);//,m_view->activeSheet()); +} + +TQRect ViewIface::selection() +{ + return m_view->selectionInfo()->selection(); +} + +void ViewIface::setSelectionMoneyFormat( bool b ) +{ + m_view->moneyFormat(b); +} + +void ViewIface::setSelectionPrecision( int delta ) +{ + m_view->setSelectionPrecision(delta); +} + +void ViewIface::setSelectionPercent( bool b ) +{ + m_view->percent(b); +} + +void ViewIface::setSelectionMultiRow( bool enable ) +{ + m_view->wrapText(enable); +} + +void ViewIface::setSelectionSize(int size) +{ + m_view->setSelectionFontSize(size); +} + +void ViewIface::setSelectionUpper() +{ + m_view->upper(); +} + +void ViewIface::setSelectionLower() +{ + m_view->lower(); +} + +void ViewIface::setSelectionFirstLetterUpper() +{ + m_view->firstLetterUpper(); +} + +void ViewIface::setSelectionVerticalText(bool enable) +{ + m_view->verticalText(enable); +} + +void ViewIface::setSelectionComment(TQString comment) +{ + m_view->setSelectionComment(comment); +} + +void ViewIface::setSelectionAngle(int value) +{ + m_view->setSelectionAngle(value); +} + +void ViewIface::setSelectionTextColor( TQColor txtColor ) +{ + m_view->setSelectionTextColor(txtColor); +} + +void ViewIface::setSelectionBgColor( TQColor bgColor ) +{ + m_view->setSelectionBackgroundColor(bgColor); +} + +void ViewIface::setSelectionBorderColor( TQColor bdColor ) +{ + m_view->setSelectionBorderColor(bdColor); +} + +void ViewIface::deleteSelection() +{ + m_view->clearTextSelection(); +} + +void ViewIface::copySelection() +{ + m_view->copySelection(); +} + +void ViewIface::cutSelection() +{ + m_view->cutSelection(); +} + +void ViewIface::setLeftBorderColor(TQColor color) +{ + m_view->setSelectionLeftBorderColor(color); +} + +void ViewIface::setTopBorderColor(TQColor color) +{ + m_view->setSelectionTopBorderColor(color); +} + +void ViewIface::setRightBorderColor(TQColor color) +{ + m_view->setSelectionRightBorderColor(color); +} + +void ViewIface::setBottomBorderColor(TQColor color) +{ + m_view->setSelectionBottomBorderColor(color); +} + +void ViewIface::setAllBorderColor(TQColor color) +{ + m_view->setSelectionAllBorderColor(color); +} + +void ViewIface::setOutlineBorderColor(TQColor color) +{ + m_view->setSelectionOutlineBorderColor(color); +} + +void ViewIface::removeBorder() +{ + m_view->borderRemove(); +} + +void ViewIface::increaseIndent() +{ + m_view->increaseIndent(); +} + +void ViewIface::decreaseIndent() +{ + m_view->increaseIndent(); +} + +void ViewIface::subtotals() +{ + m_view->subtotals(); +} + +void ViewIface::sortInc() +{ + m_view->sortInc(); +} + +void ViewIface::sortDec() +{ + m_view->sortDec(); +} + +void ViewIface::layoutDlg() +{ + m_view->layoutDlg(); +} + + +void ViewIface::increaseFontSize() +{ + m_view->increaseFontSize(); +} + +void ViewIface::decreaseFontSize() +{ + m_view->decreaseFontSize(); +} diff --git a/kspread/Makefile.am b/kspread/Makefile.am index df50d89d..da52cf90 100644 --- a/kspread/Makefile.am +++ b/kspread/Makefile.am @@ -8,24 +8,24 @@ INCLUDES = $(KOFFICE_INCLUDES) $(KOTEXT_INCLUDES) -I$(interfacedir) \ lib_LTLIBRARIES = libkspreadcommon.la kde_module_LTLIBRARIES = libkspreadpart.la -libkspreadcommon_la_SOURCES = digest.cc commands.cc damages.cc dependencies.cc \ - formula.cc functions.cc kspread_autofill.cc kspread_canvas.cc \ - kspread_cell.cc kspread_cluster.cc kspread_condition.cc kspread_doc.cc \ - kspread_editors.cc kspread_events.cc kspread_factory.cc kspread_format.cc \ - kspread_functions_conversion.cc kspread_functions_database.cc kspread_functions_datetime.cc \ - kspread_functions_engineering.cc kspread_functions_financial.cc kspread_functions_helper.cc \ - kspread_functions_information.cc kspread_functions_logic.cc kspread_functions_math.cc \ - kspread_functions_reference.cc kspread_functions_statistical.cc kspread_functions_text.cc \ - kspread_functions_trig.cc kspread_handler.cc kspread_locale.cc kspread_map.cc \ - kspread_numformat.cc kspread_object.cc kspread_style.cc kspread_style_manager.cc \ - kspread_undo.cc kspread_value.cc kspread_view.cc kspread_sheet.cc kspread_sheetprint.cc \ - kspread_util.cc kspread_toolbox.cc valuecalc.cc valueconverter.cc valueformatter.cc \ - valueparser.cc KSpreadAppIface.cc KSpreadAppIface.skel KSpreadCellIface.cc \ - KSpreadCellIface.skel KSpreadColumnIface.skel KSpreadColumnIface.cc KSpreadDocIface.cc \ - KSpreadDocIface.skel KSpreadLayoutIface.skel KSpreadLayoutIface.cc KSpreadMapIface.cc \ - KSpreadMapIface.skel KSpreadRowIface.skel KSpreadRowIface.cc KSpreadTableIface.cc \ - KSpreadTableIface.skel KSpreadViewIface.skel KSpreadViewIface.cc \ - kspread_genvalidationstyle.cc region.cc selection.cc manipulator.cc manipulator_data.cc \ +libkspreadcommon_la_SOURCES = digest.cpp commands.cpp damages.cpp dependencies.cpp \ + formula.cpp functions.cpp kspread_autofill.cpp kspread_canvas.cpp \ + kspread_cell.cpp kspread_cluster.cpp kspread_condition.cpp kspread_doc.cpp \ + kspread_editors.cpp kspread_events.cpp kspread_factory.cpp kspread_format.cpp \ + kspread_functions_conversion.cpp kspread_functions_database.cpp kspread_functions_datetime.cpp \ + kspread_functions_engineering.cpp kspread_functions_financial.cpp kspread_functions_helper.cpp \ + kspread_functions_information.cpp kspread_functions_logic.cpp kspread_functions_math.cpp \ + kspread_functions_reference.cpp kspread_functions_statistical.cpp kspread_functions_text.cpp \ + kspread_functions_trig.cpp kspread_handler.cpp kspread_locale.cpp kspread_map.cpp \ + kspread_numformat.cpp kspread_object.cpp kspread_style.cpp kspread_style_manager.cpp \ + kspread_undo.cpp kspread_value.cpp kspread_view.cpp kspread_sheet.cpp kspread_sheetprint.cpp \ + kspread_util.cpp kspread_toolbox.cpp valuecalc.cpp valueconverter.cpp valueformatter.cpp \ + valueparser.cpp KSpreadAppIface.cpp KSpreadAppIface.skel KSpreadCellIface.cpp \ + KSpreadCellIface.skel KSpreadColumnIface.skel KSpreadColumnIface.cpp KSpreadDocIface.cpp \ + KSpreadDocIface.skel KSpreadLayoutIface.skel KSpreadLayoutIface.cpp KSpreadMapIface.cpp \ + KSpreadMapIface.skel KSpreadRowIface.skel KSpreadRowIface.cpp KSpreadTableIface.cpp \ + KSpreadTableIface.skel KSpreadViewIface.skel KSpreadViewIface.cpp \ + kspread_genvalidationstyle.cpp region.cpp selection.cpp manipulator.cpp manipulator_data.cpp \ kspread_generalProperty.cpp kspread_propertyEditor.cpp libkspreadcommon_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined -ltdecore -ltdeui $(LIB_TQT) -lkjs -ltdefx -ltdeio -ltdeparts -ltdeutils @@ -35,7 +35,7 @@ libkspreadcommon_la_LIBADD = $(top_builddir)/interfaces/libkochart.la \ libkspreadpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -ltdecore -ltdeui $(LIB_TQT) -lkjs -ltdefx -ltdeio -ltdeparts libkspreadpart_la_LIBADD = libkspreadcommon.la -libkspreadpart_la_SOURCES = kspread_factory_init.cc +libkspreadpart_la_SOURCES = kspread_factory_init.cpp METASOURCES = AUTO @@ -43,7 +43,7 @@ METASOURCES = AUTO ## The tdeinit loadable module and the executable tdeinit_LTLIBRARIES = kspread.la bin_PROGRAMS = -kspread_la_SOURCES = main.cc +kspread_la_SOURCES = main.cpp kspread_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -ltdecore -ltdeui $(LIB_TQT) -lkjs -ltdefx -ltdeio -ltdeparts kspread_la_LIBADD = $(LIB_KOFFICECORE) @@ -63,10 +63,10 @@ parser: bison -p dep -b dep -d yacc.dep.y messages: rc.cpp - $(EXTRACTRC) --tag-group=koffice extensions/*.xml > xml_doc.cc + $(EXTRACTRC) --tag-group=koffice extensions/*.xml > xml_doc.cpp $(EXTRACTRC) dialogs/*.ui >> rc.cpp - $(XGETTEXT) rc.cpp *.cc kspread_aboutdata.h dialogs/*.cc tests/*.cc -o $(podir)/kspread.pot - -rm xml_doc.cc + $(XGETTEXT) rc.cpp *.cpp kspread_aboutdata.h dialogs/*.cpp tests/*.cpp -o $(podir)/kspread.pot + -rm xml_doc.cpp include ../admin/Doxyfile.am diff --git a/kspread/TODO b/kspread/TODO index 575d8c8d..0769dc6f 100644 --- a/kspread/TODO +++ b/kspread/TODO @@ -160,7 +160,7 @@ Things to do after the release of KOffice 1.4 + code cleanups 3 ---- - Merge Cell::checkForNamedAreas(.) into Oasis::decodeFormula(.). - Move Cell::convertFormulaToOasisFormat(..) to - Oasis::encodeFormula to reduce the size of kspread_cell.cc + Oasis::encodeFormula to reduce the size of kspread_cell.cpp and to have encoding/decoding in one place. - Check if all logic of Point and Range is materialized in Region. Replace all occurences of Point and Range by Region. diff --git a/kspread/commands.cc b/kspread/commands.cc deleted file mode 100644 index 490bee81..00000000 --- a/kspread/commands.cc +++ /dev/null @@ -1,946 +0,0 @@ -/* This file is part of the KDE project - Copyright 2004 Ariya Hidayat - Copyright 2004 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "commands.h" -#include "damages.h" -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_undo.h" -#include "kspread_util.h" - -#include "kspread_sheetprint.h" - -using namespace KSpread; - -// ----- UndoWrapperCommand ----- - -UndoWrapperCommand::UndoWrapperCommand( UndoAction* ua ) -{ - undoAction = ua; -} - -void UndoWrapperCommand::execute() -{ - // This is not really safe and functional, but UndoWrapperCommand - // is a workaround anyway. So leave it as it it (Ariya) - undoAction->redo(); -} - -void UndoWrapperCommand::unexecute() -{ - undoAction->undo(); -} - -TQString UndoWrapperCommand::name() const -{ - return undoAction->getName(); -} - -// ----- MergeCellsCommand ----- - -MergeCellCommand::MergeCellCommand( Cell* c, int cs, int rs ) -{ - cell = c; - colSpan = cs; - rowSpan = rs; - oldColSpan = cell->extraXCells(); - oldRowSpan = cell->extraYCells(); - if( cell ) - { - TQRect area( cell->column(), cell->row(), cs+1, rs+1 ); - rangeName = util_rangeName( area ); - } -} - -TQString MergeCellCommand::name() const -{ - if( rangeName.isEmpty() ) - return i18n("Merge Cells"); - else - return i18n("Merge Cells %1").arg( rangeName ); -} - -void MergeCellCommand::execute() -{ - Sheet* sheet = cell->sheet(); - if( !sheet ) return; - sheet->changeMergedCell( cell->column(), cell->row(), colSpan, rowSpan); -} - -void MergeCellCommand::unexecute() -{ - Sheet* sheet = cell->sheet(); - if( !sheet ) return; - sheet->changeMergedCell( cell->column(), cell->row(), oldColSpan, oldRowSpan); -} - -// ----- DissociateCellCommand ----- - -DissociateCellCommand::DissociateCellCommand( Cell* c ) -{ - cell = c; - oldColSpan = cell->extraXCells(); - oldRowSpan = cell->extraYCells(); -} - -TQString DissociateCellCommand::name() const -{ - return i18n("Dissociate Cell"); -} - -void DissociateCellCommand::execute() -{ - Sheet* sheet = cell->sheet(); - if( !sheet ) return; - sheet->changeMergedCell( cell->column(), cell->row(), 0, 0 ); -} - -void DissociateCellCommand::unexecute() -{ - Sheet* sheet = cell->sheet(); - if( !sheet ) return; - sheet->changeMergedCell( cell->column(), cell->row(), oldColSpan, oldRowSpan); -} - -// ----- RenameSheetCommand ----- - -RenameSheetCommand::RenameSheetCommand( Sheet* s, const TQString &name ) -{ - sheet = s; - if( s ) oldName = s->sheetName(); - newName = name; -} - -TQString RenameSheetCommand::name() const -{ - return i18n("Rename Sheet"); -} - -void RenameSheetCommand::execute() -{ - if( sheet ) - sheet->setSheetName( newName ); -} - -void RenameSheetCommand::unexecute() -{ - if( sheet ) - sheet->setSheetName( oldName ); -} - -// ----- HideSheetCommand ----- - -HideSheetCommand::HideSheetCommand( Sheet* sheet ) -{ - doc = sheet->doc(); - sheetName = sheet->sheetName(); -} - -void HideSheetCommand::execute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - - sheet->hideSheet( true ); -} - -void HideSheetCommand::unexecute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - - sheet->hideSheet( false ); -} - -TQString HideSheetCommand::name() const -{ - TQString n = TQString( i18n("Hide Sheet %1") ).arg( sheetName ); - if( n.length() > 64 ) n = i18n("Hide Sheet"); - return n; -} - -// ----- ShowSheetCommand ----- - -ShowSheetCommand::ShowSheetCommand( Sheet* sheet ) -{ - doc = sheet->doc(); - sheetName = sheet->sheetName(); -} - -void ShowSheetCommand::execute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - - sheet->hideSheet( false ); -} - -void ShowSheetCommand::unexecute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - - sheet->hideSheet( true ); -} - -TQString ShowSheetCommand::name() const -{ - TQString n = TQString( i18n("Show Sheet %1") ).arg( sheetName ); - if( n.length() > 64 ) n = i18n("Show Sheet"); - return n; -} - - -// ----- AddSheetCommand ----- - -AddSheetCommand::AddSheetCommand( Sheet* s ) -{ - sheet = s; - doc = sheet->doc(); - doc->map()->addSheet( s ); -} - -void AddSheetCommand::execute() -{ - sheet->workbook()->insertSheet( sheet ); - doc->insertSheet( sheet ); -} - -void AddSheetCommand::unexecute() -{ - sheet->workbook()->takeSheet( sheet ); - doc->takeSheet( sheet ); -} - -TQString AddSheetCommand::name() const -{ - return i18n("Add Sheet"); -} - - -// ----- RemoveSheetCommand ----- - -RemoveSheetCommand::RemoveSheetCommand( Sheet* s ) -{ - sheet = s; - doc = sheet->doc(); -} - -void RemoveSheetCommand::execute() -{ - sheet->workbook()->takeSheet( sheet ); - doc->takeSheet( sheet ); -} - -void RemoveSheetCommand::unexecute() -{ - sheet->workbook()->insertSheet( sheet ); - doc->insertSheet( sheet ); -} - -TQString RemoveSheetCommand::name() const -{ - return i18n("Remove Sheet"); -} - -// ----- SheetPropertiesCommand ----- - -SheetPropertiesCommand::SheetPropertiesCommand( Doc* d, Sheet* s ) -{ - sheet = s; - doc = d; - oldDirection = newDirection = sheet->layoutDirection(); - oldAutoCalc = newAutoCalc = sheet->getAutoCalc(); - oldShowGrid = newShowGrid = sheet->getShowGrid(); - oldShowPageBorders = newShowPageBorders = sheet->isShowPageBorders(); - oldShowFormula = newShowFormula = sheet->getShowFormula(); - oldHideZero = newHideZero = sheet->getHideZero(); - oldShowFormulaIndicator = newShowFormulaIndicator = sheet->getShowFormulaIndicator(); - oldShowCommentIndicator = newShowCommentIndicator = sheet->getShowCommentIndicator(); - oldColumnAsNumber = newColumnAsNumber = sheet->getShowColumnNumber(); - oldLcMode = newLcMode = sheet->getLcMode(); - oldCapitalizeFirstLetter = newCapitalizeFirstLetter = sheet->getFirstLetterUpper(); -} - -TQString SheetPropertiesCommand::name() const -{ - return i18n("Change Sheet Properties"); -} - -void SheetPropertiesCommand::setLayoutDirection( Sheet::LayoutDirection dir ) -{ - newDirection = dir; -} - -void SheetPropertiesCommand::setAutoCalc( bool b ) -{ - newAutoCalc = b; -} - -void SheetPropertiesCommand::setShowGrid( bool b ) -{ - newShowGrid = b; -} - -void SheetPropertiesCommand::setShowPageBorders( bool b ) -{ - newShowPageBorders = b; -} - -void SheetPropertiesCommand::setShowFormula( bool b ) -{ - newShowFormula = b; -} - -void SheetPropertiesCommand::setHideZero( bool b ) -{ - newHideZero = b; -} - -void SheetPropertiesCommand::setShowFormulaIndicator( bool b ) -{ - newShowFormulaIndicator = b; -} - -void SheetPropertiesCommand::setShowCommentIndicator( bool b ) -{ - newShowCommentIndicator = b; -} - -void SheetPropertiesCommand::setColumnAsNumber( bool b ) -{ - newColumnAsNumber = b; -} - -void SheetPropertiesCommand::setLcMode( bool b ) -{ - newLcMode = b; -} - -void SheetPropertiesCommand::setCapitalizeFirstLetter( bool b ) -{ - newCapitalizeFirstLetter = b; -} - -void SheetPropertiesCommand::execute() -{ - sheet->setLayoutDirection( newDirection ); - sheet->setAutoCalc( newAutoCalc ); - sheet->setShowGrid( newShowGrid ); - sheet->setShowPageBorders( newShowPageBorders ); - sheet->setShowFormula( newShowFormula ); - sheet->setHideZero( newHideZero ); - sheet->setShowFormulaIndicator( newShowFormulaIndicator ); - sheet->setShowCommentIndicator( newShowCommentIndicator ); - sheet->setShowColumnNumber( newColumnAsNumber ); - sheet->setLcMode( newLcMode ); - sheet->setFirstLetterUpper( newCapitalizeFirstLetter ); - doc->addDamage( new SheetDamage( sheet, SheetDamage::PropertiesChanged ) ); -} - -void SheetPropertiesCommand::unexecute() -{ - sheet->setLayoutDirection( oldDirection ); - sheet->setAutoCalc( oldAutoCalc ); - sheet->setShowGrid( oldShowGrid ); - sheet->setShowPageBorders( oldShowPageBorders ); - sheet->setShowFormula( oldShowFormula ); - sheet->setHideZero( oldHideZero ); - sheet->setShowFormulaIndicator( oldShowFormulaIndicator ); - sheet->setShowCommentIndicator( oldShowCommentIndicator ); - sheet->setShowColumnNumber( oldColumnAsNumber ); - sheet->setLcMode( oldLcMode ); - sheet->setFirstLetterUpper( oldCapitalizeFirstLetter ); - doc->addDamage( new SheetDamage( sheet, SheetDamage::PropertiesChanged ) ); -} - - -// ----- InsertColumnCommand ----- - -InsertColumnCommand::InsertColumnCommand( Sheet* s , unsigned int _column, unsigned int _nbCol ) -{ - doc = s->doc(); - sheetName = s->sheetName(); - insertPosColumn = _column; - nbColumnInserted = _nbCol; -} - -void InsertColumnCommand::execute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - sheet->insertColumn( insertPosColumn,nbColumnInserted); -} - -void InsertColumnCommand::unexecute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - sheet->removeColumn( insertPosColumn,nbColumnInserted ); -} - -TQString InsertColumnCommand::name() const -{ - return i18n("Insert Columns"); -} - - -// ----- DefinePrintRangeCommand ----- - - -DefinePrintRangeCommand::DefinePrintRangeCommand( Sheet *s ) -{ - doc = s->doc(); - sheetName = s->sheetName(); - printRange = s->print()->printRange(); -} - -void DefinePrintRangeCommand::execute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - sheet->print()->setPrintRange( printRangeRedo ); - -} - -void DefinePrintRangeCommand::unexecute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - printRangeRedo = sheet->print()->printRange(); - sheet->print()->setPrintRange( printRange ); -} - -TQString DefinePrintRangeCommand::name() const -{ - return i18n("Set Page Layout"); -} - -// ----- PaperLayoutCommand ----- - - -PaperLayoutCommand::PaperLayoutCommand( Sheet *s ) -{ - doc = s->doc(); - sheetName = s->sheetName(); - pl = s->print()->paperLayout(); - hf = s->print()->headFootLine(); - unit = doc->unit(); - printGrid = s->print()->printGrid(); - printCommentIndicator = s->print()->printCommentIndicator(); - printFormulaIndicator = s->print()->printFormulaIndicator(); - printRange = s->print()->printRange(); - printRepeatColumns = s->print()->printRepeatColumns(); - printRepeatRows = s->print()->printRepeatRows(); - zoom = s->print()->zoom(); - pageLimitX = s->print()->pageLimitX(); - pageLimitY = s->print()->pageLimitY(); -} - -void PaperLayoutCommand::execute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - SheetPrint* print = sheet->print(); - - print->setPaperLayout( plRedo.ptLeft, plRedo.ptTop, - plRedo.ptRight, plRedo.ptBottom, - plRedo.format, plRedo.orientation ); - - print->setHeadFootLine( hfRedo.headLeft, hfRedo.headMid, hfRedo.headRight, - hfRedo.footLeft, hfRedo.footMid, hfRedo.footRight ); - - doc->setUnit( unitRedo ); - - print->setPrintGrid( printGridRedo ); - print->setPrintCommentIndicator( printCommentIndicatorRedo ); - print->setPrintFormulaIndicator( printFormulaIndicatorRedo ); - - print->setPrintRange( printRangeRedo ); - print->setPrintRepeatColumns( printRepeatColumnsRedo ); - print->setPrintRepeatRows( printRepeatRowsRedo ); - - print->setZoom( zoomRedo ); - - print->setPageLimitX( pageLimitX ); - print->setPageLimitY( pageLimitY ); -} - -void PaperLayoutCommand::unexecute() -{ - Sheet* sheet = doc->map()->findSheet( sheetName ); - if( !sheet ) return; - SheetPrint* print = sheet->print(); - plRedo = print->paperLayout(); - print->setPaperLayout( pl.ptLeft, pl.ptTop, - pl.ptRight, pl.ptBottom, - pl.format, pl.orientation ); - - hfRedo = print->headFootLine(); - print->setHeadFootLine( hf.headLeft, hf.headMid, hf.headRight, - hf.footLeft, hf.footMid, hf.footRight ); - - unitRedo = doc->unit(); - doc->setUnit( unit ); - - printGridRedo = print->printGrid(); - print->setPrintGrid( printGrid ); - - printCommentIndicatorRedo = print->printCommentIndicator(); - print->setPrintCommentIndicator( printCommentIndicator ); - - printFormulaIndicatorRedo = print->printFormulaIndicator(); - print->setPrintFormulaIndicator( printFormulaIndicator ); - - printRangeRedo = print->printRange(); - print->setPrintRange( printRange ); - - printRepeatColumnsRedo = print->printRepeatColumns(); - print->setPrintRepeatColumns( printRepeatColumns ); - - printRepeatRowsRedo = print->printRepeatRows(); - print->setPrintRepeatRows( printRepeatRows ); - - zoomRedo = print->zoom(); - print->setZoom( zoom ); - - pageLimitXRedo = print->pageLimitX(); - print->setPageLimitX( pageLimitX ); - - pageLimitYRedo = print->pageLimitY(); - print->setPageLimitY( pageLimitY ); - -} - -TQString PaperLayoutCommand::name() const -{ - return i18n("Set Page Layout"); -} - -LinkCommand::LinkCommand( Cell* c, const TQString& text, const TQString& link ) -{ - cell = c; - oldText = cell->text(); - oldLink = cell->link(); - newText = text; - newLink = link; - - Sheet* s = cell->sheet(); - if( s ) doc = s->doc(); -} - -void LinkCommand::execute() -{ - if( !cell ) return; - - if( !newText.isEmpty() ) - cell->setCellText( newText ); - cell->setLink( newLink ); - - doc->addDamage( new CellDamage( cell ) ); -} - -void LinkCommand::unexecute() -{ - if( !cell ) return; - - cell->setCellText( oldText ); - cell->setLink( oldLink ); - - doc->addDamage( new CellDamage( cell ) ); -} - -TQString LinkCommand::name() const -{ - return newLink.isEmpty() ? i18n("Remove Link") : i18n("Set Link"); -} - -ChangeObjectGeometryCommand::ChangeObjectGeometryCommand( EmbeddedObject *_obj, const KoPoint &_m_diff, const KoSize &_r_diff ) - : m_diff( _m_diff ), r_diff( _r_diff ) -{ - obj = _obj; - obj->incCmdRef(); - doc = obj->sheet()->doc(); -} - -ChangeObjectGeometryCommand::~ChangeObjectGeometryCommand() -{ - obj->decCmdRef(); -} - -void ChangeObjectGeometryCommand::execute() -{ - doc->repaint( obj->geometry() ); - - KoRect geometry = obj->geometry(); - geometry.moveBy( m_diff.x(), m_diff.y() ); - geometry.setWidth( geometry.width() + r_diff.width() ); - geometry.setHeight( geometry.height() + r_diff.height() ); - obj->setGeometry( geometry ); - -// if ( object->isSelected()) -// doc->updateObjectStatusBarItem(); - doc->repaint( obj ); -} - -void ChangeObjectGeometryCommand::unexecute() -{ - doc->repaint( obj->geometry() ); - - KoRect geometry = obj->geometry(); - geometry.moveBy( -m_diff.x(), -m_diff.y() ); - geometry.setWidth( geometry.width() - r_diff.width() ); - geometry.setHeight( geometry.height() - r_diff.height() ); - obj->setGeometry( geometry ); - -// if ( object->isSelected()) -// doc->updateObjectStatusBarItem(); - doc->repaint( obj ); -} - -TQString ChangeObjectGeometryCommand::name() const -{ - /*if ( fabs( obj->geometry().width() - newGeometry.width() )<1e-3 && fabs( obj->geometry().height() - newGeometry.height() ) < 1e-3 ) - return i18n("Move Object"); - else */ - return i18n("Resize Object"); -} - -RemoveObjectCommand::RemoveObjectCommand( EmbeddedObject *_obj, bool _cut ) -{ - obj = _obj; - cut = _cut; - doc = obj->sheet()->doc(); -} - -RemoveObjectCommand::~RemoveObjectCommand() -{ - if ( !executed ) - return; - //kdDebug() << "*********Deleting object..." << endl; - if ( obj->getType() == OBJECT_CHART ) - { - EmbeddedKOfficeObject *chart = dynamic_cast(obj); - chart->embeddedObject()->setDeleted(true); - } - - delete obj; -} - -void RemoveObjectCommand::execute() -{ - -// I don't think we need this: -// Make shure that this child has no active embedded view -> activate ourselfs -// doc()->emitBeginOperation( false ); -// partManager()->setActivePart( koDocument(), this ); -// partManager()->setSelectedPart( 0 ); -// doc()->emitEndOperation( d->activeSheet->visibleRect( d->canvas ) ); - - doc->embeddedObjects().removeRef( obj ); - if ( obj->getType() == OBJECT_CHART || obj->getType()== OBJECT_KOFFICE_PART) - { - EmbeddedKOfficeObject *eko = dynamic_cast(obj); - eko->embeddedObject()->setDeleted(true); - } - - obj->setSelected( false ); - doc->repaint( obj ); - executed = true; -} - -void RemoveObjectCommand::unexecute() -{ - doc->embeddedObjects().append( obj ); - if ( obj->getType() == OBJECT_CHART || obj->getType()== OBJECT_KOFFICE_PART) - { - EmbeddedKOfficeObject *eko = dynamic_cast(obj); - eko->embeddedObject()->setDeleted(false); - } - doc->repaint( obj ); - executed = false; -} - -TQString RemoveObjectCommand::name() const -{ - if ( cut ) - return i18n("Cut Object"); - else - return i18n("Remove Object"); -} - -InsertObjectCommand::InsertObjectCommand( const KoRect& _geometry, KoDocumentEntry& _entry, Canvas *_canvas ) //child -{ - geometry = _geometry; - entry = _entry; - canvas = _canvas; - type = OBJECT_KOFFICE_PART; - obj = 0; -} - -InsertObjectCommand::InsertObjectCommand(const KoRect& _geometry, KoDocumentEntry& _entry, const TQRect& _data, Canvas *_canvas ) //chart -{ - geometry = _geometry; - entry = _entry; - data = _data; - canvas = _canvas; - type = OBJECT_CHART; - obj = 0; -} - -InsertObjectCommand::InsertObjectCommand( const KoRect& _geometry , KURL& _file, Canvas *_canvas ) //picture -{ - //In the case of pictures, only the top left point of the rectangle is relevant - geometry = _geometry; - file = _file; - canvas = _canvas; - type = OBJECT_PICTURE; - obj = 0; -} - -InsertObjectCommand::~InsertObjectCommand() -{ - if ( executed ) - return; - //kdDebug() << "*********Deleting object..." << endl; - if ( obj->getType() == OBJECT_CHART ) - { - EmbeddedKOfficeObject *chart = dynamic_cast(obj); - chart->embeddedObject()->setDeleted(true); - } - - delete obj; -} - -void InsertObjectCommand::execute() -{ - if ( obj ) //restore the object which was removed from the object list in InsertObjectCommand::unexecute() - { - canvas->doc()->embeddedObjects().append( obj ); - canvas->doc()->repaint( obj ); - } - else - { - bool success = false; - switch ( type ) - { - case OBJECT_CHART: - { - success = canvas->activeSheet()->insertChart( geometry, entry, data ); - break; - } - case OBJECT_KOFFICE_PART: - { - success = canvas->activeSheet()->insertChild( geometry, entry ); - break; - } - case OBJECT_PICTURE: - { - success = canvas->activeSheet()->insertPicture( geometry.topLeft() , file ); - break; - } - default: - break; - } - if ( success ) - { - obj = canvas->doc()->embeddedObjects().last(); - obj->sheet()->unifyObjectName( obj ); - } - else - obj = 0; - } - executed = true; -} - -void InsertObjectCommand::unexecute() -{ - if ( !obj ) - return; - - canvas->doc()->embeddedObjects().removeRef( obj ); - obj->setSelected( false ); - canvas->doc()->repaint( obj ); - - executed = false; -} - -TQString InsertObjectCommand::name() const -{ - return i18n("Insert Object"); -} - -RenameNameObjectCommand::RenameNameObjectCommand( const TQString &_name, const TQString &_objectName, - EmbeddedObject *_obj, Doc *_doc ): - KNamedCommand( _name ), - newObjectName( _objectName ), - object( _obj ), - doc( _doc ) -{ - oldObjectName = object->getObjectName(); - - m_page = object->sheet()/*doc->findPage( object )*/; -} - -RenameNameObjectCommand::~RenameNameObjectCommand() -{ -} - -void RenameNameObjectCommand::execute() -{ - object->setObjectName( newObjectName ); - m_page->unifyObjectName( object ); - -// doc->updateSideBarItem( m_page ); -} - -void RenameNameObjectCommand::unexecute() -{ - object->setObjectName( oldObjectName ); - -// doc->updateSideBarItem( m_page ); -} - -GeometryPropertiesCommand::GeometryPropertiesCommand( const TQString &name, TQPtrList &objects, - bool newValue, KgpType type, Doc *_doc ) -: KNamedCommand( name ) -, m_objects( objects ) -, m_newValue( newValue ) -, m_type( type ) - , m_doc( _doc ) -{ - TQPtrListIterator it( m_objects ); - for ( ; it.current() ; ++it ) - { - it.current()->incCmdRef(); - if ( m_type == ProtectSize ) - m_oldValue.append( it.current()->isProtect() ); - else if ( m_type == KeepRatio) - m_oldValue.append( it.current()->isKeepRatio() ); - } -} - -GeometryPropertiesCommand::GeometryPropertiesCommand( const TQString &name, TQValueList &lst, - TQPtrList &objects, bool newValue, - KgpType type, Doc *_doc) -: KNamedCommand( name ) -, m_oldValue( lst ) -, m_objects( objects ) -, m_newValue( newValue ) -, m_type( type ) -, m_doc ( _doc ) -{ - TQPtrListIterator it( m_objects ); - for ( ; it.current() ; ++it ) - it.current()->incCmdRef(); -} - -GeometryPropertiesCommand::~GeometryPropertiesCommand() -{ - TQPtrListIterator it( m_objects ); - for ( ; it.current() ; ++it ) - it.current()->decCmdRef(); -} - -void GeometryPropertiesCommand::execute() -{ - TQPtrListIterator it( m_objects ); - for ( ; it.current() ; ++it ) - { - if ( m_type == ProtectSize ) - { - it.current()->setProtect( m_newValue ); - if ( it.current()->isSelected() ) - m_doc->repaint( it.current() ); - } - else if ( m_type == KeepRatio) - it.current()->setKeepRatio( m_newValue ); - } -} - -void GeometryPropertiesCommand::unexecute() -{ - EmbeddedObject *obj = 0; - for ( unsigned int i = 0; i < m_objects.count(); ++i ) { - obj = m_objects.at( i ); - if ( m_type == ProtectSize ) - { - obj->setProtect( *m_oldValue.at(i) ); - if ( obj->isSelected() ) - m_doc->repaint( obj ); - } - else if ( m_type == KeepRatio) - obj->setKeepRatio( *m_oldValue.at(i) ); - } -} - -MoveObjectByCmd::MoveObjectByCmd( const TQString &_name, const KoPoint &_diff, TQPtrList &_objects, - Doc *_doc,Sheet *_page ) - : KNamedCommand( _name ), diff( _diff ), objects( _objects ) -{ - objects.setAutoDelete( false ); - doc = _doc; - m_page=_page; - TQPtrListIterator it( objects ); - for ( ; it.current() ; ++it ) - { - it.current()->incCmdRef(); - } -} - -MoveObjectByCmd::~MoveObjectByCmd() -{ - TQPtrListIterator it( objects ); - for ( ; it.current() ; ++it ) - it.current()->decCmdRef(); -} - -void MoveObjectByCmd::execute() -{ - TQRect oldRect; - - for ( unsigned int i = 0; i < objects.count(); i++ ) { - doc->repaint( objects.at( i )->geometry() ); - - KoRect r = objects.at( i )->geometry(); - r.moveBy( diff.x(), diff.y() ); - objects.at( i )->setGeometry( r ); - - doc->repaint( objects.at( i ) ); - } -} - -void MoveObjectByCmd::unexecute() -{ - TQRect oldRect; - - for ( unsigned int i = 0; i < objects.count(); i++ ) { - doc->repaint( objects.at( i )->geometry() ); - - KoRect r = objects.at( i )->geometry(); - r.moveBy( -diff.x(), -diff.y() ); - objects.at( i )->setGeometry( r ); - - doc->repaint( objects.at( i ) ); - } -} diff --git a/kspread/commands.cpp b/kspread/commands.cpp new file mode 100644 index 00000000..490bee81 --- /dev/null +++ b/kspread/commands.cpp @@ -0,0 +1,946 @@ +/* This file is part of the KDE project + Copyright 2004 Ariya Hidayat + Copyright 2004 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "commands.h" +#include "damages.h" +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_undo.h" +#include "kspread_util.h" + +#include "kspread_sheetprint.h" + +using namespace KSpread; + +// ----- UndoWrapperCommand ----- + +UndoWrapperCommand::UndoWrapperCommand( UndoAction* ua ) +{ + undoAction = ua; +} + +void UndoWrapperCommand::execute() +{ + // This is not really safe and functional, but UndoWrapperCommand + // is a workaround anyway. So leave it as it it (Ariya) + undoAction->redo(); +} + +void UndoWrapperCommand::unexecute() +{ + undoAction->undo(); +} + +TQString UndoWrapperCommand::name() const +{ + return undoAction->getName(); +} + +// ----- MergeCellsCommand ----- + +MergeCellCommand::MergeCellCommand( Cell* c, int cs, int rs ) +{ + cell = c; + colSpan = cs; + rowSpan = rs; + oldColSpan = cell->extraXCells(); + oldRowSpan = cell->extraYCells(); + if( cell ) + { + TQRect area( cell->column(), cell->row(), cs+1, rs+1 ); + rangeName = util_rangeName( area ); + } +} + +TQString MergeCellCommand::name() const +{ + if( rangeName.isEmpty() ) + return i18n("Merge Cells"); + else + return i18n("Merge Cells %1").arg( rangeName ); +} + +void MergeCellCommand::execute() +{ + Sheet* sheet = cell->sheet(); + if( !sheet ) return; + sheet->changeMergedCell( cell->column(), cell->row(), colSpan, rowSpan); +} + +void MergeCellCommand::unexecute() +{ + Sheet* sheet = cell->sheet(); + if( !sheet ) return; + sheet->changeMergedCell( cell->column(), cell->row(), oldColSpan, oldRowSpan); +} + +// ----- DissociateCellCommand ----- + +DissociateCellCommand::DissociateCellCommand( Cell* c ) +{ + cell = c; + oldColSpan = cell->extraXCells(); + oldRowSpan = cell->extraYCells(); +} + +TQString DissociateCellCommand::name() const +{ + return i18n("Dissociate Cell"); +} + +void DissociateCellCommand::execute() +{ + Sheet* sheet = cell->sheet(); + if( !sheet ) return; + sheet->changeMergedCell( cell->column(), cell->row(), 0, 0 ); +} + +void DissociateCellCommand::unexecute() +{ + Sheet* sheet = cell->sheet(); + if( !sheet ) return; + sheet->changeMergedCell( cell->column(), cell->row(), oldColSpan, oldRowSpan); +} + +// ----- RenameSheetCommand ----- + +RenameSheetCommand::RenameSheetCommand( Sheet* s, const TQString &name ) +{ + sheet = s; + if( s ) oldName = s->sheetName(); + newName = name; +} + +TQString RenameSheetCommand::name() const +{ + return i18n("Rename Sheet"); +} + +void RenameSheetCommand::execute() +{ + if( sheet ) + sheet->setSheetName( newName ); +} + +void RenameSheetCommand::unexecute() +{ + if( sheet ) + sheet->setSheetName( oldName ); +} + +// ----- HideSheetCommand ----- + +HideSheetCommand::HideSheetCommand( Sheet* sheet ) +{ + doc = sheet->doc(); + sheetName = sheet->sheetName(); +} + +void HideSheetCommand::execute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + + sheet->hideSheet( true ); +} + +void HideSheetCommand::unexecute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + + sheet->hideSheet( false ); +} + +TQString HideSheetCommand::name() const +{ + TQString n = TQString( i18n("Hide Sheet %1") ).arg( sheetName ); + if( n.length() > 64 ) n = i18n("Hide Sheet"); + return n; +} + +// ----- ShowSheetCommand ----- + +ShowSheetCommand::ShowSheetCommand( Sheet* sheet ) +{ + doc = sheet->doc(); + sheetName = sheet->sheetName(); +} + +void ShowSheetCommand::execute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + + sheet->hideSheet( false ); +} + +void ShowSheetCommand::unexecute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + + sheet->hideSheet( true ); +} + +TQString ShowSheetCommand::name() const +{ + TQString n = TQString( i18n("Show Sheet %1") ).arg( sheetName ); + if( n.length() > 64 ) n = i18n("Show Sheet"); + return n; +} + + +// ----- AddSheetCommand ----- + +AddSheetCommand::AddSheetCommand( Sheet* s ) +{ + sheet = s; + doc = sheet->doc(); + doc->map()->addSheet( s ); +} + +void AddSheetCommand::execute() +{ + sheet->workbook()->insertSheet( sheet ); + doc->insertSheet( sheet ); +} + +void AddSheetCommand::unexecute() +{ + sheet->workbook()->takeSheet( sheet ); + doc->takeSheet( sheet ); +} + +TQString AddSheetCommand::name() const +{ + return i18n("Add Sheet"); +} + + +// ----- RemoveSheetCommand ----- + +RemoveSheetCommand::RemoveSheetCommand( Sheet* s ) +{ + sheet = s; + doc = sheet->doc(); +} + +void RemoveSheetCommand::execute() +{ + sheet->workbook()->takeSheet( sheet ); + doc->takeSheet( sheet ); +} + +void RemoveSheetCommand::unexecute() +{ + sheet->workbook()->insertSheet( sheet ); + doc->insertSheet( sheet ); +} + +TQString RemoveSheetCommand::name() const +{ + return i18n("Remove Sheet"); +} + +// ----- SheetPropertiesCommand ----- + +SheetPropertiesCommand::SheetPropertiesCommand( Doc* d, Sheet* s ) +{ + sheet = s; + doc = d; + oldDirection = newDirection = sheet->layoutDirection(); + oldAutoCalc = newAutoCalc = sheet->getAutoCalc(); + oldShowGrid = newShowGrid = sheet->getShowGrid(); + oldShowPageBorders = newShowPageBorders = sheet->isShowPageBorders(); + oldShowFormula = newShowFormula = sheet->getShowFormula(); + oldHideZero = newHideZero = sheet->getHideZero(); + oldShowFormulaIndicator = newShowFormulaIndicator = sheet->getShowFormulaIndicator(); + oldShowCommentIndicator = newShowCommentIndicator = sheet->getShowCommentIndicator(); + oldColumnAsNumber = newColumnAsNumber = sheet->getShowColumnNumber(); + oldLcMode = newLcMode = sheet->getLcMode(); + oldCapitalizeFirstLetter = newCapitalizeFirstLetter = sheet->getFirstLetterUpper(); +} + +TQString SheetPropertiesCommand::name() const +{ + return i18n("Change Sheet Properties"); +} + +void SheetPropertiesCommand::setLayoutDirection( Sheet::LayoutDirection dir ) +{ + newDirection = dir; +} + +void SheetPropertiesCommand::setAutoCalc( bool b ) +{ + newAutoCalc = b; +} + +void SheetPropertiesCommand::setShowGrid( bool b ) +{ + newShowGrid = b; +} + +void SheetPropertiesCommand::setShowPageBorders( bool b ) +{ + newShowPageBorders = b; +} + +void SheetPropertiesCommand::setShowFormula( bool b ) +{ + newShowFormula = b; +} + +void SheetPropertiesCommand::setHideZero( bool b ) +{ + newHideZero = b; +} + +void SheetPropertiesCommand::setShowFormulaIndicator( bool b ) +{ + newShowFormulaIndicator = b; +} + +void SheetPropertiesCommand::setShowCommentIndicator( bool b ) +{ + newShowCommentIndicator = b; +} + +void SheetPropertiesCommand::setColumnAsNumber( bool b ) +{ + newColumnAsNumber = b; +} + +void SheetPropertiesCommand::setLcMode( bool b ) +{ + newLcMode = b; +} + +void SheetPropertiesCommand::setCapitalizeFirstLetter( bool b ) +{ + newCapitalizeFirstLetter = b; +} + +void SheetPropertiesCommand::execute() +{ + sheet->setLayoutDirection( newDirection ); + sheet->setAutoCalc( newAutoCalc ); + sheet->setShowGrid( newShowGrid ); + sheet->setShowPageBorders( newShowPageBorders ); + sheet->setShowFormula( newShowFormula ); + sheet->setHideZero( newHideZero ); + sheet->setShowFormulaIndicator( newShowFormulaIndicator ); + sheet->setShowCommentIndicator( newShowCommentIndicator ); + sheet->setShowColumnNumber( newColumnAsNumber ); + sheet->setLcMode( newLcMode ); + sheet->setFirstLetterUpper( newCapitalizeFirstLetter ); + doc->addDamage( new SheetDamage( sheet, SheetDamage::PropertiesChanged ) ); +} + +void SheetPropertiesCommand::unexecute() +{ + sheet->setLayoutDirection( oldDirection ); + sheet->setAutoCalc( oldAutoCalc ); + sheet->setShowGrid( oldShowGrid ); + sheet->setShowPageBorders( oldShowPageBorders ); + sheet->setShowFormula( oldShowFormula ); + sheet->setHideZero( oldHideZero ); + sheet->setShowFormulaIndicator( oldShowFormulaIndicator ); + sheet->setShowCommentIndicator( oldShowCommentIndicator ); + sheet->setShowColumnNumber( oldColumnAsNumber ); + sheet->setLcMode( oldLcMode ); + sheet->setFirstLetterUpper( oldCapitalizeFirstLetter ); + doc->addDamage( new SheetDamage( sheet, SheetDamage::PropertiesChanged ) ); +} + + +// ----- InsertColumnCommand ----- + +InsertColumnCommand::InsertColumnCommand( Sheet* s , unsigned int _column, unsigned int _nbCol ) +{ + doc = s->doc(); + sheetName = s->sheetName(); + insertPosColumn = _column; + nbColumnInserted = _nbCol; +} + +void InsertColumnCommand::execute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + sheet->insertColumn( insertPosColumn,nbColumnInserted); +} + +void InsertColumnCommand::unexecute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + sheet->removeColumn( insertPosColumn,nbColumnInserted ); +} + +TQString InsertColumnCommand::name() const +{ + return i18n("Insert Columns"); +} + + +// ----- DefinePrintRangeCommand ----- + + +DefinePrintRangeCommand::DefinePrintRangeCommand( Sheet *s ) +{ + doc = s->doc(); + sheetName = s->sheetName(); + printRange = s->print()->printRange(); +} + +void DefinePrintRangeCommand::execute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + sheet->print()->setPrintRange( printRangeRedo ); + +} + +void DefinePrintRangeCommand::unexecute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + printRangeRedo = sheet->print()->printRange(); + sheet->print()->setPrintRange( printRange ); +} + +TQString DefinePrintRangeCommand::name() const +{ + return i18n("Set Page Layout"); +} + +// ----- PaperLayoutCommand ----- + + +PaperLayoutCommand::PaperLayoutCommand( Sheet *s ) +{ + doc = s->doc(); + sheetName = s->sheetName(); + pl = s->print()->paperLayout(); + hf = s->print()->headFootLine(); + unit = doc->unit(); + printGrid = s->print()->printGrid(); + printCommentIndicator = s->print()->printCommentIndicator(); + printFormulaIndicator = s->print()->printFormulaIndicator(); + printRange = s->print()->printRange(); + printRepeatColumns = s->print()->printRepeatColumns(); + printRepeatRows = s->print()->printRepeatRows(); + zoom = s->print()->zoom(); + pageLimitX = s->print()->pageLimitX(); + pageLimitY = s->print()->pageLimitY(); +} + +void PaperLayoutCommand::execute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + SheetPrint* print = sheet->print(); + + print->setPaperLayout( plRedo.ptLeft, plRedo.ptTop, + plRedo.ptRight, plRedo.ptBottom, + plRedo.format, plRedo.orientation ); + + print->setHeadFootLine( hfRedo.headLeft, hfRedo.headMid, hfRedo.headRight, + hfRedo.footLeft, hfRedo.footMid, hfRedo.footRight ); + + doc->setUnit( unitRedo ); + + print->setPrintGrid( printGridRedo ); + print->setPrintCommentIndicator( printCommentIndicatorRedo ); + print->setPrintFormulaIndicator( printFormulaIndicatorRedo ); + + print->setPrintRange( printRangeRedo ); + print->setPrintRepeatColumns( printRepeatColumnsRedo ); + print->setPrintRepeatRows( printRepeatRowsRedo ); + + print->setZoom( zoomRedo ); + + print->setPageLimitX( pageLimitX ); + print->setPageLimitY( pageLimitY ); +} + +void PaperLayoutCommand::unexecute() +{ + Sheet* sheet = doc->map()->findSheet( sheetName ); + if( !sheet ) return; + SheetPrint* print = sheet->print(); + plRedo = print->paperLayout(); + print->setPaperLayout( pl.ptLeft, pl.ptTop, + pl.ptRight, pl.ptBottom, + pl.format, pl.orientation ); + + hfRedo = print->headFootLine(); + print->setHeadFootLine( hf.headLeft, hf.headMid, hf.headRight, + hf.footLeft, hf.footMid, hf.footRight ); + + unitRedo = doc->unit(); + doc->setUnit( unit ); + + printGridRedo = print->printGrid(); + print->setPrintGrid( printGrid ); + + printCommentIndicatorRedo = print->printCommentIndicator(); + print->setPrintCommentIndicator( printCommentIndicator ); + + printFormulaIndicatorRedo = print->printFormulaIndicator(); + print->setPrintFormulaIndicator( printFormulaIndicator ); + + printRangeRedo = print->printRange(); + print->setPrintRange( printRange ); + + printRepeatColumnsRedo = print->printRepeatColumns(); + print->setPrintRepeatColumns( printRepeatColumns ); + + printRepeatRowsRedo = print->printRepeatRows(); + print->setPrintRepeatRows( printRepeatRows ); + + zoomRedo = print->zoom(); + print->setZoom( zoom ); + + pageLimitXRedo = print->pageLimitX(); + print->setPageLimitX( pageLimitX ); + + pageLimitYRedo = print->pageLimitY(); + print->setPageLimitY( pageLimitY ); + +} + +TQString PaperLayoutCommand::name() const +{ + return i18n("Set Page Layout"); +} + +LinkCommand::LinkCommand( Cell* c, const TQString& text, const TQString& link ) +{ + cell = c; + oldText = cell->text(); + oldLink = cell->link(); + newText = text; + newLink = link; + + Sheet* s = cell->sheet(); + if( s ) doc = s->doc(); +} + +void LinkCommand::execute() +{ + if( !cell ) return; + + if( !newText.isEmpty() ) + cell->setCellText( newText ); + cell->setLink( newLink ); + + doc->addDamage( new CellDamage( cell ) ); +} + +void LinkCommand::unexecute() +{ + if( !cell ) return; + + cell->setCellText( oldText ); + cell->setLink( oldLink ); + + doc->addDamage( new CellDamage( cell ) ); +} + +TQString LinkCommand::name() const +{ + return newLink.isEmpty() ? i18n("Remove Link") : i18n("Set Link"); +} + +ChangeObjectGeometryCommand::ChangeObjectGeometryCommand( EmbeddedObject *_obj, const KoPoint &_m_diff, const KoSize &_r_diff ) + : m_diff( _m_diff ), r_diff( _r_diff ) +{ + obj = _obj; + obj->incCmdRef(); + doc = obj->sheet()->doc(); +} + +ChangeObjectGeometryCommand::~ChangeObjectGeometryCommand() +{ + obj->decCmdRef(); +} + +void ChangeObjectGeometryCommand::execute() +{ + doc->repaint( obj->geometry() ); + + KoRect geometry = obj->geometry(); + geometry.moveBy( m_diff.x(), m_diff.y() ); + geometry.setWidth( geometry.width() + r_diff.width() ); + geometry.setHeight( geometry.height() + r_diff.height() ); + obj->setGeometry( geometry ); + +// if ( object->isSelected()) +// doc->updateObjectStatusBarItem(); + doc->repaint( obj ); +} + +void ChangeObjectGeometryCommand::unexecute() +{ + doc->repaint( obj->geometry() ); + + KoRect geometry = obj->geometry(); + geometry.moveBy( -m_diff.x(), -m_diff.y() ); + geometry.setWidth( geometry.width() - r_diff.width() ); + geometry.setHeight( geometry.height() - r_diff.height() ); + obj->setGeometry( geometry ); + +// if ( object->isSelected()) +// doc->updateObjectStatusBarItem(); + doc->repaint( obj ); +} + +TQString ChangeObjectGeometryCommand::name() const +{ + /*if ( fabs( obj->geometry().width() - newGeometry.width() )<1e-3 && fabs( obj->geometry().height() - newGeometry.height() ) < 1e-3 ) + return i18n("Move Object"); + else */ + return i18n("Resize Object"); +} + +RemoveObjectCommand::RemoveObjectCommand( EmbeddedObject *_obj, bool _cut ) +{ + obj = _obj; + cut = _cut; + doc = obj->sheet()->doc(); +} + +RemoveObjectCommand::~RemoveObjectCommand() +{ + if ( !executed ) + return; + //kdDebug() << "*********Deleting object..." << endl; + if ( obj->getType() == OBJECT_CHART ) + { + EmbeddedKOfficeObject *chart = dynamic_cast(obj); + chart->embeddedObject()->setDeleted(true); + } + + delete obj; +} + +void RemoveObjectCommand::execute() +{ + +// I don't think we need this: +// Make shure that this child has no active embedded view -> activate ourselfs +// doc()->emitBeginOperation( false ); +// partManager()->setActivePart( koDocument(), this ); +// partManager()->setSelectedPart( 0 ); +// doc()->emitEndOperation( d->activeSheet->visibleRect( d->canvas ) ); + + doc->embeddedObjects().removeRef( obj ); + if ( obj->getType() == OBJECT_CHART || obj->getType()== OBJECT_KOFFICE_PART) + { + EmbeddedKOfficeObject *eko = dynamic_cast(obj); + eko->embeddedObject()->setDeleted(true); + } + + obj->setSelected( false ); + doc->repaint( obj ); + executed = true; +} + +void RemoveObjectCommand::unexecute() +{ + doc->embeddedObjects().append( obj ); + if ( obj->getType() == OBJECT_CHART || obj->getType()== OBJECT_KOFFICE_PART) + { + EmbeddedKOfficeObject *eko = dynamic_cast(obj); + eko->embeddedObject()->setDeleted(false); + } + doc->repaint( obj ); + executed = false; +} + +TQString RemoveObjectCommand::name() const +{ + if ( cut ) + return i18n("Cut Object"); + else + return i18n("Remove Object"); +} + +InsertObjectCommand::InsertObjectCommand( const KoRect& _geometry, KoDocumentEntry& _entry, Canvas *_canvas ) //child +{ + geometry = _geometry; + entry = _entry; + canvas = _canvas; + type = OBJECT_KOFFICE_PART; + obj = 0; +} + +InsertObjectCommand::InsertObjectCommand(const KoRect& _geometry, KoDocumentEntry& _entry, const TQRect& _data, Canvas *_canvas ) //chart +{ + geometry = _geometry; + entry = _entry; + data = _data; + canvas = _canvas; + type = OBJECT_CHART; + obj = 0; +} + +InsertObjectCommand::InsertObjectCommand( const KoRect& _geometry , KURL& _file, Canvas *_canvas ) //picture +{ + //In the case of pictures, only the top left point of the rectangle is relevant + geometry = _geometry; + file = _file; + canvas = _canvas; + type = OBJECT_PICTURE; + obj = 0; +} + +InsertObjectCommand::~InsertObjectCommand() +{ + if ( executed ) + return; + //kdDebug() << "*********Deleting object..." << endl; + if ( obj->getType() == OBJECT_CHART ) + { + EmbeddedKOfficeObject *chart = dynamic_cast(obj); + chart->embeddedObject()->setDeleted(true); + } + + delete obj; +} + +void InsertObjectCommand::execute() +{ + if ( obj ) //restore the object which was removed from the object list in InsertObjectCommand::unexecute() + { + canvas->doc()->embeddedObjects().append( obj ); + canvas->doc()->repaint( obj ); + } + else + { + bool success = false; + switch ( type ) + { + case OBJECT_CHART: + { + success = canvas->activeSheet()->insertChart( geometry, entry, data ); + break; + } + case OBJECT_KOFFICE_PART: + { + success = canvas->activeSheet()->insertChild( geometry, entry ); + break; + } + case OBJECT_PICTURE: + { + success = canvas->activeSheet()->insertPicture( geometry.topLeft() , file ); + break; + } + default: + break; + } + if ( success ) + { + obj = canvas->doc()->embeddedObjects().last(); + obj->sheet()->unifyObjectName( obj ); + } + else + obj = 0; + } + executed = true; +} + +void InsertObjectCommand::unexecute() +{ + if ( !obj ) + return; + + canvas->doc()->embeddedObjects().removeRef( obj ); + obj->setSelected( false ); + canvas->doc()->repaint( obj ); + + executed = false; +} + +TQString InsertObjectCommand::name() const +{ + return i18n("Insert Object"); +} + +RenameNameObjectCommand::RenameNameObjectCommand( const TQString &_name, const TQString &_objectName, + EmbeddedObject *_obj, Doc *_doc ): + KNamedCommand( _name ), + newObjectName( _objectName ), + object( _obj ), + doc( _doc ) +{ + oldObjectName = object->getObjectName(); + + m_page = object->sheet()/*doc->findPage( object )*/; +} + +RenameNameObjectCommand::~RenameNameObjectCommand() +{ +} + +void RenameNameObjectCommand::execute() +{ + object->setObjectName( newObjectName ); + m_page->unifyObjectName( object ); + +// doc->updateSideBarItem( m_page ); +} + +void RenameNameObjectCommand::unexecute() +{ + object->setObjectName( oldObjectName ); + +// doc->updateSideBarItem( m_page ); +} + +GeometryPropertiesCommand::GeometryPropertiesCommand( const TQString &name, TQPtrList &objects, + bool newValue, KgpType type, Doc *_doc ) +: KNamedCommand( name ) +, m_objects( objects ) +, m_newValue( newValue ) +, m_type( type ) + , m_doc( _doc ) +{ + TQPtrListIterator it( m_objects ); + for ( ; it.current() ; ++it ) + { + it.current()->incCmdRef(); + if ( m_type == ProtectSize ) + m_oldValue.append( it.current()->isProtect() ); + else if ( m_type == KeepRatio) + m_oldValue.append( it.current()->isKeepRatio() ); + } +} + +GeometryPropertiesCommand::GeometryPropertiesCommand( const TQString &name, TQValueList &lst, + TQPtrList &objects, bool newValue, + KgpType type, Doc *_doc) +: KNamedCommand( name ) +, m_oldValue( lst ) +, m_objects( objects ) +, m_newValue( newValue ) +, m_type( type ) +, m_doc ( _doc ) +{ + TQPtrListIterator it( m_objects ); + for ( ; it.current() ; ++it ) + it.current()->incCmdRef(); +} + +GeometryPropertiesCommand::~GeometryPropertiesCommand() +{ + TQPtrListIterator it( m_objects ); + for ( ; it.current() ; ++it ) + it.current()->decCmdRef(); +} + +void GeometryPropertiesCommand::execute() +{ + TQPtrListIterator it( m_objects ); + for ( ; it.current() ; ++it ) + { + if ( m_type == ProtectSize ) + { + it.current()->setProtect( m_newValue ); + if ( it.current()->isSelected() ) + m_doc->repaint( it.current() ); + } + else if ( m_type == KeepRatio) + it.current()->setKeepRatio( m_newValue ); + } +} + +void GeometryPropertiesCommand::unexecute() +{ + EmbeddedObject *obj = 0; + for ( unsigned int i = 0; i < m_objects.count(); ++i ) { + obj = m_objects.at( i ); + if ( m_type == ProtectSize ) + { + obj->setProtect( *m_oldValue.at(i) ); + if ( obj->isSelected() ) + m_doc->repaint( obj ); + } + else if ( m_type == KeepRatio) + obj->setKeepRatio( *m_oldValue.at(i) ); + } +} + +MoveObjectByCmd::MoveObjectByCmd( const TQString &_name, const KoPoint &_diff, TQPtrList &_objects, + Doc *_doc,Sheet *_page ) + : KNamedCommand( _name ), diff( _diff ), objects( _objects ) +{ + objects.setAutoDelete( false ); + doc = _doc; + m_page=_page; + TQPtrListIterator it( objects ); + for ( ; it.current() ; ++it ) + { + it.current()->incCmdRef(); + } +} + +MoveObjectByCmd::~MoveObjectByCmd() +{ + TQPtrListIterator it( objects ); + for ( ; it.current() ; ++it ) + it.current()->decCmdRef(); +} + +void MoveObjectByCmd::execute() +{ + TQRect oldRect; + + for ( unsigned int i = 0; i < objects.count(); i++ ) { + doc->repaint( objects.at( i )->geometry() ); + + KoRect r = objects.at( i )->geometry(); + r.moveBy( diff.x(), diff.y() ); + objects.at( i )->setGeometry( r ); + + doc->repaint( objects.at( i ) ); + } +} + +void MoveObjectByCmd::unexecute() +{ + TQRect oldRect; + + for ( unsigned int i = 0; i < objects.count(); i++ ) { + doc->repaint( objects.at( i )->geometry() ); + + KoRect r = objects.at( i )->geometry(); + r.moveBy( -diff.x(), -diff.y() ); + objects.at( i )->setGeometry( r ); + + doc->repaint( objects.at( i ) ); + } +} diff --git a/kspread/damages.cc b/kspread/damages.cc deleted file mode 100644 index 291db408..00000000 --- a/kspread/damages.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* This file is part of the KDE project - Copyright 2004 Ariya Hidayat - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "damages.h" - -#include "kspread_cell.h" -#include "kspread_sheet.h" - -namespace KSpread -{ - -class SheetDamage::Private -{ -public: - KSpread::Sheet* sheet; - int action; -}; - -class CellDamage::Private -{ -public: - KSpread::Cell* cell; -}; - -} - -using namespace KSpread; - - -CellDamage::CellDamage( KSpread::Cell* cell ) -{ - d = new Private; - d->cell = cell; -} - -CellDamage::~CellDamage() -{ - delete d; -} - -KSpread::Cell* CellDamage::cell() -{ - return d->cell; -} - -SheetDamage::SheetDamage( KSpread::Sheet* sheet, int action ) -{ - d = new Private; - d->sheet = sheet; - d->action = action; -} - -SheetDamage::~SheetDamage() -{ - delete d; -} - -KSpread::Sheet* SheetDamage::sheet() const -{ - return d->sheet; -} - -int SheetDamage::action() const -{ - return d->action; -} diff --git a/kspread/damages.cpp b/kspread/damages.cpp new file mode 100644 index 00000000..291db408 --- /dev/null +++ b/kspread/damages.cpp @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + Copyright 2004 Ariya Hidayat + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "damages.h" + +#include "kspread_cell.h" +#include "kspread_sheet.h" + +namespace KSpread +{ + +class SheetDamage::Private +{ +public: + KSpread::Sheet* sheet; + int action; +}; + +class CellDamage::Private +{ +public: + KSpread::Cell* cell; +}; + +} + +using namespace KSpread; + + +CellDamage::CellDamage( KSpread::Cell* cell ) +{ + d = new Private; + d->cell = cell; +} + +CellDamage::~CellDamage() +{ + delete d; +} + +KSpread::Cell* CellDamage::cell() +{ + return d->cell; +} + +SheetDamage::SheetDamage( KSpread::Sheet* sheet, int action ) +{ + d = new Private; + d->sheet = sheet; + d->action = action; +} + +SheetDamage::~SheetDamage() +{ + delete d; +} + +KSpread::Sheet* SheetDamage::sheet() const +{ + return d->sheet; +} + +int SheetDamage::action() const +{ + return d->action; +} diff --git a/kspread/dependencies.cc b/kspread/dependencies.cc deleted file mode 100644 index 66bbe61a..00000000 --- a/kspread/dependencies.cc +++ /dev/null @@ -1,682 +0,0 @@ -/* This file is part of the KDE project - Copyright 2004 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "dependencies.h" - -#include "formula.h" - -#include "kspread_cell.h" -#include "kspread_sheet.h" - -#include - -//rows x cols in one cell-chunk; bigger values lead to slower updating -//of range-dependencies, lower values will increase memory usage -#define CELLCHUNK_ROWS 128 -#define CELLCHUNK_COLS 16 - -namespace KSpread { - - -/** d-pointer of DependencyManager */ -class DependencyList { - public: - DependencyList (Sheet *s); - ~DependencyList () { reset (); }; - /** clear internal structures */ - void reset (); - - /** handle the fact that a cell has been changed */ - void cellChanged (const Point &cell); - - /** generate list of dependencies of a cell */ - void generateDependencies (const Point &cell); - /** generate list of dependencies of a range */ - void generateDependencies (const Range &range); - /** generate list of dependencies of a range list */ - void generateDependencies (const RangeList &rangeList); - - /** update cells dependending on a given cell */ - void processDependencies (const Point &cell); - /** update cells dependending on a cell in a given range */ - void processDependencies (const Range &range); - /** update cells dependending on a given range-list */ - void processDependencies (const RangeList &rangeList); - - /** get dependencies of a cell */ - RangeList getDependencies (const Point &cell); - /** get cells depending on this cell, either through normal or range dependency */ - TQValueList getDependants (const Point &cell); - - void areaModified (const TQString &name); - protected: - /** update structures: cell 1 depends on cell 2 */ - void addDependency (const Point &cell1, const Point &cell2); - /** update structures: cell depends on a range */ - void addRangeDependency (const RangeDependency &rd); - /** remove all dependencies of a cell */ - void removeDependencies (const Point &cell); - - /** update all cells depending on a range containing this cell */ - void processRangeDependencies (const Point &cell); - - /** update all cells depending on a range intersecting with this range */ - void processRangeDependencies (const Range &range); - - /** update one cell due to changed dependencies */ - void updateCell (const Point &cell) const; - - /** return a leading cell for a given cell (used to store range - dependencies effectively) */ - Point leadingCell (const Point &cell) const; - /** list of leading cells of all cell chunks that this range belongs to */ - TQValueList leadingCells (const Range &range) const; - /** retrieve a list of cells that a given cell depends on */ - RangeList computeDependencies (const Point &cell) const; - - TQValueList getCellDeps(const Point& cell) const { - CellDepsMap::const_iterator it = cellDeps.find( cell ); - return it == cellDeps.end() ? TQValueList() : *it; - } - - /** debug */ - void dump(); - - /** Sheet whose dependencies are managed by this instance */ - Sheet *sheet; - - /** dependencies of each cell */ - TQMap dependencies; - /** list of cells (but NOT ranges) that depend on a cell */ - typedef TQMap > CellDepsMap; - CellDepsMap cellDeps; - /** all range dependencies splitted into cell-chunks (TODO: describe) */ - TQMap > rangeDeps; - /** list of cells referencing a given named area */ - TQMap > areaDeps; -}; - -} // namespace KSpread - -using namespace KSpread; - -// This is currently not called - but it's really convenient to call it from -// gdb or from debug output to check that everything is set up ok. -void DependencyList::dump() -{ - TQMap::const_iterator it = dependencies.begin(); - for ( ; it != dependencies.end(); ++it ) { - Point p = it.key(); - kdDebug() << "Cell " << p.sheetName() << " " << p.pos() - << " depends on :" << endl; - RangeList rl = (*it); - TQValueList::const_iterator itp = rl.cells.begin(); - for ( ; itp != rl.cells.end(); ++itp ) - kdDebug() << " cell " << (*itp).pos() << endl; - TQValueList::const_iterator itr = rl.ranges.begin(); - for ( ; itr != rl.ranges.end(); ++itr ) - kdDebug() << " range " << (*itr).toString() << endl; - } - - CellDepsMap::const_iterator cit = cellDeps.begin(); - for ( ; cit != cellDeps.end(); ++cit ) - { - Point p = cit.key(); - kdDebug() << "The cells that depend on " << p.sheetName() << " " << p.pos() - << " are :" << endl; - TQValueList::const_iterator itp = (*cit).begin(); - for ( ; itp != (*cit).end(); ++itp ) - kdDebug() << " cell " << (*itp).pos() << endl; - } - -} - -DependencyManager::DependencyManager (Sheet *s) -{ - deps = new DependencyList (s); -} - -DependencyManager::~DependencyManager () -{ - delete deps; - deps = 0; -} - -void DependencyManager::reset () -{ - deps->reset(); -} - -void DependencyManager::cellChanged (const Point &cell) -{ - deps->cellChanged (cell); -} - -void DependencyManager::rangeChanged (const Range &range) -{ - deps->generateDependencies (range); - deps->processDependencies (range); -} - -void DependencyManager::rangeListChanged (const RangeList &rangeList) -{ - deps->generateDependencies (rangeList); - deps->processDependencies (rangeList); -} - -void DependencyManager::areaModified (const TQString &name) -{ - deps->areaModified (name); -} - -RangeList DependencyManager::getDependencies (const Point &cell) -{ - return deps->getDependencies (cell); -} - -TQValueList DependencyManager::getDependants (const Point &cell) -{ - return deps->getDependants (cell); -} - -DependencyList::DependencyList (Sheet *s) - : sheet (s) -{ -} - -void DependencyList::reset () -{ - dependencies.clear(); - cellDeps.clear(); - rangeDeps.clear(); -} - -void DependencyList::cellChanged (const Point &cell) -{ - Cell *c = cell.cell(); - - // empty or default cell? do nothing - if( c->isDefault() ) - return; - - //if the cell contains the circle error, we mustn't do anything - if (c->testFlag (Cell::Flag_CircularCalculation)) - return; - - //don't re-generate dependencies if we're updating dependencies - if ( !(c->testFlag (Cell::Flag_Progress))) - generateDependencies (cell); - - processDependencies (cell); -} - -RangeList DependencyList::getDependencies (const Point &cell) -{ - RangeList rl; - //look if the cell has any dependencies - if (!dependencies.contains (cell)) - return rl; //it doesn't - return an empty list - - //the cell does have dependencies - return them! - return dependencies[cell]; -} - -TQValueList DependencyList::getDependants (const Point &cell) -{ - //cell dependencies go first - TQValueList list = getCellDeps( cell ); - //next, append range dependencies - Point leading = leadingCell (cell); - TQValueList::iterator it; - if (!rangeDeps.count (leading)) - return list; //no range dependencies in this cell chunk -> nothing more to do - - for (it = rangeDeps[leading].begin(); - it != rangeDeps[leading].end(); ++it) - { - //process all range dependencies, and for each range including the questioned cell, - //add the depending cell to the list - if ((*it).range.contains (cell)) - { - Point c; - c.setRow ((*it).cellrow); - c.setColumn ((*it).cellcolumn); - c.setSheet ( (*it).cellsheet ); - list.push_back (c); - } - } - - return list; -} - -void DependencyList::areaModified (const TQString &name) -{ - // since area names are something like aliases, modifying an area name - // basically means that all cells referencing this area should be treated - // as modified - that will retrieve updated area ranges and also update - // everything as necessary ... - if (!areaDeps.contains (name)) - return; - - TQMap::iterator it; - for (it = areaDeps[name].begin(); it != areaDeps[name].end(); ++it) - { - Cell *c = it.key().cell(); - // this forces the cell to regenerate everything - new range dependencies - // and so on - c->setValue (c->value ()); - } -} - -void DependencyList::addDependency (const Point &cell1, - const Point &cell2) -{ - //cell2 can be in another sheet (inter-sheet dependency) - Sheet *sh = cell2.sheet(); - if (!sh) - sh = sheet; - - dependencies[cell1].cells.push_back (cell2); - sh->dependencies()->deps->cellDeps[cell2].push_back (cell1); -} - -void DependencyList::addRangeDependency (const RangeDependency &rd) -{ - //target range can be in another sheet (inter-sheet dependency) - Sheet *sh = rd.range.sheet(); - if (!sh) - sh = sheet; - - Point cell; - cell.setSheet (rd.cellsheet); - cell.setRow (rd.cellrow); - cell.setColumn (rd.cellcolumn); - dependencies[cell].ranges.push_back (rd.range); - - TQValueList leadings = leadingCells (rd.range); - TQValueList::iterator it; - for (it = leadings.begin(); it != leadings.end(); ++it) - sh->dependencies()->deps->rangeDeps[*it].push_back (rd); - - // the target range could be a named area ... - if (!rd.range.namedArea().isNull()) - areaDeps[rd.range.namedArea()][cell] = true; -} - -void DependencyList::removeDependencies (const Point &cell) -{ - //look if the cell has any dependencies - if (!dependencies.contains (cell)) - return; //it doesn't - nothing more to do - - //first we remove cell-dependencies - TQValueList cells = dependencies[cell].cells; - TQValueList::iterator it1; - for (it1 = cells.begin(); it1 != cells.end(); ++it1) - { - //get sheet-pointer - needed to handle inter-sheet dependencies correctly - Sheet *sh = (*it1).sheet(); - if (!sh) - sh = sheet; - - if (!sh->dependencies()->deps->cellDeps.contains (*it1)) - continue; //this should never happen - - //we no longer depend on this cell - TQValueList::iterator cit; - cit = sh->dependencies()->deps->cellDeps[*it1].find (cell); - if (cit != sh->dependencies()->deps->cellDeps[*it1].end()) - sh->dependencies()->deps->cellDeps[*it1].erase (cit); - } - - //then range-dependencies are removed - TQValueList ranges = dependencies[cell].ranges; - TQValueList::iterator it2; - TQValueList leads; - for (it2 = ranges.begin(); it2 != ranges.end(); ++it2) - { - //we construct a list of cell-chunks containing a range and merge it - //with lists generated from all previous ranges (duplicates are removed) - TQValueList leadings = leadingCells (*it2); - for (it1 = leadings.begin(); it1 != leadings.end(); ++it1) - if (!leads.contains (*it1)) - leads.push_back (*it1); - } - for (it1 = leads.begin(); it1 != leads.end(); ++it1) - { - //get sheet-pointer - needed to handle inter-sheet dependencies correctly - Sheet *sh = (*it1).sheet(); - if (!sh) - sh = sheet; - - if (sh->dependencies()->deps->rangeDeps.contains (*it1)) - { - TQValueList::iterator it3; - it3 = sh->dependencies()->deps->rangeDeps[*it1].begin(); - //erase all range dependencies of this cell in this cell-chunk - while (it3 != sh->dependencies()->deps->rangeDeps[*it1].end()) - if (((*it3).cellrow == cell.row()) && - ((*it3).cellcolumn == cell.column())) - it3 = sh->dependencies()->deps->rangeDeps[*it1].erase (it3); - else - ++it3; - //erase the list if we no longer need it - if (sh->dependencies()->deps->rangeDeps[*it1].empty()) - sh->dependencies()->deps->rangeDeps.erase (*it1); - } - } - - // remove information about named area dependencies - TQMap >::iterator itr; - for (itr = areaDeps.begin(); itr != areaDeps.end(); ++itr) { - if (itr.data().contains (cell)) - itr.data().remove (cell); - } - - // finally, remove the entry about this cell - dependencies[cell].cells.clear(); - dependencies[cell].ranges.clear(); - dependencies.erase (cell); -} - -void DependencyList::generateDependencies (const Point &cell) -{ - //get rid of old dependencies first - removeDependencies (cell); - - //new dependencies only need to be generated if the cell contains a formula - Cell *c = sheet->cellAt (cell.column(), cell.row()); - if( c->isDefault() ) - return; - if (!c->isFormula()) - return; - - //now we need to generate dependencies - RangeList rl = computeDependencies (cell); - - //now that we have the new dependencies, we put them into our data structures - //and we're done - TQValueList::iterator it1; - TQValueList::iterator it2; - - for (it1 = rl.cells.begin(); it1 != rl.cells.end(); ++it1) - addDependency (cell, *it1); - for (it2 = rl.ranges.begin(); it2 != rl.ranges.end(); ++it2) - { - RangeDependency rd; - rd.cellrow = cell.row(); - rd.cellcolumn = cell.column(); - rd.cellsheet = sheet; - rd.range = *it2; - - if (rd.range.sheet() == 0) - rd.range.setSheet(sheet); - - addRangeDependency (rd); - } -} - -void DependencyList::generateDependencies (const Range &range) -{ - for (int row = range.startRow(); row <= range.endRow(); row++) - for (int col = range.startCol(); col <= range.endCol(); col++) - { - Point c; - c.setRow (row); - c.setColumn (col); - c.setSheet(sheet); - generateDependencies (c); - } -} - -void DependencyList::generateDependencies (const RangeList &rangeList) -{ - TQValueList::const_iterator it1; - TQValueList::const_iterator it2; - - for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1) - generateDependencies (*it1); - for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2) - generateDependencies (*it2); -} - -void DependencyList::processDependencies (const Point &cell) -{ - const TQValueList d = getCellDeps(cell); - TQValueList::const_iterator it = d.begin(); - const TQValueList::const_iterator end = d.end(); - for (; it != end; ++it) - updateCell (*it); - - processRangeDependencies (cell); -} - -void DependencyList::processRangeDependencies (const Point &cell) -{ - Point leading = leadingCell (cell); - if (!rangeDeps.count (leading)) - return; //no range dependencies in this cell chunk - - const TQValueList rd = rangeDeps[leading]; - - TQValueList::const_iterator it; - for (it = rd.begin(); it != rd.end(); ++it) - { - //process all range dependencies, and for each range including the modified cell, - //recalc the depending cell - if ((*it).range.contains (cell)) - { - Point c; - c.setRow ((*it).cellrow); - c.setColumn ((*it).cellcolumn); - c.setSheet ( (*it).cellsheet ); - updateCell (c); - } - } -} - -void DependencyList::processDependencies (const Range &range) -{ - //each cell's dependencies need to be updated - that cannot be helped - having a range - //only helps with range dependencies - for (int row = range.startRow(); row <= range.endRow(); row++) - for (int col = range.startCol(); col <= range.endCol(); col++) - { - Point c; - c.setRow (row); - c.setColumn (col); - c.setSheet( sheet ); - - const TQValueList d = getCellDeps(c); - TQValueList::const_iterator it = d.begin(); - const TQValueList::const_iterator end = d.end(); - for (; it != end; ++it) - updateCell (*it); - } - - processRangeDependencies (range); -} - -void DependencyList::processRangeDependencies (const Range &range) -{ - //TODO: some optimization, so that we don't recompute cells depending of huge - //ranges more than once (now we recompute them once per cell-chunk used by their dependency) - //This will probably happen as a part of splitting this into dep manager - //and recalc manager - - TQValueList leadings = leadingCells (range); - TQValueList::iterator it; - for (it = leadings.begin(); it != leadings.end(); ++it) - { - if (!rangeDeps.count (*it)) - continue; //no range dependencies in this cell chunk - TQValueList::iterator it2; - for (it2 = rangeDeps[*it].begin(); it2 != rangeDeps[*it].end(); ++it2) - { - //process all range dependencies, and for each range intersecting with our range, - //recalc the depending cell - if ((*it2).range.intersects (range)) - { - Point c; - c.setRow ((*it2).range.startRow()); - c.setColumn ((*it2).range.startCol()); - c.setSheet(sheet); - updateCell (c); - } - } - } -} - -void DependencyList::processDependencies (const RangeList &rangeList) -{ - TQValueList::const_iterator it1; - TQValueList::const_iterator it2; - - for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1) - processDependencies (*it1); - for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2) - processDependencies (*it2); -} - -void DependencyList::updateCell (const Point &cell) const -{ - Cell *c = cell.cell(); - //prevent infinite recursion (circular dependencies) - if (c->testFlag (Cell::Flag_Progress) || - c->testFlag (Cell::Flag_CircularCalculation)) - { - kdError(36001) << "ERROR: Circle, cell " << c->fullName() << - ", in dep.manager for sheet " << sheet->name() << endl; - Value v; - // don't set anything if the cell already has all these things set - // this prevents endless loop for inter-sheet curcular dependencies, - // where the usual mechanisms fail doe to having multiple dependency - // managers ... - if (!c->testFlag (Cell::Flag_CircularCalculation)) - { - c->setFlag(Cell::Flag_CircularCalculation); - v.setError ( "####" ); - c->setValue (v); - } - //clear the computing-dependencies flag - c->clearFlag (Cell::Flag_Progress); - return; - } - //set the computing-dependencies flag - c->setFlag (Cell::Flag_Progress); - - //mark the cell as calc-dirty - c->setCalcDirtyFlag(); - - //recalculate the cell - c->calc (false); - - //clear the computing-dependencies flag - c->clearFlag (Cell::Flag_Progress); -} - -Point DependencyList::leadingCell (const Point &cell) const -{ - Point c; - c.setRow (cell.row() - cell.row() % CELLCHUNK_ROWS + 1); - c.setColumn (cell.column() - cell.column() % CELLCHUNK_COLS + 1); - c.setSheet(cell.sheet()); - return c; -} - -TQValueList DependencyList::leadingCells (const Range &range) const -{ - TQValueList cells; - Point cell1, cell2, cell; - - cell1.setRow (range.startRow()); - cell1.setColumn (range.startCol()); - cell2.setRow (range.endRow()); - cell2.setColumn (range.endCol()); - cell1.setSheet(range.sheet()); - cell2.setSheet(range.sheet()); - - cell1 = leadingCell (cell1); - cell2 = leadingCell (cell2); - for (int row = cell1.row(); row <= cell2.row(); row += CELLCHUNK_ROWS) - for (int col = cell1.column(); col <= cell2.column(); - col += CELLCHUNK_COLS) - { - cell.setRow (row); - cell.setColumn (col); - cell.setSheet(range.sheet()); - cells.push_back (cell); - } - return cells; -} - -RangeList DependencyList::computeDependencies (const Point &cell) const -{ - Cell *c = cell.cell(); - - // Not a formula -> no dependencies - if (!c->isFormula()) - return RangeList(); - - // Broken formula -> meaningless dependencies - // (tries to avoid c->formula() being null) - if (c->hasError()) - return RangeList(); - - Formula* f = c->formula(); - Q_ASSERT(f); - if (f==NULL) - { - kdDebug() << "Cell at row " << cell.row() << ", col " << cell.column() << " marked as formula, but formula is NULL" << endl; - return RangeList(); - } - - Tokens tokens = f->tokens(); - - //return empty list if the tokens aren't valid - if (!tokens.valid()) - return RangeList(); - - RangeList rl; - for( unsigned i = 0; i < tokens.count(); i++ ) - { - Token token = tokens[i]; - Token::Type tokenType = token.type(); - - //parse each cell/range and put it to our RangeList - if (tokenType == Token::Cell) - { - TQString text = token.text(); - Point cell (text, sheet->workbook(), sheet); - if (cell.isValid()) - rl.cells.push_back (cell); - } - else if (tokenType == Token::Range) - { - TQString text = token.text(); - Range range (text, sheet->workbook(), sheet); - if (range.isValid()) - rl.ranges.push_back (range); - } - } - - return rl; -} - diff --git a/kspread/dependencies.cpp b/kspread/dependencies.cpp new file mode 100644 index 00000000..66bbe61a --- /dev/null +++ b/kspread/dependencies.cpp @@ -0,0 +1,682 @@ +/* This file is part of the KDE project + Copyright 2004 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "dependencies.h" + +#include "formula.h" + +#include "kspread_cell.h" +#include "kspread_sheet.h" + +#include + +//rows x cols in one cell-chunk; bigger values lead to slower updating +//of range-dependencies, lower values will increase memory usage +#define CELLCHUNK_ROWS 128 +#define CELLCHUNK_COLS 16 + +namespace KSpread { + + +/** d-pointer of DependencyManager */ +class DependencyList { + public: + DependencyList (Sheet *s); + ~DependencyList () { reset (); }; + /** clear internal structures */ + void reset (); + + /** handle the fact that a cell has been changed */ + void cellChanged (const Point &cell); + + /** generate list of dependencies of a cell */ + void generateDependencies (const Point &cell); + /** generate list of dependencies of a range */ + void generateDependencies (const Range &range); + /** generate list of dependencies of a range list */ + void generateDependencies (const RangeList &rangeList); + + /** update cells dependending on a given cell */ + void processDependencies (const Point &cell); + /** update cells dependending on a cell in a given range */ + void processDependencies (const Range &range); + /** update cells dependending on a given range-list */ + void processDependencies (const RangeList &rangeList); + + /** get dependencies of a cell */ + RangeList getDependencies (const Point &cell); + /** get cells depending on this cell, either through normal or range dependency */ + TQValueList getDependants (const Point &cell); + + void areaModified (const TQString &name); + protected: + /** update structures: cell 1 depends on cell 2 */ + void addDependency (const Point &cell1, const Point &cell2); + /** update structures: cell depends on a range */ + void addRangeDependency (const RangeDependency &rd); + /** remove all dependencies of a cell */ + void removeDependencies (const Point &cell); + + /** update all cells depending on a range containing this cell */ + void processRangeDependencies (const Point &cell); + + /** update all cells depending on a range intersecting with this range */ + void processRangeDependencies (const Range &range); + + /** update one cell due to changed dependencies */ + void updateCell (const Point &cell) const; + + /** return a leading cell for a given cell (used to store range + dependencies effectively) */ + Point leadingCell (const Point &cell) const; + /** list of leading cells of all cell chunks that this range belongs to */ + TQValueList leadingCells (const Range &range) const; + /** retrieve a list of cells that a given cell depends on */ + RangeList computeDependencies (const Point &cell) const; + + TQValueList getCellDeps(const Point& cell) const { + CellDepsMap::const_iterator it = cellDeps.find( cell ); + return it == cellDeps.end() ? TQValueList() : *it; + } + + /** debug */ + void dump(); + + /** Sheet whose dependencies are managed by this instance */ + Sheet *sheet; + + /** dependencies of each cell */ + TQMap dependencies; + /** list of cells (but NOT ranges) that depend on a cell */ + typedef TQMap > CellDepsMap; + CellDepsMap cellDeps; + /** all range dependencies splitted into cell-chunks (TODO: describe) */ + TQMap > rangeDeps; + /** list of cells referencing a given named area */ + TQMap > areaDeps; +}; + +} // namespace KSpread + +using namespace KSpread; + +// This is currently not called - but it's really convenient to call it from +// gdb or from debug output to check that everything is set up ok. +void DependencyList::dump() +{ + TQMap::const_iterator it = dependencies.begin(); + for ( ; it != dependencies.end(); ++it ) { + Point p = it.key(); + kdDebug() << "Cell " << p.sheetName() << " " << p.pos() + << " depends on :" << endl; + RangeList rl = (*it); + TQValueList::const_iterator itp = rl.cells.begin(); + for ( ; itp != rl.cells.end(); ++itp ) + kdDebug() << " cell " << (*itp).pos() << endl; + TQValueList::const_iterator itr = rl.ranges.begin(); + for ( ; itr != rl.ranges.end(); ++itr ) + kdDebug() << " range " << (*itr).toString() << endl; + } + + CellDepsMap::const_iterator cit = cellDeps.begin(); + for ( ; cit != cellDeps.end(); ++cit ) + { + Point p = cit.key(); + kdDebug() << "The cells that depend on " << p.sheetName() << " " << p.pos() + << " are :" << endl; + TQValueList::const_iterator itp = (*cit).begin(); + for ( ; itp != (*cit).end(); ++itp ) + kdDebug() << " cell " << (*itp).pos() << endl; + } + +} + +DependencyManager::DependencyManager (Sheet *s) +{ + deps = new DependencyList (s); +} + +DependencyManager::~DependencyManager () +{ + delete deps; + deps = 0; +} + +void DependencyManager::reset () +{ + deps->reset(); +} + +void DependencyManager::cellChanged (const Point &cell) +{ + deps->cellChanged (cell); +} + +void DependencyManager::rangeChanged (const Range &range) +{ + deps->generateDependencies (range); + deps->processDependencies (range); +} + +void DependencyManager::rangeListChanged (const RangeList &rangeList) +{ + deps->generateDependencies (rangeList); + deps->processDependencies (rangeList); +} + +void DependencyManager::areaModified (const TQString &name) +{ + deps->areaModified (name); +} + +RangeList DependencyManager::getDependencies (const Point &cell) +{ + return deps->getDependencies (cell); +} + +TQValueList DependencyManager::getDependants (const Point &cell) +{ + return deps->getDependants (cell); +} + +DependencyList::DependencyList (Sheet *s) + : sheet (s) +{ +} + +void DependencyList::reset () +{ + dependencies.clear(); + cellDeps.clear(); + rangeDeps.clear(); +} + +void DependencyList::cellChanged (const Point &cell) +{ + Cell *c = cell.cell(); + + // empty or default cell? do nothing + if( c->isDefault() ) + return; + + //if the cell contains the circle error, we mustn't do anything + if (c->testFlag (Cell::Flag_CircularCalculation)) + return; + + //don't re-generate dependencies if we're updating dependencies + if ( !(c->testFlag (Cell::Flag_Progress))) + generateDependencies (cell); + + processDependencies (cell); +} + +RangeList DependencyList::getDependencies (const Point &cell) +{ + RangeList rl; + //look if the cell has any dependencies + if (!dependencies.contains (cell)) + return rl; //it doesn't - return an empty list + + //the cell does have dependencies - return them! + return dependencies[cell]; +} + +TQValueList DependencyList::getDependants (const Point &cell) +{ + //cell dependencies go first + TQValueList list = getCellDeps( cell ); + //next, append range dependencies + Point leading = leadingCell (cell); + TQValueList::iterator it; + if (!rangeDeps.count (leading)) + return list; //no range dependencies in this cell chunk -> nothing more to do + + for (it = rangeDeps[leading].begin(); + it != rangeDeps[leading].end(); ++it) + { + //process all range dependencies, and for each range including the questioned cell, + //add the depending cell to the list + if ((*it).range.contains (cell)) + { + Point c; + c.setRow ((*it).cellrow); + c.setColumn ((*it).cellcolumn); + c.setSheet ( (*it).cellsheet ); + list.push_back (c); + } + } + + return list; +} + +void DependencyList::areaModified (const TQString &name) +{ + // since area names are something like aliases, modifying an area name + // basically means that all cells referencing this area should be treated + // as modified - that will retrieve updated area ranges and also update + // everything as necessary ... + if (!areaDeps.contains (name)) + return; + + TQMap::iterator it; + for (it = areaDeps[name].begin(); it != areaDeps[name].end(); ++it) + { + Cell *c = it.key().cell(); + // this forces the cell to regenerate everything - new range dependencies + // and so on + c->setValue (c->value ()); + } +} + +void DependencyList::addDependency (const Point &cell1, + const Point &cell2) +{ + //cell2 can be in another sheet (inter-sheet dependency) + Sheet *sh = cell2.sheet(); + if (!sh) + sh = sheet; + + dependencies[cell1].cells.push_back (cell2); + sh->dependencies()->deps->cellDeps[cell2].push_back (cell1); +} + +void DependencyList::addRangeDependency (const RangeDependency &rd) +{ + //target range can be in another sheet (inter-sheet dependency) + Sheet *sh = rd.range.sheet(); + if (!sh) + sh = sheet; + + Point cell; + cell.setSheet (rd.cellsheet); + cell.setRow (rd.cellrow); + cell.setColumn (rd.cellcolumn); + dependencies[cell].ranges.push_back (rd.range); + + TQValueList leadings = leadingCells (rd.range); + TQValueList::iterator it; + for (it = leadings.begin(); it != leadings.end(); ++it) + sh->dependencies()->deps->rangeDeps[*it].push_back (rd); + + // the target range could be a named area ... + if (!rd.range.namedArea().isNull()) + areaDeps[rd.range.namedArea()][cell] = true; +} + +void DependencyList::removeDependencies (const Point &cell) +{ + //look if the cell has any dependencies + if (!dependencies.contains (cell)) + return; //it doesn't - nothing more to do + + //first we remove cell-dependencies + TQValueList cells = dependencies[cell].cells; + TQValueList::iterator it1; + for (it1 = cells.begin(); it1 != cells.end(); ++it1) + { + //get sheet-pointer - needed to handle inter-sheet dependencies correctly + Sheet *sh = (*it1).sheet(); + if (!sh) + sh = sheet; + + if (!sh->dependencies()->deps->cellDeps.contains (*it1)) + continue; //this should never happen + + //we no longer depend on this cell + TQValueList::iterator cit; + cit = sh->dependencies()->deps->cellDeps[*it1].find (cell); + if (cit != sh->dependencies()->deps->cellDeps[*it1].end()) + sh->dependencies()->deps->cellDeps[*it1].erase (cit); + } + + //then range-dependencies are removed + TQValueList ranges = dependencies[cell].ranges; + TQValueList::iterator it2; + TQValueList leads; + for (it2 = ranges.begin(); it2 != ranges.end(); ++it2) + { + //we construct a list of cell-chunks containing a range and merge it + //with lists generated from all previous ranges (duplicates are removed) + TQValueList leadings = leadingCells (*it2); + for (it1 = leadings.begin(); it1 != leadings.end(); ++it1) + if (!leads.contains (*it1)) + leads.push_back (*it1); + } + for (it1 = leads.begin(); it1 != leads.end(); ++it1) + { + //get sheet-pointer - needed to handle inter-sheet dependencies correctly + Sheet *sh = (*it1).sheet(); + if (!sh) + sh = sheet; + + if (sh->dependencies()->deps->rangeDeps.contains (*it1)) + { + TQValueList::iterator it3; + it3 = sh->dependencies()->deps->rangeDeps[*it1].begin(); + //erase all range dependencies of this cell in this cell-chunk + while (it3 != sh->dependencies()->deps->rangeDeps[*it1].end()) + if (((*it3).cellrow == cell.row()) && + ((*it3).cellcolumn == cell.column())) + it3 = sh->dependencies()->deps->rangeDeps[*it1].erase (it3); + else + ++it3; + //erase the list if we no longer need it + if (sh->dependencies()->deps->rangeDeps[*it1].empty()) + sh->dependencies()->deps->rangeDeps.erase (*it1); + } + } + + // remove information about named area dependencies + TQMap >::iterator itr; + for (itr = areaDeps.begin(); itr != areaDeps.end(); ++itr) { + if (itr.data().contains (cell)) + itr.data().remove (cell); + } + + // finally, remove the entry about this cell + dependencies[cell].cells.clear(); + dependencies[cell].ranges.clear(); + dependencies.erase (cell); +} + +void DependencyList::generateDependencies (const Point &cell) +{ + //get rid of old dependencies first + removeDependencies (cell); + + //new dependencies only need to be generated if the cell contains a formula + Cell *c = sheet->cellAt (cell.column(), cell.row()); + if( c->isDefault() ) + return; + if (!c->isFormula()) + return; + + //now we need to generate dependencies + RangeList rl = computeDependencies (cell); + + //now that we have the new dependencies, we put them into our data structures + //and we're done + TQValueList::iterator it1; + TQValueList::iterator it2; + + for (it1 = rl.cells.begin(); it1 != rl.cells.end(); ++it1) + addDependency (cell, *it1); + for (it2 = rl.ranges.begin(); it2 != rl.ranges.end(); ++it2) + { + RangeDependency rd; + rd.cellrow = cell.row(); + rd.cellcolumn = cell.column(); + rd.cellsheet = sheet; + rd.range = *it2; + + if (rd.range.sheet() == 0) + rd.range.setSheet(sheet); + + addRangeDependency (rd); + } +} + +void DependencyList::generateDependencies (const Range &range) +{ + for (int row = range.startRow(); row <= range.endRow(); row++) + for (int col = range.startCol(); col <= range.endCol(); col++) + { + Point c; + c.setRow (row); + c.setColumn (col); + c.setSheet(sheet); + generateDependencies (c); + } +} + +void DependencyList::generateDependencies (const RangeList &rangeList) +{ + TQValueList::const_iterator it1; + TQValueList::const_iterator it2; + + for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1) + generateDependencies (*it1); + for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2) + generateDependencies (*it2); +} + +void DependencyList::processDependencies (const Point &cell) +{ + const TQValueList d = getCellDeps(cell); + TQValueList::const_iterator it = d.begin(); + const TQValueList::const_iterator end = d.end(); + for (; it != end; ++it) + updateCell (*it); + + processRangeDependencies (cell); +} + +void DependencyList::processRangeDependencies (const Point &cell) +{ + Point leading = leadingCell (cell); + if (!rangeDeps.count (leading)) + return; //no range dependencies in this cell chunk + + const TQValueList rd = rangeDeps[leading]; + + TQValueList::const_iterator it; + for (it = rd.begin(); it != rd.end(); ++it) + { + //process all range dependencies, and for each range including the modified cell, + //recalc the depending cell + if ((*it).range.contains (cell)) + { + Point c; + c.setRow ((*it).cellrow); + c.setColumn ((*it).cellcolumn); + c.setSheet ( (*it).cellsheet ); + updateCell (c); + } + } +} + +void DependencyList::processDependencies (const Range &range) +{ + //each cell's dependencies need to be updated - that cannot be helped - having a range + //only helps with range dependencies + for (int row = range.startRow(); row <= range.endRow(); row++) + for (int col = range.startCol(); col <= range.endCol(); col++) + { + Point c; + c.setRow (row); + c.setColumn (col); + c.setSheet( sheet ); + + const TQValueList d = getCellDeps(c); + TQValueList::const_iterator it = d.begin(); + const TQValueList::const_iterator end = d.end(); + for (; it != end; ++it) + updateCell (*it); + } + + processRangeDependencies (range); +} + +void DependencyList::processRangeDependencies (const Range &range) +{ + //TODO: some optimization, so that we don't recompute cells depending of huge + //ranges more than once (now we recompute them once per cell-chunk used by their dependency) + //This will probably happen as a part of splitting this into dep manager + //and recalc manager + + TQValueList leadings = leadingCells (range); + TQValueList::iterator it; + for (it = leadings.begin(); it != leadings.end(); ++it) + { + if (!rangeDeps.count (*it)) + continue; //no range dependencies in this cell chunk + TQValueList::iterator it2; + for (it2 = rangeDeps[*it].begin(); it2 != rangeDeps[*it].end(); ++it2) + { + //process all range dependencies, and for each range intersecting with our range, + //recalc the depending cell + if ((*it2).range.intersects (range)) + { + Point c; + c.setRow ((*it2).range.startRow()); + c.setColumn ((*it2).range.startCol()); + c.setSheet(sheet); + updateCell (c); + } + } + } +} + +void DependencyList::processDependencies (const RangeList &rangeList) +{ + TQValueList::const_iterator it1; + TQValueList::const_iterator it2; + + for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1) + processDependencies (*it1); + for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2) + processDependencies (*it2); +} + +void DependencyList::updateCell (const Point &cell) const +{ + Cell *c = cell.cell(); + //prevent infinite recursion (circular dependencies) + if (c->testFlag (Cell::Flag_Progress) || + c->testFlag (Cell::Flag_CircularCalculation)) + { + kdError(36001) << "ERROR: Circle, cell " << c->fullName() << + ", in dep.manager for sheet " << sheet->name() << endl; + Value v; + // don't set anything if the cell already has all these things set + // this prevents endless loop for inter-sheet curcular dependencies, + // where the usual mechanisms fail doe to having multiple dependency + // managers ... + if (!c->testFlag (Cell::Flag_CircularCalculation)) + { + c->setFlag(Cell::Flag_CircularCalculation); + v.setError ( "####" ); + c->setValue (v); + } + //clear the computing-dependencies flag + c->clearFlag (Cell::Flag_Progress); + return; + } + //set the computing-dependencies flag + c->setFlag (Cell::Flag_Progress); + + //mark the cell as calc-dirty + c->setCalcDirtyFlag(); + + //recalculate the cell + c->calc (false); + + //clear the computing-dependencies flag + c->clearFlag (Cell::Flag_Progress); +} + +Point DependencyList::leadingCell (const Point &cell) const +{ + Point c; + c.setRow (cell.row() - cell.row() % CELLCHUNK_ROWS + 1); + c.setColumn (cell.column() - cell.column() % CELLCHUNK_COLS + 1); + c.setSheet(cell.sheet()); + return c; +} + +TQValueList DependencyList::leadingCells (const Range &range) const +{ + TQValueList cells; + Point cell1, cell2, cell; + + cell1.setRow (range.startRow()); + cell1.setColumn (range.startCol()); + cell2.setRow (range.endRow()); + cell2.setColumn (range.endCol()); + cell1.setSheet(range.sheet()); + cell2.setSheet(range.sheet()); + + cell1 = leadingCell (cell1); + cell2 = leadingCell (cell2); + for (int row = cell1.row(); row <= cell2.row(); row += CELLCHUNK_ROWS) + for (int col = cell1.column(); col <= cell2.column(); + col += CELLCHUNK_COLS) + { + cell.setRow (row); + cell.setColumn (col); + cell.setSheet(range.sheet()); + cells.push_back (cell); + } + return cells; +} + +RangeList DependencyList::computeDependencies (const Point &cell) const +{ + Cell *c = cell.cell(); + + // Not a formula -> no dependencies + if (!c->isFormula()) + return RangeList(); + + // Broken formula -> meaningless dependencies + // (tries to avoid c->formula() being null) + if (c->hasError()) + return RangeList(); + + Formula* f = c->formula(); + Q_ASSERT(f); + if (f==NULL) + { + kdDebug() << "Cell at row " << cell.row() << ", col " << cell.column() << " marked as formula, but formula is NULL" << endl; + return RangeList(); + } + + Tokens tokens = f->tokens(); + + //return empty list if the tokens aren't valid + if (!tokens.valid()) + return RangeList(); + + RangeList rl; + for( unsigned i = 0; i < tokens.count(); i++ ) + { + Token token = tokens[i]; + Token::Type tokenType = token.type(); + + //parse each cell/range and put it to our RangeList + if (tokenType == Token::Cell) + { + TQString text = token.text(); + Point cell (text, sheet->workbook(), sheet); + if (cell.isValid()) + rl.cells.push_back (cell); + } + else if (tokenType == Token::Range) + { + TQString text = token.text(); + Range range (text, sheet->workbook(), sheet); + if (range.isValid()) + rl.ranges.push_back (range); + } + } + + return rl; +} + diff --git a/kspread/dialogs/Makefile.am b/kspread/dialogs/Makefile.am index 71d7a476..6f2dce6d 100644 --- a/kspread/dialogs/Makefile.am +++ b/kspread/dialogs/Makefile.am @@ -10,38 +10,38 @@ noinst_LTLIBRARIES = \ libdialogs.la libdialogs_la_SOURCES = \ - kspread_dlg_angle.cc \ - kspread_dlg_area.cc \ - kspread_dlg_comment.cc \ - kspread_dlg_conditional.cc \ - kspread_dlg_cons.cc \ - kspread_dlg_csv.cc \ - kspread_dlg_database.cc \ - kspread_dlg_format.cc \ - kspread_dlg_formula.cc \ - kspread_dlg_goalseek.cc \ - kspread_dlg_goto.cc \ - kspread_dlg_insert.cc \ - kspread_dlg_layout.cc \ - kspread_dlg_list.cc \ - kspread_dlg_paperlayout.cc \ - kspread_dlg_pasteinsert.cc \ - kspread_dlg_preference.cc \ - kspread_dlg_reference.cc \ - kspread_dlg_resize2.cc \ - kspread_dlg_series.cc \ - kspread_dlg_show.cc \ - kspread_dlg_showColRow.cc \ - kspread_dlg_sort.cc \ - kspread_dlg_special.cc \ - kspread_dlg_styles.cc \ - kspread_dlg_subtotal.cc \ - kspread_dlg_validity.cc \ + kspread_dlg_angle.cpp \ + kspread_dlg_area.cpp \ + kspread_dlg_comment.cpp \ + kspread_dlg_conditional.cpp \ + kspread_dlg_cons.cpp \ + kspread_dlg_csv.cpp \ + kspread_dlg_database.cpp \ + kspread_dlg_format.cpp \ + kspread_dlg_formula.cpp \ + kspread_dlg_goalseek.cpp \ + kspread_dlg_goto.cpp \ + kspread_dlg_insert.cpp \ + kspread_dlg_layout.cpp \ + kspread_dlg_list.cpp \ + kspread_dlg_paperlayout.cpp \ + kspread_dlg_pasteinsert.cpp \ + kspread_dlg_preference.cpp \ + kspread_dlg_reference.cpp \ + kspread_dlg_resize2.cpp \ + kspread_dlg_series.cpp \ + kspread_dlg_show.cpp \ + kspread_dlg_showColRow.cpp \ + kspread_dlg_sort.cpp \ + kspread_dlg_special.cpp \ + kspread_dlg_styles.cpp \ + kspread_dlg_subtotal.cpp \ + kspread_dlg_validity.cpp \ kspreadsubtotal.ui \ - link.cc \ + link.cpp \ sheet_properties_base.ui \ - sheet_properties.cc \ - kspread_dlg_find.cc \ + sheet_properties.cpp \ + kspread_dlg_find.cpp \ position_cell_format.ui \ font_cell_format.ui \ protection_cell_format.ui \ diff --git a/kspread/dialogs/kspread_dlg_angle.cc b/kspread/dialogs/kspread_dlg_angle.cc deleted file mode 100644 index 763e47a5..00000000 --- a/kspread/dialogs/kspread_dlg_angle.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 2002 Ariya Hidayat - (C) 1999-2002 Laurent Montel - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_dlg_angle.h" - -using namespace KSpread; - -AngleDialog::AngleDialog(View* parent, const char* name, const TQPoint &_marker) - : KDialogBase( parent, name,TRUE,i18n("Change Angle" ), Ok|Cancel|Default ) -{ - m_pView=parent; - marker=_marker; - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - - TQVBoxLayout *lay = new TQVBoxLayout( page, 0, spacingHint() ); - m_pAngle = new KIntNumInput( page ); - m_pAngle->setRange( -90, 90, 1 ); - m_pAngle->setLabel( i18n("Angle:") ); - m_pAngle->setSuffix(" "); - lay->addWidget( m_pAngle ); - - TQWidget* spacer = new TQWidget( page ); - spacer->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Expanding ) ); - lay->addWidget( spacer ); - - m_pAngle->setFocus(); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - - Cell *cell = m_pView->activeSheet()->cellAt( marker.x(), marker.y() ); - int angle=-(cell->format()->getAngle(marker.x(), marker.y())); - m_pAngle->setValue( angle ); -} - -void AngleDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - m_pView->activeSheet()->setSelectionAngle(m_pView->selectionInfo(), -m_pAngle->value()); - m_pView->slotUpdateView( m_pView->activeSheet() ); - // m_pView->doc()->emitEndOperation(); - - accept(); -} - -void AngleDialog::slotDefault() -{ - m_pAngle->setValue( 0 ); -} - - -#include "kspread_dlg_angle.moc" diff --git a/kspread/dialogs/kspread_dlg_angle.cpp b/kspread/dialogs/kspread_dlg_angle.cpp new file mode 100644 index 00000000..763e47a5 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_angle.cpp @@ -0,0 +1,86 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 2002 Ariya Hidayat + (C) 1999-2002 Laurent Montel + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_dlg_angle.h" + +using namespace KSpread; + +AngleDialog::AngleDialog(View* parent, const char* name, const TQPoint &_marker) + : KDialogBase( parent, name,TRUE,i18n("Change Angle" ), Ok|Cancel|Default ) +{ + m_pView=parent; + marker=_marker; + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + + TQVBoxLayout *lay = new TQVBoxLayout( page, 0, spacingHint() ); + m_pAngle = new KIntNumInput( page ); + m_pAngle->setRange( -90, 90, 1 ); + m_pAngle->setLabel( i18n("Angle:") ); + m_pAngle->setSuffix(" "); + lay->addWidget( m_pAngle ); + + TQWidget* spacer = new TQWidget( page ); + spacer->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Expanding ) ); + lay->addWidget( spacer ); + + m_pAngle->setFocus(); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + + Cell *cell = m_pView->activeSheet()->cellAt( marker.x(), marker.y() ); + int angle=-(cell->format()->getAngle(marker.x(), marker.y())); + m_pAngle->setValue( angle ); +} + +void AngleDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + m_pView->activeSheet()->setSelectionAngle(m_pView->selectionInfo(), -m_pAngle->value()); + m_pView->slotUpdateView( m_pView->activeSheet() ); + // m_pView->doc()->emitEndOperation(); + + accept(); +} + +void AngleDialog::slotDefault() +{ + m_pAngle->setValue( 0 ); +} + + +#include "kspread_dlg_angle.moc" diff --git a/kspread/dialogs/kspread_dlg_area.cc b/kspread/dialogs/kspread_dlg_area.cc deleted file mode 100644 index 108511ad..00000000 --- a/kspread/dialogs/kspread_dlg_area.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 1999-2001 Laurent Montel - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include - -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "selection.h" - -#include "kspread_dlg_area.h" - -using namespace KSpread; - -AreaDialog::AreaDialog( View * parent, const char * name, const TQPoint & _marker ) - : KDialogBase( parent, name, TRUE, i18n("Area Name"), Ok | Cancel ) -{ - m_pView = parent; - m_marker = _marker; - - TQWidget * page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout * lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQLabel * label = new TQLabel( i18n("Enter the area name:"), page ); - lay1->addWidget( label ); - - m_areaName = new TQLineEdit(page); - m_areaName->setMinimumWidth( m_areaName->sizeHint().width() * 3 ); - - lay1->addWidget( m_areaName ); - m_areaName->setFocus(); - connect ( m_areaName, TQT_SIGNAL(textChanged ( const TQString & )), this, TQT_SLOT(slotAreaNamechanged( const TQString &))); - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - enableButtonOK(!m_areaName->text().isEmpty()); - -} - -void AreaDialog::slotAreaNamechanged( const TQString & text) -{ - enableButtonOK(!text.isEmpty()); -} - -void AreaDialog::slotOk() -{ - TQString tmp(m_areaName->text()); - if( !tmp.isEmpty() ) - { - tmp = tmp.lower(); - - TQRect rect( m_pView->selectionInfo()->selection() ); - bool newName = true; - TQValueList::Iterator it; - TQValueList area = m_pView->doc()->listArea(); - for ( it = area.begin(); it != area.end(); ++it ) - { - if(tmp == (*it).ref_name) - newName = false; - } - if (newName) - { - m_pView->doc()->emitBeginOperation( false ); - m_pView->doc()->addAreaName(rect, tmp, m_pView->activeSheet()->sheetName()); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); - } - else - KMessageBox::error( this, i18n("This name is already used.")); - } - else - { - KMessageBox::error( this, i18n("Area text is empty.") ); - } -} - -#include "kspread_dlg_area.moc" diff --git a/kspread/dialogs/kspread_dlg_area.cpp b/kspread/dialogs/kspread_dlg_area.cpp new file mode 100644 index 00000000..108511ad --- /dev/null +++ b/kspread/dialogs/kspread_dlg_area.cpp @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 1999-2001 Laurent Montel + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include + +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "selection.h" + +#include "kspread_dlg_area.h" + +using namespace KSpread; + +AreaDialog::AreaDialog( View * parent, const char * name, const TQPoint & _marker ) + : KDialogBase( parent, name, TRUE, i18n("Area Name"), Ok | Cancel ) +{ + m_pView = parent; + m_marker = _marker; + + TQWidget * page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout * lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQLabel * label = new TQLabel( i18n("Enter the area name:"), page ); + lay1->addWidget( label ); + + m_areaName = new TQLineEdit(page); + m_areaName->setMinimumWidth( m_areaName->sizeHint().width() * 3 ); + + lay1->addWidget( m_areaName ); + m_areaName->setFocus(); + connect ( m_areaName, TQT_SIGNAL(textChanged ( const TQString & )), this, TQT_SLOT(slotAreaNamechanged( const TQString &))); + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + enableButtonOK(!m_areaName->text().isEmpty()); + +} + +void AreaDialog::slotAreaNamechanged( const TQString & text) +{ + enableButtonOK(!text.isEmpty()); +} + +void AreaDialog::slotOk() +{ + TQString tmp(m_areaName->text()); + if( !tmp.isEmpty() ) + { + tmp = tmp.lower(); + + TQRect rect( m_pView->selectionInfo()->selection() ); + bool newName = true; + TQValueList::Iterator it; + TQValueList area = m_pView->doc()->listArea(); + for ( it = area.begin(); it != area.end(); ++it ) + { + if(tmp == (*it).ref_name) + newName = false; + } + if (newName) + { + m_pView->doc()->emitBeginOperation( false ); + m_pView->doc()->addAreaName(rect, tmp, m_pView->activeSheet()->sheetName()); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); + } + else + KMessageBox::error( this, i18n("This name is already used.")); + } + else + { + KMessageBox::error( this, i18n("Area text is empty.") ); + } +} + +#include "kspread_dlg_area.moc" diff --git a/kspread/dialogs/kspread_dlg_comment.cc b/kspread/dialogs/kspread_dlg_comment.cc deleted file mode 100644 index 2494959c..00000000 --- a/kspread/dialogs/kspread_dlg_comment.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 Philipp Mueller - (C) 1999-2002 Laurent Montel - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include -#include - -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_view.h" - -#include "kspread_dlg_comment.h" - -using namespace KSpread; - -CommentDialog::CommentDialog( View* parent, const char* name,const TQPoint &_marker) - : KDialogBase( parent, name,TRUE,i18n("Cell Comment"),Ok|Cancel ) -{ - m_pView = parent; - marker= _marker; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - multiLine = new TQMultiLineEdit( page ); - lay1->addWidget(multiLine); - - multiLine->setFocus(); - - - Cell *cell = m_pView->activeSheet()->cellAt( m_pView->canvasWidget()->markerColumn(), m_pView->canvasWidget()->markerRow() ); - if(!cell->format()->comment(marker.x(),marker.y()).isEmpty()) - multiLine->setText(cell->format()->comment(marker.x(),marker.y())); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect(multiLine, TQT_SIGNAL(textChanged ()),this, TQT_SLOT(slotTextChanged())); - - slotTextChanged(); - - resize( 400, height() ); -} - -void CommentDialog::slotTextChanged() -{ - enableButtonOK( !multiLine->text().isEmpty()); -} - -void CommentDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - m_pView->activeSheet()->setSelectionComment( m_pView->selectionInfo(), - multiLine->text().stripWhiteSpace() ); - m_pView->slotUpdateView( m_pView->activeSheet(), *m_pView->selectionInfo() ); - // m_pView->doc()->emitEndOperation(); - accept(); -} - -#include "kspread_dlg_comment.moc" diff --git a/kspread/dialogs/kspread_dlg_comment.cpp b/kspread/dialogs/kspread_dlg_comment.cpp new file mode 100644 index 00000000..2494959c --- /dev/null +++ b/kspread/dialogs/kspread_dlg_comment.cpp @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 Philipp Mueller + (C) 1999-2002 Laurent Montel + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include + +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_view.h" + +#include "kspread_dlg_comment.h" + +using namespace KSpread; + +CommentDialog::CommentDialog( View* parent, const char* name,const TQPoint &_marker) + : KDialogBase( parent, name,TRUE,i18n("Cell Comment"),Ok|Cancel ) +{ + m_pView = parent; + marker= _marker; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + multiLine = new TQMultiLineEdit( page ); + lay1->addWidget(multiLine); + + multiLine->setFocus(); + + + Cell *cell = m_pView->activeSheet()->cellAt( m_pView->canvasWidget()->markerColumn(), m_pView->canvasWidget()->markerRow() ); + if(!cell->format()->comment(marker.x(),marker.y()).isEmpty()) + multiLine->setText(cell->format()->comment(marker.x(),marker.y())); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect(multiLine, TQT_SIGNAL(textChanged ()),this, TQT_SLOT(slotTextChanged())); + + slotTextChanged(); + + resize( 400, height() ); +} + +void CommentDialog::slotTextChanged() +{ + enableButtonOK( !multiLine->text().isEmpty()); +} + +void CommentDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + m_pView->activeSheet()->setSelectionComment( m_pView->selectionInfo(), + multiLine->text().stripWhiteSpace() ); + m_pView->slotUpdateView( m_pView->activeSheet(), *m_pView->selectionInfo() ); + // m_pView->doc()->emitEndOperation(); + accept(); +} + +#include "kspread_dlg_comment.moc" diff --git a/kspread/dialogs/kspread_dlg_conditional.cc b/kspread/dialogs/kspread_dlg_conditional.cc deleted file mode 100644 index a75bd5bd..00000000 --- a/kspread/dialogs/kspread_dlg_conditional.cc +++ /dev/null @@ -1,679 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002-2003 Philipp Mueller - (C) 2002 John Dailey - (C) 1999-2001 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "kspread_dlg_conditional.h" -#include "kspread_condition.h" - -#include "kspread_canvas.h" -#include "kspread_cell.h" -#include "kspread_doc.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_view.h" - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -using namespace KSpread; - -ConditionalWidget::ConditionalWidget( TQWidget* parent, const char* name, WFlags fl ) - : TQWidget( parent, name, fl ) -{ - TQGridLayout * Form1Layout = new TQGridLayout( this, 1, 1, 11, 6, "Form1Layout"); - - TQGroupBox * groupBox1_3 = new TQGroupBox( this, "groupBox1_3" ); - groupBox1_3->setColumnLayout(0, Qt::Vertical ); - groupBox1_3->layout()->setSpacing( KDialog::spacingHint() ); - groupBox1_3->layout()->setMargin( KDialog::marginHint() ); - TQGridLayout * groupBox1_3Layout = new TQGridLayout( groupBox1_3->layout() ); - groupBox1_3Layout->setAlignment( TQt::AlignTop ); - - TQLabel * textLabel1_3 = new TQLabel( groupBox1_3, "textLabel1_3" ); - groupBox1_3Layout->addWidget( textLabel1_3, 0, 0 ); - - m_condition_3 = new TQComboBox( false, groupBox1_3, "m_condition_3" ); - groupBox1_3Layout->addWidget( m_condition_3, 0, 1 ); - - m_firstValue_3 = new KLineEdit( groupBox1_3, "m_firstValue_3" ); - m_firstValue_3->setEnabled( false ); - groupBox1_3Layout->addWidget( m_firstValue_3, 0, 2 ); - - m_secondValue_3 = new KLineEdit( groupBox1_3, "m_secondValue_3" ); - m_secondValue_3->setEnabled( false ); - groupBox1_3Layout->addWidget( m_secondValue_3, 0, 3 ); - - m_style_3 = new TQComboBox( false, groupBox1_3, "m_style_3" ); - m_style_3->setEnabled( false ); - groupBox1_3Layout->addWidget( m_style_3, 1, 1 ); - - TQLabel * textLabel2_3 = new TQLabel( groupBox1_3, "textLabel2_3" ); - groupBox1_3Layout->addWidget( textLabel2_3, 1, 0 ); - - TQSpacerItem * spacer = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_3Layout->addItem( spacer, 1, 2 ); - TQSpacerItem * spacer_2 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_3Layout->addItem( spacer_2, 1, 3 ); - - Form1Layout->addWidget( groupBox1_3, 2, 0 ); - - TQGroupBox * groupBox1_2 = new TQGroupBox( this, "groupBox1_2" ); - groupBox1_2->setColumnLayout(0, Qt::Vertical ); - groupBox1_2->layout()->setSpacing( KDialog::spacingHint() ); - groupBox1_2->layout()->setMargin( KDialog::marginHint() ); - - TQGridLayout * groupBox1_2Layout = new TQGridLayout( groupBox1_2->layout() ); - groupBox1_2Layout->setAlignment( TQt::AlignTop ); - - TQLabel * textLabel1_2 = new TQLabel( groupBox1_2, "textLabel1_2" ); - groupBox1_2Layout->addWidget( textLabel1_2, 0, 0 ); - - TQLabel * textLabel2_2 = new TQLabel( groupBox1_2, "textLabel2_2" ); - groupBox1_2Layout->addWidget( textLabel2_2, 1, 0 ); - - m_condition_2 = new TQComboBox( false, groupBox1_2, "m_condition_2" ); - groupBox1_2Layout->addWidget( m_condition_2, 0, 1 ); - - m_style_2 = new TQComboBox( false, groupBox1_2, "m_style_2" ); - m_style_2->setEnabled( false ); - groupBox1_2Layout->addWidget( m_style_2, 1, 1 ); - - m_firstValue_2 = new KLineEdit( groupBox1_2, "m_firstValue_2" ); - m_firstValue_2->setEnabled( false ); - groupBox1_2Layout->addWidget( m_firstValue_2, 0, 2 ); - - m_secondValue_2 = new KLineEdit( groupBox1_2, "m_secondValue_2" ); - m_secondValue_2->setEnabled( false ); - - groupBox1_2Layout->addWidget( m_secondValue_2, 0, 3 ); - - TQSpacerItem * spacer_3 = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_2Layout->addItem( spacer_3, 1, 2 ); - TQSpacerItem * spacer_4 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_2Layout->addItem( spacer_4, 1, 3 ); - Form1Layout->addWidget( groupBox1_2, 1, 0 ); - - TQGroupBox * groupBox1_1 = new TQGroupBox( this, "groupBox1_1" ); - groupBox1_1->setColumnLayout(0, Qt::Vertical ); - groupBox1_1->layout()->setSpacing( KDialog::spacingHint() ); - groupBox1_1->layout()->setMargin( KDialog::marginHint() ); - - TQGridLayout * groupBox1_1Layout = new TQGridLayout( groupBox1_1->layout() ); - groupBox1_1Layout->setAlignment( TQt::AlignTop ); - - TQLabel * textLabel1_1 = new TQLabel( groupBox1_1, "textLabel1_2_2" ); - groupBox1_1Layout->addWidget( textLabel1_1, 0, 0 ); - - TQLabel * textLabel2_1 = new TQLabel( groupBox1_1, "textLabel2_2_2" ); - groupBox1_1Layout->addWidget( textLabel2_1, 1, 0 ); - - m_condition_1 = new TQComboBox( false, groupBox1_1, "m_condition_1" ); - groupBox1_1Layout->addWidget( m_condition_1, 0, 1 ); - - m_style_1 = new TQComboBox( false, groupBox1_1, "m_style_1" ); - m_style_1->setEnabled( false ); - groupBox1_1Layout->addWidget( m_style_1, 1, 1 ); - - m_firstValue_1 = new KLineEdit( groupBox1_1, "m_firstValue_1" ); - m_firstValue_1->setEnabled( false ); - groupBox1_1Layout->addWidget( m_firstValue_1, 0, 2 ); - - m_secondValue_1 = new KLineEdit( groupBox1_1, "m_secondValue_1" ); - m_secondValue_1->setEnabled( false ); - groupBox1_1Layout->addWidget( m_secondValue_1, 0, 3 ); - - TQSpacerItem * spacer_5 = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_1Layout->addItem( spacer_5, 1, 2 ); - TQSpacerItem * spacer_6 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - groupBox1_1Layout->addItem( spacer_6, 1, 3 ); - - Form1Layout->addWidget( groupBox1_1, 0, 0 ); - resize( TQSize(702, 380).expandedTo( minimumSizeHint() ) ); - clearWState( WState_Polished ); - - TQStringList list; - list += i18n( "" ); - list += i18n( "equal to" ); - list += i18n( "greater than" ); - list += i18n( "less than" ); - list += i18n( "equal to or greater than" ); - list += i18n( "equal to or less than" ); - list += i18n( "between" ); - list += i18n( "outside range" ); - list += i18n( "different to" ); - - m_condition_1->clear(); - m_condition_2->clear(); - m_condition_3->clear(); - m_condition_1->insertStringList( list ); - m_condition_2->insertStringList( list ); - m_condition_3->insertStringList( list ); - - groupBox1_1->setTitle( i18n( "First Condition" ) ); - groupBox1_2->setTitle( i18n( "Second Condition" ) ); - groupBox1_3->setTitle( i18n( "Third Condition" ) ); - textLabel1_1->setText( i18n( "Cell is" ) ); - textLabel1_2->setText( i18n( "Cell is" ) ); - textLabel1_3->setText( i18n( "Cell is" ) ); - textLabel2_1->setText( i18n( "Cell style" ) ); - textLabel2_2->setText( i18n( "Cell style" ) ); - textLabel2_3->setText( i18n( "Cell style" ) ); - - connect( m_condition_1, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged1( const TQString & ) ) ); - connect( m_condition_2, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged2( const TQString & ) ) ); - connect( m_condition_3, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged3( const TQString & ) ) ); -} - -ConditionalWidget::~ConditionalWidget() -{ -} - -void ConditionalWidget::slotTextChanged1( const TQString & text ) -{ - if ( text == i18n( "" ) ) - { - m_firstValue_1->setEnabled( false ); - m_secondValue_1->setEnabled( false ); - m_style_1->setEnabled( false ); - } - else - { - m_condition_2->setEnabled( true ); - m_style_1->setEnabled( true ); - if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) - { - m_firstValue_1->setEnabled( true ); - m_secondValue_1->setEnabled( true ); - } - else - { - m_firstValue_1->setEnabled( true ); - m_secondValue_1->setEnabled( false ); - } - } -} - -void ConditionalWidget::slotTextChanged2( const TQString & text ) -{ - if ( text == i18n( "" ) ) - { - m_firstValue_2->setEnabled( false ); - m_secondValue_2->setEnabled( false ); - m_style_2->setEnabled( false ); - } - else - { - m_condition_3->setEnabled( true ); - m_style_2->setEnabled( true ); - if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) - { - m_firstValue_2->setEnabled( true ); - m_secondValue_2->setEnabled( true ); - } - else - { - m_firstValue_2->setEnabled( true ); - m_secondValue_2->setEnabled( false ); - } - } -} - -void ConditionalWidget::slotTextChanged3( const TQString & text ) -{ - if ( text == i18n( "" ) ) - { - m_firstValue_3->setEnabled( false ); - m_secondValue_3->setEnabled( false ); - m_style_3->setEnabled( false ); - } - else - { - m_style_3->setEnabled( true ); - if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) - { - m_firstValue_3->setEnabled( true ); - m_secondValue_3->setEnabled( true ); - } - else - { - m_firstValue_3->setEnabled( true ); - m_secondValue_3->setEnabled( false ); - } - } -} - -/** - * ConditionalDialog - * Sets conditional cell formattings. - */ -ConditionalDialog::ConditionalDialog( View * parent, const char * name, - const TQRect & marker ) - : KDialogBase( parent, name, true, "", KDialogBase::Ok | KDialogBase::Cancel, - KDialogBase::Ok, false ), - m_view( parent ), - m_dlg( new ConditionalWidget( this ) ), - m_marker( marker ) -{ - TQStringList list( m_view->doc()->styleManager()->styleNames() ); - - m_dlg->m_style_1->insertStringList( list ); - m_dlg->m_style_2->insertStringList( list ); - m_dlg->m_style_3->insertStringList( list ); - - setCaption( i18n( "Conditional Cell Attributes" ) ); - setButtonBoxOrientation(Qt::Vertical ); - setMainWidget( m_dlg ); - - init(); -} - -void ConditionalDialog::init() -{ - TQValueList conditionList; - TQValueList otherList; - bool found; - int numCondition; - - TQValueList::iterator it1; - TQValueList::iterator it2; - - Cell * obj = m_view->activeSheet()->cellAt( m_marker.left(), - m_marker.top() ); - - conditionList = obj->conditionList(); - /* this is the list, but only display the conditions common to all selected - cells*/ - - for ( int x = m_marker.left(); x <= m_marker.right(); x++ ) - { - for ( int y = m_marker.top(); y <= m_marker.bottom(); y++ ) - { - Cell * obj2 = m_view->activeSheet()->cellAt( x, y ); - otherList = obj2->conditionList(); - - it1 = conditionList.begin(); - while ( it1 != conditionList.end() ) - { - kdDebug() << "Here" << endl; - found = false; - for ( it2 = otherList.begin(); !found && it2 != otherList.end(); ++it2 ) - { - kdDebug() << "Found: " << found << endl; - found = ( (*it1).val1 == (*it2).val1 && - (*it1).val2 == (*it2).val2 && - (*it1).cond == (*it2).cond ); - - if ( (*it1).strVal1 && !(*it2).strVal1 ) - found = false; - if ( !(*it1).strVal1 && (*it2).strVal1 ) - found = false; - if ( (*it1).strVal1 && (*it2).strVal1 - && ( *(*it1).strVal1 != *(*it2).strVal1 ) ) - found = false; - if ( !found ) - continue; - - if ( (*it1).strVal2 && !(*it2).strVal2 ) - found = false; - if ( !(*it1).strVal2 && (*it2).strVal2 ) - found = false; - if ( (*it1).strVal2 && (*it2).strVal2 - && ( *(*it1).strVal2 != *(*it2).strVal2 ) ) - found = false; - if ( !found ) - continue; - - if ( (*it1).colorcond && !(*it2).colorcond ) - found = false; - if ( !(*it1).colorcond && (*it2).colorcond ) - found = false; - if ( (*it1).colorcond && (*it2).colorcond - && ( *(*it1).colorcond != *(*it2).colorcond ) ) - found = false; - if ( !found ) - continue; - - if ( (*it1).fontcond && !(*it2).fontcond ) - found = false; - if ( !(*it1).fontcond && (*it2).fontcond ) - found = false; - if ( (*it1).fontcond && (*it2).fontcond - && ( *(*it1).fontcond != *(*it2).fontcond ) ) - found = false; - if ( !found ) - continue; - - if ( (*it1).styleName && !(*it2).styleName ) - found = false; - if ( !(*it1).styleName && (*it2).styleName ) - found = false; - if ( (*it1).styleName && (*it2).styleName - && ( *(*it1).styleName != *(*it2).styleName ) ) - found = false; - } - - if ( !found ) /* if it's not here, don't display this condition */ - { - it1 = conditionList.remove( it1 ); - } - else - { - ++it1; - } - } - } - } - - kdDebug() << "Conditions: " << conditionList.size() << endl; - - m_dlg->m_condition_2->setEnabled( false ); - m_dlg->m_condition_3->setEnabled( false ); - - m_dlg->m_style_1->setEnabled( false ); - m_dlg->m_style_2->setEnabled( false ); - m_dlg->m_style_3->setEnabled( false ); - - numCondition = 0; - for ( it1 = conditionList.begin(); numCondition < 3 && it1 != conditionList.end(); ++it1 ) - { - init( *it1, numCondition ); - - ++numCondition; - } -} - -void ConditionalDialog::init( Conditional const & tmp, int numCondition ) -{ - kdDebug() << "Adding " << numCondition << endl; - TQComboBox * cb = 0; - TQComboBox * sb = 0; - KLineEdit * kl1 = 0; - KLineEdit * kl2 = 0; - TQString value; - - switch( numCondition ) - { - case 0: - cb = m_dlg->m_condition_1; - sb = m_dlg->m_style_1; - kl1 = m_dlg->m_firstValue_1; - kl2 = m_dlg->m_secondValue_1; - break; - case 1: - cb = m_dlg->m_condition_2; - sb = m_dlg->m_style_2; - kl1 = m_dlg->m_firstValue_2; - kl2 = m_dlg->m_secondValue_2; - break; - case 2: - cb = m_dlg->m_condition_3; - sb = m_dlg->m_style_3; - kl1 = m_dlg->m_firstValue_3; - kl2 = m_dlg->m_secondValue_3; - break; - default: - return; - } - - if ( tmp.styleName ) - { - sb->setCurrentText( *tmp.styleName ); - sb->setEnabled( true ); - } - - switch( tmp.cond ) - { - case Conditional::None : - break; - - case Conditional::Equal : - cb->setCurrentItem( 1 ); - break; - - case Conditional::Superior : - cb->setCurrentItem( 2 ); - break; - - case Conditional::Inferior : - cb->setCurrentItem( 3 ); - break; - - case Conditional::SuperiorEqual : - cb->setCurrentItem( 4 ); - break; - - case Conditional::InferiorEqual : - cb->setCurrentItem( 5 ); - break; - - case Conditional::Between : - cb->setCurrentItem(6); - - if ( tmp.strVal2 ) - kl2->setText( *tmp.strVal2 ); - else - { - value = value.setNum( tmp.val2 ); - kl2->setText( value ); - } - break; - - case Conditional::Different : - cb->setCurrentItem(7); - if ( tmp.strVal2 ) - kl2->setText( *tmp.strVal2 ); - else - { - value = value.setNum( tmp.val2 ); - kl2->setText( value ); - } - break; - case Conditional::DifferentTo : - cb->setCurrentItem(8); - break; - } - - if ( tmp.cond != Conditional::None ) - { - kl1->setEnabled( true ); - - if ( tmp.strVal1 ) - kl1->setText( *tmp.strVal1 ); - else - { - value = value.setNum( tmp.val1 ); - kl1->setText( value ); - } - } -} - -Conditional::Type ConditionalDialog::typeOfCondition( TQComboBox const * const cb ) const -{ - Conditional::Type result = Conditional::None; - switch( cb->currentItem() ) - { - case 0 : - result = Conditional::None; - break; - case 1 : - result = Conditional::Equal; - break; - case 2 : - result = Conditional::Superior; - break; - case 3 : - result = Conditional::Inferior; - break; - case 4 : - result = Conditional::SuperiorEqual; - break; - case 5 : - result = Conditional::InferiorEqual; - break; - case 6 : - result = Conditional::Between; - break; - case 7 : - result = Conditional::Different; - break; - case 8 : - result = Conditional::DifferentTo; - break; - default: - kdDebug(36001) << "Error in list" << endl; - break; - } - - return result; -} - -bool ConditionalDialog::checkInputData( KLineEdit const * const edit1, - KLineEdit const * const edit2 ) -{ - bool b1 = false; - bool b2 = false; - - if ( !edit2->isEnabled() ) - return true; - - edit1->text().toDouble( &b1 ); - edit2->text().toDouble( &b2 ); - - if ( b1 != b2 ) - { - if ( b1 ) - KMessageBox::sorry( 0, i18n( "If the first value is a number, the second value also has to be a number." ) ); - else - KMessageBox::sorry( 0, i18n( "If the first value is a string, the second value also has to be a string." ) ); - return false; - } - - return true; -} - -bool ConditionalDialog::checkInputData() -{ - if ( m_dlg->m_firstValue_1->isEnabled() && !checkInputData( m_dlg->m_firstValue_1, m_dlg->m_secondValue_1 ) ) - return false; - if ( m_dlg->m_firstValue_2->isEnabled() && !checkInputData( m_dlg->m_firstValue_2, m_dlg->m_secondValue_2 ) ) - return false; - if ( m_dlg->m_firstValue_3->isEnabled() && !checkInputData( m_dlg->m_firstValue_3, m_dlg->m_secondValue_3 ) ) - return false; - - return true; -} - -bool ConditionalDialog::getCondition( Conditional & newCondition, const TQComboBox * cb, - const KLineEdit * edit1, const KLineEdit * edit2, - const TQComboBox * sb, Style * style ) -{ - if ( !cb->isEnabled() ) - return false; - - newCondition.cond = typeOfCondition( cb ); - if ( newCondition.cond == Conditional::None ) - return false; - - bool ok = false; - double d1 = edit1->text().toDouble( &ok ); - double d2 = 0.0; - TQString * s1 = 0; - TQString * s2 = 0; - TQString * sn = 0; - - if ( ok ) - { - if ( edit2->isEnabled() ) - d2 = edit2->text().toDouble( &ok ); - // values are already checked... - } - else - { - d1 = 0.0; - s1 = new TQString( edit1->text() ); - - if ( edit2->isEnabled() ) - s2 = new TQString( edit2->text() ); - } - sn = new TQString( sb->currentText() ); - - newCondition.val1 = d1; - newCondition.val2 = d2; - newCondition.strVal1 = s1; - newCondition.strVal2 = s2; - newCondition.fontcond = 0; - newCondition.colorcond = 0; - newCondition.styleName = sn; - newCondition.style = style; - - return true; -} - -void ConditionalDialog::slotOk() -{ - kdDebug() << "slotOk" << endl; - - if ( !checkInputData() ) - return; - - kdDebug() << "Input data is valid" << endl; - - m_view->doc()->emitBeginOperation( false ); - StyleManager * manager = m_view->doc()->styleManager(); - - TQValueList newList; - - Conditional newCondition; - - if ( getCondition( newCondition, m_dlg->m_condition_1, m_dlg->m_firstValue_1, - m_dlg->m_secondValue_1, m_dlg->m_style_1, manager->style( m_dlg->m_style_1->currentText() ) ) ) - newList.append( newCondition ); - - if ( getCondition( newCondition, m_dlg->m_condition_2, m_dlg->m_firstValue_2, - m_dlg->m_secondValue_2, m_dlg->m_style_2, manager->style( m_dlg->m_style_2->currentText() ) ) ) - newList.append( newCondition ); - - if ( getCondition( newCondition, m_dlg->m_condition_3, m_dlg->m_firstValue_3, - m_dlg->m_secondValue_3, m_dlg->m_style_3, manager->style( m_dlg->m_style_3->currentText() ) ) ) - newList.append( newCondition ); - - kdDebug() << "Setting conditional list" << endl; - m_view->activeSheet()->setConditional( m_view->selectionInfo(), newList ); - m_view->slotUpdateView( m_view->activeSheet(), *m_view->selectionInfo() ); - - accept(); -} - -#include "kspread_dlg_conditional.moc" - - diff --git a/kspread/dialogs/kspread_dlg_conditional.cpp b/kspread/dialogs/kspread_dlg_conditional.cpp new file mode 100644 index 00000000..a75bd5bd --- /dev/null +++ b/kspread/dialogs/kspread_dlg_conditional.cpp @@ -0,0 +1,679 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002-2003 Philipp Mueller + (C) 2002 John Dailey + (C) 1999-2001 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "kspread_dlg_conditional.h" +#include "kspread_condition.h" + +#include "kspread_canvas.h" +#include "kspread_cell.h" +#include "kspread_doc.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_view.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using namespace KSpread; + +ConditionalWidget::ConditionalWidget( TQWidget* parent, const char* name, WFlags fl ) + : TQWidget( parent, name, fl ) +{ + TQGridLayout * Form1Layout = new TQGridLayout( this, 1, 1, 11, 6, "Form1Layout"); + + TQGroupBox * groupBox1_3 = new TQGroupBox( this, "groupBox1_3" ); + groupBox1_3->setColumnLayout(0, Qt::Vertical ); + groupBox1_3->layout()->setSpacing( KDialog::spacingHint() ); + groupBox1_3->layout()->setMargin( KDialog::marginHint() ); + TQGridLayout * groupBox1_3Layout = new TQGridLayout( groupBox1_3->layout() ); + groupBox1_3Layout->setAlignment( TQt::AlignTop ); + + TQLabel * textLabel1_3 = new TQLabel( groupBox1_3, "textLabel1_3" ); + groupBox1_3Layout->addWidget( textLabel1_3, 0, 0 ); + + m_condition_3 = new TQComboBox( false, groupBox1_3, "m_condition_3" ); + groupBox1_3Layout->addWidget( m_condition_3, 0, 1 ); + + m_firstValue_3 = new KLineEdit( groupBox1_3, "m_firstValue_3" ); + m_firstValue_3->setEnabled( false ); + groupBox1_3Layout->addWidget( m_firstValue_3, 0, 2 ); + + m_secondValue_3 = new KLineEdit( groupBox1_3, "m_secondValue_3" ); + m_secondValue_3->setEnabled( false ); + groupBox1_3Layout->addWidget( m_secondValue_3, 0, 3 ); + + m_style_3 = new TQComboBox( false, groupBox1_3, "m_style_3" ); + m_style_3->setEnabled( false ); + groupBox1_3Layout->addWidget( m_style_3, 1, 1 ); + + TQLabel * textLabel2_3 = new TQLabel( groupBox1_3, "textLabel2_3" ); + groupBox1_3Layout->addWidget( textLabel2_3, 1, 0 ); + + TQSpacerItem * spacer = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_3Layout->addItem( spacer, 1, 2 ); + TQSpacerItem * spacer_2 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_3Layout->addItem( spacer_2, 1, 3 ); + + Form1Layout->addWidget( groupBox1_3, 2, 0 ); + + TQGroupBox * groupBox1_2 = new TQGroupBox( this, "groupBox1_2" ); + groupBox1_2->setColumnLayout(0, Qt::Vertical ); + groupBox1_2->layout()->setSpacing( KDialog::spacingHint() ); + groupBox1_2->layout()->setMargin( KDialog::marginHint() ); + + TQGridLayout * groupBox1_2Layout = new TQGridLayout( groupBox1_2->layout() ); + groupBox1_2Layout->setAlignment( TQt::AlignTop ); + + TQLabel * textLabel1_2 = new TQLabel( groupBox1_2, "textLabel1_2" ); + groupBox1_2Layout->addWidget( textLabel1_2, 0, 0 ); + + TQLabel * textLabel2_2 = new TQLabel( groupBox1_2, "textLabel2_2" ); + groupBox1_2Layout->addWidget( textLabel2_2, 1, 0 ); + + m_condition_2 = new TQComboBox( false, groupBox1_2, "m_condition_2" ); + groupBox1_2Layout->addWidget( m_condition_2, 0, 1 ); + + m_style_2 = new TQComboBox( false, groupBox1_2, "m_style_2" ); + m_style_2->setEnabled( false ); + groupBox1_2Layout->addWidget( m_style_2, 1, 1 ); + + m_firstValue_2 = new KLineEdit( groupBox1_2, "m_firstValue_2" ); + m_firstValue_2->setEnabled( false ); + groupBox1_2Layout->addWidget( m_firstValue_2, 0, 2 ); + + m_secondValue_2 = new KLineEdit( groupBox1_2, "m_secondValue_2" ); + m_secondValue_2->setEnabled( false ); + + groupBox1_2Layout->addWidget( m_secondValue_2, 0, 3 ); + + TQSpacerItem * spacer_3 = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_2Layout->addItem( spacer_3, 1, 2 ); + TQSpacerItem * spacer_4 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_2Layout->addItem( spacer_4, 1, 3 ); + Form1Layout->addWidget( groupBox1_2, 1, 0 ); + + TQGroupBox * groupBox1_1 = new TQGroupBox( this, "groupBox1_1" ); + groupBox1_1->setColumnLayout(0, Qt::Vertical ); + groupBox1_1->layout()->setSpacing( KDialog::spacingHint() ); + groupBox1_1->layout()->setMargin( KDialog::marginHint() ); + + TQGridLayout * groupBox1_1Layout = new TQGridLayout( groupBox1_1->layout() ); + groupBox1_1Layout->setAlignment( TQt::AlignTop ); + + TQLabel * textLabel1_1 = new TQLabel( groupBox1_1, "textLabel1_2_2" ); + groupBox1_1Layout->addWidget( textLabel1_1, 0, 0 ); + + TQLabel * textLabel2_1 = new TQLabel( groupBox1_1, "textLabel2_2_2" ); + groupBox1_1Layout->addWidget( textLabel2_1, 1, 0 ); + + m_condition_1 = new TQComboBox( false, groupBox1_1, "m_condition_1" ); + groupBox1_1Layout->addWidget( m_condition_1, 0, 1 ); + + m_style_1 = new TQComboBox( false, groupBox1_1, "m_style_1" ); + m_style_1->setEnabled( false ); + groupBox1_1Layout->addWidget( m_style_1, 1, 1 ); + + m_firstValue_1 = new KLineEdit( groupBox1_1, "m_firstValue_1" ); + m_firstValue_1->setEnabled( false ); + groupBox1_1Layout->addWidget( m_firstValue_1, 0, 2 ); + + m_secondValue_1 = new KLineEdit( groupBox1_1, "m_secondValue_1" ); + m_secondValue_1->setEnabled( false ); + groupBox1_1Layout->addWidget( m_secondValue_1, 0, 3 ); + + TQSpacerItem * spacer_5 = new TQSpacerItem( 41, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_1Layout->addItem( spacer_5, 1, 2 ); + TQSpacerItem * spacer_6 = new TQSpacerItem( 61, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + groupBox1_1Layout->addItem( spacer_6, 1, 3 ); + + Form1Layout->addWidget( groupBox1_1, 0, 0 ); + resize( TQSize(702, 380).expandedTo( minimumSizeHint() ) ); + clearWState( WState_Polished ); + + TQStringList list; + list += i18n( "" ); + list += i18n( "equal to" ); + list += i18n( "greater than" ); + list += i18n( "less than" ); + list += i18n( "equal to or greater than" ); + list += i18n( "equal to or less than" ); + list += i18n( "between" ); + list += i18n( "outside range" ); + list += i18n( "different to" ); + + m_condition_1->clear(); + m_condition_2->clear(); + m_condition_3->clear(); + m_condition_1->insertStringList( list ); + m_condition_2->insertStringList( list ); + m_condition_3->insertStringList( list ); + + groupBox1_1->setTitle( i18n( "First Condition" ) ); + groupBox1_2->setTitle( i18n( "Second Condition" ) ); + groupBox1_3->setTitle( i18n( "Third Condition" ) ); + textLabel1_1->setText( i18n( "Cell is" ) ); + textLabel1_2->setText( i18n( "Cell is" ) ); + textLabel1_3->setText( i18n( "Cell is" ) ); + textLabel2_1->setText( i18n( "Cell style" ) ); + textLabel2_2->setText( i18n( "Cell style" ) ); + textLabel2_3->setText( i18n( "Cell style" ) ); + + connect( m_condition_1, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged1( const TQString & ) ) ); + connect( m_condition_2, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged2( const TQString & ) ) ); + connect( m_condition_3, TQT_SIGNAL( highlighted( const TQString & ) ), this, TQT_SLOT( slotTextChanged3( const TQString & ) ) ); +} + +ConditionalWidget::~ConditionalWidget() +{ +} + +void ConditionalWidget::slotTextChanged1( const TQString & text ) +{ + if ( text == i18n( "" ) ) + { + m_firstValue_1->setEnabled( false ); + m_secondValue_1->setEnabled( false ); + m_style_1->setEnabled( false ); + } + else + { + m_condition_2->setEnabled( true ); + m_style_1->setEnabled( true ); + if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) + { + m_firstValue_1->setEnabled( true ); + m_secondValue_1->setEnabled( true ); + } + else + { + m_firstValue_1->setEnabled( true ); + m_secondValue_1->setEnabled( false ); + } + } +} + +void ConditionalWidget::slotTextChanged2( const TQString & text ) +{ + if ( text == i18n( "" ) ) + { + m_firstValue_2->setEnabled( false ); + m_secondValue_2->setEnabled( false ); + m_style_2->setEnabled( false ); + } + else + { + m_condition_3->setEnabled( true ); + m_style_2->setEnabled( true ); + if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) + { + m_firstValue_2->setEnabled( true ); + m_secondValue_2->setEnabled( true ); + } + else + { + m_firstValue_2->setEnabled( true ); + m_secondValue_2->setEnabled( false ); + } + } +} + +void ConditionalWidget::slotTextChanged3( const TQString & text ) +{ + if ( text == i18n( "" ) ) + { + m_firstValue_3->setEnabled( false ); + m_secondValue_3->setEnabled( false ); + m_style_3->setEnabled( false ); + } + else + { + m_style_3->setEnabled( true ); + if ( ( text == i18n( "between" ) ) || ( text == i18n( "different from" ) ) ) + { + m_firstValue_3->setEnabled( true ); + m_secondValue_3->setEnabled( true ); + } + else + { + m_firstValue_3->setEnabled( true ); + m_secondValue_3->setEnabled( false ); + } + } +} + +/** + * ConditionalDialog + * Sets conditional cell formattings. + */ +ConditionalDialog::ConditionalDialog( View * parent, const char * name, + const TQRect & marker ) + : KDialogBase( parent, name, true, "", KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok, false ), + m_view( parent ), + m_dlg( new ConditionalWidget( this ) ), + m_marker( marker ) +{ + TQStringList list( m_view->doc()->styleManager()->styleNames() ); + + m_dlg->m_style_1->insertStringList( list ); + m_dlg->m_style_2->insertStringList( list ); + m_dlg->m_style_3->insertStringList( list ); + + setCaption( i18n( "Conditional Cell Attributes" ) ); + setButtonBoxOrientation(Qt::Vertical ); + setMainWidget( m_dlg ); + + init(); +} + +void ConditionalDialog::init() +{ + TQValueList conditionList; + TQValueList otherList; + bool found; + int numCondition; + + TQValueList::iterator it1; + TQValueList::iterator it2; + + Cell * obj = m_view->activeSheet()->cellAt( m_marker.left(), + m_marker.top() ); + + conditionList = obj->conditionList(); + /* this is the list, but only display the conditions common to all selected + cells*/ + + for ( int x = m_marker.left(); x <= m_marker.right(); x++ ) + { + for ( int y = m_marker.top(); y <= m_marker.bottom(); y++ ) + { + Cell * obj2 = m_view->activeSheet()->cellAt( x, y ); + otherList = obj2->conditionList(); + + it1 = conditionList.begin(); + while ( it1 != conditionList.end() ) + { + kdDebug() << "Here" << endl; + found = false; + for ( it2 = otherList.begin(); !found && it2 != otherList.end(); ++it2 ) + { + kdDebug() << "Found: " << found << endl; + found = ( (*it1).val1 == (*it2).val1 && + (*it1).val2 == (*it2).val2 && + (*it1).cond == (*it2).cond ); + + if ( (*it1).strVal1 && !(*it2).strVal1 ) + found = false; + if ( !(*it1).strVal1 && (*it2).strVal1 ) + found = false; + if ( (*it1).strVal1 && (*it2).strVal1 + && ( *(*it1).strVal1 != *(*it2).strVal1 ) ) + found = false; + if ( !found ) + continue; + + if ( (*it1).strVal2 && !(*it2).strVal2 ) + found = false; + if ( !(*it1).strVal2 && (*it2).strVal2 ) + found = false; + if ( (*it1).strVal2 && (*it2).strVal2 + && ( *(*it1).strVal2 != *(*it2).strVal2 ) ) + found = false; + if ( !found ) + continue; + + if ( (*it1).colorcond && !(*it2).colorcond ) + found = false; + if ( !(*it1).colorcond && (*it2).colorcond ) + found = false; + if ( (*it1).colorcond && (*it2).colorcond + && ( *(*it1).colorcond != *(*it2).colorcond ) ) + found = false; + if ( !found ) + continue; + + if ( (*it1).fontcond && !(*it2).fontcond ) + found = false; + if ( !(*it1).fontcond && (*it2).fontcond ) + found = false; + if ( (*it1).fontcond && (*it2).fontcond + && ( *(*it1).fontcond != *(*it2).fontcond ) ) + found = false; + if ( !found ) + continue; + + if ( (*it1).styleName && !(*it2).styleName ) + found = false; + if ( !(*it1).styleName && (*it2).styleName ) + found = false; + if ( (*it1).styleName && (*it2).styleName + && ( *(*it1).styleName != *(*it2).styleName ) ) + found = false; + } + + if ( !found ) /* if it's not here, don't display this condition */ + { + it1 = conditionList.remove( it1 ); + } + else + { + ++it1; + } + } + } + } + + kdDebug() << "Conditions: " << conditionList.size() << endl; + + m_dlg->m_condition_2->setEnabled( false ); + m_dlg->m_condition_3->setEnabled( false ); + + m_dlg->m_style_1->setEnabled( false ); + m_dlg->m_style_2->setEnabled( false ); + m_dlg->m_style_3->setEnabled( false ); + + numCondition = 0; + for ( it1 = conditionList.begin(); numCondition < 3 && it1 != conditionList.end(); ++it1 ) + { + init( *it1, numCondition ); + + ++numCondition; + } +} + +void ConditionalDialog::init( Conditional const & tmp, int numCondition ) +{ + kdDebug() << "Adding " << numCondition << endl; + TQComboBox * cb = 0; + TQComboBox * sb = 0; + KLineEdit * kl1 = 0; + KLineEdit * kl2 = 0; + TQString value; + + switch( numCondition ) + { + case 0: + cb = m_dlg->m_condition_1; + sb = m_dlg->m_style_1; + kl1 = m_dlg->m_firstValue_1; + kl2 = m_dlg->m_secondValue_1; + break; + case 1: + cb = m_dlg->m_condition_2; + sb = m_dlg->m_style_2; + kl1 = m_dlg->m_firstValue_2; + kl2 = m_dlg->m_secondValue_2; + break; + case 2: + cb = m_dlg->m_condition_3; + sb = m_dlg->m_style_3; + kl1 = m_dlg->m_firstValue_3; + kl2 = m_dlg->m_secondValue_3; + break; + default: + return; + } + + if ( tmp.styleName ) + { + sb->setCurrentText( *tmp.styleName ); + sb->setEnabled( true ); + } + + switch( tmp.cond ) + { + case Conditional::None : + break; + + case Conditional::Equal : + cb->setCurrentItem( 1 ); + break; + + case Conditional::Superior : + cb->setCurrentItem( 2 ); + break; + + case Conditional::Inferior : + cb->setCurrentItem( 3 ); + break; + + case Conditional::SuperiorEqual : + cb->setCurrentItem( 4 ); + break; + + case Conditional::InferiorEqual : + cb->setCurrentItem( 5 ); + break; + + case Conditional::Between : + cb->setCurrentItem(6); + + if ( tmp.strVal2 ) + kl2->setText( *tmp.strVal2 ); + else + { + value = value.setNum( tmp.val2 ); + kl2->setText( value ); + } + break; + + case Conditional::Different : + cb->setCurrentItem(7); + if ( tmp.strVal2 ) + kl2->setText( *tmp.strVal2 ); + else + { + value = value.setNum( tmp.val2 ); + kl2->setText( value ); + } + break; + case Conditional::DifferentTo : + cb->setCurrentItem(8); + break; + } + + if ( tmp.cond != Conditional::None ) + { + kl1->setEnabled( true ); + + if ( tmp.strVal1 ) + kl1->setText( *tmp.strVal1 ); + else + { + value = value.setNum( tmp.val1 ); + kl1->setText( value ); + } + } +} + +Conditional::Type ConditionalDialog::typeOfCondition( TQComboBox const * const cb ) const +{ + Conditional::Type result = Conditional::None; + switch( cb->currentItem() ) + { + case 0 : + result = Conditional::None; + break; + case 1 : + result = Conditional::Equal; + break; + case 2 : + result = Conditional::Superior; + break; + case 3 : + result = Conditional::Inferior; + break; + case 4 : + result = Conditional::SuperiorEqual; + break; + case 5 : + result = Conditional::InferiorEqual; + break; + case 6 : + result = Conditional::Between; + break; + case 7 : + result = Conditional::Different; + break; + case 8 : + result = Conditional::DifferentTo; + break; + default: + kdDebug(36001) << "Error in list" << endl; + break; + } + + return result; +} + +bool ConditionalDialog::checkInputData( KLineEdit const * const edit1, + KLineEdit const * const edit2 ) +{ + bool b1 = false; + bool b2 = false; + + if ( !edit2->isEnabled() ) + return true; + + edit1->text().toDouble( &b1 ); + edit2->text().toDouble( &b2 ); + + if ( b1 != b2 ) + { + if ( b1 ) + KMessageBox::sorry( 0, i18n( "If the first value is a number, the second value also has to be a number." ) ); + else + KMessageBox::sorry( 0, i18n( "If the first value is a string, the second value also has to be a string." ) ); + return false; + } + + return true; +} + +bool ConditionalDialog::checkInputData() +{ + if ( m_dlg->m_firstValue_1->isEnabled() && !checkInputData( m_dlg->m_firstValue_1, m_dlg->m_secondValue_1 ) ) + return false; + if ( m_dlg->m_firstValue_2->isEnabled() && !checkInputData( m_dlg->m_firstValue_2, m_dlg->m_secondValue_2 ) ) + return false; + if ( m_dlg->m_firstValue_3->isEnabled() && !checkInputData( m_dlg->m_firstValue_3, m_dlg->m_secondValue_3 ) ) + return false; + + return true; +} + +bool ConditionalDialog::getCondition( Conditional & newCondition, const TQComboBox * cb, + const KLineEdit * edit1, const KLineEdit * edit2, + const TQComboBox * sb, Style * style ) +{ + if ( !cb->isEnabled() ) + return false; + + newCondition.cond = typeOfCondition( cb ); + if ( newCondition.cond == Conditional::None ) + return false; + + bool ok = false; + double d1 = edit1->text().toDouble( &ok ); + double d2 = 0.0; + TQString * s1 = 0; + TQString * s2 = 0; + TQString * sn = 0; + + if ( ok ) + { + if ( edit2->isEnabled() ) + d2 = edit2->text().toDouble( &ok ); + // values are already checked... + } + else + { + d1 = 0.0; + s1 = new TQString( edit1->text() ); + + if ( edit2->isEnabled() ) + s2 = new TQString( edit2->text() ); + } + sn = new TQString( sb->currentText() ); + + newCondition.val1 = d1; + newCondition.val2 = d2; + newCondition.strVal1 = s1; + newCondition.strVal2 = s2; + newCondition.fontcond = 0; + newCondition.colorcond = 0; + newCondition.styleName = sn; + newCondition.style = style; + + return true; +} + +void ConditionalDialog::slotOk() +{ + kdDebug() << "slotOk" << endl; + + if ( !checkInputData() ) + return; + + kdDebug() << "Input data is valid" << endl; + + m_view->doc()->emitBeginOperation( false ); + StyleManager * manager = m_view->doc()->styleManager(); + + TQValueList newList; + + Conditional newCondition; + + if ( getCondition( newCondition, m_dlg->m_condition_1, m_dlg->m_firstValue_1, + m_dlg->m_secondValue_1, m_dlg->m_style_1, manager->style( m_dlg->m_style_1->currentText() ) ) ) + newList.append( newCondition ); + + if ( getCondition( newCondition, m_dlg->m_condition_2, m_dlg->m_firstValue_2, + m_dlg->m_secondValue_2, m_dlg->m_style_2, manager->style( m_dlg->m_style_2->currentText() ) ) ) + newList.append( newCondition ); + + if ( getCondition( newCondition, m_dlg->m_condition_3, m_dlg->m_firstValue_3, + m_dlg->m_secondValue_3, m_dlg->m_style_3, manager->style( m_dlg->m_style_3->currentText() ) ) ) + newList.append( newCondition ); + + kdDebug() << "Setting conditional list" << endl; + m_view->activeSheet()->setConditional( m_view->selectionInfo(), newList ); + m_view->slotUpdateView( m_view->activeSheet(), *m_view->selectionInfo() ); + + accept(); +} + +#include "kspread_dlg_conditional.moc" + + diff --git a/kspread/dialogs/kspread_dlg_cons.cc b/kspread/dialogs/kspread_dlg_cons.cc deleted file mode 100644 index 139113c7..00000000 --- a/kspread/dialogs/kspread_dlg_cons.cc +++ /dev/null @@ -1,687 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 2000-2001 Werner Trobin - (C) 2000-2001 Laurent Montel - (C) 1999-2002 David Faure - (C) 1999 Stephan Kulow - (C) 1999 Reginald Stadlbauer - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "kspread_dlg_cons.h" - -#include -#include -#include -#include -#include "selection.h" -#include -#include -#include - -#include -#include - -using namespace KSpread; - -ConsolidateDialog::ConsolidateDialog( View* parent, const char* name ) - : KDialogBase( parent, name, false, i18n("Consolidate"), Ok|Cancel ) -{ - m_pView = parent; - - TQWidget* page = new TQWidget( this ); - setMainWidget( page ); - - TQGridLayout *grid1 = new TQGridLayout( page, 12, 2, marginHint(), spacingHint() ); - - TQLabel* tmpTQLabel; - tmpTQLabel = new TQLabel( page, "Label_1" ); - grid1->addWidget(tmpTQLabel,0,0); - tmpTQLabel->setText( i18n("&Function:") ); - - m_pFunction = new TQComboBox( page ); - grid1->addWidget(m_pFunction,1,0); - tmpTQLabel->setBuddy(m_pFunction); - - m_pFunction->insertItem( i18n("Sum"), Sum ); - m_pFunction->insertItem( i18n("Average"), Average ); - m_pFunction->insertItem( i18n("Count"), Count ); - m_pFunction->insertItem( i18n("Max"), Max ); - m_pFunction->insertItem( i18n("Min"), Min ); - m_pFunction->insertItem( i18n("Product"), Product ); - m_pFunction->insertItem( i18n("Standard Deviation"), StdDev ); - m_pFunction->insertItem( i18n("Variance"), Var ); - - tmpTQLabel = new TQLabel( page, "Label_1" ); - tmpTQLabel->setText( i18n("Re&ference:") ); - grid1->addWidget(tmpTQLabel,2,0); - - m_pRef = new TQLineEdit( page ); - grid1->addWidget(m_pRef,3,0); - tmpTQLabel->setBuddy(m_pRef); - - tmpTQLabel = new TQLabel( page, "Label_1" ); - grid1->addWidget(tmpTQLabel,4,0); - tmpTQLabel->setText( i18n("&Entered references:") ); - - m_pRefs = new TQListBox( page ); - grid1->addMultiCellWidget( m_pRefs,5,8,0,0); - tmpTQLabel->setBuddy(m_pRefs); - - m_pRow = new TQCheckBox( i18n("&Description in row"), page ); - grid1->addWidget( m_pRow,9,0); - m_pCol = new TQCheckBox( i18n("De&scription in column"), page ); - grid1->addWidget(m_pCol,10,0); - m_pCopy = new TQCheckBox( i18n("Co&py data"), page ); - grid1->addWidget(m_pCopy,11,0); - - m_pAdd = new TQPushButton( i18n("&Add"), page ); - grid1->addWidget(m_pAdd,2,1); - m_pRemove = new TQPushButton( i18n("&Remove"), page ); - grid1->addWidget(m_pRemove,3,1); - - - connect( m_pAdd, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdd() ) ); - connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); - connect( m_pRef, TQT_SIGNAL( returnPressed() ), this, TQT_SLOT( slotReturnPressed() ) ); - - connect(m_pView->selectionInfo(), TQT_SIGNAL(changed(const Region&)), - this, TQT_SLOT(slotSelectionChanged())); -} - -ConsolidateDialog::~ConsolidateDialog() -{ - kdDebug(36001)<<"Consolidate::~Consolidate()\n"; -} - -enum Description { D_ROW, D_COL, D_NONE, D_BOTH }; - -struct st_cell -{ - TQString xdesc; - TQString ydesc; - Cell* cell; - TQString sheet; - int x; - int y; -}; - -void ConsolidateDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - Map *map = m_pView->doc()->map(); - - Sheet* sheet = m_pView->activeSheet(); - int dx = m_pView->selectionInfo()->selection().left(); - int dy = m_pView->selectionInfo()->selection().top(); - - TQString function; - - switch( m_pFunction->currentItem() ) - { - case Sum: function = "SUM"; break; - case Average: function = "AVERAGE"; break; - case Count: function = "COUNT"; break; - case Max: function = "MAX"; break; - case Min: function = "MIN"; break; - case Product: function = "PRODUCT"; break; - case StdDev: function = "STDDEV"; break; - case Var: function = "VARIANCE"; break; - default: break; // bad bad ! - } - - TQStringList r = refs(); - TQValueList ranges; - TQStringList::Iterator s = r.begin(); - for( ; s != r.end(); ++s ) - { - Range r( *s, map ); - // TODO: Check for valid - Q_ASSERT( r.isValid() ); - - if ( r.sheet() == 0 ) - { - r.setSheet(sheet); - r.setSheetName(sheet->sheetName()); - } - ranges.append( r ); - } - - Description desc; - if ( m_pRow->isChecked() && m_pCol->isChecked() ) - desc = D_BOTH; - else if ( m_pRow->isChecked() ) - desc = D_ROW; - else if ( m_pCol->isChecked() ) - desc = D_COL; - else - desc = D_NONE; - - // Check whether all ranges have same size - Q_ASSERT( ranges.count() > 0 ); - TQValueList::Iterator it = ranges.begin(); - int w = (*it).range().right() - (*it).range().left() + 1; - int h = (*it).range().bottom() - (*it).range().top() + 1; - if ( w <= ( ( desc == D_BOTH || desc == D_COL ) ? 1 : 0 ) || - h <= ( ( desc == D_BOTH || desc == D_ROW ) ? 1 : 0 ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - KMessageBox::error( this, i18n( "The range\n%1\nis too small" ).arg( *( r.begin() ) )); - return; - } - - if( (*it).range().bottom()==KS_rowMax || (*it).range().right()== KS_colMax ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - KMessageBox::error( this, i18n( "The range\n%1\nis too large" ).arg( *( r.begin() ) )); - return; - } - - ++it; - int i = 1; - for( ; it != ranges.end(); ++it, i++ ) - { - TQRect currentRange=(*it).range(); - - int w2 = currentRange.right() - currentRange.left() + 1; - int h2 = currentRange.bottom() - currentRange.top() + 1; - - if(currentRange.bottom()==KS_rowMax || currentRange.right()== KS_colMax) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - KMessageBox::error( this, i18n( "The range\n%1\nis too large" ).arg( r[i])); - return; - } - if ( ( desc == D_NONE && ( w != w2 || h != h2 ) ) || - ( desc == D_ROW && h != h2 ) || - ( desc == D_COL && w != w2 ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - TQString tmp = i18n( "The ranges\n%1\nand\n%2\nhave different size").arg( *( r.begin() ) ).arg( r[i] ); - KMessageBox::error( this, tmp); - return; - } - } - - // Create the consolidation sheet - if ( desc == D_NONE ) - { - // Check whether the destination is part of the source ... - TQRect dest; - dest.setCoords( dx, dy, dx + w - 1, dy + h - 1 ); - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - Q_ASSERT( t ); - TQRect r; - - TQRect currentRange=(*it).range(); - - r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); - if ( t == sheet && r.intersects( dest ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - TQString tmp( i18n("The source tables intersect with the destination table") ); - KMessageBox::error( this, tmp); - return; - } - } - - for( int x = 0; x < w; x++ ) - { - for( int y = 0; y < h; y++ ) - { - bool novalue=true; - TQString formula = "=" + function + "("; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - Cell *c = t->cellAt( x + (*it).range().left(), y + (*it).range().top() ); - if(!c->isDefault()) - novalue=false; - if ( it != ranges.begin() ) - formula += ";"; - formula += (*it).sheetName() + "!"; - formula += c->name(); - } - formula += ")"; - - if(!novalue) - sheet->setText( dy + y, dx + x, - m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); - } - } - } - else if ( desc == D_ROW ) - { - // Get list of all descriptions in the rows - TQStringList lst; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); -// kdDebug(36001) << "FROM " << (*it).range.left() << " to " << (*it).range.right() << endl; - for( int x = (*it).range().left(); x <= (*it).range().right() ; ++x ) - { - Cell *c = t->cellAt( x, (*it).range().top() ); - if ( c ) - { - TQString s = c->value().asString(); - if ( !lst.contains( s ) ) - lst.append( s ); - } - } - } - lst.sort(); - - // Check whether the destination is part of the source ... - TQRect dest; - dest.setCoords( dx, dy, dx + lst.count() - 1, dy + h - 1 ); - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - TQRect r; - TQRect currentRange=(*it).range(); - r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); - if ( t == sheet && r.intersects( dest ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - TQString tmp( i18n("The source tables intersect with the destination table") ); - KMessageBox::error( this, tmp); - return; - } - } - - // Now create the consolidation sheet - int x = 0; - TQStringList::Iterator s = lst.begin(); - for( ; s != lst.end(); ++s, ++x ) - { - sheet->setText( dy, dx + x, *s ); - - for( int y = 1; y < h; ++y ) - { - int count = 0; - TQString formula = "=" + function + "("; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - for( int i = (*it).range().left(); i <= (*it).range().right(); ++i ) - { - Sheet *t = (*it).sheet(); - assert( t ); - Cell *c = t->cellAt( i, (*it).range().top() ); - if ( c ) - { - if ( c->value().asString() == *s ) - { -// Cell *c2 = t->cellAt( i, y + (*it).range.top() ); - count++; - if ( it != ranges.begin() ) - formula += ";"; - formula += (*it).sheetName() + "!"; - formula += Cell::name( i, y + (*it).range().top() ); - } - } - } - } - formula += ")"; - - sheet->setText( dy + y, dx + x, - m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); - } - } - } - else if ( desc == D_COL ) - { - // Get list of all descriptions in the columns - TQStringList lst; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - for( int y = (*it).range().top(); y <= (*it).range().bottom() ; ++y ) - { - Cell *c = t->cellAt( (*it).range().left(), y ); - if ( c ) - { - TQString s = c->value().asString(); - if ( !s.isEmpty() && lst.find( s ) == lst.end() ) - lst.append( s ); - } - } - } - lst.sort(); - - // Check whether the destination is part of the source ... - TQRect dest; - dest.setCoords( dx, dy, dx + w - 1, dy + lst.count() - 1 ); - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - TQRect r; - TQRect currentRange=(*it).range(); - r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); - if ( t == sheet && r.intersects( dest ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - TQString tmp( i18n("The source tables intersect with the destination table") ); - KMessageBox::error( this, tmp); - return; - } - } - - // Now create the consolidation sheet - int y = 0; - TQStringList::Iterator s = lst.begin(); - for( ; s != lst.end(); ++s, ++y ) - { - sheet->setText( dy + y, dx, *s ); - - for( int x = 1; x < w; ++x ) - { - int count = 0; - TQString formula = "=" + function + "("; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - for( int i = (*it).range().top(); i <= (*it).range().bottom(); i++ ) - { - Sheet *t = (*it).sheet(); - assert( t ); - Cell *c = t->cellAt( (*it).range().left(), i ); - if ( c ) - { - TQString v = c->value().asString(); - if ( !v.isEmpty() && *s == v ) - { -// Cell *c2 = t->cellAt( x + (*it).range.left(), i ); - count++; - if ( it != ranges.begin() ) formula += ";"; - formula += (*it).sheetName() + "!"; - formula += Cell::name( i, y + (*it).range().top() ); - } - } - } - } - - formula += ")"; - - sheet->setText( dy + y, dx + x, - m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); - } - } - } - else if ( desc == D_BOTH ) - { - // Get list of all descriptions in the columns - TQStringList cols; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - for( int y = (*it).range().top() + 1; y <= (*it).range().bottom() ; ++y ) - { - Cell *c = t->cellAt( (*it).range().left(), y ); - if ( c ) - { - TQString s = c->value().asString(); - if ( !s.isEmpty() && cols.find( s ) == cols.end() ) - cols.append( s ); - } - } - } - cols.sort(); - - // Get list of all descriptions in the rows - TQStringList rows; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - for( int x = (*it).range().left() + 1; x <= (*it).range().right() ; ++x ) - { - Cell *c = t->cellAt( x, (*it).range().top() ); - if ( c ) - { - TQString s = c->value().asString(); - if ( !s.isEmpty() && rows.find( s ) == rows.end() ) - rows.append( s ); - } - } - } - rows.sort(); - - // Check whether the destination is part of the source ... - TQRect dest; - dest.setCoords( dx, dy, dx + cols.count(), dy + rows.count() ); - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - TQRect r; - TQRect currentRange=(*it).range(); - r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); - if ( t == sheet && r.intersects( dest ) ) - { - m_pView->slotUpdateView( m_pView->activeSheet() ); - TQString tmp( i18n("The source tables intersect with the destination table") ); - KMessageBox::error( this, tmp); - return; - } - } - - // Fill the list with all interesting cells - TQValueList lst; - it = ranges.begin(); - for( ; it != ranges.end(); ++it ) - { - Sheet *t = (*it).sheet(); - assert( t ); - for( int x = (*it).range().left() + 1; x <= (*it).range().right() ; ++x ) - { - Cell *c = t->cellAt( x, (*it).range().top() ); - if ( c ) - { - TQString ydesc = c->value().asString(); - for( int y = (*it).range().top() + 1; y <= (*it).range().bottom() ; ++y ) - { - Cell *c2 = t->cellAt( (*it).range().left(), y ); - if ( c2 ) - { - TQString xdesc = c2->value().asString(); - Cell *c3 = t->cellAt( x, y ); - if ( c3 && c3->value().isNumber() ) - { - st_cell k; - k.xdesc = xdesc; - k.ydesc = ydesc; - k.cell = c3; - k.sheet = (*it).sheetName(); - k.x = x; - k.y = y; - lst.append( k ); - } - } - } - } - } - } - - // Draw the row description - int i = 1; - TQStringList::Iterator s = rows.begin(); - for( ; s != rows.end(); ++s, ++i ) - sheet->setText( dy, dx + i, *s ); - - // Draw the column description - i = 1; - s = cols.begin(); - for( ; s != cols.end(); ++s, ++i ) - sheet->setText( dy + i, dx, *s ); - - // Draw the data - int x = 1; - TQStringList::Iterator ydesc = rows.begin(); - for( ; ydesc != rows.end(); ++ydesc, x++ ) - { - int y = 1; - TQStringList::Iterator xdesc = cols.begin(); - for( ; xdesc != cols.end(); ++xdesc, y++ ) - { - int count = 0; - TQString formula = "=" + function + "("; - TQValueList::Iterator lit = lst.begin(); - for( ; lit != lst.end(); ++lit ) - { - if ( (*lit).xdesc == *xdesc && (*lit).ydesc == *ydesc ) - { - count++; - if ( it != ranges.begin() ) formula += ";"; - formula += (*it).sheetName() + "!"; - formula += Cell::name( i, y + (*it).range().top() ); - } - } - formula += ")"; - - sheet->setText( dy + y, dx + x, - m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); - } - } - } - m_pView->updateEditWidget(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); - delete this; -} - -void ConsolidateDialog::slotCancel() -{ - reject(); - delete this; -} - -void ConsolidateDialog::slotAdd() -{ - slotReturnPressed(); -} - -void ConsolidateDialog::slotRemove() -{ - int i = m_pRefs->currentItem(); - if ( i < 0 ) - return; - - m_pRefs->removeItem( i ); - - if ( m_pRefs->count() == 0 ) - actionButton( Ok )->setEnabled( false ); -} - -TQStringList ConsolidateDialog::refs() -{ - TQStringList list; - int c = m_pRefs->count(); - - for( int i = 0; i < c; i++ ) - list.append( m_pRefs->text( i ) ); - - return list; -} - -void ConsolidateDialog::slotSelectionChanged() -{ - if (!m_pView->selectionInfo()->isValid()) - { - m_pRef->setText( "" ); - return; - } - - TQString area = m_pView->selectionInfo()->name(); - m_pRef->setText( area ); - m_pRef->setSelection( 0, area.length() ); -} - -void ConsolidateDialog::slotReturnPressed() -{ - TQString txt = m_pRef->text(); - - Range r( txt, m_pView->doc()->map() ); - if ( !r.isValid() ) - { - KMessageBox::error( this, i18n("The range\n%1\n is malformed").arg( txt )); - return; - } - - if ( !txt.isEmpty() ) - { - m_pRefs->insertItem( txt ); - actionButton( Ok )->setEnabled( true ); - } -} - -void ConsolidateDialog::closeEvent ( TQCloseEvent * ) -{ - delete this; -} - -TQString ConsolidateDialog::evaluate( const TQString& formula, Sheet* sheet ) -{ - TQString result = "###"; - Formula *f = new Formula (sheet); - f->setExpression (formula); - if (!f->isValid()) { - delete f; - return result; - } - - Value res = f->eval (); - delete f; - result = sheet->doc()->converter()->asString (res).asString (); - return result; -} - -#include "kspread_dlg_cons.moc" diff --git a/kspread/dialogs/kspread_dlg_cons.cpp b/kspread/dialogs/kspread_dlg_cons.cpp new file mode 100644 index 00000000..139113c7 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_cons.cpp @@ -0,0 +1,687 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 2000-2001 Werner Trobin + (C) 2000-2001 Laurent Montel + (C) 1999-2002 David Faure + (C) 1999 Stephan Kulow + (C) 1999 Reginald Stadlbauer + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "kspread_dlg_cons.h" + +#include +#include +#include +#include +#include "selection.h" +#include +#include +#include + +#include +#include + +using namespace KSpread; + +ConsolidateDialog::ConsolidateDialog( View* parent, const char* name ) + : KDialogBase( parent, name, false, i18n("Consolidate"), Ok|Cancel ) +{ + m_pView = parent; + + TQWidget* page = new TQWidget( this ); + setMainWidget( page ); + + TQGridLayout *grid1 = new TQGridLayout( page, 12, 2, marginHint(), spacingHint() ); + + TQLabel* tmpTQLabel; + tmpTQLabel = new TQLabel( page, "Label_1" ); + grid1->addWidget(tmpTQLabel,0,0); + tmpTQLabel->setText( i18n("&Function:") ); + + m_pFunction = new TQComboBox( page ); + grid1->addWidget(m_pFunction,1,0); + tmpTQLabel->setBuddy(m_pFunction); + + m_pFunction->insertItem( i18n("Sum"), Sum ); + m_pFunction->insertItem( i18n("Average"), Average ); + m_pFunction->insertItem( i18n("Count"), Count ); + m_pFunction->insertItem( i18n("Max"), Max ); + m_pFunction->insertItem( i18n("Min"), Min ); + m_pFunction->insertItem( i18n("Product"), Product ); + m_pFunction->insertItem( i18n("Standard Deviation"), StdDev ); + m_pFunction->insertItem( i18n("Variance"), Var ); + + tmpTQLabel = new TQLabel( page, "Label_1" ); + tmpTQLabel->setText( i18n("Re&ference:") ); + grid1->addWidget(tmpTQLabel,2,0); + + m_pRef = new TQLineEdit( page ); + grid1->addWidget(m_pRef,3,0); + tmpTQLabel->setBuddy(m_pRef); + + tmpTQLabel = new TQLabel( page, "Label_1" ); + grid1->addWidget(tmpTQLabel,4,0); + tmpTQLabel->setText( i18n("&Entered references:") ); + + m_pRefs = new TQListBox( page ); + grid1->addMultiCellWidget( m_pRefs,5,8,0,0); + tmpTQLabel->setBuddy(m_pRefs); + + m_pRow = new TQCheckBox( i18n("&Description in row"), page ); + grid1->addWidget( m_pRow,9,0); + m_pCol = new TQCheckBox( i18n("De&scription in column"), page ); + grid1->addWidget(m_pCol,10,0); + m_pCopy = new TQCheckBox( i18n("Co&py data"), page ); + grid1->addWidget(m_pCopy,11,0); + + m_pAdd = new TQPushButton( i18n("&Add"), page ); + grid1->addWidget(m_pAdd,2,1); + m_pRemove = new TQPushButton( i18n("&Remove"), page ); + grid1->addWidget(m_pRemove,3,1); + + + connect( m_pAdd, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdd() ) ); + connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); + connect( m_pRef, TQT_SIGNAL( returnPressed() ), this, TQT_SLOT( slotReturnPressed() ) ); + + connect(m_pView->selectionInfo(), TQT_SIGNAL(changed(const Region&)), + this, TQT_SLOT(slotSelectionChanged())); +} + +ConsolidateDialog::~ConsolidateDialog() +{ + kdDebug(36001)<<"Consolidate::~Consolidate()\n"; +} + +enum Description { D_ROW, D_COL, D_NONE, D_BOTH }; + +struct st_cell +{ + TQString xdesc; + TQString ydesc; + Cell* cell; + TQString sheet; + int x; + int y; +}; + +void ConsolidateDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + Map *map = m_pView->doc()->map(); + + Sheet* sheet = m_pView->activeSheet(); + int dx = m_pView->selectionInfo()->selection().left(); + int dy = m_pView->selectionInfo()->selection().top(); + + TQString function; + + switch( m_pFunction->currentItem() ) + { + case Sum: function = "SUM"; break; + case Average: function = "AVERAGE"; break; + case Count: function = "COUNT"; break; + case Max: function = "MAX"; break; + case Min: function = "MIN"; break; + case Product: function = "PRODUCT"; break; + case StdDev: function = "STDDEV"; break; + case Var: function = "VARIANCE"; break; + default: break; // bad bad ! + } + + TQStringList r = refs(); + TQValueList ranges; + TQStringList::Iterator s = r.begin(); + for( ; s != r.end(); ++s ) + { + Range r( *s, map ); + // TODO: Check for valid + Q_ASSERT( r.isValid() ); + + if ( r.sheet() == 0 ) + { + r.setSheet(sheet); + r.setSheetName(sheet->sheetName()); + } + ranges.append( r ); + } + + Description desc; + if ( m_pRow->isChecked() && m_pCol->isChecked() ) + desc = D_BOTH; + else if ( m_pRow->isChecked() ) + desc = D_ROW; + else if ( m_pCol->isChecked() ) + desc = D_COL; + else + desc = D_NONE; + + // Check whether all ranges have same size + Q_ASSERT( ranges.count() > 0 ); + TQValueList::Iterator it = ranges.begin(); + int w = (*it).range().right() - (*it).range().left() + 1; + int h = (*it).range().bottom() - (*it).range().top() + 1; + if ( w <= ( ( desc == D_BOTH || desc == D_COL ) ? 1 : 0 ) || + h <= ( ( desc == D_BOTH || desc == D_ROW ) ? 1 : 0 ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + KMessageBox::error( this, i18n( "The range\n%1\nis too small" ).arg( *( r.begin() ) )); + return; + } + + if( (*it).range().bottom()==KS_rowMax || (*it).range().right()== KS_colMax ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + KMessageBox::error( this, i18n( "The range\n%1\nis too large" ).arg( *( r.begin() ) )); + return; + } + + ++it; + int i = 1; + for( ; it != ranges.end(); ++it, i++ ) + { + TQRect currentRange=(*it).range(); + + int w2 = currentRange.right() - currentRange.left() + 1; + int h2 = currentRange.bottom() - currentRange.top() + 1; + + if(currentRange.bottom()==KS_rowMax || currentRange.right()== KS_colMax) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + KMessageBox::error( this, i18n( "The range\n%1\nis too large" ).arg( r[i])); + return; + } + if ( ( desc == D_NONE && ( w != w2 || h != h2 ) ) || + ( desc == D_ROW && h != h2 ) || + ( desc == D_COL && w != w2 ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + TQString tmp = i18n( "The ranges\n%1\nand\n%2\nhave different size").arg( *( r.begin() ) ).arg( r[i] ); + KMessageBox::error( this, tmp); + return; + } + } + + // Create the consolidation sheet + if ( desc == D_NONE ) + { + // Check whether the destination is part of the source ... + TQRect dest; + dest.setCoords( dx, dy, dx + w - 1, dy + h - 1 ); + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + Q_ASSERT( t ); + TQRect r; + + TQRect currentRange=(*it).range(); + + r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); + if ( t == sheet && r.intersects( dest ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + TQString tmp( i18n("The source tables intersect with the destination table") ); + KMessageBox::error( this, tmp); + return; + } + } + + for( int x = 0; x < w; x++ ) + { + for( int y = 0; y < h; y++ ) + { + bool novalue=true; + TQString formula = "=" + function + "("; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + Cell *c = t->cellAt( x + (*it).range().left(), y + (*it).range().top() ); + if(!c->isDefault()) + novalue=false; + if ( it != ranges.begin() ) + formula += ";"; + formula += (*it).sheetName() + "!"; + formula += c->name(); + } + formula += ")"; + + if(!novalue) + sheet->setText( dy + y, dx + x, + m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); + } + } + } + else if ( desc == D_ROW ) + { + // Get list of all descriptions in the rows + TQStringList lst; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); +// kdDebug(36001) << "FROM " << (*it).range.left() << " to " << (*it).range.right() << endl; + for( int x = (*it).range().left(); x <= (*it).range().right() ; ++x ) + { + Cell *c = t->cellAt( x, (*it).range().top() ); + if ( c ) + { + TQString s = c->value().asString(); + if ( !lst.contains( s ) ) + lst.append( s ); + } + } + } + lst.sort(); + + // Check whether the destination is part of the source ... + TQRect dest; + dest.setCoords( dx, dy, dx + lst.count() - 1, dy + h - 1 ); + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + TQRect r; + TQRect currentRange=(*it).range(); + r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); + if ( t == sheet && r.intersects( dest ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + TQString tmp( i18n("The source tables intersect with the destination table") ); + KMessageBox::error( this, tmp); + return; + } + } + + // Now create the consolidation sheet + int x = 0; + TQStringList::Iterator s = lst.begin(); + for( ; s != lst.end(); ++s, ++x ) + { + sheet->setText( dy, dx + x, *s ); + + for( int y = 1; y < h; ++y ) + { + int count = 0; + TQString formula = "=" + function + "("; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + for( int i = (*it).range().left(); i <= (*it).range().right(); ++i ) + { + Sheet *t = (*it).sheet(); + assert( t ); + Cell *c = t->cellAt( i, (*it).range().top() ); + if ( c ) + { + if ( c->value().asString() == *s ) + { +// Cell *c2 = t->cellAt( i, y + (*it).range.top() ); + count++; + if ( it != ranges.begin() ) + formula += ";"; + formula += (*it).sheetName() + "!"; + formula += Cell::name( i, y + (*it).range().top() ); + } + } + } + } + formula += ")"; + + sheet->setText( dy + y, dx + x, + m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); + } + } + } + else if ( desc == D_COL ) + { + // Get list of all descriptions in the columns + TQStringList lst; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + for( int y = (*it).range().top(); y <= (*it).range().bottom() ; ++y ) + { + Cell *c = t->cellAt( (*it).range().left(), y ); + if ( c ) + { + TQString s = c->value().asString(); + if ( !s.isEmpty() && lst.find( s ) == lst.end() ) + lst.append( s ); + } + } + } + lst.sort(); + + // Check whether the destination is part of the source ... + TQRect dest; + dest.setCoords( dx, dy, dx + w - 1, dy + lst.count() - 1 ); + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + TQRect r; + TQRect currentRange=(*it).range(); + r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); + if ( t == sheet && r.intersects( dest ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + TQString tmp( i18n("The source tables intersect with the destination table") ); + KMessageBox::error( this, tmp); + return; + } + } + + // Now create the consolidation sheet + int y = 0; + TQStringList::Iterator s = lst.begin(); + for( ; s != lst.end(); ++s, ++y ) + { + sheet->setText( dy + y, dx, *s ); + + for( int x = 1; x < w; ++x ) + { + int count = 0; + TQString formula = "=" + function + "("; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + for( int i = (*it).range().top(); i <= (*it).range().bottom(); i++ ) + { + Sheet *t = (*it).sheet(); + assert( t ); + Cell *c = t->cellAt( (*it).range().left(), i ); + if ( c ) + { + TQString v = c->value().asString(); + if ( !v.isEmpty() && *s == v ) + { +// Cell *c2 = t->cellAt( x + (*it).range.left(), i ); + count++; + if ( it != ranges.begin() ) formula += ";"; + formula += (*it).sheetName() + "!"; + formula += Cell::name( i, y + (*it).range().top() ); + } + } + } + } + + formula += ")"; + + sheet->setText( dy + y, dx + x, + m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); + } + } + } + else if ( desc == D_BOTH ) + { + // Get list of all descriptions in the columns + TQStringList cols; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + for( int y = (*it).range().top() + 1; y <= (*it).range().bottom() ; ++y ) + { + Cell *c = t->cellAt( (*it).range().left(), y ); + if ( c ) + { + TQString s = c->value().asString(); + if ( !s.isEmpty() && cols.find( s ) == cols.end() ) + cols.append( s ); + } + } + } + cols.sort(); + + // Get list of all descriptions in the rows + TQStringList rows; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + for( int x = (*it).range().left() + 1; x <= (*it).range().right() ; ++x ) + { + Cell *c = t->cellAt( x, (*it).range().top() ); + if ( c ) + { + TQString s = c->value().asString(); + if ( !s.isEmpty() && rows.find( s ) == rows.end() ) + rows.append( s ); + } + } + } + rows.sort(); + + // Check whether the destination is part of the source ... + TQRect dest; + dest.setCoords( dx, dy, dx + cols.count(), dy + rows.count() ); + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + TQRect r; + TQRect currentRange=(*it).range(); + r.setCoords( currentRange.left(), currentRange.top(), currentRange.right(), currentRange.bottom() ); + if ( t == sheet && r.intersects( dest ) ) + { + m_pView->slotUpdateView( m_pView->activeSheet() ); + TQString tmp( i18n("The source tables intersect with the destination table") ); + KMessageBox::error( this, tmp); + return; + } + } + + // Fill the list with all interesting cells + TQValueList lst; + it = ranges.begin(); + for( ; it != ranges.end(); ++it ) + { + Sheet *t = (*it).sheet(); + assert( t ); + for( int x = (*it).range().left() + 1; x <= (*it).range().right() ; ++x ) + { + Cell *c = t->cellAt( x, (*it).range().top() ); + if ( c ) + { + TQString ydesc = c->value().asString(); + for( int y = (*it).range().top() + 1; y <= (*it).range().bottom() ; ++y ) + { + Cell *c2 = t->cellAt( (*it).range().left(), y ); + if ( c2 ) + { + TQString xdesc = c2->value().asString(); + Cell *c3 = t->cellAt( x, y ); + if ( c3 && c3->value().isNumber() ) + { + st_cell k; + k.xdesc = xdesc; + k.ydesc = ydesc; + k.cell = c3; + k.sheet = (*it).sheetName(); + k.x = x; + k.y = y; + lst.append( k ); + } + } + } + } + } + } + + // Draw the row description + int i = 1; + TQStringList::Iterator s = rows.begin(); + for( ; s != rows.end(); ++s, ++i ) + sheet->setText( dy, dx + i, *s ); + + // Draw the column description + i = 1; + s = cols.begin(); + for( ; s != cols.end(); ++s, ++i ) + sheet->setText( dy + i, dx, *s ); + + // Draw the data + int x = 1; + TQStringList::Iterator ydesc = rows.begin(); + for( ; ydesc != rows.end(); ++ydesc, x++ ) + { + int y = 1; + TQStringList::Iterator xdesc = cols.begin(); + for( ; xdesc != cols.end(); ++xdesc, y++ ) + { + int count = 0; + TQString formula = "=" + function + "("; + TQValueList::Iterator lit = lst.begin(); + for( ; lit != lst.end(); ++lit ) + { + if ( (*lit).xdesc == *xdesc && (*lit).ydesc == *ydesc ) + { + count++; + if ( it != ranges.begin() ) formula += ";"; + formula += (*it).sheetName() + "!"; + formula += Cell::name( i, y + (*it).range().top() ); + } + } + formula += ")"; + + sheet->setText( dy + y, dx + x, + m_pCopy->isChecked() ? evaluate( formula, sheet ) : formula ); + } + } + } + m_pView->updateEditWidget(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); + delete this; +} + +void ConsolidateDialog::slotCancel() +{ + reject(); + delete this; +} + +void ConsolidateDialog::slotAdd() +{ + slotReturnPressed(); +} + +void ConsolidateDialog::slotRemove() +{ + int i = m_pRefs->currentItem(); + if ( i < 0 ) + return; + + m_pRefs->removeItem( i ); + + if ( m_pRefs->count() == 0 ) + actionButton( Ok )->setEnabled( false ); +} + +TQStringList ConsolidateDialog::refs() +{ + TQStringList list; + int c = m_pRefs->count(); + + for( int i = 0; i < c; i++ ) + list.append( m_pRefs->text( i ) ); + + return list; +} + +void ConsolidateDialog::slotSelectionChanged() +{ + if (!m_pView->selectionInfo()->isValid()) + { + m_pRef->setText( "" ); + return; + } + + TQString area = m_pView->selectionInfo()->name(); + m_pRef->setText( area ); + m_pRef->setSelection( 0, area.length() ); +} + +void ConsolidateDialog::slotReturnPressed() +{ + TQString txt = m_pRef->text(); + + Range r( txt, m_pView->doc()->map() ); + if ( !r.isValid() ) + { + KMessageBox::error( this, i18n("The range\n%1\n is malformed").arg( txt )); + return; + } + + if ( !txt.isEmpty() ) + { + m_pRefs->insertItem( txt ); + actionButton( Ok )->setEnabled( true ); + } +} + +void ConsolidateDialog::closeEvent ( TQCloseEvent * ) +{ + delete this; +} + +TQString ConsolidateDialog::evaluate( const TQString& formula, Sheet* sheet ) +{ + TQString result = "###"; + Formula *f = new Formula (sheet); + f->setExpression (formula); + if (!f->isValid()) { + delete f; + return result; + } + + Value res = f->eval (); + delete f; + result = sheet->doc()->converter()->asString (res).asString (); + return result; +} + +#include "kspread_dlg_cons.moc" diff --git a/kspread/dialogs/kspread_dlg_csv.cc b/kspread/dialogs/kspread_dlg_csv.cc deleted file mode 100644 index c068810b..00000000 --- a/kspread/dialogs/kspread_dlg_csv.cc +++ /dev/null @@ -1,735 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002-2003 Ariya Hidayat - (C) 2002 Laurent Montel - (C) 1999 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "kspread_dlg_csv.h" - -using namespace KSpread; - -CSVDialog::CSVDialog( View * parent, const char * name, TQRect const & rect, Mode mode) - : KDialogBase( parent, name, true, TQString(), Ok|Cancel ), - m_pView( parent ), - m_cancelled( false ), - m_adjustRows( 0 ), - m_startline( 0 ), - m_textquote( '"' ), - m_delimiter( "," ), - m_targetRect( rect ), - m_mode( mode ) -{ - if ( !name ) - setName( "CSV" ); - - setSizeGripEnabled( TRUE ); - - TQWidget* page = new TQWidget( this ); - setMainWidget( page ); - // MyDialogLayout = new TQGridLayout( page, 4, 4, marginHint(), spacingHint(), "MyDialogLayout"); - MyDialogLayout = new TQGridLayout( page, 1, 1, 11, 6, "MyDialogLayout"); - - // Limit the range - int column = m_targetRect.left(); - Cell* lastCell = m_pView->activeSheet()->getLastCellColumn( column ); - if( lastCell ) - if( m_targetRect.bottom() > lastCell->row() ) - m_targetRect.setBottom( lastCell->row() ); - - m_sheet = new TQTable( page, "m_table" ); - //m_sheet->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)7, 0, 0, m_sheet->sizePolicy().hasHeightForWidth() ) ); - m_sheet->setNumRows( 0 ); - m_sheet->setNumCols( 0 ); - - MyDialogLayout->addMultiCellWidget( m_sheet, 3, 3, 0, 3 ); - - // Delimiter: comma, semicolon, tab, space, other - m_delimiterBox = new TQButtonGroup( page, "m_delimiterBox" ); - m_delimiterBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_delimiterBox->sizePolicy().hasHeightForWidth() ) ); - m_delimiterBox->setTitle( i18n( "Delimiter" ) ); - m_delimiterBox->setColumnLayout(0, Qt::Vertical ); - m_delimiterBox->layout()->setSpacing( KDialog::spacingHint() ); - m_delimiterBox->layout()->setMargin( KDialog::marginHint() ); - m_delimiterBoxLayout = new TQGridLayout( m_delimiterBox->layout() ); - m_delimiterBoxLayout->setAlignment( TQt::AlignTop ); - MyDialogLayout->addMultiCellWidget( m_delimiterBox, 0, 2, 0, 0 ); - - m_ignoreDuplicates = new TQCheckBox( page, "m_ignoreDuplicates" ); - m_ignoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) ); - - MyDialogLayout->addMultiCellWidget( m_ignoreDuplicates, 2, 2, 2, 3 ); - - m_radioComma = new TQRadioButton( m_delimiterBox, "m_radioComma" ); - m_radioComma->setText( i18n( "Comma" ) ); - m_radioComma->setChecked( TRUE ); - m_delimiterBoxLayout->addWidget( m_radioComma, 0, 0 ); - - m_radioSemicolon = new TQRadioButton( m_delimiterBox, "m_radioSemicolon" ); - m_radioSemicolon->setText( i18n( "Semicolon" ) ); - m_delimiterBoxLayout->addWidget( m_radioSemicolon, 0, 1 ); - - m_radioTab = new TQRadioButton( m_delimiterBox, "m_radioTab" ); - m_radioTab->setText( i18n( "Tabulator" ) ); - m_delimiterBoxLayout->addWidget( m_radioTab, 1, 0 ); - - m_radioSpace = new TQRadioButton( m_delimiterBox, "m_radioSpace" ); - m_radioSpace->setText( i18n( "Space" ) ); - m_delimiterBoxLayout->addWidget( m_radioSpace, 1, 1 ); - - m_radioOther = new TQRadioButton( m_delimiterBox, "m_radioOther" ); - m_radioOther->setText( i18n( "Other" ) ); - m_delimiterBoxLayout->addWidget( m_radioOther, 0, 2 ); - - m_delimiterEdit = new TQLineEdit( m_delimiterBox, "m_delimiterEdit" ); - m_delimiterEdit->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, m_delimiterEdit->sizePolicy().hasHeightForWidth() ) ); - m_delimiterEdit->setMaximumSize( TQSize( 30, 32767 ) ); - m_delimiterBoxLayout->addWidget( m_delimiterEdit, 1, 2 ); - - - // Format: number, text, currency, - m_formatBox = new TQButtonGroup( page, "m_formatBox" ); - m_formatBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_formatBox->sizePolicy().hasHeightForWidth() ) ); - m_formatBox->setTitle( i18n( "Format" ) ); - m_formatBox->setColumnLayout(0, Qt::Vertical ); - m_formatBox->layout()->setSpacing( KDialog::spacingHint() ); - m_formatBox->layout()->setMargin( KDialog::marginHint() ); - m_formatBoxLayout = new TQGridLayout( m_formatBox->layout() ); - m_formatBoxLayout->setAlignment( TQt::AlignTop ); - MyDialogLayout->addMultiCellWidget( m_formatBox, 0, 2, 1, 1 ); - - m_radioNumber = new TQRadioButton( m_formatBox, "m_radioNumber" ); - m_radioNumber->setText( i18n( "Number" ) ); - m_formatBoxLayout->addMultiCellWidget( m_radioNumber, 1, 1, 0, 1 ); - - m_radioText = new TQRadioButton( m_formatBox, "m_radioText" ); - m_radioText->setText( i18n( "Text" ) ); - m_radioText->setChecked( TRUE ); - m_formatBoxLayout->addWidget( m_radioText, 0, 0 ); - - m_radioCurrency = new TQRadioButton( m_formatBox, "m_radioCurrency" ); - m_radioCurrency->setText( i18n( "Currency" ) ); - m_formatBoxLayout->addMultiCellWidget( m_radioCurrency, 0, 0, 1, 2 ); - - m_radioDate = new TQRadioButton( m_formatBox, "m_radioDate" ); - m_radioDate->setText( i18n( "Date" ) ); - m_formatBoxLayout->addWidget( m_radioDate, 1, 2 ); - - m_comboLine = new TQComboBox( FALSE, page, "m_comboLine" ); - m_comboLine->insertItem( i18n( "1" ) ); - m_comboLine->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboLine->sizePolicy().hasHeightForWidth() ) ); - - MyDialogLayout->addWidget( m_comboLine, 1, 3 ); - - m_comboQuote = new TQComboBox( FALSE, page, "m_comboQuote" ); - m_comboQuote->insertItem( i18n( "\"" ) ); - m_comboQuote->insertItem( i18n( "'" ) ); - m_comboQuote->insertItem( i18n( "None" ) ); - m_comboQuote->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboQuote->sizePolicy().hasHeightForWidth() ) ); - - MyDialogLayout->addWidget( m_comboQuote, 1, 2 ); - TQSpacerItem* spacer_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred ); - MyDialogLayout->addItem( spacer_2, 2, 3 ); - - TextLabel3 = new TQLabel( page, "TextLabel3" ); - TextLabel3->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel3->sizePolicy().hasHeightForWidth() ) ); - TextLabel3->setText( i18n( "Start at line:" ) ); - - MyDialogLayout->addWidget( TextLabel3, 0, 3 ); - - TextLabel2 = new TQLabel( page, "TextLabel2" ); - TextLabel2->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel2->sizePolicy().hasHeightForWidth() ) ); - TextLabel2->setText( i18n( "Textquote:" ) ); - - MyDialogLayout->addWidget( TextLabel2, 0, 2 ); - - if ( m_mode == Clipboard ) - { - setCaption( i18n( "Inserting From Clipboard" ) ); - TQMimeSource * mime = TQApplication::clipboard()->data(); - if ( !mime ) - { - KMessageBox::information( this, i18n("There is no data in the clipboard.") ); - m_cancelled = true; - return; - } - - if ( !mime->provides( "text/plain" ) ) - { - KMessageBox::information( this, i18n("There is no usable data in the clipboard.") ); - m_cancelled = true; - return; - } - m_fileArray = TQByteArray(mime->encodedData( "text/plain" ) ); - } - else if ( mode == File ) - { - setCaption( i18n( "Inserting Text File" ) ); - TQString file = KFileDialog::getOpenFileName(":", - "text/plain", - this); - //cancel action ! - if ( file.isEmpty() ) - { - actionButton( Ok )->setEnabled( false ); - m_cancelled = true; - return; - } - TQFile in(file); - if (!in.open(IO_ReadOnly)) - { - KMessageBox::sorry( this, i18n("Cannot open input file.") ); - in.close(); - actionButton( Ok )->setEnabled( false ); - m_cancelled = true; - return; - } - m_fileArray = TQByteArray(in.size()); - in.readBlock(m_fileArray.data(), in.size()); - in.close(); - } - else - { - setCaption( i18n( "Text to Columns" ) ); - m_data = ""; - Cell * cell; - Sheet * sheet = m_pView->activeSheet(); - int col = m_targetRect.left(); - for (int i = m_targetRect.top(); i <= m_targetRect.bottom(); ++i) - { - cell = sheet->cellAt( col, i ); - if ( !cell->isEmpty() && !cell->isDefault() ) - { - m_data += cell->strOutText(); - } - m_data += "\n"; - } - } - - fillSheet(); - fillComboBox(); - - resize(sizeHint()); - - m_sheet->setSelectionMode(TQTable::NoSelection); - - connect(m_formatBox, TQT_SIGNAL(clicked(int)), - this, TQT_SLOT(formatClicked(int))); - connect(m_delimiterBox, TQT_SIGNAL(clicked(int)), - this, TQT_SLOT(delimiterClicked(int))); - connect(m_delimiterEdit, TQT_SIGNAL(returnPressed()), - this, TQT_SLOT(returnPressed())); - connect(m_delimiterEdit, TQT_SIGNAL(textChanged ( const TQString & )), - this, TQT_SLOT(textChanged ( const TQString & ) )); - connect(m_comboLine, TQT_SIGNAL(activated(const TQString&)), - this, TQT_SLOT(lineSelected(const TQString&))); - connect(m_comboQuote, TQT_SIGNAL(activated(const TQString&)), - this, TQT_SLOT(textquoteSelected(const TQString&))); - connect(m_sheet, TQT_SIGNAL(currentChanged(int, int)), - this, TQT_SLOT(currentCellChanged(int, int))); - connect(m_ignoreDuplicates, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(ignoreDuplicatesChanged(int))); -} - -CSVDialog::~CSVDialog() -{ - // no need to delete child widgets, TQt does it all for us -} - -bool CSVDialog::cancelled() -{ - return m_cancelled; -} - -void CSVDialog::fillSheet() -{ - int row, column; - bool lastCharDelimiter = false; - bool ignoreDups = m_ignoreDuplicates->isChecked(); - enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD, - S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START; - - TQChar x; - TQString field = ""; - - for (row = 0; row < m_sheet->numRows(); ++row) - for (column = 0; column < m_sheet->numCols(); ++column) - m_sheet->clearCell(row, column); - - row = column = 1; - if (m_mode != Column) - { - m_mode = Column; - m_data = TQString(m_fileArray); - m_fileArray.resize(0); - } - - TQTextStream inputStream(m_data, IO_ReadOnly); - inputStream.setEncoding(TQTextStream::Locale); - - while (!inputStream.atEnd()) - { - inputStream >> x; // read one char - - if (x == '\r') inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly - - switch (state) - { - case S_START : - if (x == m_textquote) - { - state = S_QUOTED_FIELD; - } - else if (x == m_delimiter) - { - if ((ignoreDups == false) || (lastCharDelimiter == false)) - ++column; - lastCharDelimiter = true; - } - else if (x == '\n') - { - ++row; - column = 1; - } - else - { - field += x; - state = S_MAYBE_NORMAL_FIELD; - } - break; - case S_QUOTED_FIELD : - if (x == m_textquote) - { - state = S_MAYBE_END_OF_QUOTED_FIELD; - } - else if (x == '\n') - { - setText(row - m_startline, column, field); - field = ""; - if (x == '\n') - { - ++row; - column = 1; - } - else - { - if ((ignoreDups == false) || (lastCharDelimiter == false)) - ++column; - lastCharDelimiter = true; - } - state = S_START; - } - else - { - field += x; - } - break; - case S_MAYBE_END_OF_QUOTED_FIELD : - if (x == m_textquote) - { - field += x; - state = S_QUOTED_FIELD; - } - else if (x == m_delimiter || x == '\n') - { - setText(row - m_startline, column, field); - field = ""; - if (x == '\n') - { - ++row; - column = 1; - } - else - { - if ((ignoreDups == false) || (lastCharDelimiter == false)) - ++column; - lastCharDelimiter = true; - } - state = S_START; - } - else - { - state = S_END_OF_QUOTED_FIELD; - } - break; - case S_END_OF_QUOTED_FIELD : - if (x == m_delimiter || x == '\n') - { - setText(row - m_startline, column, field); - field = ""; - if (x == '\n') - { - ++row; - column = 1; - } - else - { - if ((ignoreDups == false) || (lastCharDelimiter == false)) - ++column; - lastCharDelimiter = true; - } - state = S_START; - } - else - { - state = S_END_OF_QUOTED_FIELD; - } - break; - case S_MAYBE_NORMAL_FIELD : - if (x == m_textquote) - { - field = ""; - state = S_QUOTED_FIELD; - break; - } - case S_NORMAL_FIELD : - if (x == m_delimiter || x == '\n') - { - setText(row - m_startline, column, field); - field = ""; - if (x == '\n') - { - ++row; - column = 1; - } - else - { - if ((ignoreDups == false) || (lastCharDelimiter == false)) - ++column; - lastCharDelimiter = true; - } - state = S_START; - } - else - { - field += x; - } - } - if (x != m_delimiter) - lastCharDelimiter = false; - } - - // file with only one line without '\n' - if (field.length() > 0) - { - setText(row - m_startline, column, field); - ++row; - field = ""; - } - - adjustRows( row - m_startline ); - - for (column = 0; column < m_sheet->numCols(); ++column) - { - TQString header = m_sheet->horizontalHeader()->label(column); - if (header != i18n("Text") && header != i18n("Number") && - header != i18n("Date") && header != i18n("Currency")) - m_sheet->horizontalHeader()->setLabel(column, i18n("Text")); - - m_sheet->adjustColumn(column); - } -} - -void CSVDialog::fillComboBox() -{ - m_comboLine->clear(); - for (int row = 0; row < m_sheet->numRows(); ++row) - m_comboLine->insertItem(TQString::number(row + 1), row); -} - -void CSVDialog::setText(int row, int col, const TQString& text) -{ - if (row < 1) // skipped by the user - return; - - if (m_sheet->numRows() < row) { - m_sheet->setNumRows(row+5000); /* We add 5000 at a time to limit recalculations */ - m_adjustRows=1; - } - - if (m_sheet->numCols() < col) - m_sheet->setNumCols(col); - - m_sheet->setText(row - 1, col - 1, text); -} - -/* - * Called after the first fillSheet() when number of rows are unknown. - */ -void CSVDialog::adjustRows(int iRows) -{ - if (m_adjustRows) - { - m_sheet->setNumRows( iRows ); - m_adjustRows=0; - } -} - -void CSVDialog::returnPressed() -{ - if (m_delimiterBox->id(m_delimiterBox->selected()) != 4) - return; - - m_delimiter = m_delimiterEdit->text(); - fillSheet(); -} - -void CSVDialog::textChanged ( const TQString & ) -{ - m_radioOther->setChecked ( true ); - delimiterClicked(4); // other -} - -void CSVDialog::formatClicked(int id) -{ - TQString header; - - switch (id) - { - case 1: // text - header = i18n("Text"); - break; - case 0: // number - header = i18n("Number"); - break; - case 3: // date - header = i18n("Date"); - break; - case 2: // currency - header = i18n("Currency"); - break; - } - - m_sheet->horizontalHeader()->setLabel(m_sheet->currentColumn(), header); -} - -void CSVDialog::delimiterClicked(int id) -{ - switch (id) - { - case 0: // comma - m_delimiter = ","; - break; - case 4: // other - m_delimiter = m_delimiterEdit->text(); - break; - case 2: // tab - m_delimiter = "\t"; - break; - case 3: // space - m_delimiter = " "; - break; - case 1: // semicolon - m_delimiter = ";"; - break; - } - - fillSheet(); -} - -void CSVDialog::textquoteSelected(const TQString& mark) -{ - if (mark == i18n("none")) - m_textquote = 0; - else - m_textquote = mark[0]; - - fillSheet(); -} - -void CSVDialog::lineSelected(const TQString& line) -{ - m_startline = line.toInt() - 1; - fillSheet(); -} - -void CSVDialog::currentCellChanged(int, int col) -{ - int id; - TQString header = m_sheet->horizontalHeader()->label(col); - - if (header == i18n("Text")) - id = 1; - else if (header == i18n("Number")) - id = 0; - else if (header == i18n("Date")) - id = 3; - else - id = 2; - - m_formatBox->setButton(id); -} - -void CSVDialog::accept() -{ - Sheet * sheet = m_pView->activeSheet(); - TQString csv_delimiter = TQString(); - Cell * cell; - - int numRows = m_sheet->numRows(); - int numCols = m_sheet->numCols(); - - if (numRows == 0) - ++numRows; - - if ( (numCols > m_targetRect.width()) && (m_targetRect.width() > 1) ) - { - numCols = m_targetRect.width(); - } - else - m_targetRect.setRight( m_targetRect.left() + numCols ); - - if ( (numRows > m_targetRect.height()) && (m_targetRect.height() > 1) ) - numRows = m_targetRect.height(); - else - m_targetRect.setBottom( m_targetRect.top() + numRows ); - - if ( numRows == 1 && numCols == 1) - { - Doc * doc = m_pView->doc(); - cell = sheet->nonDefaultCell( m_targetRect.left(), m_targetRect.top() ); - if ( !doc->undoLocked() ) - { - UndoSetText * undo = new UndoSetText( doc, sheet , cell->text(), m_targetRect.left(), - m_targetRect.top(), cell->formatType() ); - doc->addCommand( undo ); - } - } - else - { - UndoChangeAreaTextCell * undo = new UndoChangeAreaTextCell( m_pView->doc(), sheet , m_targetRect ); - m_pView->doc()->addCommand( undo ); - } - - m_pView->doc()->emitBeginOperation(); - - int i; - int left = m_targetRect.left(); - int top = m_targetRect.top(); - - TQMemArray widths( numCols ); - for ( i = 0; i < numCols; ++i ) - { - ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i ); - widths[i] = c->dblWidth(); - } - - for (int row = 0; row < numRows; ++row) - { - for (int col = 0; col < numCols; ++col) - { - cell = sheet->nonDefaultCell( left + col, top + row ); - cell->setCellText( getText( row, col ) ); - - TQFontMetrics fm = sheet->painter().fontMetrics(); - double w = fm.width( cell->strOutText() ); - if ( w == 0.0 ) - { - TQFontMetrics fm( cell->format()->textFont( left + col, top + row ) ); - w = fm.width('x') * (double) getText( row, col ).length(); - } - - if ( w > widths[col] ) - widths[col] = w; - - cell->format()->setFormatType(Generic_format); - /* - Disabling this code for now, everything will use Generic formatting, - hoping for the best (Tomas) - //### FIXME: long term solution is to allow to select Generic format ("autodetect") in the dialog and make it the default - - switch (getHeader(col)) - { - case TEXT: - break; - case NUMBER: - cell->format()->setFormatType(Number_format); - cell->setPrecision(2); - break; - case DATE: - cell->format()->setFormatType(ShortDate_format); - break; - case CURRENCY: - cell->format()->setFormatType(Money_format); - break; - } - */ - } - } - - for ( i = 0; i < numCols; ++i ) - { - ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i ); - c->setDblWidth( widths[i] ); - sheet->emit_updateColumn( c, left + i ); - } - - m_pView->slotUpdateView( sheet ); - TQDialog::accept(); -} - -int CSVDialog::getHeader(int col) -{ - TQString header = m_sheet->horizontalHeader()->label(col); - - if (header == i18n("Text")) - return TEXT; - else if (header == i18n("Number")) - return NUMBER; - else if (header == i18n("Currency")) - return CURRENCY; - else - return DATE; -} - -TQString CSVDialog::getText(int row, int col) -{ - return m_sheet->text(row, col); -} - -void CSVDialog::ignoreDuplicatesChanged(int) -{ - fillSheet(); -} - -#include "kspread_dlg_csv.moc" diff --git a/kspread/dialogs/kspread_dlg_csv.cpp b/kspread/dialogs/kspread_dlg_csv.cpp new file mode 100644 index 00000000..c068810b --- /dev/null +++ b/kspread/dialogs/kspread_dlg_csv.cpp @@ -0,0 +1,735 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002-2003 Ariya Hidayat + (C) 2002 Laurent Montel + (C) 1999 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "kspread_dlg_csv.h" + +using namespace KSpread; + +CSVDialog::CSVDialog( View * parent, const char * name, TQRect const & rect, Mode mode) + : KDialogBase( parent, name, true, TQString(), Ok|Cancel ), + m_pView( parent ), + m_cancelled( false ), + m_adjustRows( 0 ), + m_startline( 0 ), + m_textquote( '"' ), + m_delimiter( "," ), + m_targetRect( rect ), + m_mode( mode ) +{ + if ( !name ) + setName( "CSV" ); + + setSizeGripEnabled( TRUE ); + + TQWidget* page = new TQWidget( this ); + setMainWidget( page ); + // MyDialogLayout = new TQGridLayout( page, 4, 4, marginHint(), spacingHint(), "MyDialogLayout"); + MyDialogLayout = new TQGridLayout( page, 1, 1, 11, 6, "MyDialogLayout"); + + // Limit the range + int column = m_targetRect.left(); + Cell* lastCell = m_pView->activeSheet()->getLastCellColumn( column ); + if( lastCell ) + if( m_targetRect.bottom() > lastCell->row() ) + m_targetRect.setBottom( lastCell->row() ); + + m_sheet = new TQTable( page, "m_table" ); + //m_sheet->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)7, 0, 0, m_sheet->sizePolicy().hasHeightForWidth() ) ); + m_sheet->setNumRows( 0 ); + m_sheet->setNumCols( 0 ); + + MyDialogLayout->addMultiCellWidget( m_sheet, 3, 3, 0, 3 ); + + // Delimiter: comma, semicolon, tab, space, other + m_delimiterBox = new TQButtonGroup( page, "m_delimiterBox" ); + m_delimiterBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_delimiterBox->sizePolicy().hasHeightForWidth() ) ); + m_delimiterBox->setTitle( i18n( "Delimiter" ) ); + m_delimiterBox->setColumnLayout(0, Qt::Vertical ); + m_delimiterBox->layout()->setSpacing( KDialog::spacingHint() ); + m_delimiterBox->layout()->setMargin( KDialog::marginHint() ); + m_delimiterBoxLayout = new TQGridLayout( m_delimiterBox->layout() ); + m_delimiterBoxLayout->setAlignment( TQt::AlignTop ); + MyDialogLayout->addMultiCellWidget( m_delimiterBox, 0, 2, 0, 0 ); + + m_ignoreDuplicates = new TQCheckBox( page, "m_ignoreDuplicates" ); + m_ignoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) ); + + MyDialogLayout->addMultiCellWidget( m_ignoreDuplicates, 2, 2, 2, 3 ); + + m_radioComma = new TQRadioButton( m_delimiterBox, "m_radioComma" ); + m_radioComma->setText( i18n( "Comma" ) ); + m_radioComma->setChecked( TRUE ); + m_delimiterBoxLayout->addWidget( m_radioComma, 0, 0 ); + + m_radioSemicolon = new TQRadioButton( m_delimiterBox, "m_radioSemicolon" ); + m_radioSemicolon->setText( i18n( "Semicolon" ) ); + m_delimiterBoxLayout->addWidget( m_radioSemicolon, 0, 1 ); + + m_radioTab = new TQRadioButton( m_delimiterBox, "m_radioTab" ); + m_radioTab->setText( i18n( "Tabulator" ) ); + m_delimiterBoxLayout->addWidget( m_radioTab, 1, 0 ); + + m_radioSpace = new TQRadioButton( m_delimiterBox, "m_radioSpace" ); + m_radioSpace->setText( i18n( "Space" ) ); + m_delimiterBoxLayout->addWidget( m_radioSpace, 1, 1 ); + + m_radioOther = new TQRadioButton( m_delimiterBox, "m_radioOther" ); + m_radioOther->setText( i18n( "Other" ) ); + m_delimiterBoxLayout->addWidget( m_radioOther, 0, 2 ); + + m_delimiterEdit = new TQLineEdit( m_delimiterBox, "m_delimiterEdit" ); + m_delimiterEdit->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, m_delimiterEdit->sizePolicy().hasHeightForWidth() ) ); + m_delimiterEdit->setMaximumSize( TQSize( 30, 32767 ) ); + m_delimiterBoxLayout->addWidget( m_delimiterEdit, 1, 2 ); + + + // Format: number, text, currency, + m_formatBox = new TQButtonGroup( page, "m_formatBox" ); + m_formatBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_formatBox->sizePolicy().hasHeightForWidth() ) ); + m_formatBox->setTitle( i18n( "Format" ) ); + m_formatBox->setColumnLayout(0, Qt::Vertical ); + m_formatBox->layout()->setSpacing( KDialog::spacingHint() ); + m_formatBox->layout()->setMargin( KDialog::marginHint() ); + m_formatBoxLayout = new TQGridLayout( m_formatBox->layout() ); + m_formatBoxLayout->setAlignment( TQt::AlignTop ); + MyDialogLayout->addMultiCellWidget( m_formatBox, 0, 2, 1, 1 ); + + m_radioNumber = new TQRadioButton( m_formatBox, "m_radioNumber" ); + m_radioNumber->setText( i18n( "Number" ) ); + m_formatBoxLayout->addMultiCellWidget( m_radioNumber, 1, 1, 0, 1 ); + + m_radioText = new TQRadioButton( m_formatBox, "m_radioText" ); + m_radioText->setText( i18n( "Text" ) ); + m_radioText->setChecked( TRUE ); + m_formatBoxLayout->addWidget( m_radioText, 0, 0 ); + + m_radioCurrency = new TQRadioButton( m_formatBox, "m_radioCurrency" ); + m_radioCurrency->setText( i18n( "Currency" ) ); + m_formatBoxLayout->addMultiCellWidget( m_radioCurrency, 0, 0, 1, 2 ); + + m_radioDate = new TQRadioButton( m_formatBox, "m_radioDate" ); + m_radioDate->setText( i18n( "Date" ) ); + m_formatBoxLayout->addWidget( m_radioDate, 1, 2 ); + + m_comboLine = new TQComboBox( FALSE, page, "m_comboLine" ); + m_comboLine->insertItem( i18n( "1" ) ); + m_comboLine->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboLine->sizePolicy().hasHeightForWidth() ) ); + + MyDialogLayout->addWidget( m_comboLine, 1, 3 ); + + m_comboQuote = new TQComboBox( FALSE, page, "m_comboQuote" ); + m_comboQuote->insertItem( i18n( "\"" ) ); + m_comboQuote->insertItem( i18n( "'" ) ); + m_comboQuote->insertItem( i18n( "None" ) ); + m_comboQuote->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboQuote->sizePolicy().hasHeightForWidth() ) ); + + MyDialogLayout->addWidget( m_comboQuote, 1, 2 ); + TQSpacerItem* spacer_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred ); + MyDialogLayout->addItem( spacer_2, 2, 3 ); + + TextLabel3 = new TQLabel( page, "TextLabel3" ); + TextLabel3->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel3->sizePolicy().hasHeightForWidth() ) ); + TextLabel3->setText( i18n( "Start at line:" ) ); + + MyDialogLayout->addWidget( TextLabel3, 0, 3 ); + + TextLabel2 = new TQLabel( page, "TextLabel2" ); + TextLabel2->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel2->sizePolicy().hasHeightForWidth() ) ); + TextLabel2->setText( i18n( "Textquote:" ) ); + + MyDialogLayout->addWidget( TextLabel2, 0, 2 ); + + if ( m_mode == Clipboard ) + { + setCaption( i18n( "Inserting From Clipboard" ) ); + TQMimeSource * mime = TQApplication::clipboard()->data(); + if ( !mime ) + { + KMessageBox::information( this, i18n("There is no data in the clipboard.") ); + m_cancelled = true; + return; + } + + if ( !mime->provides( "text/plain" ) ) + { + KMessageBox::information( this, i18n("There is no usable data in the clipboard.") ); + m_cancelled = true; + return; + } + m_fileArray = TQByteArray(mime->encodedData( "text/plain" ) ); + } + else if ( mode == File ) + { + setCaption( i18n( "Inserting Text File" ) ); + TQString file = KFileDialog::getOpenFileName(":", + "text/plain", + this); + //cancel action ! + if ( file.isEmpty() ) + { + actionButton( Ok )->setEnabled( false ); + m_cancelled = true; + return; + } + TQFile in(file); + if (!in.open(IO_ReadOnly)) + { + KMessageBox::sorry( this, i18n("Cannot open input file.") ); + in.close(); + actionButton( Ok )->setEnabled( false ); + m_cancelled = true; + return; + } + m_fileArray = TQByteArray(in.size()); + in.readBlock(m_fileArray.data(), in.size()); + in.close(); + } + else + { + setCaption( i18n( "Text to Columns" ) ); + m_data = ""; + Cell * cell; + Sheet * sheet = m_pView->activeSheet(); + int col = m_targetRect.left(); + for (int i = m_targetRect.top(); i <= m_targetRect.bottom(); ++i) + { + cell = sheet->cellAt( col, i ); + if ( !cell->isEmpty() && !cell->isDefault() ) + { + m_data += cell->strOutText(); + } + m_data += "\n"; + } + } + + fillSheet(); + fillComboBox(); + + resize(sizeHint()); + + m_sheet->setSelectionMode(TQTable::NoSelection); + + connect(m_formatBox, TQT_SIGNAL(clicked(int)), + this, TQT_SLOT(formatClicked(int))); + connect(m_delimiterBox, TQT_SIGNAL(clicked(int)), + this, TQT_SLOT(delimiterClicked(int))); + connect(m_delimiterEdit, TQT_SIGNAL(returnPressed()), + this, TQT_SLOT(returnPressed())); + connect(m_delimiterEdit, TQT_SIGNAL(textChanged ( const TQString & )), + this, TQT_SLOT(textChanged ( const TQString & ) )); + connect(m_comboLine, TQT_SIGNAL(activated(const TQString&)), + this, TQT_SLOT(lineSelected(const TQString&))); + connect(m_comboQuote, TQT_SIGNAL(activated(const TQString&)), + this, TQT_SLOT(textquoteSelected(const TQString&))); + connect(m_sheet, TQT_SIGNAL(currentChanged(int, int)), + this, TQT_SLOT(currentCellChanged(int, int))); + connect(m_ignoreDuplicates, TQT_SIGNAL(stateChanged(int)), + this, TQT_SLOT(ignoreDuplicatesChanged(int))); +} + +CSVDialog::~CSVDialog() +{ + // no need to delete child widgets, TQt does it all for us +} + +bool CSVDialog::cancelled() +{ + return m_cancelled; +} + +void CSVDialog::fillSheet() +{ + int row, column; + bool lastCharDelimiter = false; + bool ignoreDups = m_ignoreDuplicates->isChecked(); + enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD, + S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START; + + TQChar x; + TQString field = ""; + + for (row = 0; row < m_sheet->numRows(); ++row) + for (column = 0; column < m_sheet->numCols(); ++column) + m_sheet->clearCell(row, column); + + row = column = 1; + if (m_mode != Column) + { + m_mode = Column; + m_data = TQString(m_fileArray); + m_fileArray.resize(0); + } + + TQTextStream inputStream(m_data, IO_ReadOnly); + inputStream.setEncoding(TQTextStream::Locale); + + while (!inputStream.atEnd()) + { + inputStream >> x; // read one char + + if (x == '\r') inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly + + switch (state) + { + case S_START : + if (x == m_textquote) + { + state = S_QUOTED_FIELD; + } + else if (x == m_delimiter) + { + if ((ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + else if (x == '\n') + { + ++row; + column = 1; + } + else + { + field += x; + state = S_MAYBE_NORMAL_FIELD; + } + break; + case S_QUOTED_FIELD : + if (x == m_textquote) + { + state = S_MAYBE_END_OF_QUOTED_FIELD; + } + else if (x == '\n') + { + setText(row - m_startline, column, field); + field = ""; + if (x == '\n') + { + ++row; + column = 1; + } + else + { + if ((ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + field += x; + } + break; + case S_MAYBE_END_OF_QUOTED_FIELD : + if (x == m_textquote) + { + field += x; + state = S_QUOTED_FIELD; + } + else if (x == m_delimiter || x == '\n') + { + setText(row - m_startline, column, field); + field = ""; + if (x == '\n') + { + ++row; + column = 1; + } + else + { + if ((ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + state = S_END_OF_QUOTED_FIELD; + } + break; + case S_END_OF_QUOTED_FIELD : + if (x == m_delimiter || x == '\n') + { + setText(row - m_startline, column, field); + field = ""; + if (x == '\n') + { + ++row; + column = 1; + } + else + { + if ((ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + state = S_END_OF_QUOTED_FIELD; + } + break; + case S_MAYBE_NORMAL_FIELD : + if (x == m_textquote) + { + field = ""; + state = S_QUOTED_FIELD; + break; + } + case S_NORMAL_FIELD : + if (x == m_delimiter || x == '\n') + { + setText(row - m_startline, column, field); + field = ""; + if (x == '\n') + { + ++row; + column = 1; + } + else + { + if ((ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + field += x; + } + } + if (x != m_delimiter) + lastCharDelimiter = false; + } + + // file with only one line without '\n' + if (field.length() > 0) + { + setText(row - m_startline, column, field); + ++row; + field = ""; + } + + adjustRows( row - m_startline ); + + for (column = 0; column < m_sheet->numCols(); ++column) + { + TQString header = m_sheet->horizontalHeader()->label(column); + if (header != i18n("Text") && header != i18n("Number") && + header != i18n("Date") && header != i18n("Currency")) + m_sheet->horizontalHeader()->setLabel(column, i18n("Text")); + + m_sheet->adjustColumn(column); + } +} + +void CSVDialog::fillComboBox() +{ + m_comboLine->clear(); + for (int row = 0; row < m_sheet->numRows(); ++row) + m_comboLine->insertItem(TQString::number(row + 1), row); +} + +void CSVDialog::setText(int row, int col, const TQString& text) +{ + if (row < 1) // skipped by the user + return; + + if (m_sheet->numRows() < row) { + m_sheet->setNumRows(row+5000); /* We add 5000 at a time to limit recalculations */ + m_adjustRows=1; + } + + if (m_sheet->numCols() < col) + m_sheet->setNumCols(col); + + m_sheet->setText(row - 1, col - 1, text); +} + +/* + * Called after the first fillSheet() when number of rows are unknown. + */ +void CSVDialog::adjustRows(int iRows) +{ + if (m_adjustRows) + { + m_sheet->setNumRows( iRows ); + m_adjustRows=0; + } +} + +void CSVDialog::returnPressed() +{ + if (m_delimiterBox->id(m_delimiterBox->selected()) != 4) + return; + + m_delimiter = m_delimiterEdit->text(); + fillSheet(); +} + +void CSVDialog::textChanged ( const TQString & ) +{ + m_radioOther->setChecked ( true ); + delimiterClicked(4); // other +} + +void CSVDialog::formatClicked(int id) +{ + TQString header; + + switch (id) + { + case 1: // text + header = i18n("Text"); + break; + case 0: // number + header = i18n("Number"); + break; + case 3: // date + header = i18n("Date"); + break; + case 2: // currency + header = i18n("Currency"); + break; + } + + m_sheet->horizontalHeader()->setLabel(m_sheet->currentColumn(), header); +} + +void CSVDialog::delimiterClicked(int id) +{ + switch (id) + { + case 0: // comma + m_delimiter = ","; + break; + case 4: // other + m_delimiter = m_delimiterEdit->text(); + break; + case 2: // tab + m_delimiter = "\t"; + break; + case 3: // space + m_delimiter = " "; + break; + case 1: // semicolon + m_delimiter = ";"; + break; + } + + fillSheet(); +} + +void CSVDialog::textquoteSelected(const TQString& mark) +{ + if (mark == i18n("none")) + m_textquote = 0; + else + m_textquote = mark[0]; + + fillSheet(); +} + +void CSVDialog::lineSelected(const TQString& line) +{ + m_startline = line.toInt() - 1; + fillSheet(); +} + +void CSVDialog::currentCellChanged(int, int col) +{ + int id; + TQString header = m_sheet->horizontalHeader()->label(col); + + if (header == i18n("Text")) + id = 1; + else if (header == i18n("Number")) + id = 0; + else if (header == i18n("Date")) + id = 3; + else + id = 2; + + m_formatBox->setButton(id); +} + +void CSVDialog::accept() +{ + Sheet * sheet = m_pView->activeSheet(); + TQString csv_delimiter = TQString(); + Cell * cell; + + int numRows = m_sheet->numRows(); + int numCols = m_sheet->numCols(); + + if (numRows == 0) + ++numRows; + + if ( (numCols > m_targetRect.width()) && (m_targetRect.width() > 1) ) + { + numCols = m_targetRect.width(); + } + else + m_targetRect.setRight( m_targetRect.left() + numCols ); + + if ( (numRows > m_targetRect.height()) && (m_targetRect.height() > 1) ) + numRows = m_targetRect.height(); + else + m_targetRect.setBottom( m_targetRect.top() + numRows ); + + if ( numRows == 1 && numCols == 1) + { + Doc * doc = m_pView->doc(); + cell = sheet->nonDefaultCell( m_targetRect.left(), m_targetRect.top() ); + if ( !doc->undoLocked() ) + { + UndoSetText * undo = new UndoSetText( doc, sheet , cell->text(), m_targetRect.left(), + m_targetRect.top(), cell->formatType() ); + doc->addCommand( undo ); + } + } + else + { + UndoChangeAreaTextCell * undo = new UndoChangeAreaTextCell( m_pView->doc(), sheet , m_targetRect ); + m_pView->doc()->addCommand( undo ); + } + + m_pView->doc()->emitBeginOperation(); + + int i; + int left = m_targetRect.left(); + int top = m_targetRect.top(); + + TQMemArray widths( numCols ); + for ( i = 0; i < numCols; ++i ) + { + ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i ); + widths[i] = c->dblWidth(); + } + + for (int row = 0; row < numRows; ++row) + { + for (int col = 0; col < numCols; ++col) + { + cell = sheet->nonDefaultCell( left + col, top + row ); + cell->setCellText( getText( row, col ) ); + + TQFontMetrics fm = sheet->painter().fontMetrics(); + double w = fm.width( cell->strOutText() ); + if ( w == 0.0 ) + { + TQFontMetrics fm( cell->format()->textFont( left + col, top + row ) ); + w = fm.width('x') * (double) getText( row, col ).length(); + } + + if ( w > widths[col] ) + widths[col] = w; + + cell->format()->setFormatType(Generic_format); + /* + Disabling this code for now, everything will use Generic formatting, + hoping for the best (Tomas) + //### FIXME: long term solution is to allow to select Generic format ("autodetect") in the dialog and make it the default + + switch (getHeader(col)) + { + case TEXT: + break; + case NUMBER: + cell->format()->setFormatType(Number_format); + cell->setPrecision(2); + break; + case DATE: + cell->format()->setFormatType(ShortDate_format); + break; + case CURRENCY: + cell->format()->setFormatType(Money_format); + break; + } + */ + } + } + + for ( i = 0; i < numCols; ++i ) + { + ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i ); + c->setDblWidth( widths[i] ); + sheet->emit_updateColumn( c, left + i ); + } + + m_pView->slotUpdateView( sheet ); + TQDialog::accept(); +} + +int CSVDialog::getHeader(int col) +{ + TQString header = m_sheet->horizontalHeader()->label(col); + + if (header == i18n("Text")) + return TEXT; + else if (header == i18n("Number")) + return NUMBER; + else if (header == i18n("Currency")) + return CURRENCY; + else + return DATE; +} + +TQString CSVDialog::getText(int row, int col) +{ + return m_sheet->text(row, col); +} + +void CSVDialog::ignoreDuplicatesChanged(int) +{ + fillSheet(); +} + +#include "kspread_dlg_csv.moc" diff --git a/kspread/dialogs/kspread_dlg_database.cc b/kspread/dialogs/kspread_dlg_database.cc deleted file mode 100644 index 34e680cd..00000000 --- a/kspread/dialogs/kspread_dlg_database.cc +++ /dev/null @@ -1,1179 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_cell.h" -#include "kspread_dlg_database.h" -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_util.h" -#include "kspread_undo.h" -#include "kspread_view.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - -#ifndef TQT_NO_SQL - -/******************************************************** - * Database wizard * - ********************************************************/ - -DatabaseDialog::DatabaseDialog( View * parent, TQRect const & rect, const char * name, bool modal, WFlags fl ) - : KWizard( (TQWidget *) parent, name, modal, fl ), - m_currentPage( eDatabase ), - m_pView( parent ), - m_targetRect( rect ), - m_dbConnection( 0L ) -{ - if ( !name ) - setName( "DatabaseDialog" ); - - setCaption( i18n( "Insert Data From Database" ) ); - - // database page - - m_database = new TQWidget( this, "m_database" ); - m_databaseLayout = new TQGridLayout( m_database, 1, 1, -1, -1, "m_databaseLayout"); - - TQFrame * Frame5 = new TQFrame( m_database, "Frame5" ); - Frame5->setFrameShape( TQFrame::MShape ); - Frame5->setFrameShadow( TQFrame::MShadow ); - TQVBoxLayout * Frame5Layout = new TQVBoxLayout( Frame5, 11, 6, "Frame5Layout"); - - - TQFrame * Frame16 = new TQFrame( Frame5, "Frame16" ); - Frame16->setFrameShape( TQFrame::NoFrame ); - Frame16->setFrameShadow( TQFrame::Plain ); - TQGridLayout * Frame16Layout = new TQGridLayout( Frame16, 1, 1, 11, 7, "Frame16Layout"); - - m_Type = new TQLabel( Frame16, "m_Type" ); - m_Type->setText( i18n( "Type:" ) ); - - Frame16Layout->addWidget( m_Type, 0, 0 ); - - TQLabel * TextLabel4 = new TQLabel( Frame16, "TextLabel4" ); - TextLabel4->setText( i18n( "User name:\n" - "(if necessary)" ) ); - Frame16Layout->addWidget( TextLabel4, 4, 0 ); - - TQLabel * TextLabel2 = new TQLabel( Frame16, "TextLabel2" ); - TextLabel2->setText( i18n( "Host:" ) ); - Frame16Layout->addWidget( TextLabel2, 2, 0 ); - - m_driver = new TQComboBox( FALSE, Frame16, "m_driver" ); - Frame16Layout->addWidget( m_driver, 0, 1 ); - - m_username = new TQLineEdit( Frame16, "m_username" ); - Frame16Layout->addWidget( m_username, 4, 1 ); - - m_host = new TQLineEdit( Frame16, "m_host" ); - m_host->setText("localhost"); - Frame16Layout->addWidget( m_host, 2, 1 ); - - TQLabel * TextLabel3 = new TQLabel( Frame16, "TextLabel3" ); - TextLabel3->setText( i18n( "Port:\n(if necessary)") ); - Frame16Layout->addWidget( TextLabel3, 3, 0 ); - - m_password = new TQLineEdit( Frame16, "m_password" ); - m_password->setEchoMode( TQLineEdit::Password ); - Frame16Layout->addWidget( m_password, 5, 1 ); - - m_port = new TQLineEdit( Frame16, "m_port" ); - m_port->setValidator( new KIntValidator( m_port ) ); - Frame16Layout->addWidget( m_port, 3, 1 ); - - TQLabel * dbName = new TQLabel( Frame16, "dbName" ); - dbName->setText( i18n( "Database name: ") ); - Frame16Layout->addWidget( dbName, 1, 0 ); - - m_databaseName = new TQLineEdit( Frame16, "m_databaseName" ); - Frame16Layout->addWidget( m_databaseName, 1, 1 ); - - TQLabel * TextLabel5 = new TQLabel( Frame16, "TextLabel5" ); - TextLabel5->setText( i18n( "Password:\n" - "(if necessary)" ) ); - Frame16Layout->addWidget( TextLabel5, 5, 0 ); - Frame5Layout->addWidget( Frame16 ); - - m_databasetStatus = new TQLabel( Frame5, "m_databasetStatus" ); - m_databasetStatus->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)5, 0, 0, m_databasetStatus->sizePolicy().hasHeightForWidth() ) ); - m_databasetStatus->setMaximumSize( TQSize( 32767, 30 ) ); - m_databasetStatus->setText( " " ); - Frame5Layout->addWidget( m_databasetStatus ); - - m_databaseLayout->addWidget( Frame5, 0, 1 ); - - TQFrame * Frame17 = new TQFrame( m_database, "Frame17" ); - Frame17->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17->sizePolicy().hasHeightForWidth() ) ); - Frame17->setMinimumSize( TQSize( 111, 0 ) ); - Frame17->setFrameShape( TQFrame::NoFrame ); - Frame17->setFrameShadow( TQFrame::Plain ); - - m_databaseLayout->addWidget( Frame17, 0, 0 ); - addPage( m_database, i18n( "Database" ) ); - - // new page - - m_sheet = new TQWidget( this, "m_table" ); - m_sheetLayout = new TQGridLayout( m_sheet, 1, 1, 11, 6, "m_tableLayout"); - - TQFrame * Frame5_2 = new TQFrame( m_sheet, "Frame5_2" ); - Frame5_2->setFrameShape( TQFrame::MShape ); - Frame5_2->setFrameShadow( TQFrame::MShadow ); - TQGridLayout * Frame5_2Layout = new TQGridLayout( Frame5_2, 1, 1, 11, 6, "Frame5_2Layout"); - - TQHBoxLayout * Layout21 = new TQHBoxLayout( 0, 0, 6, "Layout21"); - - // TQLabel * TextLabel12_2 = new TQLabel( Frame5_2, "TextLabel12_2" ); - // TextLabel12_2->setText( i18n( "Database:" ) ); - // Layout21->addWidget( TextLabel12_2 ); - - // m_databaseList = new TQComboBox( FALSE, Frame5_2, "m_databaseList" ); - // Layout21->addWidget( m_databaseList ); - - // m_connectButton = new KPushButton( Frame5_2, "m_connectButton" ); - // m_connectButton->setText( i18n( "&Connect" ) ); - // Layout21->addWidget( m_connectButton ); - - Frame5_2Layout->addLayout( Layout21, 0, 0 ); - - m_sheetStatus = new TQLabel( Frame5_2, "m_tableStatus" ); - m_sheetStatus->setText( " " ); - Frame5_2Layout->addWidget( m_sheetStatus, 3, 0 ); - - m_SelectSheetLabel = new TQLabel( Frame5_2, "m_SelectSheetLabel" ); - m_SelectSheetLabel->setText( i18n( "Select tables:" ) ); - Frame5_2Layout->addWidget( m_SelectSheetLabel, 1, 0 ); - - m_sheetView = new TDEListView( Frame5_2, "m_tableView" ); - m_sheetView->addColumn( i18n( "Sheet" ) ); - m_sheetView->setRootIsDecorated( FALSE ); - - Frame5_2Layout->addWidget( m_sheetView, 2, 0 ); - - m_sheetLayout->addWidget( Frame5_2, 0, 1 ); - - TQFrame * Frame17_2 = new TQFrame( m_sheet, "Frame17_2" ); - Frame17_2->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_2->sizePolicy().hasHeightForWidth() ) ); - Frame17_2->setMinimumSize( TQSize( 111, 0 ) ); - Frame17_2->setFrameShape( TQFrame::NoFrame ); - Frame17_2->setFrameShadow( TQFrame::Plain ); - - m_sheetLayout->addWidget( Frame17_2, 0, 0 ); - addPage( m_sheet, i18n( "Sheets" ) ); - - m_columns = new TQWidget( this, "m_columns" ); - m_columnsLayout = new TQGridLayout( m_columns, 1, 1, 11, 6, "m_columnsLayout"); - - TQFrame * Frame5_2_2 = new TQFrame( m_columns, "Frame5_2_2" ); - Frame5_2_2->setFrameShape( TQFrame::MShape ); - Frame5_2_2->setFrameShadow( TQFrame::MShadow ); - TQGridLayout * Frame5_2_2Layout = new TQGridLayout( Frame5_2_2, 1, 1, 11, 6, "Frame5_2_2Layout"); - - TQLabel * TextLabel11_2 = new TQLabel( Frame5_2_2, "TextLabel11_2" ); - TextLabel11_2->setText( i18n( "Select columns:" ) ); - - Frame5_2_2Layout->addWidget( TextLabel11_2, 0, 0 ); - - m_columnView = new TDEListView( Frame5_2_2, "m_columnView" ); - m_columnView->addColumn( i18n( "Column" ) ); - m_columnView->addColumn( i18n( "Sheet" ) ); - m_columnView->addColumn( i18n( "Data Type" ) ); - m_columnView->setRootIsDecorated( FALSE ); - - Frame5_2_2Layout->addWidget( m_columnView, 1, 0 ); - - m_columnsStatus = new TQLabel( Frame5_2_2, "m_columnsStatus" ); - m_columnsStatus->setText( " " ); - Frame5_2_2Layout->addWidget( m_columnsStatus, 2, 0 ); - - m_columnsLayout->addWidget( Frame5_2_2, 0, 1 ); - - TQFrame * Frame17_3 = new TQFrame( m_columns, "Frame17_3" ); - Frame17_3->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_3->sizePolicy().hasHeightForWidth() ) ); - Frame17_3->setMinimumSize( TQSize( 111, 0 ) ); - Frame17_3->setFrameShape( TQFrame::NoFrame ); - Frame17_3->setFrameShadow( TQFrame::Plain ); - - m_columnsLayout->addWidget( Frame17_3, 0, 0 ); - addPage( m_columns, i18n( "Columns" ) ); - - // options page - - m_options = new TQWidget( this, "m_options" ); - m_optionsLayout = new TQGridLayout( m_options, 1, 1, 11, 6, "m_optionsLayout"); - - TQFrame * optionsFrame = new TQFrame( m_options, "optionsFrame" ); - optionsFrame->setFrameShape( TQFrame::MShape ); - optionsFrame->setFrameShadow( TQFrame::MShadow ); - TQGridLayout * optionsFrameLayout = new TQGridLayout( optionsFrame, 1, 1, 11, 6, "optionsFrameLayout"); - - m_columns_1 = new TQComboBox( false, optionsFrame, "m_columns_1" ); - optionsFrameLayout->addWidget( m_columns_1, 2, 0 ); - - m_operatorValue_2 = new TQLineEdit( optionsFrame, "m_operatorValue_2" ); - optionsFrameLayout->addWidget( m_operatorValue_2, 3, 2 ); - - m_andBox = new TQRadioButton( optionsFrame, "m_andBox" ); - m_andBox->setText( i18n( "Match all of the following (AND)" ) ); - m_andBox->setChecked( true ); - - optionsFrameLayout->addMultiCellWidget( m_andBox, 0, 0, 0, 2 ); - - m_orBox = new TQRadioButton( optionsFrame, "m_orBox" ); - m_orBox->setText( i18n( "Match any of the following (OR)" ) ); - optionsFrameLayout->addMultiCellWidget( m_orBox, 1, 1, 0, 2 ); - - m_operatorValue_1 = new TQLineEdit( optionsFrame, "m_operatorValue" ); - optionsFrameLayout->addWidget( m_operatorValue_1, 2, 2 ); - - m_columns_2 = new TQComboBox( FALSE, optionsFrame, "m_columns_2" ); - optionsFrameLayout->addWidget( m_columns_2, 3, 0 ); - - m_operatorValue_3 = new TQLineEdit( optionsFrame, "m_operatorValue_3" ); - optionsFrameLayout->addWidget( m_operatorValue_3, 4, 2 ); - - m_operator_1 = new TQComboBox( FALSE, optionsFrame, "m_operator_1" ); - m_operator_1->insertItem( i18n( "equals" ) ); - m_operator_1->insertItem( i18n( "not equal" ) ); - m_operator_1->insertItem( i18n( "in" ) ); - m_operator_1->insertItem( i18n( "not in" ) ); - m_operator_1->insertItem( i18n( "like" ) ); - m_operator_1->insertItem( i18n( "greater" ) ); - m_operator_1->insertItem( i18n( "lesser" ) ); - m_operator_1->insertItem( i18n( "greater or equal" ) ); - m_operator_1->insertItem( i18n( "less or equal" ) ); - - optionsFrameLayout->addWidget( m_operator_1, 2, 1 ); - - m_operator_2 = new TQComboBox( FALSE, optionsFrame, "m_operator_2" ); - m_operator_2->insertItem( i18n( "equals" ) ); - m_operator_2->insertItem( i18n( "not equal" ) ); - m_operator_2->insertItem( i18n( "in" ) ); - m_operator_2->insertItem( i18n( "not in" ) ); - m_operator_2->insertItem( i18n( "like" ) ); - m_operator_2->insertItem( i18n( "greater" ) ); - m_operator_2->insertItem( i18n( "lesser" ) ); - - optionsFrameLayout->addWidget( m_operator_2, 3, 1 ); - - m_operator_3 = new TQComboBox( FALSE, optionsFrame, "m_operator_3" ); - m_operator_3->insertItem( i18n( "equals" ) ); - m_operator_3->insertItem( i18n( "not equal" ) ); - m_operator_3->insertItem( i18n( "in" ) ); - m_operator_3->insertItem( i18n( "not in" ) ); - m_operator_3->insertItem( i18n( "like" ) ); - m_operator_3->insertItem( i18n( "greater" ) ); - m_operator_3->insertItem( i18n( "lesser" ) ); - - optionsFrameLayout->addWidget( m_operator_3, 4, 1 ); - - m_columns_3 = new TQComboBox( false, optionsFrame, "m_columns_3" ); - - optionsFrameLayout->addWidget( m_columns_3, 4, 0 ); - - m_distinct = new TQCheckBox( optionsFrame, "m_distinct" ); - m_distinct->setText( i18n( "Distinct" ) ); - - optionsFrameLayout->addWidget( m_distinct, 7, 2 ); - - TQLabel * TextLabel19 = new TQLabel( optionsFrame, "TextLabel19" ); - TextLabel19->setText( i18n( "Sorted by" ) ); - optionsFrameLayout->addWidget( TextLabel19, 5, 0 ); - - m_columnsSort_1 = new TQComboBox( false, optionsFrame, "m_columnsSort_1" ); - optionsFrameLayout->addWidget( m_columnsSort_1, 5, 1 ); - - m_sortMode_1 = new TQComboBox( false, optionsFrame, "m_sortMode_1" ); - m_sortMode_1->insertItem( i18n( "Ascending" ) ); - m_sortMode_1->insertItem( i18n( "Descending" ) ); - optionsFrameLayout->addWidget( m_sortMode_1, 5, 2 ); - - TQLabel * TextLabel19_2 = new TQLabel( optionsFrame, "TextLabel19_2" ); - TextLabel19_2->setText( i18n( "Sorted by" ) ); - optionsFrameLayout->addWidget( TextLabel19_2, 6, 0 ); - - m_columnsSort_2 = new TQComboBox( false, optionsFrame, "m_columnsSort_2" ); - optionsFrameLayout->addWidget( m_columnsSort_2, 6, 1 ); - - m_sortMode_2 = new TQComboBox( false, optionsFrame, "m_sortMode_2" ); - m_sortMode_2->insertItem( i18n( "Ascending" ) ); - m_sortMode_2->insertItem( i18n( "Descending" ) ); - - optionsFrameLayout->addWidget( m_sortMode_2, 6, 2 ); - TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - optionsFrameLayout->addItem( spacer, 7, 1 ); - TQSpacerItem* spacer_2 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - optionsFrameLayout->addItem( spacer_2, 7, 0 ); - - m_optionsLayout->addWidget( optionsFrame, 0, 1 ); - - TQFrame * Frame17_4 = new TQFrame( m_options, "Frame17_4" ); - Frame17_4->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_4->sizePolicy().hasHeightForWidth() ) ); - Frame17_4->setMinimumSize( TQSize( 111, 0 ) ); - Frame17_4->setFrameShape( TQFrame::NoFrame ); - Frame17_4->setFrameShadow( TQFrame::Plain ); - - m_optionsLayout->addWidget( Frame17_4, 0, 0 ); - addPage( m_options, i18n( "Query Options" ) ); - - // result page - - m_result = new TQWidget( this, "m_result" ); - m_resultLayout = new TQGridLayout( m_result, 1, 1, 11, 6, "m_resultLayout"); - - TQFrame * Frame5_2_2_3 = new TQFrame( m_result, "Frame5_2_2_3" ); - Frame5_2_2_3->setFrameShape( TQFrame::MShape ); - Frame5_2_2_3->setFrameShadow( TQFrame::MShadow ); - TQGridLayout * Frame5_2_2_3Layout = new TQGridLayout( Frame5_2_2_3, 1, 1, 11, 6, "Frame5_2_2_3Layout"); - - TQLabel * TextLabel17 = new TQLabel( Frame5_2_2_3, "TextLabel17" ); - TextLabel17->setText( i18n( "SQL query:" ) ); - Frame5_2_2_3Layout->addWidget( TextLabel17, 0, 0 ); - - m_sqlQuery = new TQTextEdit( Frame5_2_2_3, "m_sqlQuery" ); - Frame5_2_2_3Layout->addWidget( m_sqlQuery, 1, 0 ); - - TQFrame * Frame12 = new TQFrame( Frame5_2_2_3, "Frame12" ); - Frame12->setFrameShape( TQFrame::StyledPanel ); - Frame12->setFrameShadow( TQFrame::Raised ); - TQGridLayout * Frame12Layout = new TQGridLayout( Frame12, 1, 1, 11, 6, "Frame12Layout"); - - m_startingRegion = new TQRadioButton( Frame12, "m_startingRegion" ); - m_startingRegion->setText( i18n( "Insert in region" ) ); - Frame12Layout->addWidget( m_startingRegion, 0, 0 ); - - m_cell = new TQLineEdit( Frame12, "m_cell" ); - Frame12Layout->addWidget( m_cell, 1, 1 ); - - m_region = new TQLineEdit( Frame12, "m_region" ); - Frame12Layout->addWidget( m_region, 0, 1 ); - - m_startingCell = new TQRadioButton( Frame12, "m_startingCell" ); - m_startingCell->setText( i18n( "Starting in cell" ) ); - m_startingCell->setChecked( TRUE ); - Frame12Layout->addWidget( m_startingCell, 1, 0 ); - - Frame5_2_2_3Layout->addWidget( Frame12, 2, 0 ); - m_resultLayout->addWidget( Frame5_2_2_3, 0, 1 ); - - TQFrame * Frame17_5 = new TQFrame( m_result, "Frame17_5" ); - Frame17_5->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_5->sizePolicy().hasHeightForWidth() ) ); - Frame17_5->setMinimumSize( TQSize( 111, 0 ) ); - Frame17_5->setFrameShape( TQFrame::NoFrame ); - Frame17_5->setFrameShadow( TQFrame::Plain ); - - m_resultLayout->addWidget( Frame17_5, 0, 0 ); - addPage( m_result, i18n( "Result" ) ); - - finishButton()->setEnabled(false); - - // signals and slots connections - connect( m_orBox, TQT_SIGNAL( clicked() ), this, TQT_SLOT( orBox_clicked() ) ); - connect( m_andBox, TQT_SIGNAL( clicked() ), this, TQT_SLOT( andBox_clicked() ) ); - connect( m_startingCell, TQT_SIGNAL( clicked() ), this, TQT_SLOT( startingCell_clicked() ) ); - connect( m_startingRegion, TQT_SIGNAL( clicked() ), this, TQT_SLOT( startingRegion_clicked() ) ); - connect( m_driver, TQT_SIGNAL( activated(int) ), this, TQT_SLOT( databaseDriverChanged(int) ) ); - connect( m_host, TQT_SIGNAL( textChanged(const TQString &) ), this, TQT_SLOT( databaseHostChanged(const TQString &) ) ); - connect( m_databaseName, TQT_SIGNAL( textChanged(const TQString &) ), this, TQT_SLOT( databaseNameChanged(const TQString &) ) ); - connect( m_sheetView, TQT_SIGNAL( contextMenuRequested( TQListViewItem *, const TQPoint &, int ) ), - this, TQT_SLOT( popupSheetViewMenu(TQListViewItem *, const TQPoint &, int ) ) ); - connect( m_sheetView, TQT_SIGNAL( clicked( TQListViewItem * ) ), this, TQT_SLOT( sheetViewClicked( TQListViewItem * ) ) ); - - TQStringList str = TQSqlDatabase::drivers(); - m_driver->insertItem(""); - m_driver->insertStringList( str ); - - - helpButton()->hide(); - setNextEnabled(m_database, false); - setNextEnabled(m_sheet, false); - setNextEnabled(m_columns, false); - setNextEnabled(m_options, false); - setNextEnabled(m_result, false); -} - -DatabaseDialog::~DatabaseDialog() -{ - // no need to delete child widgets, TQt does it all for us - if ( m_dbConnection ) - m_dbConnection->close(); -} - -void DatabaseDialog::switchPage( int id ) -{ - if ( id > eResult ) - --m_currentPage; - if ( id < eDatabase ) - ++m_currentPage; - - switch ( id ) - { - case eDatabase: - showPage(m_database); - break; - - case eSheets: - showPage(m_sheet); - break; - - case eColumns: - showPage(m_columns); - break; - - case eOptions: - showPage(m_options); - break; - - case eResult: - showPage(m_result); - break; - - default: - break; - } -} - -void DatabaseDialog::next() -{ - switch ( m_currentPage ) - { - case eDatabase: - if (!databaseDoNext()) - return; - break; - - case eSheets: - if (!sheetsDoNext()) - return; - break; - - case eColumns: - if (!columnsDoNext()) - return; - break; - - case eOptions: - if (!optionsDoNext()) - return; - break; - - case eResult: - // there is nothing to do here - break; - - default: - break; - } - - ++m_currentPage; - - switchPage( m_currentPage ); -} - -void DatabaseDialog::back() -{ - --m_currentPage; - - switchPage( m_currentPage ); -} - -void DatabaseDialog::accept() -{ - Sheet * sheet = m_pView->activeSheet(); - int top; - int left; - int width = -1; - int height = -1; - if ( m_startingRegion->isChecked() ) - { - Range range( m_region->text() ); - if ( range.isSheetKnown() ) - { - KMessageBox::error( this, i18n("You cannot specify a table here.") ); - m_region->setFocus(); - m_region->selectAll(); - return; - } - - range.setSheet(sheet); - - if ( !range.isValid() ) - { - KMessageBox::error( this, i18n("You have to specify a valid region.") ); - m_region->setFocus(); - m_region->selectAll(); - return; - } - - top = range.range().top(); - left = range.range().left(); - width = range.range().width(); - height = range.range().height(); - } - else - { - Point point( m_cell->text() ); - if ( point.isSheetKnown() ) - { - KMessageBox::error( this, i18n("You cannot specify a table here.") ); - m_cell->setFocus(); - m_cell->selectAll(); - return; - } - point.setSheet(sheet); - // if ( point.pos.x() < 1 || point.pos.y() < 1 ) - if ( !point.isValid() ) - { - KMessageBox::error( this, i18n("You have to specify a valid cell.") ); - m_cell->setFocus(); - m_cell->selectAll(); - return; - } - top = point.pos().y(); - left = point.pos().x(); - } - - int i; - TQString queryStr; - TQString tmp = m_sqlQuery->text(); - for ( i = 0; i < (int) tmp.length(); ++i ) - { - if ( tmp[i] != '\n' ) - queryStr += tmp[i]; - else - queryStr += " "; - } - - Cell * cell; - TQSqlQuery query( TQString(), m_dbConnection ); - - // Check the whole query for SQL that might modify database. - // If there is an update command, then it must be at the start of the string, - // or after an open bracket (e.g. nested update) or a space to be valid SQL. - // An update command must also be followed by a space, or it would be parsed - // as an identifier. - // For sanity, also check that there is a SELECT - TQRegExp couldModifyDB( "(^|[( \\s])(UPDATE|DELETE|INSERT|CREATE) ", false /* cs */ ); - TQRegExp couldQueryDB( "(^|[( \\s])(SELECT) ", false /* cs */ ); - - if (couldModifyDB.search( queryStr ) != -1 || couldQueryDB.search ( queryStr ) == -1 ) - { - KMessageBox::error( this, i18n("You are not allowed to change data in the database.") ); - m_sqlQuery->setFocus(); - return; - } - - if ( !query.exec( queryStr ) ) - { - KMessageBox::error( this, i18n( "Executing query failed." ) ); - m_sqlQuery->setFocus(); - return; - } - - if ( query.size() == 0 ) - { - KMessageBox::error( this, i18n( "You did not get any results with this query." ) ); - m_sqlQuery->setFocus(); - return; - } - - int y = 0; - int count = m_columns_1->count(); - if ( width != -1 ) - { - if ( count > width ) - count = width; - } - - if ( height == -1 ) - { - height = 0; - if ( query.first() ) - { - if ( query.isValid() ) - ++height; - } - while ( query.next() ) - { - if ( query.isValid() ) - ++height; - } - } - - if ( !m_pView->doc()->undoLocked() ) - { - TQRect r(left, top, count, height); - UndoInsertData * undo = new UndoInsertData( m_pView->doc(), sheet, r ); - m_pView->doc()->addCommand( undo ); - } - - m_pView->doc()->emitBeginOperation(); - - if ( query.first() ) - { - if ( query.isValid() ) - { - for ( i = 0; i < count; ++i ) - { - cell = sheet->nonDefaultCell( left + i, top + y ); - cell->setCellText( query.value( i ).toString() ); - } - ++y; - } - } - - if ( y != height ) - { - while ( query.next() ) - { - if ( !query.isValid() ) - continue; - - for ( i = 0; i < count; ++i ) - { - cell = sheet->nonDefaultCell( left + i, top + y ); - cell->setCellText( query.value( i ).toString() ); - } - ++y; - - if ( y == height ) - break; - } - } - - m_pView->slotUpdateView( sheet ); - KWizard::accept(); -} - -bool DatabaseDialog::databaseDoNext() -{ - m_dbConnection = TQSqlDatabase::addDatabase( m_driver->currentText() ); - - if ( m_dbConnection ) - { - m_dbConnection->setDatabaseName( m_databaseName->text() ); - m_dbConnection->setHostName( m_host->text() ); - - if ( !m_username->text().isEmpty() ) - m_dbConnection->setUserName( m_username->text() ); - - if ( !m_password->text().isEmpty() ) - m_dbConnection->setPassword( m_password->text() ); - - if ( !m_port->text().isEmpty() ) - { - bool ok = false; - int port = m_port->text().toInt( &ok ); - if (!ok) - { - KMessageBox::error( this, i18n("The port must be a number") ); - return false; - } - m_dbConnection->setPort( port ); - } - - m_databasetStatus->setText( i18n("Connecting to database...") ); - if ( m_dbConnection->open() ) - { - m_databasetStatus->setText( i18n("Connected. Retrieving table information...") ); - TQStringList sheetList( m_dbConnection->tables() ); - - if ( sheetList.isEmpty() ) - { - KMessageBox::error( this, i18n("This database contains no tables") ); - return false; - } - - unsigned int i; - m_sheetView->clear(); - - for ( i = 0; i < sheetList.size(); ++i ) - { - TQCheckListItem * item = new TQCheckListItem( m_sheetView, sheetList[i], - TQCheckListItem::CheckBox ); - item->setOn(false); - m_sheetView->insertItem( item ); - } - - m_sheetView->setEnabled( true ); - m_databasetStatus->setText( " " ); - } - else - { - TQSqlError error = m_dbConnection->lastError(); - TQString errorMsg; - TQString err1 = error.driverText(); - TQString err2 = error.databaseText(); - if ( !err1.isEmpty() ) - { - errorMsg.append( error.driverText() ); - errorMsg.append( "\n" ); - } - if ( !err2.isEmpty() && err1 != err2) - { - errorMsg.append( error.databaseText() ); - errorMsg.append( "\n" ); - } - m_databasetStatus->setText( " " ); - - KMessageBox::error( this, errorMsg ); - return false; - } - } - else - { - KMessageBox::error( this, i18n("Driver could not be loaded") ); - m_databasetStatus->setText( " " ); - return false; - } - setNextEnabled(m_sheet, true); - - return true; -} - -bool DatabaseDialog::sheetsDoNext() -{ - m_databasetStatus->setText( i18n("Retrieving meta data of tables...") ); - TQStringList sheets; - - for (TQListViewItem * item = (TQCheckListItem *) m_sheetView->firstChild(); item; item = item->nextSibling()) - { - if (((TQCheckListItem * ) item)->isOn()) - { - sheets.append(((TQCheckListItem * ) item)->text()); - } - } - - if (sheets.empty()) - { - KMessageBox::error( this, i18n("You have to select at least one table.") ); - return false; - } - - m_columnView->clear(); - TQSqlRecord info; - TQCheckListItem * item; - for (int i = 0; i < (int) sheets.size(); ++i) - { - info = m_dbConnection->record( sheets[i] ); - for (int j = 0; j < (int) info.count(); ++j) - { - TQString name = info.fieldName(j); - item = new TQCheckListItem( m_columnView, name, - TQCheckListItem::CheckBox ); - item->setOn(false); - m_columnView->insertItem( item ); - item->setText( 1, sheets[i] ); - TQSqlField * field = info.field(name); - item->setText( 2, TQVariant::typeToName(field->type()) ); - } - } - m_columnView->setSorting(1, true); - m_columnView->sort(); - m_columnView->setSorting( -1 ); - - setNextEnabled(m_columns, true); - - return true; -} - -bool DatabaseDialog::columnsDoNext() -{ - TQStringList columns; - for (TQListViewItem * item = m_columnView->firstChild(); item; item = item->nextSibling()) - { - if (((TQCheckListItem * ) item)->isOn()) - { - columns.append( item->text(1) + "." + ((TQCheckListItem * ) item)->text()); - } - } - - if (columns.empty()) - { - KMessageBox::error( this, i18n("You have to select at least one column.") ); - return false; - } - - m_columns_1->clear(); - m_columns_2->clear(); - m_columns_3->clear(); - m_columns_1->insertStringList(columns); - m_columns_2->insertStringList(columns); - m_columns_3->insertStringList(columns); - m_columnsSort_1->clear(); - m_columnsSort_2->clear(); - m_columnsSort_1->insertItem( i18n("None") ); - m_columnsSort_2->insertItem( i18n("None") ); - m_columnsSort_1->insertStringList(columns); - m_columnsSort_2->insertStringList(columns); - - setNextEnabled(m_options, true); - - return true; -} - - -TQString DatabaseDialog::getWhereCondition(TQString const & column, - TQString const & value, - int op) -{ - TQString wherePart; - - switch( op ) - { - case 0: - wherePart += column; - wherePart += " = "; - break; - case 1: - wherePart += "NOT "; - wherePart += column; - wherePart += " = "; - break; - case 2: - wherePart += column; - wherePart += " IN "; - break; - case 3: - wherePart += "NOT "; - wherePart += column; - wherePart += " IN "; - break; - case 4: - wherePart += column; - wherePart += " LIKE "; - break; - case 5: - wherePart += column; - wherePart += " > "; - break; - case 6: - wherePart += column; - wherePart += " < "; - break; - case 7: - wherePart += column; - wherePart += " >= "; - break; - case 8: - wherePart += column; - wherePart += " <= "; - break; - } - - if ( op != 2 && op != 3 ) - { - TQString val; - bool ok = false; - value.toDouble(&ok); - - if ( !ok ) - { - if (value[0] != '\'') - val = "'"; - - val += value; - - if (value[value.length() - 1] != '\'') - val += "'"; - } - else - val = value; - - wherePart += val; - } - else // "in" & "not in" - { - TQString val; - if (value[0] != '(') - val = "("; - val += value; - if ( value[value.length() - 1] != ')' ) - val += ")"; - wherePart += val; - } - - return wherePart; -} - -TQString DatabaseDialog::exchangeWildcards(TQString const & value) -{ - TQString str(value); - int p = str.find('*'); - while ( p > -1 ) - { - str = str.replace( p, 1, "%" ); - p = str.find('*'); - } - - p = str.find('?'); - while ( p > -1 ) - { - str = str.replace( p, 1, "_" ); - p = str.find('?'); - } - return str; -} - -bool DatabaseDialog::optionsDoNext() -{ - if ( m_operator_1->currentItem() == 4 ) - { - if ( ( m_operatorValue_1->text().find('*') != -1 ) - || ( m_operatorValue_1->text().find('?') != -1 ) ) - { - // xgettext: no-c-format - int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " - "The proper replacements are '%' or '_'. Do you want to replace them?") ); - - if ( res == KMessageBox::Yes ) - m_operatorValue_1->setText(exchangeWildcards(m_operatorValue_1->text())); - } - } - - if ( m_operator_2->currentItem() == 4 ) - { - if ( ( m_operatorValue_2->text().find('*') != -1 ) - || ( m_operatorValue_2->text().find('?') != -1 ) ) - { - // xgettext: no-c-format - int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " - "The proper replacements are '%' or '_'. Do you want to replace them?") ); - - if ( res == KMessageBox::Yes ) - m_operatorValue_2->setText(exchangeWildcards(m_operatorValue_2->text())); - } - } - - if ( m_operator_3->currentItem() == 4 ) - { - if ( ( m_operatorValue_3->text().find('*') != -1 ) - || ( m_operatorValue_3->text().find('?') != -1 ) ) - { - // xgettext: no-c-format - int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " - "The proper replacements are '%' or '_'. Do you want to replace them?") ); - - if ( res == KMessageBox::Yes ) - m_operatorValue_3->setText(exchangeWildcards(m_operatorValue_3->text())); - } - } - - TQString query("SELECT "); - - if (m_distinct->isChecked()) - query += "DISTINCT "; - - int i; - int l = m_columns_1->count() - 1; - for ( i = 0; i < l; ++i ) - { - query += m_columns_1->text( i ); - query += ", "; - } - query += m_columns_1->text( l ); - - query += "\nFROM "; - - TQListViewItem * item = (TQCheckListItem *) m_sheetView->firstChild(); - bool b = false; - while ( item ) - { - if (((TQCheckListItem * ) item)->isOn()) - { - if ( b ) - query += ", "; - b = true; - query += ((TQCheckListItem * ) item)->text(); - } - item = item->nextSibling(); - } - - if ( ( !m_operatorValue_1->text().isEmpty() ) - || ( !m_operatorValue_2->text().isEmpty() ) - || ( !m_operatorValue_3->text().isEmpty() ) ) - query += "\nWHERE "; - - bool added = false; - if ( !m_operatorValue_1->text().isEmpty() ) - { - query += getWhereCondition(m_columns_1->currentText(), - m_operatorValue_1->text(), - m_operator_1->currentItem()); - added = true; - } - - if ( !m_operatorValue_2->text().isEmpty() ) - { - if (added) - query += ( m_andBox->isChecked() ? " AND " : " OR " ); - - query += getWhereCondition(m_columns_2->currentText(), - m_operatorValue_2->text(), - m_operator_2->currentItem()); - added = true; - } - - if ( !m_operatorValue_3->text().isEmpty() ) - { - if (added) - query += ( m_andBox->isChecked() ? " AND " : " OR " ); - - query += getWhereCondition(m_columns_3->currentText(), - m_operatorValue_3->text(), - m_operator_3->currentItem()); - } - - if ( (m_columnsSort_1->currentItem() != 0) - || (m_columnsSort_2->currentItem() != 0) ) - { - query += "\nORDER BY "; - bool added = false; - if ( m_columnsSort_1->currentItem() != 0 ) - { - added = true; - query += m_columnsSort_1->currentText(); - if ( m_sortMode_1->currentItem() == 1 ) - query += " DESC "; - } - - if ( m_columnsSort_2->currentItem() != 0 ) - { - if ( added ) - query += ", "; - - query += m_columnsSort_2->currentText(); - if ( m_sortMode_2->currentItem() == 1 ) - query += " DESC "; - } - } - - m_sqlQuery->setText(query); - m_cell->setText(Cell::name( m_targetRect.left(), m_targetRect.top() ) ); - m_region->setText(util_rangeName( m_targetRect ) ); - - setFinishEnabled( m_result, true ); - - return true; -} - -void DatabaseDialog::orBox_clicked() -{ - m_andBox->setChecked( false ); - m_orBox->setChecked( true ); -} - -void DatabaseDialog::andBox_clicked() -{ - m_andBox->setChecked( true ); - m_orBox->setChecked( false ); -} - -void DatabaseDialog::startingCell_clicked() -{ - m_startingCell->setChecked( true ); - m_startingRegion->setChecked( false ); -} - -void DatabaseDialog::startingRegion_clicked() -{ - m_startingCell->setChecked( false ); - m_startingRegion->setChecked( true ); -} - -void DatabaseDialog::connectButton_clicked() -{ - tqWarning( "DatabaseDialog::connectButton_clicked(): Not implemented yet!" ); -} - -void DatabaseDialog::databaseNameChanged(const TQString & s) -{ - if ( !m_driver->currentText().isEmpty() && !s.isEmpty() - && !m_host->text().isEmpty() ) - setNextEnabled(m_database, true); - else - setNextEnabled(m_database, false); -} - -void DatabaseDialog::databaseHostChanged(const TQString & s) -{ - if ( !m_driver->currentText().isEmpty() && !s.isEmpty() - && !m_databaseName->text().isEmpty() ) - setNextEnabled(m_database, true); - else - setNextEnabled(m_database, false); -} - -void DatabaseDialog::databaseDriverChanged(int index) -{ - if ( index > 0 && !m_host->text().isEmpty() - && !m_databaseName->text().isEmpty() ) - setNextEnabled(m_database, true); - else - setNextEnabled(m_database, false); -} - -void DatabaseDialog::popupSheetViewMenu( TQListViewItem *, const TQPoint &, int ) -{ - // TODO: popup menu with "Select All", "Inverse selection", "remove selection" -} - -void DatabaseDialog::sheetViewClicked( TQListViewItem * ) -{ -// if ( item ) -// { -// TQCheckListItem * i = (TQCheckListItem *) item; -// i->setOn( !i->isOn() ); -// } -// kdDebug() << "clicked" << endl; -} - - -#include "kspread_dlg_database.moc" - -#endif // TQT_NO_SQL diff --git a/kspread/dialogs/kspread_dlg_database.cpp b/kspread/dialogs/kspread_dlg_database.cpp new file mode 100644 index 00000000..34e680cd --- /dev/null +++ b/kspread/dialogs/kspread_dlg_database.cpp @@ -0,0 +1,1179 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_cell.h" +#include "kspread_dlg_database.h" +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_util.h" +#include "kspread_undo.h" +#include "kspread_view.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + +#ifndef TQT_NO_SQL + +/******************************************************** + * Database wizard * + ********************************************************/ + +DatabaseDialog::DatabaseDialog( View * parent, TQRect const & rect, const char * name, bool modal, WFlags fl ) + : KWizard( (TQWidget *) parent, name, modal, fl ), + m_currentPage( eDatabase ), + m_pView( parent ), + m_targetRect( rect ), + m_dbConnection( 0L ) +{ + if ( !name ) + setName( "DatabaseDialog" ); + + setCaption( i18n( "Insert Data From Database" ) ); + + // database page + + m_database = new TQWidget( this, "m_database" ); + m_databaseLayout = new TQGridLayout( m_database, 1, 1, -1, -1, "m_databaseLayout"); + + TQFrame * Frame5 = new TQFrame( m_database, "Frame5" ); + Frame5->setFrameShape( TQFrame::MShape ); + Frame5->setFrameShadow( TQFrame::MShadow ); + TQVBoxLayout * Frame5Layout = new TQVBoxLayout( Frame5, 11, 6, "Frame5Layout"); + + + TQFrame * Frame16 = new TQFrame( Frame5, "Frame16" ); + Frame16->setFrameShape( TQFrame::NoFrame ); + Frame16->setFrameShadow( TQFrame::Plain ); + TQGridLayout * Frame16Layout = new TQGridLayout( Frame16, 1, 1, 11, 7, "Frame16Layout"); + + m_Type = new TQLabel( Frame16, "m_Type" ); + m_Type->setText( i18n( "Type:" ) ); + + Frame16Layout->addWidget( m_Type, 0, 0 ); + + TQLabel * TextLabel4 = new TQLabel( Frame16, "TextLabel4" ); + TextLabel4->setText( i18n( "User name:\n" + "(if necessary)" ) ); + Frame16Layout->addWidget( TextLabel4, 4, 0 ); + + TQLabel * TextLabel2 = new TQLabel( Frame16, "TextLabel2" ); + TextLabel2->setText( i18n( "Host:" ) ); + Frame16Layout->addWidget( TextLabel2, 2, 0 ); + + m_driver = new TQComboBox( FALSE, Frame16, "m_driver" ); + Frame16Layout->addWidget( m_driver, 0, 1 ); + + m_username = new TQLineEdit( Frame16, "m_username" ); + Frame16Layout->addWidget( m_username, 4, 1 ); + + m_host = new TQLineEdit( Frame16, "m_host" ); + m_host->setText("localhost"); + Frame16Layout->addWidget( m_host, 2, 1 ); + + TQLabel * TextLabel3 = new TQLabel( Frame16, "TextLabel3" ); + TextLabel3->setText( i18n( "Port:\n(if necessary)") ); + Frame16Layout->addWidget( TextLabel3, 3, 0 ); + + m_password = new TQLineEdit( Frame16, "m_password" ); + m_password->setEchoMode( TQLineEdit::Password ); + Frame16Layout->addWidget( m_password, 5, 1 ); + + m_port = new TQLineEdit( Frame16, "m_port" ); + m_port->setValidator( new KIntValidator( m_port ) ); + Frame16Layout->addWidget( m_port, 3, 1 ); + + TQLabel * dbName = new TQLabel( Frame16, "dbName" ); + dbName->setText( i18n( "Database name: ") ); + Frame16Layout->addWidget( dbName, 1, 0 ); + + m_databaseName = new TQLineEdit( Frame16, "m_databaseName" ); + Frame16Layout->addWidget( m_databaseName, 1, 1 ); + + TQLabel * TextLabel5 = new TQLabel( Frame16, "TextLabel5" ); + TextLabel5->setText( i18n( "Password:\n" + "(if necessary)" ) ); + Frame16Layout->addWidget( TextLabel5, 5, 0 ); + Frame5Layout->addWidget( Frame16 ); + + m_databasetStatus = new TQLabel( Frame5, "m_databasetStatus" ); + m_databasetStatus->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)5, 0, 0, m_databasetStatus->sizePolicy().hasHeightForWidth() ) ); + m_databasetStatus->setMaximumSize( TQSize( 32767, 30 ) ); + m_databasetStatus->setText( " " ); + Frame5Layout->addWidget( m_databasetStatus ); + + m_databaseLayout->addWidget( Frame5, 0, 1 ); + + TQFrame * Frame17 = new TQFrame( m_database, "Frame17" ); + Frame17->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17->sizePolicy().hasHeightForWidth() ) ); + Frame17->setMinimumSize( TQSize( 111, 0 ) ); + Frame17->setFrameShape( TQFrame::NoFrame ); + Frame17->setFrameShadow( TQFrame::Plain ); + + m_databaseLayout->addWidget( Frame17, 0, 0 ); + addPage( m_database, i18n( "Database" ) ); + + // new page + + m_sheet = new TQWidget( this, "m_table" ); + m_sheetLayout = new TQGridLayout( m_sheet, 1, 1, 11, 6, "m_tableLayout"); + + TQFrame * Frame5_2 = new TQFrame( m_sheet, "Frame5_2" ); + Frame5_2->setFrameShape( TQFrame::MShape ); + Frame5_2->setFrameShadow( TQFrame::MShadow ); + TQGridLayout * Frame5_2Layout = new TQGridLayout( Frame5_2, 1, 1, 11, 6, "Frame5_2Layout"); + + TQHBoxLayout * Layout21 = new TQHBoxLayout( 0, 0, 6, "Layout21"); + + // TQLabel * TextLabel12_2 = new TQLabel( Frame5_2, "TextLabel12_2" ); + // TextLabel12_2->setText( i18n( "Database:" ) ); + // Layout21->addWidget( TextLabel12_2 ); + + // m_databaseList = new TQComboBox( FALSE, Frame5_2, "m_databaseList" ); + // Layout21->addWidget( m_databaseList ); + + // m_connectButton = new KPushButton( Frame5_2, "m_connectButton" ); + // m_connectButton->setText( i18n( "&Connect" ) ); + // Layout21->addWidget( m_connectButton ); + + Frame5_2Layout->addLayout( Layout21, 0, 0 ); + + m_sheetStatus = new TQLabel( Frame5_2, "m_tableStatus" ); + m_sheetStatus->setText( " " ); + Frame5_2Layout->addWidget( m_sheetStatus, 3, 0 ); + + m_SelectSheetLabel = new TQLabel( Frame5_2, "m_SelectSheetLabel" ); + m_SelectSheetLabel->setText( i18n( "Select tables:" ) ); + Frame5_2Layout->addWidget( m_SelectSheetLabel, 1, 0 ); + + m_sheetView = new TDEListView( Frame5_2, "m_tableView" ); + m_sheetView->addColumn( i18n( "Sheet" ) ); + m_sheetView->setRootIsDecorated( FALSE ); + + Frame5_2Layout->addWidget( m_sheetView, 2, 0 ); + + m_sheetLayout->addWidget( Frame5_2, 0, 1 ); + + TQFrame * Frame17_2 = new TQFrame( m_sheet, "Frame17_2" ); + Frame17_2->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_2->sizePolicy().hasHeightForWidth() ) ); + Frame17_2->setMinimumSize( TQSize( 111, 0 ) ); + Frame17_2->setFrameShape( TQFrame::NoFrame ); + Frame17_2->setFrameShadow( TQFrame::Plain ); + + m_sheetLayout->addWidget( Frame17_2, 0, 0 ); + addPage( m_sheet, i18n( "Sheets" ) ); + + m_columns = new TQWidget( this, "m_columns" ); + m_columnsLayout = new TQGridLayout( m_columns, 1, 1, 11, 6, "m_columnsLayout"); + + TQFrame * Frame5_2_2 = new TQFrame( m_columns, "Frame5_2_2" ); + Frame5_2_2->setFrameShape( TQFrame::MShape ); + Frame5_2_2->setFrameShadow( TQFrame::MShadow ); + TQGridLayout * Frame5_2_2Layout = new TQGridLayout( Frame5_2_2, 1, 1, 11, 6, "Frame5_2_2Layout"); + + TQLabel * TextLabel11_2 = new TQLabel( Frame5_2_2, "TextLabel11_2" ); + TextLabel11_2->setText( i18n( "Select columns:" ) ); + + Frame5_2_2Layout->addWidget( TextLabel11_2, 0, 0 ); + + m_columnView = new TDEListView( Frame5_2_2, "m_columnView" ); + m_columnView->addColumn( i18n( "Column" ) ); + m_columnView->addColumn( i18n( "Sheet" ) ); + m_columnView->addColumn( i18n( "Data Type" ) ); + m_columnView->setRootIsDecorated( FALSE ); + + Frame5_2_2Layout->addWidget( m_columnView, 1, 0 ); + + m_columnsStatus = new TQLabel( Frame5_2_2, "m_columnsStatus" ); + m_columnsStatus->setText( " " ); + Frame5_2_2Layout->addWidget( m_columnsStatus, 2, 0 ); + + m_columnsLayout->addWidget( Frame5_2_2, 0, 1 ); + + TQFrame * Frame17_3 = new TQFrame( m_columns, "Frame17_3" ); + Frame17_3->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_3->sizePolicy().hasHeightForWidth() ) ); + Frame17_3->setMinimumSize( TQSize( 111, 0 ) ); + Frame17_3->setFrameShape( TQFrame::NoFrame ); + Frame17_3->setFrameShadow( TQFrame::Plain ); + + m_columnsLayout->addWidget( Frame17_3, 0, 0 ); + addPage( m_columns, i18n( "Columns" ) ); + + // options page + + m_options = new TQWidget( this, "m_options" ); + m_optionsLayout = new TQGridLayout( m_options, 1, 1, 11, 6, "m_optionsLayout"); + + TQFrame * optionsFrame = new TQFrame( m_options, "optionsFrame" ); + optionsFrame->setFrameShape( TQFrame::MShape ); + optionsFrame->setFrameShadow( TQFrame::MShadow ); + TQGridLayout * optionsFrameLayout = new TQGridLayout( optionsFrame, 1, 1, 11, 6, "optionsFrameLayout"); + + m_columns_1 = new TQComboBox( false, optionsFrame, "m_columns_1" ); + optionsFrameLayout->addWidget( m_columns_1, 2, 0 ); + + m_operatorValue_2 = new TQLineEdit( optionsFrame, "m_operatorValue_2" ); + optionsFrameLayout->addWidget( m_operatorValue_2, 3, 2 ); + + m_andBox = new TQRadioButton( optionsFrame, "m_andBox" ); + m_andBox->setText( i18n( "Match all of the following (AND)" ) ); + m_andBox->setChecked( true ); + + optionsFrameLayout->addMultiCellWidget( m_andBox, 0, 0, 0, 2 ); + + m_orBox = new TQRadioButton( optionsFrame, "m_orBox" ); + m_orBox->setText( i18n( "Match any of the following (OR)" ) ); + optionsFrameLayout->addMultiCellWidget( m_orBox, 1, 1, 0, 2 ); + + m_operatorValue_1 = new TQLineEdit( optionsFrame, "m_operatorValue" ); + optionsFrameLayout->addWidget( m_operatorValue_1, 2, 2 ); + + m_columns_2 = new TQComboBox( FALSE, optionsFrame, "m_columns_2" ); + optionsFrameLayout->addWidget( m_columns_2, 3, 0 ); + + m_operatorValue_3 = new TQLineEdit( optionsFrame, "m_operatorValue_3" ); + optionsFrameLayout->addWidget( m_operatorValue_3, 4, 2 ); + + m_operator_1 = new TQComboBox( FALSE, optionsFrame, "m_operator_1" ); + m_operator_1->insertItem( i18n( "equals" ) ); + m_operator_1->insertItem( i18n( "not equal" ) ); + m_operator_1->insertItem( i18n( "in" ) ); + m_operator_1->insertItem( i18n( "not in" ) ); + m_operator_1->insertItem( i18n( "like" ) ); + m_operator_1->insertItem( i18n( "greater" ) ); + m_operator_1->insertItem( i18n( "lesser" ) ); + m_operator_1->insertItem( i18n( "greater or equal" ) ); + m_operator_1->insertItem( i18n( "less or equal" ) ); + + optionsFrameLayout->addWidget( m_operator_1, 2, 1 ); + + m_operator_2 = new TQComboBox( FALSE, optionsFrame, "m_operator_2" ); + m_operator_2->insertItem( i18n( "equals" ) ); + m_operator_2->insertItem( i18n( "not equal" ) ); + m_operator_2->insertItem( i18n( "in" ) ); + m_operator_2->insertItem( i18n( "not in" ) ); + m_operator_2->insertItem( i18n( "like" ) ); + m_operator_2->insertItem( i18n( "greater" ) ); + m_operator_2->insertItem( i18n( "lesser" ) ); + + optionsFrameLayout->addWidget( m_operator_2, 3, 1 ); + + m_operator_3 = new TQComboBox( FALSE, optionsFrame, "m_operator_3" ); + m_operator_3->insertItem( i18n( "equals" ) ); + m_operator_3->insertItem( i18n( "not equal" ) ); + m_operator_3->insertItem( i18n( "in" ) ); + m_operator_3->insertItem( i18n( "not in" ) ); + m_operator_3->insertItem( i18n( "like" ) ); + m_operator_3->insertItem( i18n( "greater" ) ); + m_operator_3->insertItem( i18n( "lesser" ) ); + + optionsFrameLayout->addWidget( m_operator_3, 4, 1 ); + + m_columns_3 = new TQComboBox( false, optionsFrame, "m_columns_3" ); + + optionsFrameLayout->addWidget( m_columns_3, 4, 0 ); + + m_distinct = new TQCheckBox( optionsFrame, "m_distinct" ); + m_distinct->setText( i18n( "Distinct" ) ); + + optionsFrameLayout->addWidget( m_distinct, 7, 2 ); + + TQLabel * TextLabel19 = new TQLabel( optionsFrame, "TextLabel19" ); + TextLabel19->setText( i18n( "Sorted by" ) ); + optionsFrameLayout->addWidget( TextLabel19, 5, 0 ); + + m_columnsSort_1 = new TQComboBox( false, optionsFrame, "m_columnsSort_1" ); + optionsFrameLayout->addWidget( m_columnsSort_1, 5, 1 ); + + m_sortMode_1 = new TQComboBox( false, optionsFrame, "m_sortMode_1" ); + m_sortMode_1->insertItem( i18n( "Ascending" ) ); + m_sortMode_1->insertItem( i18n( "Descending" ) ); + optionsFrameLayout->addWidget( m_sortMode_1, 5, 2 ); + + TQLabel * TextLabel19_2 = new TQLabel( optionsFrame, "TextLabel19_2" ); + TextLabel19_2->setText( i18n( "Sorted by" ) ); + optionsFrameLayout->addWidget( TextLabel19_2, 6, 0 ); + + m_columnsSort_2 = new TQComboBox( false, optionsFrame, "m_columnsSort_2" ); + optionsFrameLayout->addWidget( m_columnsSort_2, 6, 1 ); + + m_sortMode_2 = new TQComboBox( false, optionsFrame, "m_sortMode_2" ); + m_sortMode_2->insertItem( i18n( "Ascending" ) ); + m_sortMode_2->insertItem( i18n( "Descending" ) ); + + optionsFrameLayout->addWidget( m_sortMode_2, 6, 2 ); + TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + optionsFrameLayout->addItem( spacer, 7, 1 ); + TQSpacerItem* spacer_2 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + optionsFrameLayout->addItem( spacer_2, 7, 0 ); + + m_optionsLayout->addWidget( optionsFrame, 0, 1 ); + + TQFrame * Frame17_4 = new TQFrame( m_options, "Frame17_4" ); + Frame17_4->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_4->sizePolicy().hasHeightForWidth() ) ); + Frame17_4->setMinimumSize( TQSize( 111, 0 ) ); + Frame17_4->setFrameShape( TQFrame::NoFrame ); + Frame17_4->setFrameShadow( TQFrame::Plain ); + + m_optionsLayout->addWidget( Frame17_4, 0, 0 ); + addPage( m_options, i18n( "Query Options" ) ); + + // result page + + m_result = new TQWidget( this, "m_result" ); + m_resultLayout = new TQGridLayout( m_result, 1, 1, 11, 6, "m_resultLayout"); + + TQFrame * Frame5_2_2_3 = new TQFrame( m_result, "Frame5_2_2_3" ); + Frame5_2_2_3->setFrameShape( TQFrame::MShape ); + Frame5_2_2_3->setFrameShadow( TQFrame::MShadow ); + TQGridLayout * Frame5_2_2_3Layout = new TQGridLayout( Frame5_2_2_3, 1, 1, 11, 6, "Frame5_2_2_3Layout"); + + TQLabel * TextLabel17 = new TQLabel( Frame5_2_2_3, "TextLabel17" ); + TextLabel17->setText( i18n( "SQL query:" ) ); + Frame5_2_2_3Layout->addWidget( TextLabel17, 0, 0 ); + + m_sqlQuery = new TQTextEdit( Frame5_2_2_3, "m_sqlQuery" ); + Frame5_2_2_3Layout->addWidget( m_sqlQuery, 1, 0 ); + + TQFrame * Frame12 = new TQFrame( Frame5_2_2_3, "Frame12" ); + Frame12->setFrameShape( TQFrame::StyledPanel ); + Frame12->setFrameShadow( TQFrame::Raised ); + TQGridLayout * Frame12Layout = new TQGridLayout( Frame12, 1, 1, 11, 6, "Frame12Layout"); + + m_startingRegion = new TQRadioButton( Frame12, "m_startingRegion" ); + m_startingRegion->setText( i18n( "Insert in region" ) ); + Frame12Layout->addWidget( m_startingRegion, 0, 0 ); + + m_cell = new TQLineEdit( Frame12, "m_cell" ); + Frame12Layout->addWidget( m_cell, 1, 1 ); + + m_region = new TQLineEdit( Frame12, "m_region" ); + Frame12Layout->addWidget( m_region, 0, 1 ); + + m_startingCell = new TQRadioButton( Frame12, "m_startingCell" ); + m_startingCell->setText( i18n( "Starting in cell" ) ); + m_startingCell->setChecked( TRUE ); + Frame12Layout->addWidget( m_startingCell, 1, 0 ); + + Frame5_2_2_3Layout->addWidget( Frame12, 2, 0 ); + m_resultLayout->addWidget( Frame5_2_2_3, 0, 1 ); + + TQFrame * Frame17_5 = new TQFrame( m_result, "Frame17_5" ); + Frame17_5->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)7, 0, 0, Frame17_5->sizePolicy().hasHeightForWidth() ) ); + Frame17_5->setMinimumSize( TQSize( 111, 0 ) ); + Frame17_5->setFrameShape( TQFrame::NoFrame ); + Frame17_5->setFrameShadow( TQFrame::Plain ); + + m_resultLayout->addWidget( Frame17_5, 0, 0 ); + addPage( m_result, i18n( "Result" ) ); + + finishButton()->setEnabled(false); + + // signals and slots connections + connect( m_orBox, TQT_SIGNAL( clicked() ), this, TQT_SLOT( orBox_clicked() ) ); + connect( m_andBox, TQT_SIGNAL( clicked() ), this, TQT_SLOT( andBox_clicked() ) ); + connect( m_startingCell, TQT_SIGNAL( clicked() ), this, TQT_SLOT( startingCell_clicked() ) ); + connect( m_startingRegion, TQT_SIGNAL( clicked() ), this, TQT_SLOT( startingRegion_clicked() ) ); + connect( m_driver, TQT_SIGNAL( activated(int) ), this, TQT_SLOT( databaseDriverChanged(int) ) ); + connect( m_host, TQT_SIGNAL( textChanged(const TQString &) ), this, TQT_SLOT( databaseHostChanged(const TQString &) ) ); + connect( m_databaseName, TQT_SIGNAL( textChanged(const TQString &) ), this, TQT_SLOT( databaseNameChanged(const TQString &) ) ); + connect( m_sheetView, TQT_SIGNAL( contextMenuRequested( TQListViewItem *, const TQPoint &, int ) ), + this, TQT_SLOT( popupSheetViewMenu(TQListViewItem *, const TQPoint &, int ) ) ); + connect( m_sheetView, TQT_SIGNAL( clicked( TQListViewItem * ) ), this, TQT_SLOT( sheetViewClicked( TQListViewItem * ) ) ); + + TQStringList str = TQSqlDatabase::drivers(); + m_driver->insertItem(""); + m_driver->insertStringList( str ); + + + helpButton()->hide(); + setNextEnabled(m_database, false); + setNextEnabled(m_sheet, false); + setNextEnabled(m_columns, false); + setNextEnabled(m_options, false); + setNextEnabled(m_result, false); +} + +DatabaseDialog::~DatabaseDialog() +{ + // no need to delete child widgets, TQt does it all for us + if ( m_dbConnection ) + m_dbConnection->close(); +} + +void DatabaseDialog::switchPage( int id ) +{ + if ( id > eResult ) + --m_currentPage; + if ( id < eDatabase ) + ++m_currentPage; + + switch ( id ) + { + case eDatabase: + showPage(m_database); + break; + + case eSheets: + showPage(m_sheet); + break; + + case eColumns: + showPage(m_columns); + break; + + case eOptions: + showPage(m_options); + break; + + case eResult: + showPage(m_result); + break; + + default: + break; + } +} + +void DatabaseDialog::next() +{ + switch ( m_currentPage ) + { + case eDatabase: + if (!databaseDoNext()) + return; + break; + + case eSheets: + if (!sheetsDoNext()) + return; + break; + + case eColumns: + if (!columnsDoNext()) + return; + break; + + case eOptions: + if (!optionsDoNext()) + return; + break; + + case eResult: + // there is nothing to do here + break; + + default: + break; + } + + ++m_currentPage; + + switchPage( m_currentPage ); +} + +void DatabaseDialog::back() +{ + --m_currentPage; + + switchPage( m_currentPage ); +} + +void DatabaseDialog::accept() +{ + Sheet * sheet = m_pView->activeSheet(); + int top; + int left; + int width = -1; + int height = -1; + if ( m_startingRegion->isChecked() ) + { + Range range( m_region->text() ); + if ( range.isSheetKnown() ) + { + KMessageBox::error( this, i18n("You cannot specify a table here.") ); + m_region->setFocus(); + m_region->selectAll(); + return; + } + + range.setSheet(sheet); + + if ( !range.isValid() ) + { + KMessageBox::error( this, i18n("You have to specify a valid region.") ); + m_region->setFocus(); + m_region->selectAll(); + return; + } + + top = range.range().top(); + left = range.range().left(); + width = range.range().width(); + height = range.range().height(); + } + else + { + Point point( m_cell->text() ); + if ( point.isSheetKnown() ) + { + KMessageBox::error( this, i18n("You cannot specify a table here.") ); + m_cell->setFocus(); + m_cell->selectAll(); + return; + } + point.setSheet(sheet); + // if ( point.pos.x() < 1 || point.pos.y() < 1 ) + if ( !point.isValid() ) + { + KMessageBox::error( this, i18n("You have to specify a valid cell.") ); + m_cell->setFocus(); + m_cell->selectAll(); + return; + } + top = point.pos().y(); + left = point.pos().x(); + } + + int i; + TQString queryStr; + TQString tmp = m_sqlQuery->text(); + for ( i = 0; i < (int) tmp.length(); ++i ) + { + if ( tmp[i] != '\n' ) + queryStr += tmp[i]; + else + queryStr += " "; + } + + Cell * cell; + TQSqlQuery query( TQString(), m_dbConnection ); + + // Check the whole query for SQL that might modify database. + // If there is an update command, then it must be at the start of the string, + // or after an open bracket (e.g. nested update) or a space to be valid SQL. + // An update command must also be followed by a space, or it would be parsed + // as an identifier. + // For sanity, also check that there is a SELECT + TQRegExp couldModifyDB( "(^|[( \\s])(UPDATE|DELETE|INSERT|CREATE) ", false /* cs */ ); + TQRegExp couldQueryDB( "(^|[( \\s])(SELECT) ", false /* cs */ ); + + if (couldModifyDB.search( queryStr ) != -1 || couldQueryDB.search ( queryStr ) == -1 ) + { + KMessageBox::error( this, i18n("You are not allowed to change data in the database.") ); + m_sqlQuery->setFocus(); + return; + } + + if ( !query.exec( queryStr ) ) + { + KMessageBox::error( this, i18n( "Executing query failed." ) ); + m_sqlQuery->setFocus(); + return; + } + + if ( query.size() == 0 ) + { + KMessageBox::error( this, i18n( "You did not get any results with this query." ) ); + m_sqlQuery->setFocus(); + return; + } + + int y = 0; + int count = m_columns_1->count(); + if ( width != -1 ) + { + if ( count > width ) + count = width; + } + + if ( height == -1 ) + { + height = 0; + if ( query.first() ) + { + if ( query.isValid() ) + ++height; + } + while ( query.next() ) + { + if ( query.isValid() ) + ++height; + } + } + + if ( !m_pView->doc()->undoLocked() ) + { + TQRect r(left, top, count, height); + UndoInsertData * undo = new UndoInsertData( m_pView->doc(), sheet, r ); + m_pView->doc()->addCommand( undo ); + } + + m_pView->doc()->emitBeginOperation(); + + if ( query.first() ) + { + if ( query.isValid() ) + { + for ( i = 0; i < count; ++i ) + { + cell = sheet->nonDefaultCell( left + i, top + y ); + cell->setCellText( query.value( i ).toString() ); + } + ++y; + } + } + + if ( y != height ) + { + while ( query.next() ) + { + if ( !query.isValid() ) + continue; + + for ( i = 0; i < count; ++i ) + { + cell = sheet->nonDefaultCell( left + i, top + y ); + cell->setCellText( query.value( i ).toString() ); + } + ++y; + + if ( y == height ) + break; + } + } + + m_pView->slotUpdateView( sheet ); + KWizard::accept(); +} + +bool DatabaseDialog::databaseDoNext() +{ + m_dbConnection = TQSqlDatabase::addDatabase( m_driver->currentText() ); + + if ( m_dbConnection ) + { + m_dbConnection->setDatabaseName( m_databaseName->text() ); + m_dbConnection->setHostName( m_host->text() ); + + if ( !m_username->text().isEmpty() ) + m_dbConnection->setUserName( m_username->text() ); + + if ( !m_password->text().isEmpty() ) + m_dbConnection->setPassword( m_password->text() ); + + if ( !m_port->text().isEmpty() ) + { + bool ok = false; + int port = m_port->text().toInt( &ok ); + if (!ok) + { + KMessageBox::error( this, i18n("The port must be a number") ); + return false; + } + m_dbConnection->setPort( port ); + } + + m_databasetStatus->setText( i18n("Connecting to database...") ); + if ( m_dbConnection->open() ) + { + m_databasetStatus->setText( i18n("Connected. Retrieving table information...") ); + TQStringList sheetList( m_dbConnection->tables() ); + + if ( sheetList.isEmpty() ) + { + KMessageBox::error( this, i18n("This database contains no tables") ); + return false; + } + + unsigned int i; + m_sheetView->clear(); + + for ( i = 0; i < sheetList.size(); ++i ) + { + TQCheckListItem * item = new TQCheckListItem( m_sheetView, sheetList[i], + TQCheckListItem::CheckBox ); + item->setOn(false); + m_sheetView->insertItem( item ); + } + + m_sheetView->setEnabled( true ); + m_databasetStatus->setText( " " ); + } + else + { + TQSqlError error = m_dbConnection->lastError(); + TQString errorMsg; + TQString err1 = error.driverText(); + TQString err2 = error.databaseText(); + if ( !err1.isEmpty() ) + { + errorMsg.append( error.driverText() ); + errorMsg.append( "\n" ); + } + if ( !err2.isEmpty() && err1 != err2) + { + errorMsg.append( error.databaseText() ); + errorMsg.append( "\n" ); + } + m_databasetStatus->setText( " " ); + + KMessageBox::error( this, errorMsg ); + return false; + } + } + else + { + KMessageBox::error( this, i18n("Driver could not be loaded") ); + m_databasetStatus->setText( " " ); + return false; + } + setNextEnabled(m_sheet, true); + + return true; +} + +bool DatabaseDialog::sheetsDoNext() +{ + m_databasetStatus->setText( i18n("Retrieving meta data of tables...") ); + TQStringList sheets; + + for (TQListViewItem * item = (TQCheckListItem *) m_sheetView->firstChild(); item; item = item->nextSibling()) + { + if (((TQCheckListItem * ) item)->isOn()) + { + sheets.append(((TQCheckListItem * ) item)->text()); + } + } + + if (sheets.empty()) + { + KMessageBox::error( this, i18n("You have to select at least one table.") ); + return false; + } + + m_columnView->clear(); + TQSqlRecord info; + TQCheckListItem * item; + for (int i = 0; i < (int) sheets.size(); ++i) + { + info = m_dbConnection->record( sheets[i] ); + for (int j = 0; j < (int) info.count(); ++j) + { + TQString name = info.fieldName(j); + item = new TQCheckListItem( m_columnView, name, + TQCheckListItem::CheckBox ); + item->setOn(false); + m_columnView->insertItem( item ); + item->setText( 1, sheets[i] ); + TQSqlField * field = info.field(name); + item->setText( 2, TQVariant::typeToName(field->type()) ); + } + } + m_columnView->setSorting(1, true); + m_columnView->sort(); + m_columnView->setSorting( -1 ); + + setNextEnabled(m_columns, true); + + return true; +} + +bool DatabaseDialog::columnsDoNext() +{ + TQStringList columns; + for (TQListViewItem * item = m_columnView->firstChild(); item; item = item->nextSibling()) + { + if (((TQCheckListItem * ) item)->isOn()) + { + columns.append( item->text(1) + "." + ((TQCheckListItem * ) item)->text()); + } + } + + if (columns.empty()) + { + KMessageBox::error( this, i18n("You have to select at least one column.") ); + return false; + } + + m_columns_1->clear(); + m_columns_2->clear(); + m_columns_3->clear(); + m_columns_1->insertStringList(columns); + m_columns_2->insertStringList(columns); + m_columns_3->insertStringList(columns); + m_columnsSort_1->clear(); + m_columnsSort_2->clear(); + m_columnsSort_1->insertItem( i18n("None") ); + m_columnsSort_2->insertItem( i18n("None") ); + m_columnsSort_1->insertStringList(columns); + m_columnsSort_2->insertStringList(columns); + + setNextEnabled(m_options, true); + + return true; +} + + +TQString DatabaseDialog::getWhereCondition(TQString const & column, + TQString const & value, + int op) +{ + TQString wherePart; + + switch( op ) + { + case 0: + wherePart += column; + wherePart += " = "; + break; + case 1: + wherePart += "NOT "; + wherePart += column; + wherePart += " = "; + break; + case 2: + wherePart += column; + wherePart += " IN "; + break; + case 3: + wherePart += "NOT "; + wherePart += column; + wherePart += " IN "; + break; + case 4: + wherePart += column; + wherePart += " LIKE "; + break; + case 5: + wherePart += column; + wherePart += " > "; + break; + case 6: + wherePart += column; + wherePart += " < "; + break; + case 7: + wherePart += column; + wherePart += " >= "; + break; + case 8: + wherePart += column; + wherePart += " <= "; + break; + } + + if ( op != 2 && op != 3 ) + { + TQString val; + bool ok = false; + value.toDouble(&ok); + + if ( !ok ) + { + if (value[0] != '\'') + val = "'"; + + val += value; + + if (value[value.length() - 1] != '\'') + val += "'"; + } + else + val = value; + + wherePart += val; + } + else // "in" & "not in" + { + TQString val; + if (value[0] != '(') + val = "("; + val += value; + if ( value[value.length() - 1] != ')' ) + val += ")"; + wherePart += val; + } + + return wherePart; +} + +TQString DatabaseDialog::exchangeWildcards(TQString const & value) +{ + TQString str(value); + int p = str.find('*'); + while ( p > -1 ) + { + str = str.replace( p, 1, "%" ); + p = str.find('*'); + } + + p = str.find('?'); + while ( p > -1 ) + { + str = str.replace( p, 1, "_" ); + p = str.find('?'); + } + return str; +} + +bool DatabaseDialog::optionsDoNext() +{ + if ( m_operator_1->currentItem() == 4 ) + { + if ( ( m_operatorValue_1->text().find('*') != -1 ) + || ( m_operatorValue_1->text().find('?') != -1 ) ) + { + // xgettext: no-c-format + int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " + "The proper replacements are '%' or '_'. Do you want to replace them?") ); + + if ( res == KMessageBox::Yes ) + m_operatorValue_1->setText(exchangeWildcards(m_operatorValue_1->text())); + } + } + + if ( m_operator_2->currentItem() == 4 ) + { + if ( ( m_operatorValue_2->text().find('*') != -1 ) + || ( m_operatorValue_2->text().find('?') != -1 ) ) + { + // xgettext: no-c-format + int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " + "The proper replacements are '%' or '_'. Do you want to replace them?") ); + + if ( res == KMessageBox::Yes ) + m_operatorValue_2->setText(exchangeWildcards(m_operatorValue_2->text())); + } + } + + if ( m_operator_3->currentItem() == 4 ) + { + if ( ( m_operatorValue_3->text().find('*') != -1 ) + || ( m_operatorValue_3->text().find('?') != -1 ) ) + { + // xgettext: no-c-format + int res = KMessageBox::warningYesNo( this, i18n("'*' or '?' are not valid wildcards in SQL. " + "The proper replacements are '%' or '_'. Do you want to replace them?") ); + + if ( res == KMessageBox::Yes ) + m_operatorValue_3->setText(exchangeWildcards(m_operatorValue_3->text())); + } + } + + TQString query("SELECT "); + + if (m_distinct->isChecked()) + query += "DISTINCT "; + + int i; + int l = m_columns_1->count() - 1; + for ( i = 0; i < l; ++i ) + { + query += m_columns_1->text( i ); + query += ", "; + } + query += m_columns_1->text( l ); + + query += "\nFROM "; + + TQListViewItem * item = (TQCheckListItem *) m_sheetView->firstChild(); + bool b = false; + while ( item ) + { + if (((TQCheckListItem * ) item)->isOn()) + { + if ( b ) + query += ", "; + b = true; + query += ((TQCheckListItem * ) item)->text(); + } + item = item->nextSibling(); + } + + if ( ( !m_operatorValue_1->text().isEmpty() ) + || ( !m_operatorValue_2->text().isEmpty() ) + || ( !m_operatorValue_3->text().isEmpty() ) ) + query += "\nWHERE "; + + bool added = false; + if ( !m_operatorValue_1->text().isEmpty() ) + { + query += getWhereCondition(m_columns_1->currentText(), + m_operatorValue_1->text(), + m_operator_1->currentItem()); + added = true; + } + + if ( !m_operatorValue_2->text().isEmpty() ) + { + if (added) + query += ( m_andBox->isChecked() ? " AND " : " OR " ); + + query += getWhereCondition(m_columns_2->currentText(), + m_operatorValue_2->text(), + m_operator_2->currentItem()); + added = true; + } + + if ( !m_operatorValue_3->text().isEmpty() ) + { + if (added) + query += ( m_andBox->isChecked() ? " AND " : " OR " ); + + query += getWhereCondition(m_columns_3->currentText(), + m_operatorValue_3->text(), + m_operator_3->currentItem()); + } + + if ( (m_columnsSort_1->currentItem() != 0) + || (m_columnsSort_2->currentItem() != 0) ) + { + query += "\nORDER BY "; + bool added = false; + if ( m_columnsSort_1->currentItem() != 0 ) + { + added = true; + query += m_columnsSort_1->currentText(); + if ( m_sortMode_1->currentItem() == 1 ) + query += " DESC "; + } + + if ( m_columnsSort_2->currentItem() != 0 ) + { + if ( added ) + query += ", "; + + query += m_columnsSort_2->currentText(); + if ( m_sortMode_2->currentItem() == 1 ) + query += " DESC "; + } + } + + m_sqlQuery->setText(query); + m_cell->setText(Cell::name( m_targetRect.left(), m_targetRect.top() ) ); + m_region->setText(util_rangeName( m_targetRect ) ); + + setFinishEnabled( m_result, true ); + + return true; +} + +void DatabaseDialog::orBox_clicked() +{ + m_andBox->setChecked( false ); + m_orBox->setChecked( true ); +} + +void DatabaseDialog::andBox_clicked() +{ + m_andBox->setChecked( true ); + m_orBox->setChecked( false ); +} + +void DatabaseDialog::startingCell_clicked() +{ + m_startingCell->setChecked( true ); + m_startingRegion->setChecked( false ); +} + +void DatabaseDialog::startingRegion_clicked() +{ + m_startingCell->setChecked( false ); + m_startingRegion->setChecked( true ); +} + +void DatabaseDialog::connectButton_clicked() +{ + tqWarning( "DatabaseDialog::connectButton_clicked(): Not implemented yet!" ); +} + +void DatabaseDialog::databaseNameChanged(const TQString & s) +{ + if ( !m_driver->currentText().isEmpty() && !s.isEmpty() + && !m_host->text().isEmpty() ) + setNextEnabled(m_database, true); + else + setNextEnabled(m_database, false); +} + +void DatabaseDialog::databaseHostChanged(const TQString & s) +{ + if ( !m_driver->currentText().isEmpty() && !s.isEmpty() + && !m_databaseName->text().isEmpty() ) + setNextEnabled(m_database, true); + else + setNextEnabled(m_database, false); +} + +void DatabaseDialog::databaseDriverChanged(int index) +{ + if ( index > 0 && !m_host->text().isEmpty() + && !m_databaseName->text().isEmpty() ) + setNextEnabled(m_database, true); + else + setNextEnabled(m_database, false); +} + +void DatabaseDialog::popupSheetViewMenu( TQListViewItem *, const TQPoint &, int ) +{ + // TODO: popup menu with "Select All", "Inverse selection", "remove selection" +} + +void DatabaseDialog::sheetViewClicked( TQListViewItem * ) +{ +// if ( item ) +// { +// TQCheckListItem * i = (TQCheckListItem *) item; +// i->setOn( !i->isOn() ); +// } +// kdDebug() << "clicked" << endl; +} + + +#include "kspread_dlg_database.moc" + +#endif // TQT_NO_SQL diff --git a/kspread/dialogs/kspread_dlg_find.cc b/kspread/dialogs/kspread_dlg_find.cc deleted file mode 100644 index aa1c7f71..00000000 --- a/kspread/dialogs/kspread_dlg_find.cc +++ /dev/null @@ -1,167 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999-2005 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "kspread_dlg_find.h" -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - -FindOption::FindOption( TQWidget *parent) -{ - TQVBoxLayout *layout = new TQVBoxLayout(parent); - m_moreOptions = new TQPushButton( i18n( "More Options" ), parent ); - layout->addWidget( m_moreOptions ); - - connect( m_moreOptions, TQT_SIGNAL( clicked () ), this, TQT_SLOT( slotMoreOptions() ) ); - - m_findExtension = new TQWidget( parent ); - layout->addWidget( m_findExtension ); - TQVBoxLayout *layout1 = new TQVBoxLayout( m_findExtension ); - m_searchInAllSheet = new TQCheckBox( i18n( "Search entire sheet" ),m_findExtension ); - layout1->addWidget( m_searchInAllSheet ); - - TQHBoxLayout *comboLayout = new TQHBoxLayout( m_findExtension ); - TQLabel *label = new TQLabel( i18n( "Search in:" ), m_findExtension ); - comboLayout->addWidget( label ); - - m_searchIn = new TQComboBox( m_findExtension ); - comboLayout->addWidget( m_searchIn ); - layout1->addLayout( comboLayout ); - - TQStringList lst; - lst << i18n( "Cell Values" ); - lst << i18n( "Comments" ); - m_searchIn->insertStringList( lst ); - - comboLayout = new TQHBoxLayout( m_findExtension ); - label = new TQLabel( i18n( "Search direction:" ), m_findExtension ); - comboLayout->addWidget( label ); - - m_searchDirection = new TQComboBox( m_findExtension ); - comboLayout->addWidget( m_searchDirection ); - layout1->addLayout( comboLayout ); - - lst.clear(); - lst << i18n( "Across then Down" ); - lst << i18n( "Down then Across" ); - m_searchDirection->insertStringList( lst ); - - m_findExtension->hide(); - emit adjustSize(); -} - -FindOption::searchTypeValue FindOption::searchType() const -{ - int pos = m_searchIn->currentItem(); - if ( pos == 0 ) - return Value; - else if ( pos == 1 ) - return Note; - else - return Value; -} - -FindOption::searchDirectionValue FindOption::searchDirection() const -{ - int pos = m_searchDirection->currentItem(); - if ( pos == 0 ) - return Row; - else if ( pos == 1 ) - return Column; - else - return Row; -} - - -void FindOption::slotMoreOptions() -{ - if ( m_findExtension->isHidden() ) - { - m_findExtension->show(); - m_moreOptions->setText( i18n( "Fewer Options" )); - } - else - { - m_findExtension->hide(); - m_moreOptions->setText( i18n( "More Options" )); - } - emit adjustSize(); -} - -bool FindOption::searchInAllSheet() const -{ - return m_searchInAllSheet->isChecked(); -} - -FindDlg::FindDlg(TQWidget *parent, const char *name, long options, const TQStringList &findStrings, bool hasSelection ) - : KFindDialog(parent,name,options,findStrings,hasSelection ) -{ - m_findOptions = new FindOption( findExtension() ); - connect( m_findOptions, TQT_SIGNAL( adjustSize() ), TQT_SLOT( slotAjustSize() ) ); - setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); -} - -FindDlg::~FindDlg() -{ - // no need to delete child widgets, TQt does it all for us -} - -void FindDlg::slotAjustSize() -{ - adjustSize(); -} - -bool FindDlg::searchInAllSheet() const -{ - return m_findOptions->searchInAllSheet(); -} - - -SearchDlg::SearchDlg(TQWidget *parent, const char *name, long options, const TQStringList &findStrings, const TQStringList &replaceStrings, bool hasSelection ) - : KReplaceDialog(parent,name,options,findStrings,replaceStrings,hasSelection ) -{ - m_findOptions = new FindOption( findExtension() ); - connect( m_findOptions, TQT_SIGNAL( adjustSize() ), TQT_SLOT( slotAjustSize() ) ); - setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); -} - -SearchDlg::~SearchDlg() -{ - // no need to delete child widgets, TQt does it all for us -} - -void SearchDlg::slotAjustSize() -{ - adjustSize(); - setFixedSize(size()); -} - -bool SearchDlg::searchInAllSheet() const -{ - return m_findOptions->searchInAllSheet(); -} - - -#include "kspread_dlg_find.moc" diff --git a/kspread/dialogs/kspread_dlg_find.cpp b/kspread/dialogs/kspread_dlg_find.cpp new file mode 100644 index 00000000..aa1c7f71 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_find.cpp @@ -0,0 +1,167 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2005 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "kspread_dlg_find.h" +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + +FindOption::FindOption( TQWidget *parent) +{ + TQVBoxLayout *layout = new TQVBoxLayout(parent); + m_moreOptions = new TQPushButton( i18n( "More Options" ), parent ); + layout->addWidget( m_moreOptions ); + + connect( m_moreOptions, TQT_SIGNAL( clicked () ), this, TQT_SLOT( slotMoreOptions() ) ); + + m_findExtension = new TQWidget( parent ); + layout->addWidget( m_findExtension ); + TQVBoxLayout *layout1 = new TQVBoxLayout( m_findExtension ); + m_searchInAllSheet = new TQCheckBox( i18n( "Search entire sheet" ),m_findExtension ); + layout1->addWidget( m_searchInAllSheet ); + + TQHBoxLayout *comboLayout = new TQHBoxLayout( m_findExtension ); + TQLabel *label = new TQLabel( i18n( "Search in:" ), m_findExtension ); + comboLayout->addWidget( label ); + + m_searchIn = new TQComboBox( m_findExtension ); + comboLayout->addWidget( m_searchIn ); + layout1->addLayout( comboLayout ); + + TQStringList lst; + lst << i18n( "Cell Values" ); + lst << i18n( "Comments" ); + m_searchIn->insertStringList( lst ); + + comboLayout = new TQHBoxLayout( m_findExtension ); + label = new TQLabel( i18n( "Search direction:" ), m_findExtension ); + comboLayout->addWidget( label ); + + m_searchDirection = new TQComboBox( m_findExtension ); + comboLayout->addWidget( m_searchDirection ); + layout1->addLayout( comboLayout ); + + lst.clear(); + lst << i18n( "Across then Down" ); + lst << i18n( "Down then Across" ); + m_searchDirection->insertStringList( lst ); + + m_findExtension->hide(); + emit adjustSize(); +} + +FindOption::searchTypeValue FindOption::searchType() const +{ + int pos = m_searchIn->currentItem(); + if ( pos == 0 ) + return Value; + else if ( pos == 1 ) + return Note; + else + return Value; +} + +FindOption::searchDirectionValue FindOption::searchDirection() const +{ + int pos = m_searchDirection->currentItem(); + if ( pos == 0 ) + return Row; + else if ( pos == 1 ) + return Column; + else + return Row; +} + + +void FindOption::slotMoreOptions() +{ + if ( m_findExtension->isHidden() ) + { + m_findExtension->show(); + m_moreOptions->setText( i18n( "Fewer Options" )); + } + else + { + m_findExtension->hide(); + m_moreOptions->setText( i18n( "More Options" )); + } + emit adjustSize(); +} + +bool FindOption::searchInAllSheet() const +{ + return m_searchInAllSheet->isChecked(); +} + +FindDlg::FindDlg(TQWidget *parent, const char *name, long options, const TQStringList &findStrings, bool hasSelection ) + : KFindDialog(parent,name,options,findStrings,hasSelection ) +{ + m_findOptions = new FindOption( findExtension() ); + connect( m_findOptions, TQT_SIGNAL( adjustSize() ), TQT_SLOT( slotAjustSize() ) ); + setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); +} + +FindDlg::~FindDlg() +{ + // no need to delete child widgets, TQt does it all for us +} + +void FindDlg::slotAjustSize() +{ + adjustSize(); +} + +bool FindDlg::searchInAllSheet() const +{ + return m_findOptions->searchInAllSheet(); +} + + +SearchDlg::SearchDlg(TQWidget *parent, const char *name, long options, const TQStringList &findStrings, const TQStringList &replaceStrings, bool hasSelection ) + : KReplaceDialog(parent,name,options,findStrings,replaceStrings,hasSelection ) +{ + m_findOptions = new FindOption( findExtension() ); + connect( m_findOptions, TQT_SIGNAL( adjustSize() ), TQT_SLOT( slotAjustSize() ) ); + setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); +} + +SearchDlg::~SearchDlg() +{ + // no need to delete child widgets, TQt does it all for us +} + +void SearchDlg::slotAjustSize() +{ + adjustSize(); + setFixedSize(size()); +} + +bool SearchDlg::searchInAllSheet() const +{ + return m_findOptions->searchInAllSheet(); +} + + +#include "kspread_dlg_find.moc" diff --git a/kspread/dialogs/kspread_dlg_format.cc b/kspread/dialogs/kspread_dlg_format.cc deleted file mode 100644 index 501d8bf3..00000000 --- a/kspread/dialogs/kspread_dlg_format.cc +++ /dev/null @@ -1,352 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 John Dailey - (C) 2001-2002 Philipp Mueller - (C) 2000-2002 Laurent Montel - (C) 2000 Werner Trobin - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_dlg_format.h" -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_undo.h" -#include "kspread_view.h" -#include "selection.h" - - -using namespace KSpread; - -FormatDialog::FormatDialog( View* view, const char* name ) - : KDialogBase( view, name, TRUE,i18n("Sheet Style"),Ok|Cancel ) -{ - for( int i = 0; i < 16; ++i ) - m_cells[ i ] = 0; - - m_view = view; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *vbox = new TQVBoxLayout( page, 0, spacingHint() ); - - TQLabel *toplabel = new TQLabel( i18n("Select the sheet style to apply:"), page ); - m_combo = new TQComboBox( page ); - m_label = new TQLabel( page ); - - vbox->addWidget( toplabel ); - vbox->addWidget( m_combo ); - vbox->addWidget( m_label ); - - - TQStringList lst = Factory::global()->dirs()->findAllResources( "sheet-styles", "*.ksts", TRUE ); - - TQStringList::Iterator it = lst.begin(); - for( ; it != lst.end(); ++it ) - { - KSimpleConfig cfg( *it, TRUE ); - cfg.setGroup( "Sheet-Style" ); - - Entry e; - e.config = *it; - e.xml = cfg.readEntry( "XML" ); - e.image = cfg.readEntry( "Image" ); - e.name = cfg.readEntry( "Name" ); - - m_entries.append( e ); - - m_combo->insertItem( e.name ); - } - - slotActivated( 0 ); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( m_combo, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotActivated( int ) ) ); -} - -FormatDialog::~FormatDialog() -{ - for( int i = 0; i < 16; ++i ) - delete m_cells[ i ]; -} - -void FormatDialog::slotActivated( int index ) -{ - enableButtonOK(true); - - TQString img = Factory::global()->dirs()->findResource( "sheet-styles", m_entries[ index ].image ); - if ( img.isEmpty() ) - { - TQString str( i18n( "Could not find image %1." ) ); - str = str.arg( m_entries[ index ].image ); - KMessageBox::error( this, str ); - - enableButtonOK(false); - - return; - } - - TQPixmap pix( img ); - if ( pix.isNull() ) - { - TQString str( i18n( "Could not load image %1." ) ); - str = str.arg( img ); - KMessageBox::error( this,str ); - - enableButtonOK(false); - - return; - } - - m_label->setPixmap( pix ); -} - -void FormatDialog::slotOk() -{ - - m_view->doc()->emitBeginOperation( false ); - - TQString xml = Factory::global()->dirs()->findResource( "sheet-styles", m_entries[ m_combo->currentItem() ].xml ); - if ( xml.isEmpty() ) - { - TQString str( i18n( "Could not find sheet-style XML file '%1'." ) ); - str = str.arg( m_entries[ m_combo->currentItem() ].xml ); - KMessageBox::error( this, str ); - return; - } - - TQFile file( xml ); - file.open( IO_ReadOnly ); - TQDomDocument doc; - doc.setContent( &file ); - file.close(); - - if ( !parseXML( doc ) ) - { - TQString str( i18n( "Parsing error in sheet-style XML file %1." ) ); - str = str.arg( m_entries[ m_combo->currentItem() ].xml ); - KMessageBox::error( this, str ); - return; - } - - TQRect r = m_view->selectionInfo()->selection(); - - if ( !m_view->doc()->undoLocked() ) - { - TQString title=i18n("Change Format"); - UndoCellFormat *undo = new UndoCellFormat( m_view->doc(), m_view->activeSheet(), r, title); - m_view->doc()->addCommand( undo ); - } - // - // Set colors, borders etc. - // - - // Top left corner - Cell* cell = m_view->activeSheet()->nonDefaultCell( r.left(), r.top() ); - cell->format()->copy( *m_cells[0] ); - - // Top column - int x, y; - for( x = r.left() + 1; x <= r.right(); ++x ) - { - int pos = 1 + ( ( x - r.left() - 1 ) % 2 ); - Cell* cell = m_view->activeSheet()->nonDefaultCell( x, r.top() ); - if(!cell->isPartOfMerged()) - { - cell->format()->copy( *m_cells[ pos ] ); - - Format* c; - if ( x == r.right() ) - c = m_cells[2]; - else - c = m_cells[1]; - - if ( c ) - cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); - - if ( x == r.left() + 1 ) - c = m_cells[1]; - else - c = m_cells[2]; - - if ( c ) - cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); - } - } - - cell = m_view->activeSheet()->nonDefaultCell( r.right(), r.top() ); - if ( m_cells[3] ) - cell->setRightBorderPen( m_cells[3]->leftBorderPen( 0, 0 ) ); - - // Left row - for( y = r.top() + 1; y <= r.bottom(); ++y ) - { - int pos = 4 + ( ( y - r.top() - 1 ) % 2 ) * 4; - Cell* cell = m_view->activeSheet()->nonDefaultCell( r.left(), y ); - if(!cell->isPartOfMerged()) - { - cell->format()->copy( *m_cells[ pos ] ); - - Format* c; - if ( y == r.bottom() ) - c = m_cells[8]; - else - c = m_cells[4]; - - if ( c ) - cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); - - if ( y == r.top() + 1 ) - c = m_cells[4]; - else - c = m_cells[8]; - - if ( c ) - cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); - } - } - - // Body - for( x = r.left() + 1; x <= r.right(); ++x ) - for( y = r.top() + 1; y <= r.bottom(); ++y ) - { - int pos = 5 + ( ( y - r.top() - 1 ) % 2 ) * 4 + ( ( x - r.left() - 1 ) % 2 ); - Cell* cell = m_view->activeSheet()->nonDefaultCell( x, y ); - if(!cell->isPartOfMerged()) - { - cell->format()->copy( *m_cells[ pos ] ); - - Format* c; - if ( x == r.left() + 1 ) - c = m_cells[ 5 + ( ( y - r.top() - 1 ) % 2 ) * 4 ]; - else - c = m_cells[ 6 + ( ( y - r.top() - 1 ) % 2 ) * 4 ]; - - if ( c ) - cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); - - if ( y == r.top() + 1 ) - c = m_cells[ 5 + ( ( x - r.left() - 1 ) % 2 ) ]; - else - c = m_cells[ 9 + ( ( x - r.left() - 1 ) % 2 ) ]; - - if ( c ) - cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); - } - } - - // Outer right border - for( y = r.top(); y <= r.bottom(); ++y ) - { - Cell* cell = m_view->activeSheet()->nonDefaultCell( r.right(), y ); - if(!cell->isPartOfMerged()) - { - if ( y == r.top() ) - { - if ( m_cells[3] ) - cell->setRightBorderPen( m_cells[3]->leftBorderPen( 0, 0 ) ); - } - else if ( y == r.right() ) - { - if ( m_cells[11] ) - cell->setRightBorderPen( m_cells[11]->leftBorderPen( 0, 0 ) ); - } - else - { - if ( m_cells[7] ) - cell->setRightBorderPen( m_cells[7]->leftBorderPen( 0, 0 ) ); - } - } - } - - // Outer bottom border - for( x = r.left(); x <= r.right(); ++x ) - { - Cell* cell = m_view->activeSheet()->nonDefaultCell( x, r.bottom() ); - if(!cell->isPartOfMerged()) - { - if ( x == r.left() ) - { - if ( m_cells[12] ) - cell->setBottomBorderPen( m_cells[12]->topBorderPen( 0, 0 ) ); - } - else if ( x == r.right() ) - { - if ( m_cells[14] ) - cell->setBottomBorderPen( m_cells[14]->topBorderPen( 0, 0 ) ); - } - else - { - if ( m_cells[13] ) - cell->setBottomBorderPen( m_cells[13]->topBorderPen( 0, 0 ) ); - } - } - } - - m_view->selectionInfo()->initialize(r);//, m_view->activeSheet() ); - m_view->doc()->setModified( true ); - m_view->slotUpdateView( m_view->activeSheet() ); - accept(); -} - -bool FormatDialog::parseXML( const TQDomDocument& doc ) -{ - for( int i = 0; i < 16; ++i ) - { - delete m_cells[ i ]; - m_cells[ i ] = 0; - } - - TQDomElement e = doc.documentElement().firstChild().toElement(); - for( ; !e.isNull(); e = e.nextSibling().toElement() ) - { - if ( e.tagName() == "cell" ) - { - Sheet* sheet = m_view->activeSheet(); - Format* cell = new Format( sheet, sheet->doc()->styleManager()->defaultStyle() ); - - if ( !cell->load( e.namedItem("format").toElement(), Paste::Normal ) ) - return false; - - int row = e.attribute("row").toInt(); - int column = e.attribute("column").toInt(); - int i = (row-1)*4 + (column-1); - if ( i < 0 || i >= 16 ) - return false; - - m_cells[ i ] = cell; - } - } - - return TRUE; -} - -#include "kspread_dlg_format.moc" diff --git a/kspread/dialogs/kspread_dlg_format.cpp b/kspread/dialogs/kspread_dlg_format.cpp new file mode 100644 index 00000000..501d8bf3 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_format.cpp @@ -0,0 +1,352 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 John Dailey + (C) 2001-2002 Philipp Mueller + (C) 2000-2002 Laurent Montel + (C) 2000 Werner Trobin + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_dlg_format.h" +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_undo.h" +#include "kspread_view.h" +#include "selection.h" + + +using namespace KSpread; + +FormatDialog::FormatDialog( View* view, const char* name ) + : KDialogBase( view, name, TRUE,i18n("Sheet Style"),Ok|Cancel ) +{ + for( int i = 0; i < 16; ++i ) + m_cells[ i ] = 0; + + m_view = view; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *vbox = new TQVBoxLayout( page, 0, spacingHint() ); + + TQLabel *toplabel = new TQLabel( i18n("Select the sheet style to apply:"), page ); + m_combo = new TQComboBox( page ); + m_label = new TQLabel( page ); + + vbox->addWidget( toplabel ); + vbox->addWidget( m_combo ); + vbox->addWidget( m_label ); + + + TQStringList lst = Factory::global()->dirs()->findAllResources( "sheet-styles", "*.ksts", TRUE ); + + TQStringList::Iterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + { + KSimpleConfig cfg( *it, TRUE ); + cfg.setGroup( "Sheet-Style" ); + + Entry e; + e.config = *it; + e.xml = cfg.readEntry( "XML" ); + e.image = cfg.readEntry( "Image" ); + e.name = cfg.readEntry( "Name" ); + + m_entries.append( e ); + + m_combo->insertItem( e.name ); + } + + slotActivated( 0 ); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( m_combo, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotActivated( int ) ) ); +} + +FormatDialog::~FormatDialog() +{ + for( int i = 0; i < 16; ++i ) + delete m_cells[ i ]; +} + +void FormatDialog::slotActivated( int index ) +{ + enableButtonOK(true); + + TQString img = Factory::global()->dirs()->findResource( "sheet-styles", m_entries[ index ].image ); + if ( img.isEmpty() ) + { + TQString str( i18n( "Could not find image %1." ) ); + str = str.arg( m_entries[ index ].image ); + KMessageBox::error( this, str ); + + enableButtonOK(false); + + return; + } + + TQPixmap pix( img ); + if ( pix.isNull() ) + { + TQString str( i18n( "Could not load image %1." ) ); + str = str.arg( img ); + KMessageBox::error( this,str ); + + enableButtonOK(false); + + return; + } + + m_label->setPixmap( pix ); +} + +void FormatDialog::slotOk() +{ + + m_view->doc()->emitBeginOperation( false ); + + TQString xml = Factory::global()->dirs()->findResource( "sheet-styles", m_entries[ m_combo->currentItem() ].xml ); + if ( xml.isEmpty() ) + { + TQString str( i18n( "Could not find sheet-style XML file '%1'." ) ); + str = str.arg( m_entries[ m_combo->currentItem() ].xml ); + KMessageBox::error( this, str ); + return; + } + + TQFile file( xml ); + file.open( IO_ReadOnly ); + TQDomDocument doc; + doc.setContent( &file ); + file.close(); + + if ( !parseXML( doc ) ) + { + TQString str( i18n( "Parsing error in sheet-style XML file %1." ) ); + str = str.arg( m_entries[ m_combo->currentItem() ].xml ); + KMessageBox::error( this, str ); + return; + } + + TQRect r = m_view->selectionInfo()->selection(); + + if ( !m_view->doc()->undoLocked() ) + { + TQString title=i18n("Change Format"); + UndoCellFormat *undo = new UndoCellFormat( m_view->doc(), m_view->activeSheet(), r, title); + m_view->doc()->addCommand( undo ); + } + // + // Set colors, borders etc. + // + + // Top left corner + Cell* cell = m_view->activeSheet()->nonDefaultCell( r.left(), r.top() ); + cell->format()->copy( *m_cells[0] ); + + // Top column + int x, y; + for( x = r.left() + 1; x <= r.right(); ++x ) + { + int pos = 1 + ( ( x - r.left() - 1 ) % 2 ); + Cell* cell = m_view->activeSheet()->nonDefaultCell( x, r.top() ); + if(!cell->isPartOfMerged()) + { + cell->format()->copy( *m_cells[ pos ] ); + + Format* c; + if ( x == r.right() ) + c = m_cells[2]; + else + c = m_cells[1]; + + if ( c ) + cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); + + if ( x == r.left() + 1 ) + c = m_cells[1]; + else + c = m_cells[2]; + + if ( c ) + cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); + } + } + + cell = m_view->activeSheet()->nonDefaultCell( r.right(), r.top() ); + if ( m_cells[3] ) + cell->setRightBorderPen( m_cells[3]->leftBorderPen( 0, 0 ) ); + + // Left row + for( y = r.top() + 1; y <= r.bottom(); ++y ) + { + int pos = 4 + ( ( y - r.top() - 1 ) % 2 ) * 4; + Cell* cell = m_view->activeSheet()->nonDefaultCell( r.left(), y ); + if(!cell->isPartOfMerged()) + { + cell->format()->copy( *m_cells[ pos ] ); + + Format* c; + if ( y == r.bottom() ) + c = m_cells[8]; + else + c = m_cells[4]; + + if ( c ) + cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); + + if ( y == r.top() + 1 ) + c = m_cells[4]; + else + c = m_cells[8]; + + if ( c ) + cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); + } + } + + // Body + for( x = r.left() + 1; x <= r.right(); ++x ) + for( y = r.top() + 1; y <= r.bottom(); ++y ) + { + int pos = 5 + ( ( y - r.top() - 1 ) % 2 ) * 4 + ( ( x - r.left() - 1 ) % 2 ); + Cell* cell = m_view->activeSheet()->nonDefaultCell( x, y ); + if(!cell->isPartOfMerged()) + { + cell->format()->copy( *m_cells[ pos ] ); + + Format* c; + if ( x == r.left() + 1 ) + c = m_cells[ 5 + ( ( y - r.top() - 1 ) % 2 ) * 4 ]; + else + c = m_cells[ 6 + ( ( y - r.top() - 1 ) % 2 ) * 4 ]; + + if ( c ) + cell->setLeftBorderPen( c->leftBorderPen( 0, 0 ) ); + + if ( y == r.top() + 1 ) + c = m_cells[ 5 + ( ( x - r.left() - 1 ) % 2 ) ]; + else + c = m_cells[ 9 + ( ( x - r.left() - 1 ) % 2 ) ]; + + if ( c ) + cell->setTopBorderPen( c->topBorderPen( 0, 0 ) ); + } + } + + // Outer right border + for( y = r.top(); y <= r.bottom(); ++y ) + { + Cell* cell = m_view->activeSheet()->nonDefaultCell( r.right(), y ); + if(!cell->isPartOfMerged()) + { + if ( y == r.top() ) + { + if ( m_cells[3] ) + cell->setRightBorderPen( m_cells[3]->leftBorderPen( 0, 0 ) ); + } + else if ( y == r.right() ) + { + if ( m_cells[11] ) + cell->setRightBorderPen( m_cells[11]->leftBorderPen( 0, 0 ) ); + } + else + { + if ( m_cells[7] ) + cell->setRightBorderPen( m_cells[7]->leftBorderPen( 0, 0 ) ); + } + } + } + + // Outer bottom border + for( x = r.left(); x <= r.right(); ++x ) + { + Cell* cell = m_view->activeSheet()->nonDefaultCell( x, r.bottom() ); + if(!cell->isPartOfMerged()) + { + if ( x == r.left() ) + { + if ( m_cells[12] ) + cell->setBottomBorderPen( m_cells[12]->topBorderPen( 0, 0 ) ); + } + else if ( x == r.right() ) + { + if ( m_cells[14] ) + cell->setBottomBorderPen( m_cells[14]->topBorderPen( 0, 0 ) ); + } + else + { + if ( m_cells[13] ) + cell->setBottomBorderPen( m_cells[13]->topBorderPen( 0, 0 ) ); + } + } + } + + m_view->selectionInfo()->initialize(r);//, m_view->activeSheet() ); + m_view->doc()->setModified( true ); + m_view->slotUpdateView( m_view->activeSheet() ); + accept(); +} + +bool FormatDialog::parseXML( const TQDomDocument& doc ) +{ + for( int i = 0; i < 16; ++i ) + { + delete m_cells[ i ]; + m_cells[ i ] = 0; + } + + TQDomElement e = doc.documentElement().firstChild().toElement(); + for( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + if ( e.tagName() == "cell" ) + { + Sheet* sheet = m_view->activeSheet(); + Format* cell = new Format( sheet, sheet->doc()->styleManager()->defaultStyle() ); + + if ( !cell->load( e.namedItem("format").toElement(), Paste::Normal ) ) + return false; + + int row = e.attribute("row").toInt(); + int column = e.attribute("column").toInt(); + int i = (row-1)*4 + (column-1); + if ( i < 0 || i >= 16 ) + return false; + + m_cells[ i ] = cell; + } + } + + return TRUE; +} + +#include "kspread_dlg_format.moc" diff --git a/kspread/dialogs/kspread_dlg_formula.cc b/kspread/dialogs/kspread_dlg_formula.cc deleted file mode 100644 index 8e53c525..00000000 --- a/kspread/dialogs/kspread_dlg_formula.cc +++ /dev/null @@ -1,763 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 1999-2003 Laurent Montel - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 2002 Daniel Herring - (C) 2000-2001 Werner Trobin - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include "kspread_dlg_formula.h" -#include "kspread_canvas.h" -#include "kspread_util.h" -#include "kspread_editors.h" -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_map.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "functions.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - -FormulaDialog::FormulaDialog( View* parent, const char* name,const TQString& formulaName) - : KDialogBase( parent, name,false,i18n("Function"), Ok|Cancel ) -{ - setWFlags( TQt::WDestructiveClose ); - - m_pView = parent; - m_focus = 0; - m_desc = 0; - - Cell* cell = m_pView->activeSheet()->cellAt( m_pView->canvasWidget()->markerColumn(), - m_pView->canvasWidget()->markerRow() ); - m_oldText=cell->text(); - // Make sure that there is a cell editor running. - if ( !m_pView->canvasWidget()->editor() ) - { - m_pView->canvasWidget()->createEditor( Canvas::CellEditor ); - if(cell->text().isEmpty()) - m_pView->canvasWidget()->editor()->setText( "=" ); - else - if(cell->text().at(0)!='=') - m_pView->canvasWidget()->editor()->setText( "="+cell->text() ); - else - m_pView->canvasWidget()->editor()->setText( cell->text() ); - } - - Q_ASSERT( m_pView->canvasWidget()->editor() ); - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - - TQGridLayout *grid1 = new TQGridLayout(page,11,2,KDialog::marginHint(), KDialog::spacingHint()); - - searchFunct = new KLineEdit(page); - TQSizePolicy sp3( TQSizePolicy::Preferred, TQSizePolicy::Fixed ); - searchFunct->setSizePolicy( sp3 ); - - grid1->addWidget( searchFunct, 0, 0 ); - - typeFunction = new TQComboBox(page); - TQStringList cats = FunctionRepository::self()->groups(); - cats.prepend( i18n("All") ); - typeFunction->insertStringList( cats ); - grid1->addWidget( typeFunction, 1, 0 ); - - functions = new TQListBox(page); - TQSizePolicy sp1( TQSizePolicy::Preferred, TQSizePolicy::Expanding ); - functions->setSizePolicy( sp1 ); - grid1->addWidget( functions, 2, 0 ); - - selectFunction = new TQPushButton( page ); - TQToolTip::add(selectFunction, i18n("Insert function") ); - selectFunction->setPixmap( BarIcon( "go-down", TDEIcon::SizeSmall ) ); - grid1->addWidget( selectFunction, 3, 0 ); - - result = new TQLineEdit( page ); - grid1->addMultiCellWidget( result, 4, 4, 0, 1 ); - - m_tabwidget = new TQTabWidget( page ); - TQSizePolicy sp2( TQSizePolicy::Expanding, TQSizePolicy::Expanding ); - m_tabwidget->setSizePolicy( sp2 ); - grid1->addMultiCellWidget( m_tabwidget, 0, 2, 1, 1 ); - - m_browser = new TQTextBrowser( m_tabwidget ); - m_browser->setMinimumWidth( 300 ); - - m_tabwidget->addTab( m_browser, i18n("&Help") ); - int index = m_tabwidget->currentPageIndex(); - - m_input = new TQWidget( m_tabwidget ); - TQVBoxLayout *grid2 = new TQVBoxLayout( m_input, KDialog::marginHint(), KDialog::spacingHint() ); - - // grid2->setResizeMode (TQLayout::Minimum); - - label1 = new TQLabel(m_input); - grid2->addWidget( label1 ); - - firstElement=new TQLineEdit(m_input); - grid2->addWidget( firstElement ); - - label2=new TQLabel(m_input); - grid2->addWidget( label2 ); - - secondElement=new TQLineEdit(m_input); - grid2->addWidget( secondElement ); - - label3=new TQLabel(m_input); - grid2->addWidget( label3 ); - - thirdElement=new TQLineEdit(m_input); - grid2->addWidget( thirdElement ); - - label4=new TQLabel(m_input); - grid2->addWidget( label4 ); - - fourElement=new TQLineEdit(m_input); - grid2->addWidget( fourElement ); - - label5=new TQLabel(m_input); - grid2->addWidget( label5 ); - - fiveElement=new TQLineEdit(m_input); - grid2->addWidget( fiveElement ); - - grid2->addStretch( 10 ); - - m_tabwidget->addTab( m_input, i18n("&Parameters") ); - m_tabwidget->setTabEnabled( m_input, FALSE ); - - m_tabwidget->setCurrentPage( index ); - - refresh_result = true; - - connect( this, TQT_SIGNAL( cancelClicked() ), this, TQT_SLOT( slotClose() ) ); - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( typeFunction, TQT_SIGNAL( activated(const TQString &) ), - this, TQT_SLOT( slotActivated(const TQString &) ) ); - connect( functions, TQT_SIGNAL( highlighted(const TQString &) ), - this, TQT_SLOT( slotSelected(const TQString &) ) ); - connect( functions, TQT_SIGNAL( selected(const TQString &) ), - this, TQT_SLOT( slotSelected(const TQString &) ) ); - connect( functions, TQT_SIGNAL( doubleClicked(TQListBoxItem * ) ), - this ,TQT_SLOT( slotDoubleClicked(TQListBoxItem *) ) ); - - slotActivated(i18n("All")); - - connect( selectFunction, TQT_SIGNAL(clicked()), - this,TQT_SLOT(slotSelectButton())); - - connect( firstElement,TQT_SIGNAL(textChanged ( const TQString & )), - this,TQT_SLOT(slotChangeText(const TQString &))); - connect( secondElement,TQT_SIGNAL(textChanged ( const TQString & )), - this,TQT_SLOT(slotChangeText(const TQString &))); - connect( thirdElement,TQT_SIGNAL(textChanged ( const TQString & )), - this,TQT_SLOT(slotChangeText(const TQString &))); - connect( fourElement,TQT_SIGNAL(textChanged ( const TQString & )), - this,TQT_SLOT(slotChangeText(const TQString &))); - connect( fiveElement,TQT_SIGNAL(textChanged ( const TQString & )), - this,TQT_SLOT(slotChangeText(const TQString &))); - - connect( m_pView->choice(), TQT_SIGNAL(changed(const Region&)), - this, TQT_SLOT(slotSelectionChanged())); - - connect( m_browser, TQT_SIGNAL( linkClicked( const TQString& ) ), - this, TQT_SLOT( slotShowFunction( const TQString& ) ) ); - - // Save the name of the active sheet. - m_sheetName = m_pView->activeSheet()->sheetName(); - // Save the cells current text. - TQString tmp_oldText = m_pView->canvasWidget()->editor()->text(); - // Position of the cell. - m_column = m_pView->canvasWidget()->markerColumn(); - m_row = m_pView->canvasWidget()->markerRow(); - - if( tmp_oldText.isEmpty() ) - result->setText("="); - else - { - if( tmp_oldText.at(0)!='=') - result->setText( "=" + tmp_oldText ); - else - result->setText( tmp_oldText ); - } - - // Allow the user to select cells on the spreadsheet. - m_pView->canvasWidget()->startChoose(); - - tqApp->installEventFilter( this ); - - // Was a function name passed along with the constructor ? Then activate it. - if( !formulaName.isEmpty() ) - { - functions->setCurrentItem( functions->index( functions->findItem( formulaName ) ) ); - slotDoubleClicked( functions->findItem( formulaName ) ); - } - else - { - // Set keyboard focus to allow selection of a formula. - searchFunct->setFocus(); - } - - // Add auto completion. - searchFunct->setCompletionMode( TDEGlobalSettings::CompletionAuto ); - searchFunct->setCompletionObject( &listFunct, true ); - - if( functions->currentItem() == -1 ) - selectFunction->setEnabled( false ); - - connect( searchFunct, TQT_SIGNAL( textChanged( const TQString & ) ), - this, TQT_SLOT( slotSearchText(const TQString &) ) ); - connect( searchFunct, TQT_SIGNAL( returnPressed() ), - this, TQT_SLOT( slotPressReturn() ) ); -} - -FormulaDialog::~FormulaDialog() -{ - kdDebug(36001)<<"FormulaDialog::~FormulaDialog() \n"; -} - -void FormulaDialog::slotPressReturn() -{ - //laurent 2001-07-07 desactivate this code - //because kspread crash. - //TODO fix it - /* - if( !functions->currentText().isEmpty() ) - slotDoubleClicked( functions->findItem( functions->currentText() ) ); - */ -} - -void FormulaDialog::slotSearchText(const TQString &_text) -{ - TQString result = listFunct.makeCompletion( _text.upper() ); - if( !result.isNull() ) - functions->setCurrentItem( functions->index( functions->findItem( result ) ) ); -} - -bool FormulaDialog::eventFilter( TQObject* obj, TQEvent* ev ) -{ - if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(firstElement) && ev->type() == TQEvent::FocusIn ) - m_focus = firstElement; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(secondElement) && ev->type() == TQEvent::FocusIn ) - m_focus = secondElement; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(thirdElement) && ev->type() == TQEvent::FocusIn ) - m_focus = thirdElement; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(fourElement) && ev->type() == TQEvent::FocusIn ) - m_focus = fourElement; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(fiveElement) && ev->type() == TQEvent::FocusIn ) - m_focus = fiveElement; - else - return FALSE; - - if ( m_focus ) - m_pView->canvasWidget()->startChoose(); - - return FALSE; -} - -void FormulaDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - m_pView->canvasWidget()->endChoose(); - // Switch back to the old sheet - if( m_pView->activeSheet()->sheetName() != m_sheetName ) - { - Sheet *sheet=m_pView->doc()->map()->findSheet(m_sheetName); - if( sheet) - m_pView->setActiveSheet(sheet); - } - - // Revert the marker to its original position - m_pView->selectionInfo()->initialize( TQPoint( m_column, m_row ) ); - - // If there is still an editor then set the text. - // Usually the editor is always in place. - if( m_pView->canvasWidget()->editor() != 0 ) - { - Q_ASSERT( m_pView->canvasWidget()->editor() ); - TQString tmp = result->text(); - if( tmp.at(0) != '=') - tmp = "=" + tmp; - int pos = m_pView->canvasWidget()->editor()->cursorPosition()+ tmp.length(); - m_pView->canvasWidget()->editor()->setText( tmp ); - m_pView->canvasWidget()->editor()->setFocus(); - m_pView->canvasWidget()->editor()->setCursorPosition( pos ); - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); - // delete this; -} - -void FormulaDialog::slotClose() -{ - m_pView->doc()->emitBeginOperation( false ); - - m_pView->canvasWidget()->endChoose(); - - // Switch back to the old sheet - if(m_pView->activeSheet()->sheetName() != m_sheetName ) - { - Sheet *sheet=m_pView->doc()->map()->findSheet(m_sheetName); - if( !sheet ) - return; - m_pView->setActiveSheet(sheet); - } - - - // Revert the marker to its original position - m_pView->selectionInfo()->initialize( TQPoint( m_column, m_row ) ); - - // If there is still an editor then reset the text. - // Usually the editor is always in place. - if( m_pView->canvasWidget()->editor() != 0 ) - { - Q_ASSERT( m_pView->canvasWidget()->editor() ); - m_pView->canvasWidget()->editor()->setText( m_oldText ); - m_pView->canvasWidget()->editor()->setFocus(); - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - reject(); - //laurent 2002-01-03 comment this line otherwise kspread crash - //but dialog box is not deleted => not good - //delete this; -} - -void FormulaDialog::slotSelectButton() -{ - if( functions->currentItem() != -1 ) - { - slotDoubleClicked(functions->findItem(functions->text(functions->currentItem()))); - } -} - -void FormulaDialog::slotChangeText( const TQString& ) -{ - // Test the lock - if( !refresh_result ) - return; - - if ( m_focus == 0 ) - return; - - TQString tmp = m_leftText+m_funcName+"("; - tmp += createFormula(); - tmp = tmp+ ")" + m_rightText; - - result->setText( tmp ); -} - -TQString FormulaDialog::createFormula() -{ - TQString tmp( "" ); - - if ( !m_desc ) - return TQString(); - - bool first = TRUE; - - int count = m_desc->params(); - - if(!firstElement->text().isEmpty() && count >= 1 ) - { - tmp=tmp+createParameter(firstElement->text(), 0 ); - first = FALSE; - } - - if(!secondElement->text().isEmpty() && count >= 2 ) - { - first = FALSE; - if ( !first ) - tmp=tmp+";"+createParameter(secondElement->text(), 1 ); - else - tmp=tmp+createParameter(secondElement->text(), 1 ); - } - if(!thirdElement->text().isEmpty() && count >= 3 ) - { - first = FALSE; - if ( !first ) - tmp=tmp+";"+createParameter(thirdElement->text(), 2 ); - else - tmp=tmp+createParameter(thirdElement->text(), 2 ); - } - if(!fourElement->text().isEmpty() && count >= 4 ) - { - first = FALSE; - if ( !first ) - tmp=tmp+";"+createParameter(fourElement->text(), 3 ); - else - tmp=tmp+createParameter(fourElement->text(), 3 ); - } - if(!fiveElement->text().isEmpty() && count >= 5 ) - { - first = FALSE; - if ( !first ) - tmp=tmp+";"+createParameter(fiveElement->text(), 4 ); - else - tmp=tmp+createParameter(fiveElement->text(), 4 ); - } - - return(tmp); -} - -TQString FormulaDialog::createParameter( const TQString& _text, int param ) -{ - if ( _text.isEmpty() ) - return TQString( "" ); - - if ( !m_desc ) - return TQString( "" ); - - TQString text; - - ParameterType elementType = m_desc->param( param ).type(); - - switch( elementType ) - { - case KSpread_Any: - { - bool isNumber; - double tmp = m_pView->doc()->locale()->readNumber( _text, &isNumber ); - Q_UNUSED( tmp ); - - //In case of number or boolean return _text, else return value as KSpread_String - if ( isNumber || _text.upper() =="FALSE" || _text.upper() == "TRUE" ) - return _text; - } - // fall through - case KSpread_String: - { - // Does the text start with quotes? - if ( _text[0] == '"' ) - { - text = "\\"; // changed: was "\"" - - // Escape quotes - TQString tmp = _text; - int pos; - int start = 1; - while( ( pos = tmp.find( '"', start ) ) != -1 ) - { - if (tmp[pos - 1] != '\\') - tmp.replace( pos, 1, "\\\"" ); - else - start = pos + 1; - } - - text += tmp; - text += "\""; - } - else - { - Point p = Point( _text, m_pView->doc()->map() ); - Range r = Range( _text, m_pView->doc()->map() ); - - if( !p.isValid() && !r.isValid() ) - { - text = "\""; - - // Escape quotes - TQString tmp = _text; - int pos; - int start = 1; - while( ( pos = tmp.find( '"', start ) ) != -1 ) - { - if (tmp[pos - 1] != '\\') - tmp.replace( pos, 1, "\\\"" ); - else - start = pos + 1; - } - - text += tmp; - text += "\""; - } - else - text = _text; - } - } - return text; - case KSpread_Float: - return _text; - case KSpread_Boolean: - return _text; - case KSpread_Int: - return _text; - } - - // Never reached - return text; -} - -static void showEntry( TQLineEdit* edit, TQLabel* label, - FunctionDescription* desc, int param ) -{ - edit->show(); - label->setText( desc->param( param ).helpText()+":" ); - label->show(); - ParameterType elementType = desc->param( param ).type(); - KFloatValidator *validate=0L; - switch( elementType ) - { - case KSpread_String: - case KSpread_Boolean: - case KSpread_Any: - edit->clearValidator (); - break; - case KSpread_Float: - validate=new KFloatValidator (edit); - validate->setAcceptLocalizedNumbers(true); - edit->setValidator(validate); - edit->setText( "0" ); - break; - case KSpread_Int: - edit->setValidator(new TQIntValidator (TQT_TQOBJECT(edit))); - edit->setText( "0" ); - break; - } - -} - -void FormulaDialog::slotDoubleClicked( TQListBoxItem* item ) -{ - if ( !item ) - return; - refresh_result = false; - if ( !m_desc ) - { - m_browser->setText( "" ); - return; - } - - m_focus = 0; - int old_length = result->text().length(); - - // Dont change order of these function calls due to a bug in TQt 2.2 - m_browser->setText( m_desc->toTQML() ); - m_tabwidget->setTabEnabled( m_input, TRUE ); - m_tabwidget->setCurrentPage( 1 ); - - // - // Show as many TQLineEdits as needed. - // - if( m_desc->params() > 0 ) - { - m_focus = firstElement; - firstElement->setFocus(); - - showEntry( firstElement, label1, m_desc, 0 ); - } - else - { - label1->hide(); - firstElement->hide(); - } - - if( m_desc->params() > 1 ) - { - showEntry( secondElement, label2, m_desc, 1 ); - } - else - { - label2->hide(); - secondElement->hide(); - } - - if( m_desc->params() > 2 ) - { - showEntry( thirdElement, label3, m_desc, 2 ); - } - else - { - label3->hide(); - thirdElement->hide(); - } - - if( m_desc->params() > 3 ) - { - showEntry( fourElement, label4, m_desc, 3 ); - } - else - { - label4->hide(); - fourElement->hide(); - } - - if( m_desc->params() > 4 ) - { - showEntry( fiveElement, label5, m_desc, 4 ); - } - else - { - label5->hide(); - fiveElement->hide(); - } - - if( m_desc->params() > 5 ) - { - kdDebug(36001) << "Error in param->nb_param" << endl; - } - refresh_result= true; - // - // Put the new function call in the result. - // - if( result->cursorPosition() < old_length ) - { - m_rightText=result->text().right(old_length-result->cursorPosition()); - m_leftText=result->text().left(result->cursorPosition()); - } - else - { - m_rightText=""; - m_leftText=result->text(); - } - int pos = result->cursorPosition(); - result->setText( m_leftText+functions->text( functions->currentItem() ) + "()" + m_rightText); - - if (result->text()[0] != '=') - result->setText("=" + result->text()); - - // - // Put focus somewhere is there are no TQLineEdits visible - // - if( m_desc->params() == 0 ) - { - label1->show(); - label1->setText( i18n("This function has no parameters.") ); - - result->setFocus(); - result->setCursorPosition(pos+functions->text(functions->currentItem()).length()+2); - } - slotChangeText( "" ); -} - -void FormulaDialog::slotSelected( const TQString& function ) -{ - FunctionDescription* desc = - FunctionRepository::self()->functionInfo (function); - if ( !desc ) - { - m_browser->setText (i18n ("Description is not available.")); - return; - } - - if( functions->currentItem() !=- 1 ) - selectFunction->setEnabled( TRUE ); - - // Lock - refresh_result = false; - - m_funcName = function; - m_desc = desc; - - // Set the help text - m_browser->setText( m_desc->toTQML() ); - m_browser->setContentsPos( 0, 0 ); - - m_focus=0; - - m_tabwidget->setCurrentPage( 0 ); - m_tabwidget->setTabEnabled( m_input, FALSE ); - - // Unlock - refresh_result=true; -} - -// from hyperlink in the "Related Function" -void FormulaDialog::slotShowFunction( const TQString& function ) -{ - FunctionDescription* desc = - FunctionRepository::self()->functionInfo( function ); - if ( !desc ) return; - - // select the category - TQString category = desc->group(); - typeFunction->setCurrentText( category ); - slotActivated( category ); - - // select the function - TQListBoxItem* item = functions->findItem( function, - TQt::ExactMatch | TQt::CaseSensitive ); - if( item ) functions->setCurrentItem( item ); - - slotSelected( function ); -} - -void FormulaDialog::slotSelectionChanged() -{ - if ( !m_focus ) - return; - - if (m_pView->choice()->isValid()) - { - TQString area = m_pView->choice()->name(); - m_focus->setText( area ); - } -} - -void FormulaDialog::slotActivated( const TQString& category ) -{ - TQStringList lst; - if ( category == i18n("All") ) - lst = FunctionRepository::self()->functionNames(); - else - lst = FunctionRepository::self()->functionNames( category ); - - kdDebug(36001)<<"category: "<clear(); - functions->insertStringList( lst ); - - TQStringList upperList; - for ( TQStringList::Iterator it = lst.begin(); it != lst.end();++it ) - upperList.append((*it).upper()); - - listFunct.setItems( upperList ); - - // Go to the first function in the list. - functions->setCurrentItem(0); - slotSelected( functions->text(0) ); -} - -void FormulaDialog::closeEvent ( TQCloseEvent * e ) -{ - e->accept(); -} - -#include "kspread_dlg_formula.moc" diff --git a/kspread/dialogs/kspread_dlg_formula.cpp b/kspread/dialogs/kspread_dlg_formula.cpp new file mode 100644 index 00000000..8e53c525 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_formula.cpp @@ -0,0 +1,763 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 1999-2003 Laurent Montel + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 2002 Daniel Herring + (C) 2000-2001 Werner Trobin + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "kspread_dlg_formula.h" +#include "kspread_canvas.h" +#include "kspread_util.h" +#include "kspread_editors.h" +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_map.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "functions.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + +FormulaDialog::FormulaDialog( View* parent, const char* name,const TQString& formulaName) + : KDialogBase( parent, name,false,i18n("Function"), Ok|Cancel ) +{ + setWFlags( TQt::WDestructiveClose ); + + m_pView = parent; + m_focus = 0; + m_desc = 0; + + Cell* cell = m_pView->activeSheet()->cellAt( m_pView->canvasWidget()->markerColumn(), + m_pView->canvasWidget()->markerRow() ); + m_oldText=cell->text(); + // Make sure that there is a cell editor running. + if ( !m_pView->canvasWidget()->editor() ) + { + m_pView->canvasWidget()->createEditor( Canvas::CellEditor ); + if(cell->text().isEmpty()) + m_pView->canvasWidget()->editor()->setText( "=" ); + else + if(cell->text().at(0)!='=') + m_pView->canvasWidget()->editor()->setText( "="+cell->text() ); + else + m_pView->canvasWidget()->editor()->setText( cell->text() ); + } + + Q_ASSERT( m_pView->canvasWidget()->editor() ); + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + + TQGridLayout *grid1 = new TQGridLayout(page,11,2,KDialog::marginHint(), KDialog::spacingHint()); + + searchFunct = new KLineEdit(page); + TQSizePolicy sp3( TQSizePolicy::Preferred, TQSizePolicy::Fixed ); + searchFunct->setSizePolicy( sp3 ); + + grid1->addWidget( searchFunct, 0, 0 ); + + typeFunction = new TQComboBox(page); + TQStringList cats = FunctionRepository::self()->groups(); + cats.prepend( i18n("All") ); + typeFunction->insertStringList( cats ); + grid1->addWidget( typeFunction, 1, 0 ); + + functions = new TQListBox(page); + TQSizePolicy sp1( TQSizePolicy::Preferred, TQSizePolicy::Expanding ); + functions->setSizePolicy( sp1 ); + grid1->addWidget( functions, 2, 0 ); + + selectFunction = new TQPushButton( page ); + TQToolTip::add(selectFunction, i18n("Insert function") ); + selectFunction->setPixmap( BarIcon( "go-down", TDEIcon::SizeSmall ) ); + grid1->addWidget( selectFunction, 3, 0 ); + + result = new TQLineEdit( page ); + grid1->addMultiCellWidget( result, 4, 4, 0, 1 ); + + m_tabwidget = new TQTabWidget( page ); + TQSizePolicy sp2( TQSizePolicy::Expanding, TQSizePolicy::Expanding ); + m_tabwidget->setSizePolicy( sp2 ); + grid1->addMultiCellWidget( m_tabwidget, 0, 2, 1, 1 ); + + m_browser = new TQTextBrowser( m_tabwidget ); + m_browser->setMinimumWidth( 300 ); + + m_tabwidget->addTab( m_browser, i18n("&Help") ); + int index = m_tabwidget->currentPageIndex(); + + m_input = new TQWidget( m_tabwidget ); + TQVBoxLayout *grid2 = new TQVBoxLayout( m_input, KDialog::marginHint(), KDialog::spacingHint() ); + + // grid2->setResizeMode (TQLayout::Minimum); + + label1 = new TQLabel(m_input); + grid2->addWidget( label1 ); + + firstElement=new TQLineEdit(m_input); + grid2->addWidget( firstElement ); + + label2=new TQLabel(m_input); + grid2->addWidget( label2 ); + + secondElement=new TQLineEdit(m_input); + grid2->addWidget( secondElement ); + + label3=new TQLabel(m_input); + grid2->addWidget( label3 ); + + thirdElement=new TQLineEdit(m_input); + grid2->addWidget( thirdElement ); + + label4=new TQLabel(m_input); + grid2->addWidget( label4 ); + + fourElement=new TQLineEdit(m_input); + grid2->addWidget( fourElement ); + + label5=new TQLabel(m_input); + grid2->addWidget( label5 ); + + fiveElement=new TQLineEdit(m_input); + grid2->addWidget( fiveElement ); + + grid2->addStretch( 10 ); + + m_tabwidget->addTab( m_input, i18n("&Parameters") ); + m_tabwidget->setTabEnabled( m_input, FALSE ); + + m_tabwidget->setCurrentPage( index ); + + refresh_result = true; + + connect( this, TQT_SIGNAL( cancelClicked() ), this, TQT_SLOT( slotClose() ) ); + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( typeFunction, TQT_SIGNAL( activated(const TQString &) ), + this, TQT_SLOT( slotActivated(const TQString &) ) ); + connect( functions, TQT_SIGNAL( highlighted(const TQString &) ), + this, TQT_SLOT( slotSelected(const TQString &) ) ); + connect( functions, TQT_SIGNAL( selected(const TQString &) ), + this, TQT_SLOT( slotSelected(const TQString &) ) ); + connect( functions, TQT_SIGNAL( doubleClicked(TQListBoxItem * ) ), + this ,TQT_SLOT( slotDoubleClicked(TQListBoxItem *) ) ); + + slotActivated(i18n("All")); + + connect( selectFunction, TQT_SIGNAL(clicked()), + this,TQT_SLOT(slotSelectButton())); + + connect( firstElement,TQT_SIGNAL(textChanged ( const TQString & )), + this,TQT_SLOT(slotChangeText(const TQString &))); + connect( secondElement,TQT_SIGNAL(textChanged ( const TQString & )), + this,TQT_SLOT(slotChangeText(const TQString &))); + connect( thirdElement,TQT_SIGNAL(textChanged ( const TQString & )), + this,TQT_SLOT(slotChangeText(const TQString &))); + connect( fourElement,TQT_SIGNAL(textChanged ( const TQString & )), + this,TQT_SLOT(slotChangeText(const TQString &))); + connect( fiveElement,TQT_SIGNAL(textChanged ( const TQString & )), + this,TQT_SLOT(slotChangeText(const TQString &))); + + connect( m_pView->choice(), TQT_SIGNAL(changed(const Region&)), + this, TQT_SLOT(slotSelectionChanged())); + + connect( m_browser, TQT_SIGNAL( linkClicked( const TQString& ) ), + this, TQT_SLOT( slotShowFunction( const TQString& ) ) ); + + // Save the name of the active sheet. + m_sheetName = m_pView->activeSheet()->sheetName(); + // Save the cells current text. + TQString tmp_oldText = m_pView->canvasWidget()->editor()->text(); + // Position of the cell. + m_column = m_pView->canvasWidget()->markerColumn(); + m_row = m_pView->canvasWidget()->markerRow(); + + if( tmp_oldText.isEmpty() ) + result->setText("="); + else + { + if( tmp_oldText.at(0)!='=') + result->setText( "=" + tmp_oldText ); + else + result->setText( tmp_oldText ); + } + + // Allow the user to select cells on the spreadsheet. + m_pView->canvasWidget()->startChoose(); + + tqApp->installEventFilter( this ); + + // Was a function name passed along with the constructor ? Then activate it. + if( !formulaName.isEmpty() ) + { + functions->setCurrentItem( functions->index( functions->findItem( formulaName ) ) ); + slotDoubleClicked( functions->findItem( formulaName ) ); + } + else + { + // Set keyboard focus to allow selection of a formula. + searchFunct->setFocus(); + } + + // Add auto completion. + searchFunct->setCompletionMode( TDEGlobalSettings::CompletionAuto ); + searchFunct->setCompletionObject( &listFunct, true ); + + if( functions->currentItem() == -1 ) + selectFunction->setEnabled( false ); + + connect( searchFunct, TQT_SIGNAL( textChanged( const TQString & ) ), + this, TQT_SLOT( slotSearchText(const TQString &) ) ); + connect( searchFunct, TQT_SIGNAL( returnPressed() ), + this, TQT_SLOT( slotPressReturn() ) ); +} + +FormulaDialog::~FormulaDialog() +{ + kdDebug(36001)<<"FormulaDialog::~FormulaDialog() \n"; +} + +void FormulaDialog::slotPressReturn() +{ + //laurent 2001-07-07 desactivate this code + //because kspread crash. + //TODO fix it + /* + if( !functions->currentText().isEmpty() ) + slotDoubleClicked( functions->findItem( functions->currentText() ) ); + */ +} + +void FormulaDialog::slotSearchText(const TQString &_text) +{ + TQString result = listFunct.makeCompletion( _text.upper() ); + if( !result.isNull() ) + functions->setCurrentItem( functions->index( functions->findItem( result ) ) ); +} + +bool FormulaDialog::eventFilter( TQObject* obj, TQEvent* ev ) +{ + if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(firstElement) && ev->type() == TQEvent::FocusIn ) + m_focus = firstElement; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(secondElement) && ev->type() == TQEvent::FocusIn ) + m_focus = secondElement; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(thirdElement) && ev->type() == TQEvent::FocusIn ) + m_focus = thirdElement; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(fourElement) && ev->type() == TQEvent::FocusIn ) + m_focus = fourElement; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(fiveElement) && ev->type() == TQEvent::FocusIn ) + m_focus = fiveElement; + else + return FALSE; + + if ( m_focus ) + m_pView->canvasWidget()->startChoose(); + + return FALSE; +} + +void FormulaDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + m_pView->canvasWidget()->endChoose(); + // Switch back to the old sheet + if( m_pView->activeSheet()->sheetName() != m_sheetName ) + { + Sheet *sheet=m_pView->doc()->map()->findSheet(m_sheetName); + if( sheet) + m_pView->setActiveSheet(sheet); + } + + // Revert the marker to its original position + m_pView->selectionInfo()->initialize( TQPoint( m_column, m_row ) ); + + // If there is still an editor then set the text. + // Usually the editor is always in place. + if( m_pView->canvasWidget()->editor() != 0 ) + { + Q_ASSERT( m_pView->canvasWidget()->editor() ); + TQString tmp = result->text(); + if( tmp.at(0) != '=') + tmp = "=" + tmp; + int pos = m_pView->canvasWidget()->editor()->cursorPosition()+ tmp.length(); + m_pView->canvasWidget()->editor()->setText( tmp ); + m_pView->canvasWidget()->editor()->setFocus(); + m_pView->canvasWidget()->editor()->setCursorPosition( pos ); + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); + // delete this; +} + +void FormulaDialog::slotClose() +{ + m_pView->doc()->emitBeginOperation( false ); + + m_pView->canvasWidget()->endChoose(); + + // Switch back to the old sheet + if(m_pView->activeSheet()->sheetName() != m_sheetName ) + { + Sheet *sheet=m_pView->doc()->map()->findSheet(m_sheetName); + if( !sheet ) + return; + m_pView->setActiveSheet(sheet); + } + + + // Revert the marker to its original position + m_pView->selectionInfo()->initialize( TQPoint( m_column, m_row ) ); + + // If there is still an editor then reset the text. + // Usually the editor is always in place. + if( m_pView->canvasWidget()->editor() != 0 ) + { + Q_ASSERT( m_pView->canvasWidget()->editor() ); + m_pView->canvasWidget()->editor()->setText( m_oldText ); + m_pView->canvasWidget()->editor()->setFocus(); + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + reject(); + //laurent 2002-01-03 comment this line otherwise kspread crash + //but dialog box is not deleted => not good + //delete this; +} + +void FormulaDialog::slotSelectButton() +{ + if( functions->currentItem() != -1 ) + { + slotDoubleClicked(functions->findItem(functions->text(functions->currentItem()))); + } +} + +void FormulaDialog::slotChangeText( const TQString& ) +{ + // Test the lock + if( !refresh_result ) + return; + + if ( m_focus == 0 ) + return; + + TQString tmp = m_leftText+m_funcName+"("; + tmp += createFormula(); + tmp = tmp+ ")" + m_rightText; + + result->setText( tmp ); +} + +TQString FormulaDialog::createFormula() +{ + TQString tmp( "" ); + + if ( !m_desc ) + return TQString(); + + bool first = TRUE; + + int count = m_desc->params(); + + if(!firstElement->text().isEmpty() && count >= 1 ) + { + tmp=tmp+createParameter(firstElement->text(), 0 ); + first = FALSE; + } + + if(!secondElement->text().isEmpty() && count >= 2 ) + { + first = FALSE; + if ( !first ) + tmp=tmp+";"+createParameter(secondElement->text(), 1 ); + else + tmp=tmp+createParameter(secondElement->text(), 1 ); + } + if(!thirdElement->text().isEmpty() && count >= 3 ) + { + first = FALSE; + if ( !first ) + tmp=tmp+";"+createParameter(thirdElement->text(), 2 ); + else + tmp=tmp+createParameter(thirdElement->text(), 2 ); + } + if(!fourElement->text().isEmpty() && count >= 4 ) + { + first = FALSE; + if ( !first ) + tmp=tmp+";"+createParameter(fourElement->text(), 3 ); + else + tmp=tmp+createParameter(fourElement->text(), 3 ); + } + if(!fiveElement->text().isEmpty() && count >= 5 ) + { + first = FALSE; + if ( !first ) + tmp=tmp+";"+createParameter(fiveElement->text(), 4 ); + else + tmp=tmp+createParameter(fiveElement->text(), 4 ); + } + + return(tmp); +} + +TQString FormulaDialog::createParameter( const TQString& _text, int param ) +{ + if ( _text.isEmpty() ) + return TQString( "" ); + + if ( !m_desc ) + return TQString( "" ); + + TQString text; + + ParameterType elementType = m_desc->param( param ).type(); + + switch( elementType ) + { + case KSpread_Any: + { + bool isNumber; + double tmp = m_pView->doc()->locale()->readNumber( _text, &isNumber ); + Q_UNUSED( tmp ); + + //In case of number or boolean return _text, else return value as KSpread_String + if ( isNumber || _text.upper() =="FALSE" || _text.upper() == "TRUE" ) + return _text; + } + // fall through + case KSpread_String: + { + // Does the text start with quotes? + if ( _text[0] == '"' ) + { + text = "\\"; // changed: was "\"" + + // Escape quotes + TQString tmp = _text; + int pos; + int start = 1; + while( ( pos = tmp.find( '"', start ) ) != -1 ) + { + if (tmp[pos - 1] != '\\') + tmp.replace( pos, 1, "\\\"" ); + else + start = pos + 1; + } + + text += tmp; + text += "\""; + } + else + { + Point p = Point( _text, m_pView->doc()->map() ); + Range r = Range( _text, m_pView->doc()->map() ); + + if( !p.isValid() && !r.isValid() ) + { + text = "\""; + + // Escape quotes + TQString tmp = _text; + int pos; + int start = 1; + while( ( pos = tmp.find( '"', start ) ) != -1 ) + { + if (tmp[pos - 1] != '\\') + tmp.replace( pos, 1, "\\\"" ); + else + start = pos + 1; + } + + text += tmp; + text += "\""; + } + else + text = _text; + } + } + return text; + case KSpread_Float: + return _text; + case KSpread_Boolean: + return _text; + case KSpread_Int: + return _text; + } + + // Never reached + return text; +} + +static void showEntry( TQLineEdit* edit, TQLabel* label, + FunctionDescription* desc, int param ) +{ + edit->show(); + label->setText( desc->param( param ).helpText()+":" ); + label->show(); + ParameterType elementType = desc->param( param ).type(); + KFloatValidator *validate=0L; + switch( elementType ) + { + case KSpread_String: + case KSpread_Boolean: + case KSpread_Any: + edit->clearValidator (); + break; + case KSpread_Float: + validate=new KFloatValidator (edit); + validate->setAcceptLocalizedNumbers(true); + edit->setValidator(validate); + edit->setText( "0" ); + break; + case KSpread_Int: + edit->setValidator(new TQIntValidator (TQT_TQOBJECT(edit))); + edit->setText( "0" ); + break; + } + +} + +void FormulaDialog::slotDoubleClicked( TQListBoxItem* item ) +{ + if ( !item ) + return; + refresh_result = false; + if ( !m_desc ) + { + m_browser->setText( "" ); + return; + } + + m_focus = 0; + int old_length = result->text().length(); + + // Dont change order of these function calls due to a bug in TQt 2.2 + m_browser->setText( m_desc->toTQML() ); + m_tabwidget->setTabEnabled( m_input, TRUE ); + m_tabwidget->setCurrentPage( 1 ); + + // + // Show as many TQLineEdits as needed. + // + if( m_desc->params() > 0 ) + { + m_focus = firstElement; + firstElement->setFocus(); + + showEntry( firstElement, label1, m_desc, 0 ); + } + else + { + label1->hide(); + firstElement->hide(); + } + + if( m_desc->params() > 1 ) + { + showEntry( secondElement, label2, m_desc, 1 ); + } + else + { + label2->hide(); + secondElement->hide(); + } + + if( m_desc->params() > 2 ) + { + showEntry( thirdElement, label3, m_desc, 2 ); + } + else + { + label3->hide(); + thirdElement->hide(); + } + + if( m_desc->params() > 3 ) + { + showEntry( fourElement, label4, m_desc, 3 ); + } + else + { + label4->hide(); + fourElement->hide(); + } + + if( m_desc->params() > 4 ) + { + showEntry( fiveElement, label5, m_desc, 4 ); + } + else + { + label5->hide(); + fiveElement->hide(); + } + + if( m_desc->params() > 5 ) + { + kdDebug(36001) << "Error in param->nb_param" << endl; + } + refresh_result= true; + // + // Put the new function call in the result. + // + if( result->cursorPosition() < old_length ) + { + m_rightText=result->text().right(old_length-result->cursorPosition()); + m_leftText=result->text().left(result->cursorPosition()); + } + else + { + m_rightText=""; + m_leftText=result->text(); + } + int pos = result->cursorPosition(); + result->setText( m_leftText+functions->text( functions->currentItem() ) + "()" + m_rightText); + + if (result->text()[0] != '=') + result->setText("=" + result->text()); + + // + // Put focus somewhere is there are no TQLineEdits visible + // + if( m_desc->params() == 0 ) + { + label1->show(); + label1->setText( i18n("This function has no parameters.") ); + + result->setFocus(); + result->setCursorPosition(pos+functions->text(functions->currentItem()).length()+2); + } + slotChangeText( "" ); +} + +void FormulaDialog::slotSelected( const TQString& function ) +{ + FunctionDescription* desc = + FunctionRepository::self()->functionInfo (function); + if ( !desc ) + { + m_browser->setText (i18n ("Description is not available.")); + return; + } + + if( functions->currentItem() !=- 1 ) + selectFunction->setEnabled( TRUE ); + + // Lock + refresh_result = false; + + m_funcName = function; + m_desc = desc; + + // Set the help text + m_browser->setText( m_desc->toTQML() ); + m_browser->setContentsPos( 0, 0 ); + + m_focus=0; + + m_tabwidget->setCurrentPage( 0 ); + m_tabwidget->setTabEnabled( m_input, FALSE ); + + // Unlock + refresh_result=true; +} + +// from hyperlink in the "Related Function" +void FormulaDialog::slotShowFunction( const TQString& function ) +{ + FunctionDescription* desc = + FunctionRepository::self()->functionInfo( function ); + if ( !desc ) return; + + // select the category + TQString category = desc->group(); + typeFunction->setCurrentText( category ); + slotActivated( category ); + + // select the function + TQListBoxItem* item = functions->findItem( function, + TQt::ExactMatch | TQt::CaseSensitive ); + if( item ) functions->setCurrentItem( item ); + + slotSelected( function ); +} + +void FormulaDialog::slotSelectionChanged() +{ + if ( !m_focus ) + return; + + if (m_pView->choice()->isValid()) + { + TQString area = m_pView->choice()->name(); + m_focus->setText( area ); + } +} + +void FormulaDialog::slotActivated( const TQString& category ) +{ + TQStringList lst; + if ( category == i18n("All") ) + lst = FunctionRepository::self()->functionNames(); + else + lst = FunctionRepository::self()->functionNames( category ); + + kdDebug(36001)<<"category: "<clear(); + functions->insertStringList( lst ); + + TQStringList upperList; + for ( TQStringList::Iterator it = lst.begin(); it != lst.end();++it ) + upperList.append((*it).upper()); + + listFunct.setItems( upperList ); + + // Go to the first function in the list. + functions->setCurrentItem(0); + slotSelected( functions->text(0) ); +} + +void FormulaDialog::closeEvent ( TQCloseEvent * e ) +{ + e->accept(); +} + +#include "kspread_dlg_formula.moc" diff --git a/kspread/dialogs/kspread_dlg_goalseek.cc b/kspread/dialogs/kspread_dlg_goalseek.cc deleted file mode 100644 index b45525ad..00000000 --- a/kspread/dialogs/kspread_dlg_goalseek.cc +++ /dev/null @@ -1,486 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002-2003 Philipp Mueller - (C) 2002 Laurent Montel - (C) 2002 John Dailey - (C) 2002 Ariya Hidayat - (C) 2002 Werner Trobin - (C) 2002 Harri Porten - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_dlg_goalseek.h" - -#include "kspread_canvas.h" -#include "kspread_cell.h" -#include "kspread_doc.h" -#include "kspread_map.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_undo.h" -#include "kspread_util.h" -#include "kspread_view.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace KSpread; - -GoalSeekDialog::GoalSeekDialog( View * parent, TQPoint const & marker, - const char * name, bool, WFlags fl ) - : KDialog( parent, name, false, fl ), - m_pView( parent ), - m_maxIter( 1000 ), - m_restored( true ), - m_focus(0), - m_anchor( m_pView->selectionInfo()->anchor() ), - m_marker( m_pView->selectionInfo()->marker() ), - m_selection( m_pView->selectionInfo()->selection() ) -{ - setWFlags( TQt::WDestructiveClose ); - - if ( !name ) - setName( "GoalSeekDialog" ); - - resize( 458, 153 ); - setCaption( i18n( "Goal Seek" ) ); - setSizeGripEnabled( true ); - - GoalSeekDialogLayout = new TQGridLayout( this, 1, 1, 11, 6, "GoalSeekDialogLayout"); - - m_startFrame = new TQFrame( this, "m_startFrame" ); - m_startFrame->setFrameShape( TQFrame::StyledPanel ); - m_startFrame->setFrameShadow( TQFrame::Raised ); - m_startFrameLayout = new TQGridLayout( m_startFrame, 1, 1, 11, 6, "m_startFrameLayout"); - - TQLabel * TextLabel4 = new TQLabel( m_startFrame, "TextLabel4" ); - TextLabel4->setText( i18n( "To value:" ) ); - m_startFrameLayout->addWidget( TextLabel4, 1, 0 ); - - m_targetValueEdit = new TQLineEdit( m_startFrame, "m_targetValueEdit" ); - m_startFrameLayout->addWidget( m_targetValueEdit, 1, 1 ); - - m_targetEdit = new TQLineEdit( m_startFrame, "m_targetEdit" ); - m_startFrameLayout->addWidget( m_targetEdit, 0, 1 ); - m_targetEdit->setText( Cell::name( marker.x(), marker.y() ) ); - - m_sourceEdit = new TQLineEdit( m_startFrame, "m_sourceEdit" ); - m_startFrameLayout->addWidget( m_sourceEdit, 2, 1 ); - - TQLabel * TextLabel5 = new TQLabel( m_startFrame, "TextLabel5" ); - TextLabel5->setText( i18n( "By changing cell:" ) ); - - m_startFrameLayout->addWidget( TextLabel5, 2, 0 ); - - TQLabel * TextLabel3 = new TQLabel( m_startFrame, "TextLabel3" ); - TextLabel3->setText( i18n( "Set cell:" ) ); - - m_startFrameLayout->addWidget( TextLabel3, 0, 0 ); - GoalSeekDialogLayout->addWidget( m_startFrame, 0, 0 ); - - TQVBoxLayout * Layout5 = new TQVBoxLayout( 0, 0, 6, "Layout5"); - - m_buttonOk = new TQPushButton( this, "m_buttonOk" ); - m_buttonOk->setText( i18n( "&Start" ) ); - m_buttonOk->setAccel( 276824143 ); - m_buttonOk->setAutoDefault( TRUE ); - m_buttonOk->setDefault( TRUE ); - Layout5->addWidget( m_buttonOk ); - - m_buttonCancel = new KPushButton( KStdGuiItem::cancel(), this, "m_buttonCancel" ); - m_buttonCancel->setAccel( 276824131 ); - m_buttonCancel->setAutoDefault( TRUE ); - Layout5->addWidget( m_buttonCancel ); - TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding ); - Layout5->addItem( spacer ); - - GoalSeekDialogLayout->addMultiCellLayout( Layout5, 0, 1, 1, 1 ); - - m_resultFrame = new TQFrame( this, "m_resultFrame" ); - m_resultFrame->setFrameShape( TQFrame::StyledPanel ); - m_resultFrame->setFrameShadow( TQFrame::Raised ); - m_resultFrame->setMinimumWidth( 350 ); - m_resultFrameLayout = new TQGridLayout( m_resultFrame, 1, 1, 11, 6, "m_resultFrameLayout"); - - m_currentValueLabel = new TQLabel( m_resultFrame, "m_currentValueLabel" ); - m_currentValueLabel->setText( i18n( "Current value:" ) ); - - m_resultFrameLayout->addWidget( m_currentValueLabel, 2, 0 ); - - m_newValueDesc = new TQLabel( m_resultFrame, "m_newValueDesc" ); - m_newValueDesc->setText( i18n( "New value:" ) ); - - m_resultFrameLayout->addWidget( m_newValueDesc, 1, 0 ); - - m_newValue = new TQLabel( m_resultFrame, "m_newValue" ); - m_newValue->setText( "m_targetValueEdit" ); - - m_resultFrameLayout->addWidget( m_newValue, 1, 1 ); - - m_currentValue = new TQLabel( m_resultFrame, "m_currentValue" ); - m_currentValue->setText( "m_currentValue" ); - - m_resultFrameLayout->addWidget( m_currentValue, 2, 1 ); - - m_resultText = new TQLabel( m_resultFrame, "m_resultText" ); - m_resultText->setText( "Goal seeking with cell found solution:" ); - m_resultText->setAlignment( int( TQLabel::WordBreak | TQLabel::AlignVCenter ) ); - - m_resultFrameLayout->addMultiCellWidget( m_resultText, 0, 0, 0, 1 ); - - // GoalSeekDialogLayout->addWidget( m_resultFrame, 1, 0 ); - - m_resultFrame->hide(); - - m_sheetName = m_pView->activeSheet()->sheetName(); - - // Allow the user to select cells on the spreadsheet. - m_pView->canvasWidget()->startChoose(); - - tqApp->installEventFilter( this ); - - // signals and slots connections - connect( m_buttonOk, TQT_SIGNAL( clicked() ), this, TQT_SLOT( buttonOkClicked() ) ); - connect( m_buttonCancel, TQT_SIGNAL( clicked() ), this, TQT_SLOT( buttonCancelClicked() ) ); - - connect( m_pView->choice(), TQT_SIGNAL(changed(const Region&)), - this, TQT_SLOT(slotSelectionChanged())); - - // tab order - setTabOrder( m_targetEdit, m_targetValueEdit ); - setTabOrder( m_targetValueEdit, m_sourceEdit ); - setTabOrder( m_sourceEdit, m_buttonOk ); - setTabOrder( m_buttonOk, m_buttonCancel ); -} - -GoalSeekDialog::~GoalSeekDialog() -{ - kdDebug() << "~GoalSeekDialog" << endl; - - if ( !m_restored ) - { - m_pView->doc()->emitBeginOperation( false ); - m_sourceCell->setValue(m_oldSource); - m_targetCell->setCalcDirtyFlag(); - m_targetCell->calc(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - } -} - -bool GoalSeekDialog::eventFilter( TQObject* obj, TQEvent* ev ) -{ - if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_targetValueEdit) && ev->type() == TQEvent::FocusIn ) - m_focus = m_targetValueEdit; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_targetEdit) && ev->type() == TQEvent::FocusIn ) - m_focus = m_targetEdit; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_sourceEdit) && ev->type() == TQEvent::FocusIn ) - m_focus = m_sourceEdit; - else - return FALSE; - - if ( m_focus ) - m_pView->canvasWidget()->startChoose(); - - return FALSE; -} - -void GoalSeekDialog::closeEvent ( TQCloseEvent * e ) -{ - e->accept(); -} - -void GoalSeekDialog::slotSelectionChanged() -{ - if ( !m_focus ) - return; - - if (m_pView->choice()->isValid()) - { - TQString area = m_pView->choice()->name(); - m_focus->setText( area ); - } -} - -void GoalSeekDialog::buttonOkClicked() -{ - Doc * pDoc = m_pView->doc(); - pDoc->emitBeginOperation( false ); - if (m_maxIter > 0) - { - Sheet * sheet = m_pView->activeSheet(); - - Point source( m_sourceEdit->text(), sheet->workbook(), sheet ); - if (!source.isValid()) - { - KMessageBox::error( this, i18n("Cell reference is invalid.") ); - m_sourceEdit->selectAll(); - m_sourceEdit->setFocus(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } - - Point target( m_targetEdit->text(), sheet->workbook(), sheet ); - if (!target.isValid()) - { - KMessageBox::error( this, i18n("Cell reference is invalid.") ); - m_targetEdit->selectAll(); - m_targetEdit->setFocus(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } - - bool ok = false; - double goal = m_pView->doc()->locale()->readNumber(m_targetValueEdit->text(), &ok ); - if ( !ok ) - { - KMessageBox::error( this, i18n("Target value is invalid.") ); - m_targetValueEdit->selectAll(); - m_targetValueEdit->setFocus(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } - - m_sourceCell = source.cell(); - m_targetCell = target.cell(); - - if ( !m_sourceCell->value().isNumber() ) - { - KMessageBox::error( this, i18n("Source cell must contain a numeric value.") ); - m_sourceEdit->selectAll(); - m_sourceEdit->setFocus(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } - - if ( !m_targetCell->isFormula() ) - { - KMessageBox::error( this, i18n("Target cell must contain a formula.") ); - m_targetEdit->selectAll(); - m_targetEdit->setFocus(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } - - m_buttonOk->setText( i18n("&OK") ); - m_buttonOk->setEnabled(false); - m_buttonCancel->setEnabled(false); - GoalSeekDialogLayout->addWidget( m_resultFrame, 0, 0 ); - m_startFrame->hide(); - m_resultFrame->show(); - if ( m_startFrame->width() > 350 ) - m_resultFrame->setMinimumWidth( m_startFrame->width() ); - - m_restored = false; - - startCalc( m_sourceCell->value().asFloat(), goal ); - m_pView->slotUpdateView( m_pView->activeSheet() ); - - return; - } - else - { - if ( !pDoc->undoLocked() ) - { - UndoSetText * undo - = new UndoSetText( pDoc, m_pView->activeSheet(), TQString::number(m_oldSource), - m_sourceCell->column(), m_sourceCell->row(), - m_sourceCell->formatType() ); - - pDoc->addCommand( undo ); - } - - m_restored = true; - } - chooseCleanup(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void GoalSeekDialog::buttonCancelClicked() -{ - if ( !m_restored ) - { - m_pView->doc()->emitBeginOperation( false ); - m_sourceCell->setValue(m_oldSource); - m_targetCell->setCalcDirtyFlag(); - m_targetCell->calc(); - m_restored = true; - m_pView->slotUpdateView( m_pView->activeSheet() ); - } - - chooseCleanup(); - reject(); -} - -void GoalSeekDialog::chooseCleanup() -{ - m_pView->canvasWidget()->endChoose(); - - Sheet * sheet = 0; - - // Switch back to the old sheet - if ( m_pView->activeSheet()->sheetName() != m_sheetName ) - { - sheet = m_pView->doc()->map()->findSheet( m_sheetName ); - if ( sheet ) - m_pView->setActiveSheet( sheet ); - } - else - sheet = m_pView->activeSheet(); - - // Revert the marker to its original position - m_pView->selectionInfo()->initialize(TQRect(m_marker, m_anchor));//, sheet ); -} - - -void GoalSeekDialog::startCalc(double _start, double _goal) -{ - m_resultText->setText( i18n( "Starting..." ) ); - m_newValueDesc->setText( i18n( "Iteration:" ) ); - - // lets be optimistic - bool ok = true; - - // TODO: make this configurable - double eps = 0.0000001; - - double startA = 0.0, startB; - double resultA, resultB; - - // save old value - m_oldSource = m_sourceCell->value().asFloat(); - resultA = _goal; - - // initialize start value - startB = _start; - double x = startB + 0.5; - - // while the result is not close enough to zero - // or while the max number of iterations is not reached... - while ( fabs( resultA ) > eps && ( m_maxIter >= 0 ) ) - { - startA = startB; - startB = x; - - m_sourceCell->setValue(startA); - // m_sourceCell->updateDepending(); - m_sourceCell->setCalcDirtyFlag(); - m_targetCell->calc( false ); - resultA = m_targetCell->value().asFloat() - _goal; - // kdDebug() << "Target A: " << m_targetCell->value().asFloat() << ", " << m_targetCell->text() << " Calc: " << resultA << endl; - - m_sourceCell->setValue(startB); - // m_sourceCell->updateDepending(); - m_sourceCell->setCalcDirtyFlag(); - m_targetCell->calc( false ); - resultB = m_targetCell->value().asFloat() - _goal; - /* - kdDebug() << "Target B: " << m_targetCell->value().asFloat() << ", " << m_targetCell->text() << " Calc: " << resultB << endl; - - kdDebug() << "Iteration: " << m_maxIter << ", StartA: " << startA - << ", ResultA: " << resultA << " (eps: " << eps << "), StartB: " - << startB << ", ResultB: " << resultB << endl; - */ - - // find zero with secant method (rough implementation was provided by Franz-Xaver Meier): - // if the function returns the same for two different - // values we have something like a horizontal line - // => can't get zero. - if ( resultB == resultA ) - { - // kdDebug() << " resultA == resultB" << endl; - if ( fabs( resultA ) < eps ) - { - ok = true; - break; - } - - ok = false; - break; - } - - // Point of intersection of secant with x-axis - x = ( startA * resultB - startB * resultA ) / ( resultB - resultA ); - - if ( fabs(x) > 100000000 ) - { - // kdDebug() << "fabs(x) > 100000000: " << x << endl; - ok = false; - break; - } - - // kdDebug() << "X: " << x << ", fabs (resultA): " << fabs(resultA) << ", Real start: " << startA << ", Real result: " << resultA << ", Iteration: " << m_maxIter << endl; - - --m_maxIter; - if ( m_maxIter % 20 == 0 ) - m_newValue->setText( TQString::number(m_maxIter) ); - } - - m_newValueDesc->setText( i18n( "New value:" ) ); - if ( ok ) - { - m_sourceCell->setValue( startA ); - m_sourceCell->setCalcDirtyFlag(); - m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect()); - // m_targetCell->setCalcDirtyFlag(); - m_targetCell->calc( false ); - - m_resultText->setText( i18n( "Goal seeking with cell %1 found a solution:" ).arg( m_sourceEdit->text() ) ); - m_newValue->setText( m_pView->doc()->locale()->formatNumber( startA ) ); - m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) ); - m_restored = false; - } - else - { - // restore the old value - m_sourceCell->setValue( m_oldSource ); - m_targetCell->setCalcDirtyFlag(); - m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect()); - m_targetCell->calc( false ); - m_resultText->setText( i18n( "Goal seeking with cell %1 has found NO solution." ).arg( m_sourceEdit->text() ) ); - m_newValue->setText( "" ); - m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) ); - m_restored = true; - } - - m_buttonOk->setEnabled( true ); - m_buttonCancel->setEnabled( true ); - m_maxIter = 0; -} - -#include "kspread_dlg_goalseek.moc" - diff --git a/kspread/dialogs/kspread_dlg_goalseek.cpp b/kspread/dialogs/kspread_dlg_goalseek.cpp new file mode 100644 index 00000000..b45525ad --- /dev/null +++ b/kspread/dialogs/kspread_dlg_goalseek.cpp @@ -0,0 +1,486 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002-2003 Philipp Mueller + (C) 2002 Laurent Montel + (C) 2002 John Dailey + (C) 2002 Ariya Hidayat + (C) 2002 Werner Trobin + (C) 2002 Harri Porten + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_dlg_goalseek.h" + +#include "kspread_canvas.h" +#include "kspread_cell.h" +#include "kspread_doc.h" +#include "kspread_map.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_undo.h" +#include "kspread_util.h" +#include "kspread_view.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace KSpread; + +GoalSeekDialog::GoalSeekDialog( View * parent, TQPoint const & marker, + const char * name, bool, WFlags fl ) + : KDialog( parent, name, false, fl ), + m_pView( parent ), + m_maxIter( 1000 ), + m_restored( true ), + m_focus(0), + m_anchor( m_pView->selectionInfo()->anchor() ), + m_marker( m_pView->selectionInfo()->marker() ), + m_selection( m_pView->selectionInfo()->selection() ) +{ + setWFlags( TQt::WDestructiveClose ); + + if ( !name ) + setName( "GoalSeekDialog" ); + + resize( 458, 153 ); + setCaption( i18n( "Goal Seek" ) ); + setSizeGripEnabled( true ); + + GoalSeekDialogLayout = new TQGridLayout( this, 1, 1, 11, 6, "GoalSeekDialogLayout"); + + m_startFrame = new TQFrame( this, "m_startFrame" ); + m_startFrame->setFrameShape( TQFrame::StyledPanel ); + m_startFrame->setFrameShadow( TQFrame::Raised ); + m_startFrameLayout = new TQGridLayout( m_startFrame, 1, 1, 11, 6, "m_startFrameLayout"); + + TQLabel * TextLabel4 = new TQLabel( m_startFrame, "TextLabel4" ); + TextLabel4->setText( i18n( "To value:" ) ); + m_startFrameLayout->addWidget( TextLabel4, 1, 0 ); + + m_targetValueEdit = new TQLineEdit( m_startFrame, "m_targetValueEdit" ); + m_startFrameLayout->addWidget( m_targetValueEdit, 1, 1 ); + + m_targetEdit = new TQLineEdit( m_startFrame, "m_targetEdit" ); + m_startFrameLayout->addWidget( m_targetEdit, 0, 1 ); + m_targetEdit->setText( Cell::name( marker.x(), marker.y() ) ); + + m_sourceEdit = new TQLineEdit( m_startFrame, "m_sourceEdit" ); + m_startFrameLayout->addWidget( m_sourceEdit, 2, 1 ); + + TQLabel * TextLabel5 = new TQLabel( m_startFrame, "TextLabel5" ); + TextLabel5->setText( i18n( "By changing cell:" ) ); + + m_startFrameLayout->addWidget( TextLabel5, 2, 0 ); + + TQLabel * TextLabel3 = new TQLabel( m_startFrame, "TextLabel3" ); + TextLabel3->setText( i18n( "Set cell:" ) ); + + m_startFrameLayout->addWidget( TextLabel3, 0, 0 ); + GoalSeekDialogLayout->addWidget( m_startFrame, 0, 0 ); + + TQVBoxLayout * Layout5 = new TQVBoxLayout( 0, 0, 6, "Layout5"); + + m_buttonOk = new TQPushButton( this, "m_buttonOk" ); + m_buttonOk->setText( i18n( "&Start" ) ); + m_buttonOk->setAccel( 276824143 ); + m_buttonOk->setAutoDefault( TRUE ); + m_buttonOk->setDefault( TRUE ); + Layout5->addWidget( m_buttonOk ); + + m_buttonCancel = new KPushButton( KStdGuiItem::cancel(), this, "m_buttonCancel" ); + m_buttonCancel->setAccel( 276824131 ); + m_buttonCancel->setAutoDefault( TRUE ); + Layout5->addWidget( m_buttonCancel ); + TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding ); + Layout5->addItem( spacer ); + + GoalSeekDialogLayout->addMultiCellLayout( Layout5, 0, 1, 1, 1 ); + + m_resultFrame = new TQFrame( this, "m_resultFrame" ); + m_resultFrame->setFrameShape( TQFrame::StyledPanel ); + m_resultFrame->setFrameShadow( TQFrame::Raised ); + m_resultFrame->setMinimumWidth( 350 ); + m_resultFrameLayout = new TQGridLayout( m_resultFrame, 1, 1, 11, 6, "m_resultFrameLayout"); + + m_currentValueLabel = new TQLabel( m_resultFrame, "m_currentValueLabel" ); + m_currentValueLabel->setText( i18n( "Current value:" ) ); + + m_resultFrameLayout->addWidget( m_currentValueLabel, 2, 0 ); + + m_newValueDesc = new TQLabel( m_resultFrame, "m_newValueDesc" ); + m_newValueDesc->setText( i18n( "New value:" ) ); + + m_resultFrameLayout->addWidget( m_newValueDesc, 1, 0 ); + + m_newValue = new TQLabel( m_resultFrame, "m_newValue" ); + m_newValue->setText( "m_targetValueEdit" ); + + m_resultFrameLayout->addWidget( m_newValue, 1, 1 ); + + m_currentValue = new TQLabel( m_resultFrame, "m_currentValue" ); + m_currentValue->setText( "m_currentValue" ); + + m_resultFrameLayout->addWidget( m_currentValue, 2, 1 ); + + m_resultText = new TQLabel( m_resultFrame, "m_resultText" ); + m_resultText->setText( "Goal seeking with cell found solution:" ); + m_resultText->setAlignment( int( TQLabel::WordBreak | TQLabel::AlignVCenter ) ); + + m_resultFrameLayout->addMultiCellWidget( m_resultText, 0, 0, 0, 1 ); + + // GoalSeekDialogLayout->addWidget( m_resultFrame, 1, 0 ); + + m_resultFrame->hide(); + + m_sheetName = m_pView->activeSheet()->sheetName(); + + // Allow the user to select cells on the spreadsheet. + m_pView->canvasWidget()->startChoose(); + + tqApp->installEventFilter( this ); + + // signals and slots connections + connect( m_buttonOk, TQT_SIGNAL( clicked() ), this, TQT_SLOT( buttonOkClicked() ) ); + connect( m_buttonCancel, TQT_SIGNAL( clicked() ), this, TQT_SLOT( buttonCancelClicked() ) ); + + connect( m_pView->choice(), TQT_SIGNAL(changed(const Region&)), + this, TQT_SLOT(slotSelectionChanged())); + + // tab order + setTabOrder( m_targetEdit, m_targetValueEdit ); + setTabOrder( m_targetValueEdit, m_sourceEdit ); + setTabOrder( m_sourceEdit, m_buttonOk ); + setTabOrder( m_buttonOk, m_buttonCancel ); +} + +GoalSeekDialog::~GoalSeekDialog() +{ + kdDebug() << "~GoalSeekDialog" << endl; + + if ( !m_restored ) + { + m_pView->doc()->emitBeginOperation( false ); + m_sourceCell->setValue(m_oldSource); + m_targetCell->setCalcDirtyFlag(); + m_targetCell->calc(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + } +} + +bool GoalSeekDialog::eventFilter( TQObject* obj, TQEvent* ev ) +{ + if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_targetValueEdit) && ev->type() == TQEvent::FocusIn ) + m_focus = m_targetValueEdit; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_targetEdit) && ev->type() == TQEvent::FocusIn ) + m_focus = m_targetEdit; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_sourceEdit) && ev->type() == TQEvent::FocusIn ) + m_focus = m_sourceEdit; + else + return FALSE; + + if ( m_focus ) + m_pView->canvasWidget()->startChoose(); + + return FALSE; +} + +void GoalSeekDialog::closeEvent ( TQCloseEvent * e ) +{ + e->accept(); +} + +void GoalSeekDialog::slotSelectionChanged() +{ + if ( !m_focus ) + return; + + if (m_pView->choice()->isValid()) + { + TQString area = m_pView->choice()->name(); + m_focus->setText( area ); + } +} + +void GoalSeekDialog::buttonOkClicked() +{ + Doc * pDoc = m_pView->doc(); + pDoc->emitBeginOperation( false ); + if (m_maxIter > 0) + { + Sheet * sheet = m_pView->activeSheet(); + + Point source( m_sourceEdit->text(), sheet->workbook(), sheet ); + if (!source.isValid()) + { + KMessageBox::error( this, i18n("Cell reference is invalid.") ); + m_sourceEdit->selectAll(); + m_sourceEdit->setFocus(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } + + Point target( m_targetEdit->text(), sheet->workbook(), sheet ); + if (!target.isValid()) + { + KMessageBox::error( this, i18n("Cell reference is invalid.") ); + m_targetEdit->selectAll(); + m_targetEdit->setFocus(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } + + bool ok = false; + double goal = m_pView->doc()->locale()->readNumber(m_targetValueEdit->text(), &ok ); + if ( !ok ) + { + KMessageBox::error( this, i18n("Target value is invalid.") ); + m_targetValueEdit->selectAll(); + m_targetValueEdit->setFocus(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } + + m_sourceCell = source.cell(); + m_targetCell = target.cell(); + + if ( !m_sourceCell->value().isNumber() ) + { + KMessageBox::error( this, i18n("Source cell must contain a numeric value.") ); + m_sourceEdit->selectAll(); + m_sourceEdit->setFocus(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } + + if ( !m_targetCell->isFormula() ) + { + KMessageBox::error( this, i18n("Target cell must contain a formula.") ); + m_targetEdit->selectAll(); + m_targetEdit->setFocus(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } + + m_buttonOk->setText( i18n("&OK") ); + m_buttonOk->setEnabled(false); + m_buttonCancel->setEnabled(false); + GoalSeekDialogLayout->addWidget( m_resultFrame, 0, 0 ); + m_startFrame->hide(); + m_resultFrame->show(); + if ( m_startFrame->width() > 350 ) + m_resultFrame->setMinimumWidth( m_startFrame->width() ); + + m_restored = false; + + startCalc( m_sourceCell->value().asFloat(), goal ); + m_pView->slotUpdateView( m_pView->activeSheet() ); + + return; + } + else + { + if ( !pDoc->undoLocked() ) + { + UndoSetText * undo + = new UndoSetText( pDoc, m_pView->activeSheet(), TQString::number(m_oldSource), + m_sourceCell->column(), m_sourceCell->row(), + m_sourceCell->formatType() ); + + pDoc->addCommand( undo ); + } + + m_restored = true; + } + chooseCleanup(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void GoalSeekDialog::buttonCancelClicked() +{ + if ( !m_restored ) + { + m_pView->doc()->emitBeginOperation( false ); + m_sourceCell->setValue(m_oldSource); + m_targetCell->setCalcDirtyFlag(); + m_targetCell->calc(); + m_restored = true; + m_pView->slotUpdateView( m_pView->activeSheet() ); + } + + chooseCleanup(); + reject(); +} + +void GoalSeekDialog::chooseCleanup() +{ + m_pView->canvasWidget()->endChoose(); + + Sheet * sheet = 0; + + // Switch back to the old sheet + if ( m_pView->activeSheet()->sheetName() != m_sheetName ) + { + sheet = m_pView->doc()->map()->findSheet( m_sheetName ); + if ( sheet ) + m_pView->setActiveSheet( sheet ); + } + else + sheet = m_pView->activeSheet(); + + // Revert the marker to its original position + m_pView->selectionInfo()->initialize(TQRect(m_marker, m_anchor));//, sheet ); +} + + +void GoalSeekDialog::startCalc(double _start, double _goal) +{ + m_resultText->setText( i18n( "Starting..." ) ); + m_newValueDesc->setText( i18n( "Iteration:" ) ); + + // lets be optimistic + bool ok = true; + + // TODO: make this configurable + double eps = 0.0000001; + + double startA = 0.0, startB; + double resultA, resultB; + + // save old value + m_oldSource = m_sourceCell->value().asFloat(); + resultA = _goal; + + // initialize start value + startB = _start; + double x = startB + 0.5; + + // while the result is not close enough to zero + // or while the max number of iterations is not reached... + while ( fabs( resultA ) > eps && ( m_maxIter >= 0 ) ) + { + startA = startB; + startB = x; + + m_sourceCell->setValue(startA); + // m_sourceCell->updateDepending(); + m_sourceCell->setCalcDirtyFlag(); + m_targetCell->calc( false ); + resultA = m_targetCell->value().asFloat() - _goal; + // kdDebug() << "Target A: " << m_targetCell->value().asFloat() << ", " << m_targetCell->text() << " Calc: " << resultA << endl; + + m_sourceCell->setValue(startB); + // m_sourceCell->updateDepending(); + m_sourceCell->setCalcDirtyFlag(); + m_targetCell->calc( false ); + resultB = m_targetCell->value().asFloat() - _goal; + /* + kdDebug() << "Target B: " << m_targetCell->value().asFloat() << ", " << m_targetCell->text() << " Calc: " << resultB << endl; + + kdDebug() << "Iteration: " << m_maxIter << ", StartA: " << startA + << ", ResultA: " << resultA << " (eps: " << eps << "), StartB: " + << startB << ", ResultB: " << resultB << endl; + */ + + // find zero with secant method (rough implementation was provided by Franz-Xaver Meier): + // if the function returns the same for two different + // values we have something like a horizontal line + // => can't get zero. + if ( resultB == resultA ) + { + // kdDebug() << " resultA == resultB" << endl; + if ( fabs( resultA ) < eps ) + { + ok = true; + break; + } + + ok = false; + break; + } + + // Point of intersection of secant with x-axis + x = ( startA * resultB - startB * resultA ) / ( resultB - resultA ); + + if ( fabs(x) > 100000000 ) + { + // kdDebug() << "fabs(x) > 100000000: " << x << endl; + ok = false; + break; + } + + // kdDebug() << "X: " << x << ", fabs (resultA): " << fabs(resultA) << ", Real start: " << startA << ", Real result: " << resultA << ", Iteration: " << m_maxIter << endl; + + --m_maxIter; + if ( m_maxIter % 20 == 0 ) + m_newValue->setText( TQString::number(m_maxIter) ); + } + + m_newValueDesc->setText( i18n( "New value:" ) ); + if ( ok ) + { + m_sourceCell->setValue( startA ); + m_sourceCell->setCalcDirtyFlag(); + m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect()); + // m_targetCell->setCalcDirtyFlag(); + m_targetCell->calc( false ); + + m_resultText->setText( i18n( "Goal seeking with cell %1 found a solution:" ).arg( m_sourceEdit->text() ) ); + m_newValue->setText( m_pView->doc()->locale()->formatNumber( startA ) ); + m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) ); + m_restored = false; + } + else + { + // restore the old value + m_sourceCell->setValue( m_oldSource ); + m_targetCell->setCalcDirtyFlag(); + m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect()); + m_targetCell->calc( false ); + m_resultText->setText( i18n( "Goal seeking with cell %1 has found NO solution." ).arg( m_sourceEdit->text() ) ); + m_newValue->setText( "" ); + m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) ); + m_restored = true; + } + + m_buttonOk->setEnabled( true ); + m_buttonCancel->setEnabled( true ); + m_maxIter = 0; +} + +#include "kspread_dlg_goalseek.moc" + diff --git a/kspread/dialogs/kspread_dlg_goto.cc b/kspread/dialogs/kspread_dlg_goto.cc deleted file mode 100644 index 2d9935ac..00000000 --- a/kspread/dialogs/kspread_dlg_goto.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999-2003 Laurent Montel - (C) 2003 Philipp Mueller - (C) 2003 Ariya Hidayat - (C) 2003 Norbert Andres - (C) 1999 Stephan Kulow - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include - -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_util.h" -#include "kspread_view.h" -#include "selection.h" - -#include "kspread_dlg_goto.h" - -using namespace KSpread; - -GotoDialog::GotoDialog( View* parent, const char* name ) - : KDialogBase( parent, name, TRUE, i18n("Goto Cell"), Ok|Cancel ) -{ - m_pView = parent; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQLabel *label = new TQLabel(i18n("Enter cell:"), page); - lay1->addWidget(label); - - m_nameCell = new KLineEdit( page ); - lay1->addWidget(m_nameCell); - - m_nameCell->setFocus(); - enableButtonOK( false ); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( m_nameCell, TQT_SIGNAL(textChanged ( const TQString & )), - this, TQT_SLOT(textChanged ( const TQString & ))); -} - -void GotoDialog::textChanged ( const TQString &_text ) -{ - enableButtonOK(!_text.isEmpty()); -} - -void GotoDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - TQString tmp_upper; - tmp_upper=m_nameCell->text().upper(); - Region region(m_pView, tmp_upper); - if ( region.isValid() ) - { - m_pView->selectionInfo()->initialize(region); - accept(); - } - else - { - m_nameCell->clear(); - } - m_pView->slotUpdateView( m_pView->activeSheet() ); -} - -#include "kspread_dlg_goto.moc" diff --git a/kspread/dialogs/kspread_dlg_goto.cpp b/kspread/dialogs/kspread_dlg_goto.cpp new file mode 100644 index 00000000..2d9935ac --- /dev/null +++ b/kspread/dialogs/kspread_dlg_goto.cpp @@ -0,0 +1,87 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2003 Laurent Montel + (C) 2003 Philipp Mueller + (C) 2003 Ariya Hidayat + (C) 2003 Norbert Andres + (C) 1999 Stephan Kulow + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include + +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_util.h" +#include "kspread_view.h" +#include "selection.h" + +#include "kspread_dlg_goto.h" + +using namespace KSpread; + +GotoDialog::GotoDialog( View* parent, const char* name ) + : KDialogBase( parent, name, TRUE, i18n("Goto Cell"), Ok|Cancel ) +{ + m_pView = parent; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQLabel *label = new TQLabel(i18n("Enter cell:"), page); + lay1->addWidget(label); + + m_nameCell = new KLineEdit( page ); + lay1->addWidget(m_nameCell); + + m_nameCell->setFocus(); + enableButtonOK( false ); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( m_nameCell, TQT_SIGNAL(textChanged ( const TQString & )), + this, TQT_SLOT(textChanged ( const TQString & ))); +} + +void GotoDialog::textChanged ( const TQString &_text ) +{ + enableButtonOK(!_text.isEmpty()); +} + +void GotoDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + TQString tmp_upper; + tmp_upper=m_nameCell->text().upper(); + Region region(m_pView, tmp_upper); + if ( region.isValid() ) + { + m_pView->selectionInfo()->initialize(region); + accept(); + } + else + { + m_nameCell->clear(); + } + m_pView->slotUpdateView( m_pView->activeSheet() ); +} + +#include "kspread_dlg_goto.moc" diff --git a/kspread/dialogs/kspread_dlg_insert.cc b/kspread/dialogs/kspread_dlg_insert.cc deleted file mode 100644 index 454a43ba..00000000 --- a/kspread/dialogs/kspread_dlg_insert.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Norbert Andres - (C) 1999-2002 Laurent Montel - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 2000-2001 Werner Trobin - (C) 2000 David Faure - (C) 1999 Stephan Kulow - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_view.h" - -#include "kspread_dlg_insert.h" - -using namespace KSpread; - -InsertDialog::InsertDialog( View* parent, const char* name,const TQRect &_rect,Mode _mode) - : KDialogBase( parent, name, TRUE,"",Ok|Cancel ) -{ - m_pView = parent; - rect=_rect; - insRem=_mode; - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Insert"),page); - grp->setRadioButtonExclusive( TRUE ); - grp->layout(); - lay1->addWidget(grp); - if( insRem==Insert) - { - rb1 = new TQRadioButton( i18n("Move towards right"), grp ); - rb2 = new TQRadioButton( i18n("Move towards bottom"), grp ); - rb3 = new TQRadioButton( i18n("Insert rows"), grp ); - rb4 = new TQRadioButton( i18n("Insert columns"), grp ); - setCaption( i18n("Insert Cells") ); - } - else if(insRem==Remove) - { - grp->setTitle(i18n("Remove")); - rb1 = new TQRadioButton( i18n("Move towards left"), grp ); - rb2 = new TQRadioButton( i18n("Move towards top"), grp ); - rb3 = new TQRadioButton( i18n("Remove rows"), grp ); - rb4 = new TQRadioButton( i18n("Remove columns"), grp ); - setCaption( i18n("Remove Cells") ); - } - else - kdDebug(36001) << "Error in kspread_dlg_InsertDialog" << endl; - - rb1->setChecked(true); - - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); -} - -void InsertDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - if( rb1->isChecked() ) - { - if( insRem == Insert ) - { - if ( !m_pView->activeSheet()->shiftRow( rect ) ) - KMessageBox::error( this, i18n("The row is full. Cannot move cells to the right.") ); - } - else if( insRem == Remove ) - { - m_pView->activeSheet()->unshiftRow(rect); - } - } - else if( rb2->isChecked() ) - { - if( insRem == Insert ) - { - if ( !m_pView->activeSheet()->shiftColumn( rect ) ) - KMessageBox::error( this, i18n("The column is full. Cannot move cells towards the bottom.") ); - } - else if( insRem == Remove ) - { - m_pView->activeSheet()->unshiftColumn( rect ); - } - } - else if( rb3->isChecked() ) - { - if( insRem == Insert ) - { - if ( !m_pView->activeSheet()->insertRow( rect.top(),(rect.bottom()-rect.top() ) ) ) - KMessageBox::error( this, i18n("The row is full. Cannot move cells to the right.") ); - } - else if( insRem == Remove ) - { - m_pView->activeSheet()->removeRow( rect.top(),(rect.bottom()-rect.top() ) ); - } - } - else if( rb4->isChecked() ) - { - if( insRem == Insert ) - { - if ( !m_pView->activeSheet()->insertColumn( rect.left(),(rect.right()-rect.left() )) ) - KMessageBox::error( this, i18n("The column is full. Cannot move cells towards the bottom.") ); - } - else if( insRem == Remove ) - { - m_pView->activeSheet()->removeColumn( rect.left(),(rect.right()-rect.left() ) ); - } - } - else - { - kdDebug(36001) << "Error in kspread_dlg_InsertDialog" << endl; - } - - m_pView->updateEditWidget(); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -#include "kspread_dlg_insert.moc" diff --git a/kspread/dialogs/kspread_dlg_insert.cpp b/kspread/dialogs/kspread_dlg_insert.cpp new file mode 100644 index 00000000..454a43ba --- /dev/null +++ b/kspread/dialogs/kspread_dlg_insert.cpp @@ -0,0 +1,148 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres + (C) 1999-2002 Laurent Montel + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 2000-2001 Werner Trobin + (C) 2000 David Faure + (C) 1999 Stephan Kulow + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_view.h" + +#include "kspread_dlg_insert.h" + +using namespace KSpread; + +InsertDialog::InsertDialog( View* parent, const char* name,const TQRect &_rect,Mode _mode) + : KDialogBase( parent, name, TRUE,"",Ok|Cancel ) +{ + m_pView = parent; + rect=_rect; + insRem=_mode; + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Insert"),page); + grp->setRadioButtonExclusive( TRUE ); + grp->layout(); + lay1->addWidget(grp); + if( insRem==Insert) + { + rb1 = new TQRadioButton( i18n("Move towards right"), grp ); + rb2 = new TQRadioButton( i18n("Move towards bottom"), grp ); + rb3 = new TQRadioButton( i18n("Insert rows"), grp ); + rb4 = new TQRadioButton( i18n("Insert columns"), grp ); + setCaption( i18n("Insert Cells") ); + } + else if(insRem==Remove) + { + grp->setTitle(i18n("Remove")); + rb1 = new TQRadioButton( i18n("Move towards left"), grp ); + rb2 = new TQRadioButton( i18n("Move towards top"), grp ); + rb3 = new TQRadioButton( i18n("Remove rows"), grp ); + rb4 = new TQRadioButton( i18n("Remove columns"), grp ); + setCaption( i18n("Remove Cells") ); + } + else + kdDebug(36001) << "Error in kspread_dlg_InsertDialog" << endl; + + rb1->setChecked(true); + + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); +} + +void InsertDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + if( rb1->isChecked() ) + { + if( insRem == Insert ) + { + if ( !m_pView->activeSheet()->shiftRow( rect ) ) + KMessageBox::error( this, i18n("The row is full. Cannot move cells to the right.") ); + } + else if( insRem == Remove ) + { + m_pView->activeSheet()->unshiftRow(rect); + } + } + else if( rb2->isChecked() ) + { + if( insRem == Insert ) + { + if ( !m_pView->activeSheet()->shiftColumn( rect ) ) + KMessageBox::error( this, i18n("The column is full. Cannot move cells towards the bottom.") ); + } + else if( insRem == Remove ) + { + m_pView->activeSheet()->unshiftColumn( rect ); + } + } + else if( rb3->isChecked() ) + { + if( insRem == Insert ) + { + if ( !m_pView->activeSheet()->insertRow( rect.top(),(rect.bottom()-rect.top() ) ) ) + KMessageBox::error( this, i18n("The row is full. Cannot move cells to the right.") ); + } + else if( insRem == Remove ) + { + m_pView->activeSheet()->removeRow( rect.top(),(rect.bottom()-rect.top() ) ); + } + } + else if( rb4->isChecked() ) + { + if( insRem == Insert ) + { + if ( !m_pView->activeSheet()->insertColumn( rect.left(),(rect.right()-rect.left() )) ) + KMessageBox::error( this, i18n("The column is full. Cannot move cells towards the bottom.") ); + } + else if( insRem == Remove ) + { + m_pView->activeSheet()->removeColumn( rect.left(),(rect.right()-rect.left() ) ); + } + } + else + { + kdDebug(36001) << "Error in kspread_dlg_InsertDialog" << endl; + } + + m_pView->updateEditWidget(); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +#include "kspread_dlg_insert.moc" diff --git a/kspread/dialogs/kspread_dlg_layout.cc b/kspread/dialogs/kspread_dlg_layout.cc deleted file mode 100644 index ad876b3b..00000000 --- a/kspread/dialogs/kspread_dlg_layout.cc +++ /dev/null @@ -1,3928 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2006 Stefan Nikolaus - (C) 2004 Tomas Mecir - (C) 2002-2004 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 2001-2003 Philipp Mueller - (C) 2002 John Dailey - (C) 1999-2002 Laurent Montel - (C) 1999-2002 Harri Porten - (C) 2000-2001 David Faure - (C) 1998-2000 Torben Weis - (C) 2000 Werner Trobin - (C) 1999 Reginald Stadlbauer - (C) 1998-1999 Stephan Kulow - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "kspread_canvas.h" -#include "kspread_dlg_layout.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_undo.h" -#include "kspread_util.h" -#include "manipulator.h" -#include "selection.h" -#include "valueformatter.h" - -using namespace KSpread; - -/*************************************************************************** - * - * PatternSelect - * - ***************************************************************************/ - -PatternSelect::PatternSelect( TQWidget *parent, const char * ) - : TQFrame( parent ) -{ - penStyle = Qt::NoPen; - penWidth = 1; - penColor = colorGroup().text(); - selected = false; - undefined = false; -} - -void PatternSelect::setPattern( const TQColor &_color, int _width, Qt::PenStyle _style ) -{ - penStyle = _style; - penColor = _color; - penWidth = _width; - repaint(); -} - -void PatternSelect::setUndefined() -{ - undefined = true; -} - -void PatternSelect::paintEvent( TQPaintEvent *_ev ) -{ - TQFrame::paintEvent( _ev ); - - TQPainter painter( this ); - - if ( !undefined ) - { - TQPen pen( penColor, penWidth, penStyle); - painter.setPen( pen ); - painter.drawLine( 6, height()/2, width() - 6,height()/2 ); - } - else - { - painter.fillRect( 2, 2, width() - 4, height() - 4, BDiagPattern ); - } -} - -void PatternSelect::mousePressEvent( TQMouseEvent * ) -{ - slotSelect(); - - emit clicked( this ); -} - -void PatternSelect::slotUnselect() -{ - selected = false; - - setLineWidth( 1 ); - setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - repaint(); -} - -void PatternSelect::slotSelect() -{ - selected = true; - - setLineWidth( 2 ); - setFrameStyle( TQFrame::Panel | TQFrame::Plain ); - repaint(); -} - - - -/*************************************************************************** - * - * GeneralTab - * - ***************************************************************************/ - -GeneralTab::GeneralTab( TQWidget* parent, CellFormatDialog * dlg ) - : TQWidget( parent ), - m_dlg( dlg ) -{ - TQGridLayout * layout = new TQGridLayout( this, 1, 1, KDialog::marginHint(), KDialog::spacingHint(), "layout"); - - TQGroupBox * groupBox = new TQGroupBox( this, "groupBox1" ); - groupBox->setColumnLayout(0, Qt::Vertical ); - groupBox->setTitle( i18n( "Style" ) ); - groupBox->layout()->setSpacing( KDialog::spacingHint() ); - groupBox->layout()->setMargin( KDialog::marginHint() ); - - TQGridLayout * groupBoxLayout = new TQGridLayout( groupBox->layout() ); - groupBoxLayout->setAlignment( TQt::AlignTop ); - - TQLabel * label1 = new TQLabel( groupBox, "label1" ); - label1->setText( i18n( "Name:" ) ); - groupBoxLayout->addWidget( label1, 0, 0 ); - - m_nameEdit = new KLineEdit( groupBox, "m_nameEdit" ); - m_nameEdit->setText( m_dlg->styleName ); - groupBoxLayout->addWidget( m_nameEdit, 0, 1 ); - - TQLabel * label2 = new TQLabel( groupBox, "label2" ); - label2->setText( i18n( "Inherit style:" ) ); - groupBoxLayout->addWidget( label2, 1, 0 ); - - m_parentBox = new KComboBox( false, groupBox, "m_parentBox" ); - m_parentBox->clear(); - m_parentBox->insertItem( i18n( "" ) ); - TQStringList tmp = m_dlg->getStyleManager()->styleNames(); - tmp.remove( m_dlg->styleName ); - m_parentBox->insertStringList( tmp ); - - if ( m_dlg->getStyle()->parent() ) - m_parentBox->setCurrentText( m_dlg->getStyle()->parentName() ); - else - { - m_parentBox->setCurrentText( i18n( "" ) ); - - if ( m_dlg->getStyle()->definesAll() ) - m_parentBox->setEnabled( false ); - } - - connect( m_parentBox, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SLOT( slotNewParent( const TQString & ) ) ); - connect( m_nameEdit, TQT_SIGNAL( lostFocus() ), this, TQT_SLOT( slotNameChanged() ) ); - - groupBoxLayout->addWidget( m_parentBox, 1, 1 ); - - TQSpacerItem * spacer = new TQSpacerItem( 20, 260, TQSizePolicy::Minimum, TQSizePolicy::Expanding ); - - layout->addWidget( groupBox, 0, 0 ); - layout->addItem( spacer, 1, 0 ); - - if ( m_dlg->getStyle()->type() == Style::BUILTIN ) - { - m_nameEdit->setEnabled( false ); - m_parentBox->setEnabled( false ); - } - - resize( TQSize( 534, 447 ).expandedTo(minimumSizeHint()) ); -} - -GeneralTab::~GeneralTab() -{ -} - -void GeneralTab::slotNameChanged() -{ - checkName(); -} - -void GeneralTab::slotNewParent( const TQString & parentName ) -{ - kdDebug() << "New Parent" << endl; - if ( !checkParent( parentName ) ) - return; - - if ( parentName.isEmpty() || parentName == i18n( "" ) ) - m_dlg->getStyle()->setParent( 0 ); - else - m_dlg->getStyle()->setParent( m_dlg->getStyleManager()->style( parentName ) ); - - // Set difference to new parent, set GUI to parent values, add changes made before - // m_dlg->initGUI(); -} - -bool GeneralTab::checkName() -{ - if ( m_nameEdit->isEnabled() ) - { - if ( !m_dlg->getStyleManager()->validateStyleName( m_nameEdit->text(), m_dlg->getStyle() ) ) - { - KMessageBox::sorry( this, i18n( "A style with this name already exists." ) ); - return false; - } - } - - return true; -} - -bool GeneralTab::checkParent( const TQString & parentName ) -{ - if ( m_dlg->getStyle()->parentName() != parentName - && m_parentBox->isEnabled() && parentName != i18n( "" ) && !parentName.isEmpty() ) - { - if ( m_nameEdit->text() == parentName ) - { - KMessageBox::sorry( this, i18n( "A style cannot inherit from itself." ) ); - return false; - } - if ( !m_dlg->checkCircle( m_nameEdit->text(), parentName ) ) - { - KMessageBox::sorry( this, - i18n( "The style cannot inherit from '%1' because of recursive references." ) - .arg( m_parentBox->currentText() ) ); - return false; - } - - CustomStyle * p = m_dlg->getStyleManager()->style( parentName ); - - if ( !p ) - { - KMessageBox::sorry( this, i18n( "The parent style does not exist." ) ); - return false; - } - } - - return true; -} - -bool GeneralTab::apply( CustomStyle * style ) -{ - if ( !checkParent( m_parentBox->currentText() ) ) - return false; - - if ( !checkName() ) - return false; - - if ( m_nameEdit->isEnabled() ) - { - if ( style->type() != Style::BUILTIN ) - { - TQString name( style->name() ); - style->setName( m_nameEdit->text() ); - if ( m_parentBox->isEnabled() ) - { - if ( m_parentBox->currentText() == i18n( "None" ) || m_parentBox->currentText().isEmpty() ) - style->setParent( 0 ); - else - style->setParent( m_dlg->getStyleManager()->style( m_parentBox->currentText() ) ); - } - m_dlg->getStyleManager()->changeName( name, m_nameEdit->text() ); - } - } - - if ( style->type() == Style::TENTATIVE ) - style->setType( Style::CUSTOM ); - - return true; -} - - - -/*************************************************************************** - * - * CellFormatDialog - * - ***************************************************************************/ - -CellFormatDialog::CellFormatDialog( View * _view, Sheet * _sheet ) - : TQObject(), - m_doc( _sheet->doc() ), - m_sheet( _sheet ), - m_pView( _view ), - m_style( 0 ) -{ - initMembers(); - - //We need both conditions quite often, so store the condition here too - isRowSelected = _view->selectionInfo()->isRowSelected(); - isColumnSelected = _view->selectionInfo()->isColumnSelected(); - - TQRect range = _view->selectionInfo()->selection(); - left = range.left(); - top = range.top(); - right = range.right(); - bottom = range.bottom(); - - if ( left == right ) - oneCol = true; - else - oneCol = false; - - if ( top == bottom ) - oneRow = true; - else - oneRow = false; - - Cell* obj = m_sheet->cellAt( left, top ); - oneCell = (left == right && top == bottom && - !obj->doesMergeCells()); - - isMerged = ((obj->doesMergeCells() && - left + obj->extraXCells() >= right && - top + obj->extraYCells() >= bottom)); - - // Initialize with the upper left object. - borders[BorderType_Left].style = obj->format()->leftBorderStyle( left, top ); - borders[BorderType_Left].width = obj->format()->leftBorderWidth( left, top ); - borders[BorderType_Left].color = obj->format()->leftBorderColor( left, top ); - borders[BorderType_Top].style = obj->format()->topBorderStyle( left, top ); - borders[BorderType_Top].width = obj->format()->topBorderWidth( left, top ); - borders[BorderType_Top].color = obj->format()->topBorderColor( left, top ); - borders[BorderType_FallingDiagonal].style = - obj->format()->fallDiagonalStyle( left, top ); - borders[BorderType_FallingDiagonal].width = - obj->format()->fallDiagonalWidth( left, top ); - borders[BorderType_FallingDiagonal].color = - obj->format()->fallDiagonalColor( left, top ); - borders[BorderType_RisingDiagonal].style = - obj->format()->goUpDiagonalStyle( left, top ); - borders[BorderType_RisingDiagonal].width = - obj->format()->goUpDiagonalWidth( left, top ); - borders[BorderType_RisingDiagonal].color = - obj->format()->goUpDiagonalColor( left, top ); - - // Look at the upper right one for the right border. - obj = m_sheet->cellAt( right, top ); - borders[BorderType_Right].style = obj->format()->rightBorderStyle( right, top ); - borders[BorderType_Right].width = obj->format()->rightBorderWidth( right, top ); - borders[BorderType_Right].color = obj->format()->rightBorderColor( right, top ); - - // Look at the bottom left cell for the bottom border. - obj = m_sheet->cellAt( left, bottom ); - borders[BorderType_Bottom].style = obj->format()->bottomBorderStyle( left, bottom ); - borders[BorderType_Bottom].width = obj->format()->bottomBorderWidth( left, bottom ); - borders[BorderType_Bottom].color = obj->format()->bottomBorderColor( left, bottom ); - - // Just an assumption - obj = m_sheet->cellAt( right, top ); - if ( obj->isPartOfMerged() ) - { - obj = obj->obscuringCells().first(); - int moveX = obj->column(); - int moveY = top; - int moveX2 = right; - int moveY2 = obj->row(); - borders[BorderType_Vertical].style = obj->format()->leftBorderStyle( moveX, moveY ); - borders[BorderType_Vertical].width = obj->format()->leftBorderWidth( moveX, moveY ); - borders[BorderType_Vertical].color = obj->format()->leftBorderColor( moveX, moveY ); - - obj = m_sheet->cellAt( moveX2, moveY2 ); - borders[BorderType_Horizontal].style = obj->format()->topBorderStyle( moveX2, moveY2 ); - borders[BorderType_Horizontal].width = obj->format()->topBorderWidth( moveX2, moveY2 ); - borders[BorderType_Horizontal].color = obj->format()->topBorderColor( moveX2, moveY2 ); - } - else - { - borders[BorderType_Vertical].style = obj->format()->leftBorderStyle( right, top ); - borders[BorderType_Vertical].width = obj->format()->leftBorderWidth( right, top ); - borders[BorderType_Vertical].color = obj->format()->leftBorderColor( right, top ); - borders[BorderType_Horizontal].style = obj->format()->topBorderStyle(right, bottom); - borders[BorderType_Horizontal].width = obj->format()->topBorderWidth(right, bottom); - borders[BorderType_Horizontal].color = obj->format()->topBorderColor(right, bottom); - } - - obj = m_sheet->cellAt( left, top ); - prefix = obj->format()->prefix( left, top ); - postfix = obj->format()->postfix( left, top ); - precision = obj->format()->precision( left, top ); - floatFormat = obj->format()->floatFormat( left, top ); - floatColor = obj->format()->floatColor( left, top ); - alignX = obj->format()->align( left, top ); - alignY = obj->format()->alignY( left, top ); - textColor = obj->format()->textColor( left, top ); - bgColor = obj->bgColor( left, top ); - textFontSize = obj->format()->textFontSize( left, top ); - textFontFamily = obj->format()->textFontFamily( left, top ); - textFontBold = obj->format()->textFontBold( left, top ); - textFontItalic = obj->format()->textFontItalic( left, top ); - strike=obj->format()->textFontStrike( left, top ); - underline = obj->format()->textFontUnderline( left, top ); - // Needed to initialize the font correctly ( bug in TQt ) - textFont = obj->format()->textFont( left, top ); - obj->format()->currencyInfo( cCurrency ); - - brushColor = obj->format()->backGroundBrushColor( left, top ); - brushStyle = obj->format()->backGroundBrushStyle( left,top ); - - bMultiRow = obj->format()->multiRow( left, top ); - bVerticalText = obj->format()->verticalText( left, top ); - textRotation = obj->format()->getAngle(left, top); - formatType = obj->format()->getFormatType(left, top); - - bDontPrintText = obj->format()->getDontprintText( left, top ); - bHideFormula = obj->format()->isHideFormula( left, top ); - bHideAll = obj->format()->isHideAll( left, top ); - bIsProtected = !obj->format()->notProtected( left, top ); - - indent = obj->format()->getIndent(left, top); - - value = obj->value(); - - RowFormat *rl; - ColumnFormat *cl; - widthSize = 0.0; - heightSize = 0.0; - - if ( !isRowSelected ) - { - for ( int x = left; x <= right; x++ ) - { - cl = m_pView->activeSheet()->columnFormat( x ); - widthSize = TQMAX( cl->dblWidth(), widthSize ); - } - } - - if ( !isColumnSelected ) - { - for ( int y = top; y <= bottom; y++ ) - { - rl = m_pView->activeSheet()->rowFormat(y); - heightSize = TQMAX( rl->dblHeight(), heightSize ); - } - } - - //select column(s) - if ( isColumnSelected ) - { - int y = 1; - Cell* cell = NULL; - for (int x = left;x <= right; x++) - { - ColumnFormat *obj = m_sheet->nonDefaultColumnFormat(x); - initParameters( obj,x,y); - - for (cell = m_sheet->getFirstCellColumn(x); cell != NULL; - cell = m_sheet->getNextCellDown(cell->column(), cell->row())) - { - initParameters( cell->format(), x, cell->row()); - } - } - - } - else if ( isRowSelected ) - { - int x = 1; - Cell* c = NULL; - for ( int y = top;y<=bottom;y++) - { - RowFormat *obj = m_sheet->nonDefaultRowFormat(y); - initParameters( obj,x,y); - - for (c = m_sheet->getFirstCellRow(y); c != NULL; - c = m_sheet->getNextCellRight(c->column(), c->row()) ) - { - initParameters( c->format(), c->column(), c->row()); - } - } - } - else - { - // Do the other objects have the same values ? - for ( int x = left; x <= right; x++ ) - { - for ( int y = top; y <= bottom; y++ ) - { - Cell *obj = m_sheet->cellAt( x, y ); - - if ( obj->isPartOfMerged() ) - continue; - - initParameters( obj->format(),x,y); - } - } - } - if ( !bTextRotation ) - textRotation = 0; - - if ( isColumnSelected ) - { - int y=1; - ColumnFormat *obj=m_sheet->nonDefaultColumnFormat(left); - checkBorderLeft( obj,left, y); - - Cell* c = NULL; - for (c = m_sheet->getFirstCellColumn(left); c != NULL; - c = m_sheet->getNextCellDown(c->column(), c->row()) ) - { - checkBorderLeft(c->format(), c->column(), c->row()); - } - - - obj=m_sheet->nonDefaultColumnFormat(right); - checkBorderRight(obj,right,y); - c = NULL; - for (c = m_sheet->getFirstCellColumn(right); c != NULL; - c = m_sheet->getNextCellDown(c->column(), c->row()) ) - { - checkBorderRight(c->format(), c->column(), c->row()); - } - - for ( int x = left; x <= right; x++ ) - { - Cell *obj = m_sheet->cellAt( x, top ); - checkBorderTop(obj->format(),x, top); - obj = m_sheet->cellAt( x, bottom ); - checkBorderBottom(obj->format(),x, bottom); - if ( x > left ) - { - ColumnFormat *obj = m_sheet->nonDefaultColumnFormat(x); - checkBorderHorizontal(obj,x, y); - checkBorderVertical(obj,x, y); - } - } - } - else if ( isRowSelected ) - { - int x=1; - for ( int y = top; y <= bottom; y++ ) - { - Cell *obj = m_sheet->cellAt( right, y ); - checkBorderRight(obj->format(),right,y); - obj = m_sheet->cellAt( left, y ); - checkBorderLeft( obj->format(),left, y); - if ( y > top ) - { - RowFormat* obj = m_sheet->nonDefaultRowFormat(y); - checkBorderHorizontal(obj,x, y); - checkBorderVertical(obj,x, y); - } - } - - RowFormat *obj=m_sheet->nonDefaultRowFormat(top); - checkBorderTop(obj,x, top); - obj=m_sheet->nonDefaultRowFormat(bottom); - checkBorderBottom(obj,x, bottom); - } - else - { - for ( int y = top; y <= bottom; y++ ) - { - Cell *obj = m_sheet->cellAt( left, y ); - checkBorderLeft( obj->format(),left, y); - obj = m_sheet->cellAt( right, y ); - checkBorderRight(obj->format(),right,y); - } - - for ( int x = left; x <= right; x++ ) - { - Cell *obj = m_sheet->cellAt( x, top ); - checkBorderTop( obj->format(), x, top ); - obj = m_sheet->cellAt( x, bottom ); - checkBorderBottom( obj->format(), x, bottom ); - } - - // Look for the Outline - for ( int x = left; x <= right; x++ ) - { - for ( int y = top+1; y <= bottom; y++ ) - { - Cell *obj = m_sheet->cellAt( x, y ); - checkBorderHorizontal(obj->format(),x, y); - } - } - - for ( int x = left+1; x <= right; x++ ) - { - for ( int y = top; y <= bottom; y++ ) - { - Cell *obj = m_sheet->cellAt( x, y ); - checkBorderVertical(obj->format(),x,y); - } - } - } - - init(); -} - -CellFormatDialog::CellFormatDialog( View * _view, CustomStyle * _style, - StyleManager * _manager, Doc * doc ) - : TQObject(), - m_doc( doc ), - m_sheet( 0 ), - m_pView( _view ), - m_style( _style ), - m_styleManager( _manager ) -{ - initMembers(); - initGUI(); - init(); -} - -void CellFormatDialog::initGUI() -{ - isRowSelected = false; - isColumnSelected = false; - styleName = m_style->name(); - - borders[BorderType_Left].style = m_style->leftBorderPen().style(); - borders[BorderType_Left].width = m_style->leftBorderPen().width(); - borders[BorderType_Left].color = m_style->leftBorderPen().color(); - - borders[BorderType_Top].style = m_style->topBorderPen().style(); - borders[BorderType_Top].width = m_style->topBorderPen().width(); - borders[BorderType_Top].color = m_style->topBorderPen().color(); - - borders[BorderType_Right].style = m_style->rightBorderPen().style(); - borders[BorderType_Right].width = m_style->rightBorderPen().width(); - borders[BorderType_Right].color = m_style->rightBorderPen().color(); - - borders[BorderType_Bottom].style = m_style->bottomBorderPen().style(); - borders[BorderType_Bottom].width = m_style->bottomBorderPen().width(); - borders[BorderType_Bottom].color = m_style->bottomBorderPen().color(); - - borders[BorderType_FallingDiagonal].style = m_style->fallDiagonalPen().style(); - borders[BorderType_FallingDiagonal].width = m_style->fallDiagonalPen().width(); - borders[BorderType_FallingDiagonal].color = m_style->fallDiagonalPen().color(); - - borders[BorderType_RisingDiagonal].style = m_style->goUpDiagonalPen().style(); - borders[BorderType_RisingDiagonal].width = m_style->goUpDiagonalPen().width(); - borders[BorderType_RisingDiagonal].color = m_style->goUpDiagonalPen().color(); - - borders[BorderType_Vertical].style = m_style->leftBorderPen().style(); - borders[BorderType_Vertical].width = m_style->leftBorderPen().width(); - borders[BorderType_Vertical].color = m_style->leftBorderPen().color(); - borders[BorderType_Horizontal].style = m_style->topBorderPen().style(); - borders[BorderType_Horizontal].width = m_style->topBorderPen().width(); - borders[BorderType_Horizontal].color = m_style->topBorderPen().color(); - - prefix = m_style->prefix(); - postfix = m_style->postfix(); - precision = m_style->precision(); - floatFormat = m_style->floatFormat(); - floatColor = m_style->floatColor(); - alignX = m_style->alignX(); - alignY = m_style->alignY(); - textColor = m_style->pen().color(); - bgColor = m_style->bgColor(); - textFontSize = m_style->fontSize(); - textFontFamily = m_style->fontFamily(); - - uint flags = m_style->fontFlags(); - textFontBold = ( flags & (uint) Style::FBold ); - textFontItalic = ( flags & (uint) Style::FItalic ); - strike = ( flags & (uint) Style::FStrike ); - underline = ( flags & (uint) Style::FUnderline ); - - // Needed to initialize the font correctly ( bug in TQt ) - textFont = m_style->font(); - cCurrency = m_style->currency(); - brushColor = m_style->backGroundBrush().color(); - brushStyle = m_style->backGroundBrush().style(); - - bMultiRow = m_style->hasProperty( Style::PMultiRow ); - bVerticalText = m_style->hasProperty( Style::PVerticalText ); - textRotation = m_style->rotateAngle(); - formatType = m_style->formatType(); - indent = m_style->indent(); - - bDontPrintText = m_style->hasProperty( Style::PDontPrintText ); - bHideFormula = m_style->hasProperty( Style::PHideFormula ); - bHideAll = m_style->hasProperty( Style::PHideAll ); - bIsProtected = !m_style->hasProperty( Style::PNotProtected ); - - widthSize = defaultWidthSize; - heightSize = defaultHeightSize; -} - -CellFormatDialog::~CellFormatDialog() -{ - delete formatOnlyNegSignedPixmap; - delete formatRedOnlyNegSignedPixmap; - delete formatRedNeverSignedPixmap; - delete formatAlwaysSignedPixmap; - delete formatRedAlwaysSignedPixmap; -} - -void CellFormatDialog::initMembers() -{ - formatOnlyNegSignedPixmap = 0L; - formatRedOnlyNegSignedPixmap = 0L; - formatRedNeverSignedPixmap = 0L; - formatAlwaysSignedPixmap = 0L; - formatRedAlwaysSignedPixmap = 0L; - - // We assume, that all other objects have the same values - for ( int i = 0; i < BorderType_END; ++i ) - { - borders[i].bStyle = true; - borders[i].bColor = true; - } - bFloatFormat = true; - bFloatColor = true; - bTextColor = true; - bBgColor = true; - bTextFontFamily = true; - bTextFontSize = true; - bTextFontBold = true; - bTextFontItalic = true; - bStrike = true; - bUnderline = true; - bTextRotation = true; - bFormatType = true; - bCurrency = true; - bDontPrintText = false; - bHideFormula = false; - bHideAll = false; - bIsProtected = true; - - cCurrency.symbol = locale()->currencySymbol(); - cCurrency.type = 0; - - Sheet* sheet = m_pView->activeSheet(); - defaultWidthSize = sheet ? sheet->columnFormat(0)->dblWidth() : 0; - defaultHeightSize = sheet ? sheet->rowFormat(0)->dblHeight() : 0; -} - -bool CellFormatDialog::checkCircle( TQString const & name, TQString const & parent ) -{ - return m_styleManager->checkCircle( name, parent ); -} - -void CellFormatDialog::checkBorderRight(Format *obj,int x,int y) -{ - if ( borders[BorderType_Right].style != obj->rightBorderStyle( x, y ) || - borders[BorderType_Right].width != obj->rightBorderWidth( x, y ) ) - borders[BorderType_Right].bStyle = false; - if ( borders[BorderType_Right].color != obj->rightBorderColor( x, y ) ) - borders[BorderType_Right].bColor = false; -} - -void CellFormatDialog::checkBorderLeft(Format *obj,int x,int y) -{ - if ( borders[BorderType_Left].style != obj->leftBorderStyle( x, y ) || - borders[BorderType_Left].width != obj->leftBorderWidth( x, y ) ) - borders[BorderType_Left].bStyle = false; - if ( borders[BorderType_Left].color != obj->leftBorderColor( x, y ) ) - borders[BorderType_Left].bColor = false; -} - -void CellFormatDialog::checkBorderTop(Format *obj,int x,int y) -{ - if ( borders[BorderType_Top].style != obj->topBorderStyle( x, y ) || - borders[BorderType_Top].width != obj->topBorderWidth( x, y ) ) - borders[BorderType_Top].bStyle = false; - if ( borders[BorderType_Top].color != obj->topBorderColor( x, y ) ) - borders[BorderType_Top].bColor = false; -} - -void CellFormatDialog::checkBorderBottom(Format *obj,int x,int y) -{ - if ( borders[BorderType_Bottom].style != obj->bottomBorderStyle( x, y ) || - borders[BorderType_Bottom].width != obj->bottomBorderWidth( x, y ) ) - borders[BorderType_Bottom].bStyle = false; - if ( borders[BorderType_Bottom].color != obj->bottomBorderColor( x, y ) ) - borders[BorderType_Bottom].bColor = false; -} - -void CellFormatDialog::checkBorderVertical(Format *obj,int x,int y) -{ - if (borders[BorderType_Vertical].style != obj->leftBorderStyle( x, y ) || - borders[BorderType_Vertical].width != obj->leftBorderWidth( x, y )) - borders[BorderType_Vertical].bStyle = false; - if ( borders[BorderType_Vertical].color != obj->leftBorderColor( x, y ) ) - borders[BorderType_Vertical].bColor = false; -} - -void CellFormatDialog::checkBorderHorizontal(Format *obj,int x,int y) -{ - if ( borders[BorderType_Horizontal].style != obj->topBorderStyle( x, y ) || - borders[BorderType_Horizontal].width != obj->topBorderWidth( x, y ) ) - borders[BorderType_Horizontal].bStyle = false; - if ( borders[BorderType_Horizontal].color != obj->topBorderColor( x, y ) ) - borders[BorderType_Horizontal].bColor = false; -} - - -void CellFormatDialog::initParameters(Format *obj,int x,int y) -{ - if (borders[BorderType_FallingDiagonal].style != obj->fallDiagonalStyle( x, y )) - borders[BorderType_FallingDiagonal].bStyle = false; - if (borders[BorderType_FallingDiagonal].width != obj->fallDiagonalWidth( x, y )) - borders[BorderType_FallingDiagonal].bStyle = false; - if (borders[BorderType_FallingDiagonal].color != obj->fallDiagonalColor( x, y )) - borders[BorderType_FallingDiagonal].bColor = false; - - if (borders[BorderType_RisingDiagonal].style != obj->goUpDiagonalStyle( x, y )) - borders[BorderType_RisingDiagonal].bStyle = false; - if (borders[BorderType_RisingDiagonal].width != obj->goUpDiagonalWidth( x, y )) - borders[BorderType_RisingDiagonal].bStyle = false; - if (borders[BorderType_RisingDiagonal].color != obj->goUpDiagonalColor( x, y )) - borders[BorderType_RisingDiagonal].bColor = false; - if ( strike != obj->textFontStrike( x, y ) ) - bStrike = false; - if ( underline != obj->textFontUnderline( x, y ) ) - bUnderline = false; - if ( prefix != obj->prefix( x, y ) ) - prefix = TQString(); - if ( postfix != obj->postfix( x, y ) ) - postfix = TQString(); - if ( floatFormat != obj->floatFormat( x, y ) ) - bFloatFormat = false; - if ( floatColor != obj->floatColor( x, y ) ) - bFloatColor = false; - if ( textColor != obj->textColor( x, y ) ) - bTextColor = false; - if ( textFontFamily != obj->textFontFamily( x, y ) ) - bTextFontFamily = false; - if ( textFontSize != obj->textFontSize( x, y ) ) - bTextFontSize = false; - if ( textFontBold != obj->textFontBold( x, y ) ) - bTextFontBold = false; - if ( textFontItalic != obj->textFontItalic( x, y ) ) - bTextFontItalic = false; - if ( bgColor != obj->bgColor( x, y ) ) - bBgColor = false; - if ( textRotation != obj->getAngle(left, top) ) - bTextRotation = false; - if ( formatType != obj->getFormatType(left, top) ) - bFormatType = false; - if ( bMultiRow != obj->multiRow( left, top ) ) - bMultiRow = false; - if ( bVerticalText!=obj->verticalText( left, top ) ) - bVerticalText = false; - if ( bDontPrintText!=obj->getDontprintText( left, top ) ) - bDontPrintText= false; - - Format::Currency cur; - if (!obj->currencyInfo(cur)) - bCurrency = false; - else - if (cur.symbol != cCurrency.symbol) - bCurrency = false; -} - -void CellFormatDialog::init() -{ - TQColorGroup colorGroup = TQApplication::palette().active(); - - // Did we initialize the bitmaps ? - if ( formatOnlyNegSignedPixmap == 0L ) - { - TQColor black = colorGroup.text(); // not necessarily black :) - formatOnlyNegSignedPixmap = paintFormatPixmap( "123.456", black, "-123.456", black ); - formatRedOnlyNegSignedPixmap = paintFormatPixmap( "123.456", black, "-123.456", TQt::red ); - formatRedNeverSignedPixmap = paintFormatPixmap( "123.456", black, "123.456", TQt::red ); - formatAlwaysSignedPixmap = paintFormatPixmap( "+123.456", black, "-123.456", black ); - formatRedAlwaysSignedPixmap = paintFormatPixmap( "+123.456", black, "-123.456", TQt::red ); - } - - tab = new TQTabDialog( (TQWidget*)m_pView, 0L, true ); - //tab->setGeometry( tab->x(), tab->y(), 420, 400 ); - - if ( m_style ) - { - generalPage = new GeneralTab( tab, this ); - tab->addTab( generalPage, i18n( "&General" ) ); - } - - floatPage = new CellFormatPageFloat( tab, this ); - tab->addTab( floatPage, i18n("&Data Format") ); - - fontPage = new CellFormatPageFont( tab, this ); - tab->addTab( fontPage, i18n("&Font") ); - - // miscPage = new CellFormatPageMisc( tab, this ); - // tab->addTab( miscPage, i18n("&Misc") ); - - positionPage = new CellFormatPagePosition( tab, this); - tab->addTab( positionPage, i18n("&Position") ); - - borderPage = new CellFormatPageBorder( tab, this ); - tab->addTab( borderPage, i18n("&Border") ); - - patternPage=new CellFormatPagePattern(tab,this); - tab->addTab( patternPage,i18n("Back&ground")); - - protectPage = new CellFormatPageProtection( tab, this ); - tab->addTab( protectPage, i18n("&Cell Protection") ); - - tab->setCancelButton( i18n( "&Cancel" ) ); - tab->setOkButton( i18n( "&OK" ) ); - - tab->setCaption( i18n( "Cell Format" ) ); - - tab->adjustSize(); - - connect( tab, TQT_SIGNAL( applyButtonPressed() ), this, TQT_SLOT( slotApply() ) ); - - tab->exec(); -} - -TQPixmap * CellFormatDialog::paintFormatPixmap( const char * _string1, const TQColor & _color1, - const char *_string2, const TQColor & _color2 ) -{ - TQPixmap * pixmap = new TQPixmap( 150, 14 ); - - TQPainter painter; - painter.begin( pixmap ); - painter.fillRect( 0, 0, 150, 14, TQApplication::palette().active().base() ); - painter.setPen( _color1 ); - painter.drawText( 2, 11, TQString(_string1) ); - painter.setPen( _color2 ); - painter.drawText( 75, 11, TQString(_string2) ); - painter.end(); - - TQBitmap bm( pixmap->size() ); - bm.fill( color0 ); - painter.begin( &bm ); - painter.setPen( color1 ); - painter.drawText( 2, 11, TQString(_string1) ); - painter.drawText( 75, 11, TQString(_string2) ); - painter.end(); - pixmap->setMask( bm ); - - return pixmap; -} - -int CellFormatDialog::exec() -{ - return ( tab->exec() ); -} - -void CellFormatDialog::applyStyle() -{ - generalPage->apply( m_style ); - - borderPage->apply(0); - floatPage->apply( m_style ); - // miscPage->apply( m_style ); - fontPage->apply( m_style ); - positionPage->apply( m_style ); - patternPage->apply( m_style ); - protectPage->apply( m_style ); - m_pView->refreshView(); -} - -void CellFormatDialog::slotApply() -{ - if ( m_style ) - { - applyStyle(); - return; - } - - // (Tomas) TODO: this will be slow !!! - // We need to create a manipulator that would act as KMacroCommand, - // but which would also ensure that updates are not painted until everything - // is updated properly ... - KMacroCommand* macroCommand = new KMacroCommand( i18n("Change Format") ); - - if ( isMerged != positionPage->getMergedCellState() ) - { - if ( positionPage->getMergedCellState() ) - { - Manipulator* manipulator = new MergeManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setRegisterUndo(false); - manipulator->add(*m_pView->selectionInfo()); - macroCommand->addCommand( manipulator ); - } - else - { - //dissociate cells - Manipulator* manipulator = new MergeManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setReverse(true); - manipulator->setRegisterUndo(false); - manipulator->add(*m_pView->selectionInfo()); - macroCommand->addCommand( manipulator ); - } - } - - FormatManipulator* manipulator = new FormatManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setRegisterUndo(false); - manipulator->add(*m_pView->selectionInfo()); - borderPage->apply(manipulator); - floatPage->apply(manipulator); - fontPage->apply(manipulator); - positionPage->apply(manipulator); - patternPage->apply(manipulator); - protectPage->apply(manipulator); - - if (!manipulator->isEmpty()) - { - macroCommand->addCommand( manipulator ); - } - else - { - delete manipulator; - } - - if ( int( positionPage->getSizeHeight() ) != int( heightSize ) ) - { - ResizeRowManipulator* manipulator = new ResizeRowManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setSize(positionPage->getSizeHeight()); - // TODO Stefan: - manipulator->setOldSize(heightSize); - manipulator->add(*m_pView->selectionInfo()); - macroCommand->addCommand( manipulator ); - } - if ( int( positionPage->getSizeWidth() ) != int( widthSize ) ) - { - ResizeColumnManipulator* manipulator = new ResizeColumnManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setSize(positionPage->getSizeWidth()); - // TODO Stefan: - manipulator->setOldSize(widthSize); - manipulator->add(*m_pView->selectionInfo()); - macroCommand->addCommand( manipulator ); - } - - macroCommand->execute(); - m_doc->addCommand( macroCommand ); - - // Update the toolbar (bold/italic/font...) - m_pView->updateEditWidget(); -} - - - -/*************************************************************************** - * - * CellFormatPageFloat - * - ***************************************************************************/ - -CellFormatPageFloat::CellFormatPageFloat( TQWidget* parent, CellFormatDialog *_dlg ) - : TQWidget ( parent ), - dlg( _dlg ) -{ - TQVBoxLayout* layout = new TQVBoxLayout( this, 6,10 ); - - TQButtonGroup *grp = new TQButtonGroup( i18n("Format"),this); - TQGridLayout *grid = new TQGridLayout(grp,11,2,KDialog::marginHint(), KDialog::spacingHint()); - - int fHeight = grp->fontMetrics().height(); - grid->addRowSpacing( 0, fHeight/2 ); // groupbox title - - grp->setRadioButtonExclusive( true ); - generic=new TQRadioButton(i18n("Generic"),grp); - TQWhatsThis::add(generic, i18n( "This is the default format and KSpread autodetects the actual data type depending on the current cell data. By default, KSpread right justifies numbers, dates and times within a cell and left justifies anything else." ) ); - grid->addWidget(generic,1,0); - - number=new TQRadioButton(i18n("Number"),grp); - TQWhatsThis::add(number, i18n( "The number notation uses the notation you globally choose in KControl -> Regional & Accessibility -> Numbers tab. Numbers are right justified by default." ) ); - grid->addWidget(number,2,0); - - percent=new TQRadioButton(i18n("Percent"),grp); - TQWhatsThis::add(percent, i18n( "When you have a number in the current cell and you switch from the dcell format from Generic to Percent, the current cell number will be multiplied by 100%.\nFor example if you enter 12 and set the cell format to Percent, the number will then be 1,200 %. Switching back to Generic cell format will bring it back to 12.\nYou can also use the Percent icon in the Format Toolbar." ) ); - grid->addWidget(percent,3,0); - - money=new TQRadioButton(i18n("Money"),grp); - TQWhatsThis::add(money, i18n( "The Money format converts your number into money notation using the settings globally fixed in KControl in Regional & Accessibility -> Money. The currency symbol will be displayed and the precision will be the one set in KControl.\nYou can also use the Currency icon in the Format Toolbar to set the cell formatting to look like your current currency." ) ); - grid->addWidget(money,4,0); - - scientific=new TQRadioButton(i18n("Scientific"),grp); - TQWhatsThis::add(scientific, i18n( "The scientific format changes your number using the scientific notation. For example, 0.0012 will be changed to 1.2E-03. Going back using Generic cell format will display 0.0012 again." ) ); - grid->addWidget(scientific,5,0); - - fraction=new TQRadioButton(i18n("Fraction"),grp); - TQWhatsThis::add(fraction, i18n( "The fraction format changes your number into a fraction. For example, 0.1 can be changed to 1/8, 2/16, 1/10, etc. You define the type of fraction by choosing it in the field on the right. If the exact fraction is not possible in the fraction mode you choose, the nearest closest match is chosen.\n For example: when we have 1.5 as number, we choose Fraction and Sixteenths 1/16 the text displayed into cell is \"1 8/16\" which is an exact fraction. If you have 1.4 as number in your cell and you choose Fraction and Sixteenths 1/16 then the cell will display \"1 6/16\" which is the nearest closest Sixteenth fraction." ) ); - grid->addWidget(fraction,6,0); - - date=new TQRadioButton(i18n("Date format"),grp); - TQWhatsThis::add(date, i18n( "To enter a date, you should enter it in one of the formats set in KControl in Regional & Accessibility ->Time & Dates. There are two formats set here: the date format and the short date format.\nJust like you can drag down numbers you can also drag down dates and the next cells will also get dates." ) ); - grid->addWidget(date,7,0); - - time=new TQRadioButton(i18n("Time format"),grp); - TQWhatsThis::add(time, i18n( "This formats your cell content as a time. To enter a time, you should enter it in the Time format set in KControl in Regional & Accessibility ->Time & Dates. In the Cell Format dialog box you can set how the time should be displayed by choosing one of the available time format options. The default format is the system format set in KControl. When the number in the cell does not make sense as a time, KSpread will display 00:00 in the global format you have in KControl." ) ); - grid->addWidget(time,8,0); - - textFormat=new TQRadioButton(i18n("Text"),grp); - TQWhatsThis::add(textFormat, i18n( "This formats your cell content as text. This can be useful if you want a number treated as text instead as a number, for example for a ZIP code. Setting a number as text format will left justify it. When numbers are formatted as text, they cannot be used in calculations or formulas. It also change the way the cell is justified." ) ); - grid->addWidget(textFormat,9,0); - - customFormat=new TQRadioButton(i18n("Custom"),grp); - TQWhatsThis::add(customFormat, i18n( "The custom format does not work yet. To be enabled in the next release." ) ); - grid->addWidget(customFormat,10,0); - customFormat->setEnabled( false ); - - TQGroupBox *box2 = new TQGroupBox( grp, "Box"); - box2->setTitle(i18n("Preview")); - TQGridLayout *grid3 = new TQGridLayout(box2,1,3,KDialog::marginHint(), KDialog::spacingHint()); - - exampleLabel=new TQLabel(box2); - TQWhatsThis::add(exampleLabel, i18n( "This will display a preview of your choice so you can know what it does before clicking the OK button to validate it." ) ); - grid3->addWidget(exampleLabel,0,1); - - grid->addMultiCellWidget(box2,9,10,1,1); - - customFormatEdit = new TQLineEdit( grp ); - grid->addMultiCellWidget( customFormatEdit, 1, 1, 1, 1 ); - customFormatEdit->setHidden( true ); - - listFormat=new TQListBox(grp); - grid->addMultiCellWidget(listFormat,2,7,1,1); - TQWhatsThis::add(listFormat, i18n( "Displays choices of format for the fraction, date or time formats." ) ); - layout->addWidget(grp); - - /* *** */ - - TQGroupBox *box = new TQGroupBox( this, "Box"); - - grid = new TQGridLayout(box,3,4,KDialog::marginHint(), KDialog::spacingHint()); - - postfix = new TQLineEdit( box, "LineEdit_1" ); - TQWhatsThis::add(postfix, i18n( "You can add here a Postfix such as a $HK symbol to the end of each cell content in the checked format." ) ); - grid->addWidget(postfix,2,1); - precision = new KIntNumInput( dlg->precision, box, 10 ); - precision->setSpecialValueText(i18n("variable")); - precision->setRange(-1,10,1,false); - TQWhatsThis::add(precision, i18n( "You can control how many digits are displayed after the decimal point for numeric values. This can also be changed using the Increase precision or Decrease precision icons in the Format toolbar. " ) ); - grid->addWidget(precision,1,1); - - prefix = new TQLineEdit( box, "LineEdit_3" ); - TQWhatsThis::add(prefix, i18n( "You can add here a Prefix such as a $ symbol at the start of each cell content in the checked format." ) ); - grid->addWidget(prefix,0,1); - - format = new TQComboBox( box, "ListBox_1" ); - TQWhatsThis::add(format, i18n( "You can choose whether positive values are displayed with a leading + sign and whether negative values are shown in red." ) ); - grid->addWidget(format,0,3); - - TQLabel* tmpTQLabel; - tmpTQLabel = new TQLabel( box, "Label_1" ); - grid->addWidget(tmpTQLabel,2,0); - tmpTQLabel->setText( i18n("Postfix:") ); - - postfix->setText( dlg->postfix ); - - tmpTQLabel = new TQLabel( box, "Label_2" ); - grid->addWidget(tmpTQLabel,0,0); - - tmpTQLabel->setText( i18n("Prefix:") ); - tmpTQLabel = new TQLabel( box, "Label_3" ); - grid->addWidget(tmpTQLabel,1,0); - tmpTQLabel->setText( i18n("Precision:") ); - - prefix->setText( dlg->prefix ); - - format->insertItem( *_dlg->formatOnlyNegSignedPixmap, 0 ); - format->insertItem( *_dlg->formatRedOnlyNegSignedPixmap, 1 ); - format->insertItem( *_dlg->formatRedNeverSignedPixmap, 2 ); - format->insertItem( *_dlg->formatAlwaysSignedPixmap, 3 ); - format->insertItem( *_dlg->formatRedAlwaysSignedPixmap, 4 ); - - tmpTQLabel = new TQLabel( box, "Label_4" ); - grid->addWidget(tmpTQLabel, 0, 2); - tmpTQLabel->setText( i18n("Format:") ); - - currencyLabel = new TQLabel( box, "LabelCurrency" ); - grid->addWidget(currencyLabel, 1, 2); - currencyLabel->setText( i18n("Currency:") ); - - currency = new TQComboBox( box, "ComboCurrency" ); - grid->addWidget(currency, 1, 3); - - currency->insertItem( i18n("Automatic") ); - - int index = 2; //ignore first two in the list - bool ok = true; - TQString text; - - while ( ok ) - { - text = Currency::getChooseString( index, ok ); - if ( ok ) - { - currency->insertItem( text ); - } - else - { - break; - } - - ++index; - } - - currency->setCurrentItem( 0 ); - currency->hide(); - currencyLabel->hide(); - - if ( !dlg->bFloatFormat || !dlg->bFloatColor ) - format->setCurrentItem( 5 ); - else if ( dlg->floatFormat == Format::OnlyNegSigned && dlg->floatColor == Format::AllBlack ) - format->setCurrentItem( 0 ); - else if ( dlg->floatFormat == Format::OnlyNegSigned && dlg->floatColor == Format::NegRed ) - format->setCurrentItem( 1 ); - else if ( dlg->floatFormat == Format::AlwaysUnsigned && dlg->floatColor == Format::NegRed ) - format->setCurrentItem( 2 ); - else if ( dlg->floatFormat == Format::AlwaysSigned && dlg->floatColor == Format::AllBlack ) - format->setCurrentItem( 3 ); - else if ( dlg->floatFormat == Format::AlwaysSigned && dlg->floatColor == Format::NegRed ) - format->setCurrentItem( 4 ); - layout->addWidget(box); - - cellFormatType=dlg->formatType; - newFormatType = cellFormatType; - - if (!cellFormatType) - generic->setChecked(true); - else - { - if (cellFormatType==Number_format) - number->setChecked(true); - else if (cellFormatType==Percentage_format) - percent->setChecked(true); - else if (cellFormatType==Money_format) - { - money->setChecked(true); - currencyLabel->show(); - currency->show(); - if (dlg->bCurrency) - { - TQString tmp; - if (dlg->cCurrency.type != 1) - { - Currency curr(dlg->cCurrency.type); - bool ok = true; - tmp = Currency::getChooseString(dlg->cCurrency.type, ok); - if ( !ok ) - tmp = dlg->cCurrency.symbol; - } - else - tmp = dlg->cCurrency.symbol; - currency->setCurrentText( tmp ); - } - } - else if ( cellFormatType == Scientific_format ) - scientific->setChecked(true); - else if ( formatIsDate (cellFormatType) ) - date->setChecked(true); - else if ( formatIsTime (cellFormatType) ) - time->setChecked(true); - else if ( formatIsFraction (cellFormatType) ) - fraction->setChecked(true); - else if (cellFormatType == Text_format) - textFormat->setChecked(true); - else if (cellFormatType == Custom_format) - customFormat->setChecked(true); - } - - connect(generic,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(fraction,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(money,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(date,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(scientific,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(number,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(percent,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(time,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); - connect(textFormat,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotChangeState())); - connect(customFormat,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotChangeState())); - - connect(listFormat,TQT_SIGNAL(selectionChanged ()),this,TQT_SLOT(makeformat())); - connect(precision,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(slotChangeValue(int))); - connect(prefix,TQT_SIGNAL(textChanged ( const TQString & ) ),this,TQT_SLOT(makeformat())); - connect(postfix,TQT_SIGNAL(textChanged ( const TQString & ) ),this,TQT_SLOT(makeformat())); - connect(currency,TQT_SIGNAL(activated ( const TQString & ) ),this, TQT_SLOT(currencyChanged(const TQString &))); - connect(format,TQT_SIGNAL(activated ( int ) ),this,TQT_SLOT(formatChanged(int))); - connect(format, TQT_SIGNAL(activated(int)), this, TQT_SLOT(makeformat())); - slotChangeState(); - m_bFormatColorChanged=false; - m_bFormatTypeChanged=false; - this->resize( 400, 400 ); -} - -void CellFormatPageFloat::formatChanged(int) -{ - m_bFormatColorChanged=true; -} - -void CellFormatPageFloat::slotChangeValue(int) -{ - makeformat(); -} -void CellFormatPageFloat::slotChangeState() -{ - TQStringList list; - listFormat->clear(); - currency->hide(); - currencyLabel->hide(); - - // start with enabled, they get disabled when inappropriate further down - precision->setEnabled(true); - prefix->setEnabled(true); - postfix->setEnabled(true); - format->setEnabled(true); - - if (generic->isChecked() || number->isChecked() || percent->isChecked() || - scientific->isChecked() || textFormat->isChecked()) - listFormat->setEnabled(false); - else if (money->isChecked()) - { - listFormat->setEnabled(false); - precision->setValue(2); - currency->show(); - currencyLabel->show(); - } - else if (date->isChecked()) - { - format->setEnabled(false); - precision->setEnabled(false); - prefix->setEnabled(false); - postfix->setEnabled(false); - listFormat->setEnabled(true); - init(); - } - else if (fraction->isChecked()) - { - precision->setEnabled(false); - listFormat->setEnabled(true); - list+=i18n("Halves 1/2"); - list+=i18n("Quarters 1/4"); - list+=i18n("Eighths 1/8"); - list+=i18n("Sixteenths 1/16"); - list+=i18n("Tenths 1/10"); - list+=i18n("Hundredths 1/100"); - list+=i18n("One digit 5/9"); - list+=i18n("Two digits 15/22"); - list+=i18n("Three digits 153/652"); - listFormat->insertStringList(list); - if (cellFormatType == fraction_half) - listFormat->setCurrentItem(0); - else if (cellFormatType == fraction_quarter) - listFormat->setCurrentItem(1); - else if (cellFormatType == fraction_eighth ) - listFormat->setCurrentItem(2); - else if (cellFormatType == fraction_sixteenth ) - listFormat->setCurrentItem(3); - else if (cellFormatType == fraction_tenth ) - listFormat->setCurrentItem(4); - else if (cellFormatType == fraction_hundredth ) - listFormat->setCurrentItem(5); - else if (cellFormatType == fraction_one_digit ) - listFormat->setCurrentItem(6); - else if (cellFormatType == fraction_two_digits ) - listFormat->setCurrentItem(7); - else if (cellFormatType == fraction_three_digits ) - listFormat->setCurrentItem(8); - else - listFormat->setCurrentItem(0); - } - else if (time->isChecked()) - { - precision->setEnabled(false); - prefix->setEnabled(false); - postfix->setEnabled(false); - format->setEnabled(false); - listFormat->setEnabled(true); - - - list+=i18n("System: ")+dlg->locale()->formatTime(TQTime::currentTime(),false); - list+=i18n("System: ")+dlg->locale()->formatTime(TQTime::currentTime(),true); - TQDateTime tmpTime (TQDate (1, 1, 1900), TQTime (10, 35, 25)); - - - ValueFormatter *fmt = dlg->getDoc()->formatter(); - list+= fmt->timeFormat(tmpTime, Time_format1); - list+= fmt->timeFormat(tmpTime, Time_format2); - list+= fmt->timeFormat(tmpTime, Time_format3); - list+= fmt->timeFormat(tmpTime, Time_format4); - list+= fmt->timeFormat(tmpTime, Time_format5); - list+= ( fmt->timeFormat(tmpTime, Time_format6) + i18n(" (=[mm]::ss)") ); - list+= ( fmt->timeFormat(tmpTime, Time_format7) + i18n(" (=[hh]::mm::ss)") ); - list+= ( fmt->timeFormat(tmpTime, Time_format8) + i18n(" (=[hh]::mm)") ); - listFormat->insertStringList(list); - - if ( cellFormatType == Time_format ) - listFormat->setCurrentItem(0); - else if (cellFormatType == SecondeTime_format) - listFormat->setCurrentItem(1); - else if (cellFormatType == Time_format1) - listFormat->setCurrentItem(2); - else if (cellFormatType == Time_format2) - listFormat->setCurrentItem(3); - else if (cellFormatType == Time_format3) - listFormat->setCurrentItem(4); - else if (cellFormatType == Time_format4) - listFormat->setCurrentItem(5); - else if (cellFormatType == Time_format5) - listFormat->setCurrentItem(6); - else if (cellFormatType == Time_format6) - listFormat->setCurrentItem(7); - else if (cellFormatType == Time_format7) - listFormat->setCurrentItem(8); - else if (cellFormatType == Time_format8) - listFormat->setCurrentItem(9); - else - listFormat->setCurrentItem(0); - } - - if (customFormat->isChecked()) - { - customFormatEdit->setHidden( false ); - precision->setEnabled(false); - prefix->setEnabled(false); - postfix->setEnabled(false); - format->setEnabled(false); - listFormat->setEnabled(true); - } - else - customFormatEdit->setHidden( true ); - - m_bFormatTypeChanged=true; - - makeformat(); -} - -void CellFormatPageFloat::init() -{ - TQStringList list; - TQString tmp; - TQString tmp2; - TQDate tmpDate( 2000,2,18); - list+=i18n("System: ")+dlg->locale()->formatDate (TQDate::currentDate(), true); - list+=i18n("System: ")+dlg->locale()->formatDate (TQDate::currentDate(), false); - - ValueFormatter *fmt = dlg->getDoc()->formatter(); - - /*18-Feb-00*/ - list+=fmt->dateFormat( tmpDate, date_format1); - /*18-Feb-1999*/ - list+=fmt->dateFormat( tmpDate, date_format2); - /*18-Feb*/ - list+=fmt->dateFormat( tmpDate, date_format3); - /*18-2*/ - list+=fmt->dateFormat( tmpDate, date_format4); - /*18/2/00*/ - list+=fmt->dateFormat( tmpDate, date_format5); - /*18/5/1999*/ - list+=fmt->dateFormat( tmpDate, date_format6); - /*Feb-99*/ - list+=fmt->dateFormat( tmpDate, date_format7); - /*February-99*/ - list+=fmt->dateFormat( tmpDate, date_format8); - /*February-1999*/ - list+=fmt->dateFormat( tmpDate, date_format9); - /*F-99*/ - list+=fmt->dateFormat( tmpDate, date_format10); - /*18/Feb*/ - list+=fmt->dateFormat( tmpDate, date_format11); - /*18/2*/ - list+=fmt->dateFormat( tmpDate, date_format12); - /*18/Feb/1999*/ - list+=fmt->dateFormat( tmpDate, date_format13); - /*2000/Feb/18*/ - list+=fmt->dateFormat( tmpDate, date_format14); - /*2000-Feb-18*/ - list+=fmt->dateFormat( tmpDate, date_format15); - /*2000-2-18*/ - list+=fmt->dateFormat( tmpDate, date_format16); - /*2 february 2000*/ - list+=fmt->dateFormat( tmpDate, date_format17); - list+=fmt->dateFormat( tmpDate, date_format18); - list+=fmt->dateFormat( tmpDate, date_format19); - list+=fmt->dateFormat( tmpDate, date_format20); - list+=fmt->dateFormat( tmpDate, date_format21); - list+=fmt->dateFormat( tmpDate, date_format22); - list+=fmt->dateFormat( tmpDate, date_format23); - list+=fmt->dateFormat( tmpDate, date_format24); - list+=fmt->dateFormat( tmpDate, date_format25); - list+=fmt->dateFormat( tmpDate, date_format26); - - listFormat->insertStringList(list); - if ( cellFormatType == ShortDate_format ) - listFormat->setCurrentItem(0); - else if (cellFormatType == TextDate_format) - listFormat->setCurrentItem(1); - else if (cellFormatType == date_format1) - listFormat->setCurrentItem(2); - else if (cellFormatType == date_format2) - listFormat->setCurrentItem(3); - else if (cellFormatType == date_format3) - listFormat->setCurrentItem(4); - else if (cellFormatType == date_format4) - listFormat->setCurrentItem(5); - else if (cellFormatType == date_format5) - listFormat->setCurrentItem(6); - else if (cellFormatType == date_format6) - listFormat->setCurrentItem(7); - else if (cellFormatType == date_format7) - listFormat->setCurrentItem(8); - else if (cellFormatType == date_format8) - listFormat->setCurrentItem(9); - else if (cellFormatType == date_format9) - listFormat->setCurrentItem(10); - else if (cellFormatType == date_format10) - listFormat->setCurrentItem(11); - else if (cellFormatType == date_format11) - listFormat->setCurrentItem(12); - else if (cellFormatType == date_format12) - listFormat->setCurrentItem(13); - else if (cellFormatType == date_format13) - listFormat->setCurrentItem(14); - else if (cellFormatType == date_format14) - listFormat->setCurrentItem(15); - else if (cellFormatType == date_format15) - listFormat->setCurrentItem(16); - else if (cellFormatType == date_format16) - listFormat->setCurrentItem(17); - else if (cellFormatType == date_format17) - listFormat->setCurrentItem(18); - else if (cellFormatType == date_format18) - listFormat->setCurrentItem(19); - else if (cellFormatType == date_format19) - listFormat->setCurrentItem(20); - else if (cellFormatType == date_format20) - listFormat->setCurrentItem(21); - else if (cellFormatType == date_format21) - listFormat->setCurrentItem(22); - else if (cellFormatType == date_format22) - listFormat->setCurrentItem(23); - else if (cellFormatType == date_format23) - listFormat->setCurrentItem(24); - else if (cellFormatType == date_format24) - listFormat->setCurrentItem(25); - else if (cellFormatType == date_format25) - listFormat->setCurrentItem(26); - else if (cellFormatType == date_format26) - listFormat->setCurrentItem(27); - else - listFormat->setCurrentItem(0); - -} - -void CellFormatPageFloat::currencyChanged(const TQString &) -{ - int index = currency->currentItem(); - if (index > 0) - ++index; - dlg->cCurrency.symbol = Currency::getDisplaySymbol(index); - dlg->cCurrency.type = index; - - makeformat(); -} - -void CellFormatPageFloat::updateFormatType () -{ - if (generic->isChecked()) - newFormatType = Generic_format; - else if (number->isChecked()) - newFormatType = Number_format; - else if (percent->isChecked()) - newFormatType = Percentage_format; - else if (date->isChecked()) - { - newFormatType=ShortDate_format; - switch (listFormat->currentItem()) - { - case 0: newFormatType=ShortDate_format; break; - case 1: newFormatType=TextDate_format; break; - case 2: newFormatType=date_format1; break; /*18-Feb-99*/ - case 3: newFormatType=date_format2; break; /*18-Feb-1999*/ - case 4: newFormatType=date_format3; break; /*18-Feb*/ - case 5: newFormatType=date_format4; break; /*18-05*/ - case 6: newFormatType=date_format5; break; /*18/05/00*/ - case 7: newFormatType=date_format6; break; /*18/05/1999*/ - case 8: newFormatType=date_format7; break;/*Feb-99*/ - case 9: newFormatType=date_format8; break; /*February-99*/ - case 10: newFormatType=date_format9; break; /*February-1999*/ - case 11: newFormatType=date_format10; break; /*F-99*/ - case 12: newFormatType=date_format11; break; /*18/Feb*/ - case 13: newFormatType=date_format12; break; /*18/02*/ - case 14: newFormatType=date_format13; break; /*18/Feb/1999*/ - case 15: newFormatType=date_format14; break; /*2000/Feb/18*/ - case 16: newFormatType=date_format15; break;/*2000-Feb-18*/ - case 17: newFormatType=date_format16; break;/*2000-02-18*/ - case 18: newFormatType=date_format17; break; /*2000-02-18*/ - case 19: newFormatType=date_format18; break; - case 20: newFormatType=date_format19; break; - case 21: newFormatType=date_format20; break; - case 22: newFormatType=date_format21; break; - case 23: newFormatType=date_format22; break; - case 24: newFormatType=date_format23; break; - case 25: newFormatType=date_format24; break; - case 26: newFormatType=date_format25; break; - case 27: newFormatType=date_format26; break; - } - } - else if (money->isChecked()) - newFormatType = Money_format; - else if (scientific->isChecked()) - newFormatType = Scientific_format; - else if (fraction->isChecked()) - { - newFormatType=fraction_half; - switch (listFormat->currentItem()) - { - case 0: newFormatType=fraction_half; break; - case 1: newFormatType=fraction_quarter; break; - case 2: newFormatType=fraction_eighth; break; - case 3: newFormatType=fraction_sixteenth; break; - case 4: newFormatType=fraction_tenth; break; - case 5: newFormatType=fraction_hundredth; break; - case 6: newFormatType=fraction_one_digit; break; - case 7: newFormatType=fraction_two_digits; break; - case 8: newFormatType=fraction_three_digits; break; - } - } - else if (time->isChecked()) - { - newFormatType=Time_format; - switch (listFormat->currentItem()) - { - case 0: newFormatType=Time_format; break; - case 1: newFormatType=SecondeTime_format; break; - case 2: newFormatType=Time_format1; break; - case 3: newFormatType=Time_format2; break; - case 4: newFormatType=Time_format3; break; - case 5: newFormatType=Time_format4; break; - case 6: newFormatType=Time_format5; break; - case 7: newFormatType=Time_format6; break; - case 8: newFormatType=Time_format7; break; - case 9: newFormatType=Time_format8; break; - } - } - else if (textFormat->isChecked()) - newFormatType = Text_format; - else if (customFormat->isChecked()) - newFormatType = Custom_format; -} - -void CellFormatPageFloat::makeformat() -{ - m_bFormatTypeChanged=true; - TQString tmp; - - updateFormatType(); - TQColor color; - Format::FloatFormat floatFormat = Format::OnlyNegSigned; - switch( format->currentItem() ) - { - case 0: - floatFormat = Format::OnlyNegSigned; - color = black; - break; - case 1: - floatFormat = Format::OnlyNegSigned; - color = TQt::red; - break; - case 2: - floatFormat = Format::AlwaysUnsigned; - color = TQt::red; - break; - case 3: - floatFormat = Format::AlwaysSigned; - color = black; - break; - case 4: - floatFormat = Format::AlwaysSigned; - color = TQt::red; - break; - } - if (!dlg->value.isNumber() || dlg->value.asFloat() >= 0 || !format->isEnabled()) - { - color = black; - } - ValueFormatter *fmt = dlg->getDoc()->formatter(); - tmp = fmt->formatText(dlg->value, newFormatType, precision->value(), - floatFormat, - prefix->isEnabled() ? prefix->text() : TQString(), - postfix->isEnabled() ? postfix->text() : TQString(), - newFormatType == Money_format ? dlg->cCurrency.symbol : TQString()); - if (tmp.length() > 50) - tmp = tmp.left (50); - exampleLabel->setText(tmp.prepend("").append("")); -} - -void CellFormatPageFloat::apply( CustomStyle * style ) -{ - if ( postfix->text() != dlg->postfix ) - { - if ( postfix->isEnabled()) - style->changePostfix( postfix->text() ); - else - style->changePostfix( "" ); - } - if ( prefix->text() != dlg->prefix ) - { - if (prefix->isEnabled()) - style->changePrefix( prefix->text() ); - else - style->changePrefix( "" ); - } - - if ( dlg->precision != precision->value() ) - style->changePrecision( precision->value() ); - - if ( m_bFormatColorChanged ) - { - switch( format->currentItem() ) - { - case 0: - style->changeFloatFormat( Format::OnlyNegSigned ); - style->changeFloatColor( Format::AllBlack ); - break; - case 1: - style->changeFloatFormat( Format::OnlyNegSigned ); - style->changeFloatColor( Format::NegRed ); - break; - case 2: - style->changeFloatFormat( Format::AlwaysUnsigned ); - style->changeFloatColor( Format::NegRed ); - break; - case 3: - style->changeFloatFormat( Format::AlwaysSigned ); - style->changeFloatColor( Format::AllBlack ); - break; - case 4: - style->changeFloatFormat( Format::AlwaysSigned ); - style->changeFloatColor( Format::NegRed ); - break; - } - } - if ( m_bFormatTypeChanged ) - { - style->changeFormatType (newFormatType); - if ( money->isChecked() ) - { - Format::Currency cur; - int index = currency->currentItem(); - if (index == 0) - { - if ( currency->currentText() == i18n( "Automatic" ) ) - { - cur.symbol = dlg->locale()->currencySymbol(); - cur.type = 0; - } - else - { - cur.type = 1; - cur.symbol = currency->currentText(); - } - } - else - { - cur.type = ++index; - cur.symbol = Currency::getDisplaySymbol( index ); - } - - style->changeCurrency( cur ); - } - } -} - -void CellFormatPageFloat::apply(FormatManipulator* _obj) -{ - if ( postfix->text() != dlg->postfix ) - if ( postfix->isEnabled()) - { - // If we are in here it *never* can be disabled - FIXME (Werner)! - if ( postfix->isEnabled()) - _obj->setPostfix( postfix->text() ); - else - _obj->setPostfix( "" ); - } - if ( prefix->text() != dlg->prefix ) - if (prefix->isEnabled()) - _obj->setPrefix( prefix->text() ); - else - _obj->setPrefix( "" ); - - if ( dlg->precision != precision->value() ) - _obj->setPrecision( precision->value() ); - - if (m_bFormatColorChanged) - { - switch( format->currentItem() ) - { - case 0: - _obj->setFloatFormat( Format::OnlyNegSigned ); - _obj->setFloatColor( Format::AllBlack ); - break; - case 1: - _obj->setFloatFormat( Format::OnlyNegSigned ); - _obj->setFloatColor( Format::NegRed ); - break; - case 2: - _obj->setFloatFormat( Format::AlwaysUnsigned ); - _obj->setFloatColor( Format::NegRed ); - break; - case 3: - _obj->setFloatFormat( Format::AlwaysSigned ); - _obj->setFloatColor( Format::AllBlack ); - break; - case 4: - _obj->setFloatFormat( Format::AlwaysSigned ); - _obj->setFloatColor( Format::NegRed ); - break; - } - } - if (m_bFormatTypeChanged) - { - _obj->setFormatType (newFormatType); - if (money->isChecked()) - { - Format::Currency cur; - int index = currency->currentItem(); - if (index == 0) - { - if ( currency->currentText() == i18n( "Automatic" ) ) - { - cur.symbol = dlg->locale()->currencySymbol(); - cur.type = 0; - } - else - { - cur.type = 1; - cur.symbol = currency->currentText(); - } - } - else - { - cur.type = ++index; - cur.symbol = Currency::getDisplaySymbol( index ); - } - - _obj->setCurrency( cur.type, cur.symbol ); - } - } -} - - - -/*************************************************************************** - * - * CellFormatPageProtection - * - ***************************************************************************/ - -CellFormatPageProtection::CellFormatPageProtection( TQWidget* parent, CellFormatDialog * _dlg ) - : ProtectionTab( parent ), - m_dlg( _dlg ) -{ - m_bDontPrint->setChecked( m_dlg->bDontPrintText ); - m_bHideAll->setChecked( m_dlg->bHideAll ); - m_bHideFormula->setChecked( m_dlg->bHideFormula ); - m_bIsProtected->setChecked( m_dlg->bIsProtected ); -} - -CellFormatPageProtection::~CellFormatPageProtection() -{ -} - -void CellFormatPageProtection::apply( CustomStyle * style ) -{ - if ( m_dlg->bDontPrintText != m_bDontPrint->isChecked() ) - { - if ( m_bDontPrint->isChecked() ) - style->addProperty( Style::PDontPrintText ); - else - style->removeProperty( Style::PDontPrintText ); - } - - if ( m_dlg->bIsProtected != m_bIsProtected->isChecked() ) - { - if ( !m_bIsProtected->isChecked() ) - style->addProperty( Style::PNotProtected ); - else - style->removeProperty( Style::PNotProtected ); - } - - if ( m_dlg->bHideAll != m_bHideAll->isChecked() ) - { - if ( m_bHideAll->isChecked() ) - style->addProperty( Style::PHideAll ); - else - style->removeProperty( Style::PHideAll ); - } - - if ( m_dlg->bHideFormula != m_bHideFormula->isChecked() ) - { - if ( m_bHideFormula->isChecked() ) - style->addProperty( Style::PHideFormula ); - else - style->removeProperty( Style::PHideFormula ); - } -} - -void CellFormatPageProtection::apply(FormatManipulator* _obj) -{ - if ( m_dlg->bDontPrintText != m_bDontPrint->isChecked()) - _obj->setDontPrintText( m_bDontPrint->isChecked() ); - - if ( m_dlg->bIsProtected != m_bIsProtected->isChecked()) - _obj->setNotProtected( !m_bIsProtected->isChecked() ); - - if ( m_dlg->bHideAll != m_bHideAll->isChecked()) - _obj->setHideAll( m_bHideAll->isChecked() ); - - if ( m_dlg->bHideFormula != m_bHideFormula->isChecked()) - _obj->setHideFormula( m_bHideFormula->isChecked() ); -} - - - -/*************************************************************************** - * - * CellFormatPageFont - * - ***************************************************************************/ - -CellFormatPageFont::CellFormatPageFont( TQWidget* parent, CellFormatDialog *_dlg ) : FontTab( parent ) -{ - dlg = _dlg; - - bTextColorUndefined = !dlg->bTextColor; - - connect( textColorButton, TQT_SIGNAL( changed( const TQColor & ) ), - this, TQT_SLOT( slotSetTextColor( const TQColor & ) ) ); - - - TQStringList tmpListFont; - TQFontDatabase *fontDataBase = new TQFontDatabase(); - tmpListFont = fontDataBase->families(); - delete fontDataBase; - - family_combo->insertStringList( tmpListFont); - selFont = dlg->textFont; - - if ( dlg->bTextFontFamily ) - { - selFont.setFamily( dlg->textFontFamily ); - kdDebug(36001) << "Family = " << dlg->textFontFamily << endl; - - if ( !family_combo->findItem(dlg->textFontFamily)) - { - family_combo->insertItem("",0); - family_combo->setCurrentItem(0); - } - else - family_combo->setCurrentItem(family_combo->index(family_combo->findItem(dlg->textFontFamily))); - } - else - { - family_combo->insertItem("",0); - family_combo->setCurrentItem(0); - } - - connect( family_combo, TQT_SIGNAL(highlighted(const TQString &)), - TQT_SLOT(family_chosen_slot(const TQString &)) ); - - TQStringList lst; - lst.append(""); - for ( unsigned int i = 1; i < 100; ++i ) - lst.append( TQString( "%1" ).arg( i ) ); - - size_combo->insertStringList( lst ); - - - size_combo->setInsertionPolicy(TQComboBox::NoInsertion); - - connect( size_combo, TQT_SIGNAL(activated(const TQString &)), - TQT_SLOT(size_chosen_slot(const TQString &)) ); - connect( size_combo ,TQT_SIGNAL( textChanged(const TQString &)), - this,TQT_SLOT(size_chosen_slot(const TQString &))); - - connect( weight_combo, TQT_SIGNAL(activated(const TQString &)), - TQT_SLOT(weight_chosen_slot(const TQString &)) ); - - connect( style_combo, TQT_SIGNAL(activated(const TQString &)), - TQT_SLOT(style_chosen_slot(const TQString &)) ); - - strike->setChecked(dlg->strike); - connect( strike, TQT_SIGNAL( clicked()), - TQT_SLOT(strike_chosen_slot()) ); - - underline->setChecked(dlg->underline); - connect( underline, TQT_SIGNAL( clicked()), - TQT_SLOT(underline_chosen_slot()) ); - - example_label->setText(i18n("Dolor Ipse")); - - connect(this,TQT_SIGNAL(fontSelected( const TQFont& )), - this,TQT_SLOT(display_example( const TQFont&))); - - setCombos(); - display_example( selFont ); - fontChanged=false; - this->resize( 400, 400 ); -} - -void CellFormatPageFont::slotSetTextColor( const TQColor &_color ) -{ - textColor = _color; - bTextColorUndefined = false; -} - -void CellFormatPageFont::apply( CustomStyle * style ) -{ - if ( !bTextColorUndefined && textColor != dlg->textColor ) - style->changeTextColor( textColor ); - - if ( ( size_combo->currentItem() != 0 ) - && ( dlg->textFontSize != selFont.pointSize() ) ) - style->changeFontSize( selFont.pointSize() ); - - if ( ( selFont.family() != dlg->textFontFamily ) - && !family_combo->currentText().isEmpty() ) - style->changeFontFamily( selFont.family() ); - - uint flags = 0; - - if ( weight_combo->currentItem() != 0 && selFont.bold() ) - flags |= Style::FBold; - else - flags &= ~(uint) Style::FBold; - - if ( style_combo->currentItem() != 0 && selFont.italic() ) - flags |= Style::FItalic; - else - flags &= ~(uint) Style::FItalic; - - if ( strike->isChecked() ) - flags |= Style::FStrike; - else - flags &= ~(uint) Style::FStrike; - - if ( underline->isChecked() ) - flags |= Style::FUnderline; - else - flags &= ~(uint) Style::FUnderline; - - style->changeFontFlags( flags ); -} - -void CellFormatPageFont::apply(FormatManipulator* _obj) -{ - if ( !bTextColorUndefined && textColor != dlg->textColor ) - _obj->setTextColor( textColor ); - if (fontChanged) - { - if ( ( size_combo->currentItem() != 0 ) - && ( dlg->textFontSize != selFont.pointSize() ) ) - _obj->setFontSize( selFont.pointSize() ); - if ( ( selFont.family() != dlg->textFontFamily ) && ( !family_combo->currentText().isEmpty() ) ) - _obj->setFontFamily( selFont.family() ); - if ( weight_combo->currentItem() != 0 ) - _obj->setFontBold( selFont.bold() ); - if ( style_combo->currentItem() != 0 ) - _obj->setFontItalic( selFont.italic() ); - _obj->setFontStrike( strike->isChecked() ); - _obj->setFontUnderline(underline->isChecked() ); - } -} - -void CellFormatPageFont::underline_chosen_slot() -{ - selFont.setUnderline( underline->isChecked() ); - emit fontSelected(selFont); -} - -void CellFormatPageFont::strike_chosen_slot() -{ - selFont.setStrikeOut( strike->isChecked() ); - emit fontSelected(selFont); -} - -void CellFormatPageFont::family_chosen_slot(const TQString & family) -{ - selFont.setFamily(family); - emit fontSelected(selFont); -} - -void CellFormatPageFont::size_chosen_slot(const TQString & size) -{ - TQString size_string = size; - - selFont.setPointSize(size_string.toInt()); - emit fontSelected(selFont); -} - -void CellFormatPageFont::weight_chosen_slot(const TQString & weight) -{ - TQString weight_string = weight; - - if ( weight_string == i18n("Normal")) - selFont.setBold(false); - if ( weight_string == i18n("Bold")) - selFont.setBold(true); - emit fontSelected(selFont); -} - -void CellFormatPageFont::style_chosen_slot(const TQString & style) -{ - TQString style_string = style; - - if ( style_string == i18n("Roman")) - selFont.setItalic(false); - if ( style_string == i18n("Italic")) - selFont.setItalic(true); - emit fontSelected(selFont); -} - - -void CellFormatPageFont::display_example(const TQFont& font) -{ - TQString string; - fontChanged=true; - example_label->setFont(font); - example_label->repaint(); -} - -void CellFormatPageFont::setCombos() -{ - TQString string; - TQComboBox* combo; - int number_of_entries; - bool found; - - if ( dlg->bTextColor ) - textColor = dlg->textColor; - else - textColor = colorGroup().text(); - - if ( !textColor.isValid() ) - textColor =colorGroup().text(); - - textColorButton->setColor( textColor ); - - - combo = size_combo; - if ( dlg->bTextFontSize ) - { - kdDebug(36001) << "SIZE=" << dlg->textFontSize << endl; - selFont.setPointSize( dlg->textFontSize ); - number_of_entries = size_combo->count(); - string.setNum( dlg->textFontSize ); - found = false; - - for (int i = 0; i < number_of_entries ; i++){ - if ( string == (TQString) combo->text(i)){ - combo->setCurrentItem(i); - found = true; - // kdDebug(36001) << "Found Size " << string.data() << " setting to item " i << endl; - break; - } - } - } - else - combo->setCurrentItem( 0 ); - - if ( !dlg->bTextFontBold ) - weight_combo->setCurrentItem(0); - else if ( dlg->textFontBold ) - { - selFont.setBold( dlg->textFontBold ); - weight_combo->setCurrentItem(2); - } - else - { - selFont.setBold( dlg->textFontBold ); - weight_combo->setCurrentItem(1); - } - - if ( !dlg->bTextFontItalic ) - weight_combo->setCurrentItem(0); - else if ( dlg->textFontItalic ) - { - selFont.setItalic( dlg->textFontItalic ); - style_combo->setCurrentItem(2); - } - else - { - selFont.setItalic( dlg->textFontItalic ); - style_combo->setCurrentItem(1); - } -} - - - -/*************************************************************************** - * - * CellFormatPagePosition - * - ***************************************************************************/ - -CellFormatPagePosition::CellFormatPagePosition( TQWidget* parent, CellFormatDialog *_dlg ) - : PositionTab(parent ), - dlg( _dlg ) -{ - if ( dlg->alignX == Format::Left ) - left->setChecked( true ); - else if ( dlg->alignX == Format::Center ) - center->setChecked( true ); - else if ( dlg->alignX == Format::Right ) - right->setChecked( true ); - else if ( dlg->alignX == Format::Undefined ) - standard->setChecked( true ); - - connect(horizontalGroup, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotStateChanged(int))); - - if ( dlg->alignY ==Format::Top ) - top->setChecked( true ); - else if ( dlg->alignY ==Format::Middle ) - middle->setChecked(true ); - else if ( dlg->alignY ==Format::Bottom ) - bottom->setChecked( true ); - - multi->setChecked(dlg->bMultiRow); - - vertical->setChecked(dlg->bVerticalText); - - angleRotation->setValue(-dlg->textRotation);//annma - spinBox3->setValue(-dlg->textRotation); - if ( dlg->textRotation != 0 ) - { - multi->setEnabled(false ); - vertical->setEnabled(false); - } - - mergeCell->setChecked(dlg->isMerged); - mergeCell->setEnabled(!dlg->oneCell && ((!dlg->isRowSelected) && (!dlg->isColumnSelected))); - - TQGridLayout *grid2 = new TQGridLayout(indentGroup, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); - grid2->addRowSpacing( 0, indentGroup->fontMetrics().height()/8 ); // groupbox title - m_indent = new KoUnitDoubleSpinBox( indentGroup, 0.0, 400.0, 10.0,dlg->indent,dlg->getDoc()->unit() ); - grid2->addWidget(m_indent, 0, 0); - - width = new KoUnitDoubleSpinBox( m_widthPanel ); - TQGridLayout *gridWidth = new TQGridLayout(m_widthPanel, 1, 1, 0, 0); - gridWidth->addWidget(width, 0, 0); - width->setValue ( dlg->widthSize ); - width->setUnit( dlg->getDoc()->unit() ); - //to ensure, that we don't get rounding problems, we store the displayed value (for later check for changes) - dlg->widthSize = width->value(); - - if ( dlg->isRowSelected ) - width->setEnabled(false); - - defaultWidth->setText(i18n("Default width (%1 %2)").arg(KoUnit::toUserValue(dlg->defaultWidthSize, dlg->getDoc()->unit()), 0, 'f', 2).arg(dlg->getDoc()->unitName())); - if ( dlg->isRowSelected ) - defaultWidth->setEnabled(false); - - height=new KoUnitDoubleSpinBox( m_heightPanel ); - TQGridLayout *gridHeight = new TQGridLayout(m_heightPanel, 1, 1, 0, 0); - gridHeight->addWidget(height, 0, 0); - height->setValue( dlg->heightSize ); - height->setUnit( dlg->getDoc()->unit() ); - //to ensure, that we don't get rounding problems, we store the displayed value (for later check for changes) - dlg->heightSize = height->value(); - - if ( dlg->isColumnSelected ) - height->setEnabled(false); - - defaultHeight->setText(i18n("Default height (%1 %2)").arg(KoUnit::toUserValue(dlg->defaultHeightSize, dlg->getDoc()->unit()), 0, 'f', 2).arg(dlg->getDoc()->unitName())); //annma - if ( dlg->isColumnSelected ) - defaultHeight->setEnabled(false); - - // in case we're editing a style, we disable the cell size settings - if (dlg->getStyle()) - { - defaultHeight->setEnabled(false); - defaultWidth->setEnabled(false); - } - - connect(defaultWidth , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeWidthState())); - connect(defaultHeight , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeHeightState())); - connect(vertical , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeVerticalState())); - connect(multi , TQT_SIGNAL(clicked() ), this, TQT_SLOT(slotChangeMultiState())); - connect(angleRotation, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotChangeAngle(int))); - - slotStateChanged( 0 ); - m_bOptionText = false; - this->resize( 400, 400 ); -} - -void CellFormatPagePosition::slotChangeMultiState() -{ - m_bOptionText = true; - if (vertical->isChecked()) - { - vertical->setChecked(false); - } -} - -void CellFormatPagePosition::slotChangeVerticalState() -{ - m_bOptionText=true; - if (multi->isChecked()) - { - multi->setChecked(false); - } - -} - -void CellFormatPagePosition::slotStateChanged(int) -{ - if (right->isChecked() || center->isChecked()) - m_indent->setEnabled(false); - else - m_indent->setEnabled(true); -} - -bool CellFormatPagePosition::getMergedCellState() const -{ - return mergeCell->isChecked(); -} - -void CellFormatPagePosition::slotChangeWidthState() -{ - if ( defaultWidth->isChecked()) - width->setEnabled(false); - else - width->setEnabled(true); -} - -void CellFormatPagePosition::slotChangeHeightState() -{ - if ( defaultHeight->isChecked()) - height->setEnabled(false); - else - height->setEnabled(true); -} - -void CellFormatPagePosition::slotChangeAngle(int _angle) -{ - if ( _angle == 0 ) - { - multi->setEnabled( true ); - vertical->setEnabled( true ); - } - else - { - multi->setEnabled( false ); - vertical->setEnabled( false ); - } -} - -void CellFormatPagePosition::apply( CustomStyle * style ) -{ - if ( top->isChecked() && dlg->alignY != Format::Top ) - style->changeAlignY( Format::Top ); - else if ( bottom->isChecked() && dlg->alignY != Format::Bottom ) - style->changeAlignY( Format::Bottom ); - else if ( middle->isChecked() && dlg->alignY != Format::Middle ) - style->changeAlignY( Format::Middle ); - - if ( left->isChecked() && dlg->alignX != Format::Left ) - style->changeAlignX( Format::Left ); - else if ( right->isChecked() && dlg->alignX != Format::Right ) - style->changeAlignX( Format::Right ); - else if ( center->isChecked() && dlg->alignX != Format::Center ) - style->changeAlignX( Format::Center ); - else if ( standard->isChecked() && dlg->alignX != Format::Undefined ) - style->changeAlignX( Format::Undefined ); - - if ( m_bOptionText ) - { - if ( multi->isEnabled() ) - { - if ( multi->isChecked() ) - style->addProperty( Style::PMultiRow ); - else - style->removeProperty( Style::PMultiRow ); - } - } - - if ( m_bOptionText ) - { - if ( vertical->isEnabled() ) - { - if ( vertical->isChecked() ) - style->addProperty( Style::PVerticalText ); - else - style->removeProperty( Style::PVerticalText ); - } - } - - if ( dlg->textRotation != angleRotation->value() ) - style->changeRotateAngle( (-angleRotation->value()) ); - - if ( m_indent->isEnabled() - && dlg->indent != m_indent->value() ) - style->changeIndent( m_indent->value() ); - - // setting the default column width and row height - if ( dlg->getStyle()->type() == Style::BUILTIN && dlg->getStyle()->name() == "Default" ) - { - if ( (int) height->value() != (int) dlg->heightSize ) - { - Format::setGlobalRowHeight( height->value() ); - } - if ( (int) width->value() != (int) dlg->widthSize ) - { - Format::setGlobalColWidth( width->value() ); - } - } -} - -void CellFormatPagePosition::apply(FormatManipulator* _obj) -{ - Format::Align ax; - Format::AlignY ay; - - if ( top->isChecked() ) - ay = Format::Top; - else if ( bottom->isChecked() ) - ay = Format::Bottom; - else if ( middle->isChecked() ) - ay = Format::Middle; - else - ay = Format::Middle; // Default, just in case - - if ( left->isChecked() ) - ax = Format::Left; - else if ( right->isChecked() ) - ax = Format::Right; - else if ( center->isChecked() ) - ax = Format::Center; - else if ( standard->isChecked() ) - ax = Format::Undefined; - else - ax = Format::Undefined; //Default, just in case - - if ( top->isChecked() && ay != dlg->alignY ) - _obj->setVerticalAlignment( Format::Top ); - else if ( bottom->isChecked() && ay != dlg->alignY ) - _obj->setVerticalAlignment( Format::Bottom ); - else if ( middle->isChecked() && ay != dlg->alignY ) - _obj->setVerticalAlignment( Format::Middle ); - - if ( left->isChecked() && ax != dlg->alignX ) - _obj->setHorizontalAlignment( Format::Left ); - else if ( right->isChecked() && ax != dlg->alignX ) - _obj->setHorizontalAlignment( Format::Right ); - else if ( center->isChecked() && ax != dlg->alignX ) - _obj->setHorizontalAlignment( Format::Center ); - else if ( standard->isChecked() && ax != dlg->alignX ) - _obj->setHorizontalAlignment( Format::Undefined ); - - if ( m_bOptionText ) - { - if ( multi->isEnabled() ) - _obj->setMultiRow( multi->isChecked() ); - else - _obj->setMultiRow( false ); - } - - if ( m_bOptionText ) - { - if ( vertical->isEnabled() ) - _obj->setVerticalText( vertical->isChecked() ); - else - _obj->setVerticalText( false ); - } - - if ( dlg->textRotation!=angleRotation->value() ) - _obj->setAngle( (-angleRotation->value() ) ); - if ( m_indent->isEnabled() - && dlg->indent != m_indent->value() ) - _obj->setIndent( m_indent->value() ); -} - -double CellFormatPagePosition::getSizeHeight() const -{ - if ( defaultHeight->isChecked() ) - return dlg->defaultHeightSize; // guess who calls this! - else - return height->value(); -} - -double CellFormatPagePosition::getSizeWidth() const -{ - if ( defaultWidth->isChecked() ) - return dlg->defaultWidthSize; // guess who calls this! - else - return width->value(); -} - - - -/*************************************************************************** - * - * BorderButton - * - ***************************************************************************/ - -BorderButton::BorderButton( TQWidget *parent, const char *_name ) : TQPushButton(parent,_name) -{ - penStyle = Qt::NoPen; - penWidth = 1; - penColor = colorGroup().text(); - setToggleButton( true ); - setOn( false); - setChanged(false); -} -void BorderButton::mousePressEvent( TQMouseEvent * ) -{ - - this->setOn(!isOn()); - emit clicked( this ); -} - -void BorderButton::setUndefined() -{ - setPenStyle(Qt::SolidLine ); - setPenWidth(1); - setColor(colorGroup().midlight()); -} - - -void BorderButton::unselect() -{ - setOn(false); - setPenWidth(1); - setPenStyle(Qt::NoPen); - setColor( colorGroup().text() ); - setChanged(true); -} - - - -/*************************************************************************** - * - * Border - * - ***************************************************************************/ - -Border::Border( TQWidget *parent, const char *_name,bool _oneCol, bool _oneRow ) - : TQFrame( parent, _name ) -{ - oneCol=_oneCol; - oneRow=_oneRow; -} - - -#define OFFSETX 5 -#define OFFSETY 5 -void Border::paintEvent( TQPaintEvent *_ev ) -{ - TQFrame::paintEvent( _ev ); - TQPen pen; - TQPainter painter; - painter.begin( this ); - pen=TQPen( colorGroup().midlight(),2,SolidLine); - painter.setPen( pen ); - - painter.drawLine( OFFSETX-5, OFFSETY, OFFSETX , OFFSETY ); - painter.drawLine( OFFSETX, OFFSETY-5, OFFSETX , OFFSETY ); - painter.drawLine( width()-OFFSETX, OFFSETY, width() , OFFSETY ); - painter.drawLine( width()-OFFSETX, OFFSETY-5, width()-OFFSETX , OFFSETY ); - - painter.drawLine( OFFSETX, height()-OFFSETY, OFFSETX , height() ); - painter.drawLine( OFFSETX-5, height()-OFFSETY, OFFSETX , height()-OFFSETY ); - - painter.drawLine( width()-OFFSETX, height()-OFFSETY, width() , height()-OFFSETY ); - painter.drawLine( width()-OFFSETX, height()-OFFSETY, width()-OFFSETX , height() ); - if (oneCol==false) - { - painter.drawLine( width()/2, OFFSETY-5, width()/2 , OFFSETY ); - painter.drawLine( width()/2-5, OFFSETY, width()/2+5 , OFFSETY ); - painter.drawLine( width()/2, height()-OFFSETY, width()/2 , height() ); - painter.drawLine( width()/2-5, height()-OFFSETY, width()/2+5 , height()-OFFSETY ); - } - if (oneRow==false) - { - painter.drawLine( OFFSETX-5, height()/2, OFFSETX , height()/2 ); - painter.drawLine( OFFSETX, height()/2-5, OFFSETX , height()/2+5 ); - painter.drawLine( width()-OFFSETX, height()/2, width(), height()/2 ); - painter.drawLine( width()-OFFSETX, height()/2-5, width()-OFFSETX , height()/2+5 ); - } - painter.end(); - emit redraw(); -} - -void Border::mousePressEvent( TQMouseEvent* _ev ) -{ - emit choosearea(_ev); -} - - - -/*************************************************************************** - * - * CellFormatPageBorder - * - ***************************************************************************/ - -CellFormatPageBorder::CellFormatPageBorder( TQWidget* parent, CellFormatDialog *_dlg ) - : TQWidget( parent ), - dlg( _dlg ) -{ - sheet = dlg->getSheet(); - - InitializeGrids(); - InitializeBorderButtons(); - InitializePatterns(); - SetConnections(); - - preview->slotSelect(); - pattern[2]->slotSelect(); - - style->setEnabled(false); - size->setEnabled(false); - preview->setPattern( black , 1, Qt::SolidLine ); - this->resize( 400, 400 ); -} - -void CellFormatPageBorder::InitializeGrids() -{ - TQGridLayout *grid = new TQGridLayout(this,5,2,KDialog::marginHint(), KDialog::spacingHint()); - TQGridLayout *grid2 = NULL; - TQGroupBox* tmpTQGroupBox = NULL; - - /***********************/ - /* here is the data to initialize all the border buttons with */ - const char borderButtonNames[BorderType_END][20] = - {"top", "bottom", "left", "right", "vertical", "fall", "go", "horizontal"}; - - const char shortcutButtonNames[BorderShortcutType_END][20] = - {"remove", "all", "outline"}; - - TQString borderButtonIconNames[BorderType_END] = - {"border_top", "border_bottom", "border_left", "border_right", - "border_vertical", "border_horizontal", "border_fall", "border_up"}; - - TQString shortcutButtonIconNames[BorderShortcutType_END] = - { "border_remove", "", "border_outline"}; - - int borderButtonPositions[BorderType_END][2] = - {{0,2}, {4,2}, {2,0}, {2,4}, {4,4}, {4,0}, {0,0}, {0,4}}; - - int shortcutButtonPositions[BorderShortcutType_END][2] = - { {0,0}, {0,1},{0,2} }; - /***********************/ - - /* set up a layout box for most of the border setting buttons */ - tmpTQGroupBox = new TQGroupBox( this, "GroupBox_1" ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setTitle( i18n("Border") ); - tmpTQGroupBox->setAlignment( AlignLeft ); - grid2 = new TQGridLayout(tmpTQGroupBox,6,5,KDialog::marginHint(), KDialog::spacingHint()); - int fHeight = tmpTQGroupBox->fontMetrics().height(); - grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title - - area=new Border(tmpTQGroupBox,"area",dlg->oneCol,dlg->oneRow); - grid2->addMultiCellWidget(area,2,4,1,3); - area->setBackgroundColor( colorGroup().base() ); - - /* initailize the buttons that are in this box */ - for (int i=BorderType_Top; i < BorderType_END; i++) - { - borderButtons[i] = new BorderButton(tmpTQGroupBox, - borderButtonNames[i]); - loadIcon(borderButtonIconNames[i], borderButtons[i]); - grid2->addWidget(borderButtons[i], borderButtonPositions[i][0] + 1, - borderButtonPositions[i][1]); - } - - grid->addMultiCellWidget(tmpTQGroupBox,0,2,0,0); - - /* the remove, all, and outline border buttons are in a second box down - below.*/ - - tmpTQGroupBox = new TQGroupBox( this, "GroupBox_3" ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setTitle( i18n("Preselect") ); - tmpTQGroupBox->setAlignment( AlignLeft ); - - grid2 = new TQGridLayout(tmpTQGroupBox,1,3,KDialog::marginHint(), KDialog::spacingHint()); - - /* the "all" button is different depending on what kind of region is currently - selected */ - if ((dlg->oneRow==true)&&(dlg->oneCol==false)) - { - shortcutButtonIconNames[BorderShortcutType_All] = "border_vertical"; - } - else if ((dlg->oneRow==false)&&(dlg->oneCol==true)) - { - shortcutButtonIconNames[BorderShortcutType_All] = "border_horizontal"; - } - else - { - shortcutButtonIconNames[BorderShortcutType_All] = "border_inside"; - } - - for (int i=BorderShortcutType_Remove; i < BorderShortcutType_END; i++) - { - shortcutButtons[i] = new BorderButton(tmpTQGroupBox, - shortcutButtonNames[i]); - loadIcon(shortcutButtonIconNames[i], shortcutButtons[i]); - grid2->addWidget(shortcutButtons[i], shortcutButtonPositions[i][0], - shortcutButtonPositions[i][1]); - } - - if (dlg->oneRow && dlg->oneCol) - { - shortcutButtons[BorderShortcutType_All]->setEnabled(false); - } - - grid->addMultiCellWidget(tmpTQGroupBox,3,4,0,0); - - /* now set up the group box with the pattern selector */ - tmpTQGroupBox = new TQGroupBox( this, "GroupBox_10" ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setTitle( i18n("Pattern") ); - tmpTQGroupBox->setAlignment( AlignLeft ); - - grid2 = new TQGridLayout(tmpTQGroupBox,7,2,KDialog::marginHint(), KDialog::spacingHint()); - fHeight = tmpTQGroupBox->fontMetrics().height(); - grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title - - char name[] = "PatternXX"; - Q_ASSERT(NUM_BORDER_PATTERNS < 100); - - for (int i=0; i < NUM_BORDER_PATTERNS; i++) - { - name[7] = '0' + (i+1) / 10; - name[8] = '0' + (i+1) % 10; - pattern[i] = new PatternSelect( tmpTQGroupBox, name ); - pattern[i]->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(pattern[i], i % 5 + 1, i / 5); - /* this puts them in the pattern: - 1 6 - 2 7 - 3 8 - 4 9 - 5 10 - */ - } - - color = new KColorButton (tmpTQGroupBox, "PushButton_1" ); - grid2->addWidget(color,7,1); - - TQLabel *tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_6" ); - tmpTQLabel->setText( i18n("Color:") ); - grid2->addWidget(tmpTQLabel,7,0); - - /* tack on the 'customize' border pattern selector */ - TQGridLayout *grid3 = new TQGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint() ); - customize = new TQCheckBox(i18n("Customize"),tmpTQGroupBox); - grid3->addWidget(customize,0,0); - connect( customize, TQT_SIGNAL( clicked()), TQT_SLOT(cutomize_chosen_slot()) ); - - size=new TQComboBox(true,tmpTQGroupBox); - grid3->addWidget(size,1,1); - size->setValidator(new KIntValidator( size )); - TQString tmp; - for ( int i=0;i<10;i++) - { - tmp=tmp.setNum(i); - size->insertItem(tmp); - } - size->setCurrentItem(1); - - style=new TQComboBox(tmpTQGroupBox); - grid3->addWidget(style,1,0); - style->insertItem(paintFormatPixmap(DotLine),0 ); - style->insertItem(paintFormatPixmap(DashLine) ,1); - style->insertItem(paintFormatPixmap(DashDotLine),2 ); - style->insertItem(paintFormatPixmap(DashDotDotLine),3 ); - style->insertItem(paintFormatPixmap(SolidLine),4); - style->setBackgroundColor( colorGroup().background() ); - - grid2->addMultiCell(grid3,6,6,0,1); - grid->addMultiCellWidget(tmpTQGroupBox,0,3,1,1); - - /* Now the preview box is put together */ - tmpTQGroupBox = new TQGroupBox(this, "GroupBox_4" ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setTitle( i18n("Preview") ); - tmpTQGroupBox->setAlignment( AlignLeft ); - - grid2 = new TQGridLayout(tmpTQGroupBox,1,1,KDialog::marginHint(), KDialog::spacingHint()); - fHeight = tmpTQGroupBox->fontMetrics().height(); - grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title - - preview = new PatternSelect( tmpTQGroupBox, "Pattern_preview" ); - preview->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(preview,1,0); - - grid->addWidget(tmpTQGroupBox,4,1); -} - -void CellFormatPageBorder::InitializeBorderButtons() -{ - for (int i=BorderType_Top; i < BorderType_END; i++) - { - if (dlg->borders[i].style != TQt::NoPen || - !dlg->borders[i].bStyle ) - { - /* the horozontil and vertical buttons might be disabled depending on what - kind of area is selected so check that first. */ - if ((dlg->oneRow == true && i == BorderType_Horizontal) || - (dlg->oneCol == true && i == BorderType_Vertical)) - { - borderButtons[i]->setEnabled(false); - } - else if ( dlg->borders[i].bColor && dlg->borders[i].bStyle ) - { - borderButtons[i]->setPenStyle(dlg->borders[i].style ); - borderButtons[i]->setPenWidth(dlg->borders[i].width); - borderButtons[i]->setColor(dlg->borders[i].color); - borderButtons[i]->setOn(true); - } - else - { - borderButtons[i]->setUndefined(); - } - } - } - - -} - -void CellFormatPageBorder::InitializePatterns() -{ - pattern[0]->setPattern( black, 1, Qt::DotLine ); - pattern[1]->setPattern( black, 1, Qt::DashLine ); - pattern[2]->setPattern( black, 1, Qt::SolidLine ); - pattern[3]->setPattern( black, 1, Qt::DashDotLine ); - pattern[4]->setPattern( black, 1, Qt::DashDotDotLine ); - pattern[5]->setPattern( black, 2, Qt::SolidLine ); - pattern[6]->setPattern( black, 3, Qt::SolidLine ); - pattern[7]->setPattern( black, 4, Qt::SolidLine ); - pattern[8]->setPattern( black, 5, Qt::SolidLine ); - pattern[9]->setPattern( black, 1, Qt::NoPen ); - - slotSetColorButton( black ); -} - -void CellFormatPageBorder::SetConnections() -{ - connect( color, TQT_SIGNAL( changed( const TQColor & ) ), - this, TQT_SLOT( slotSetColorButton( const TQColor & ) ) ); - - for (int i=0; i < NUM_BORDER_PATTERNS; i++) - { - connect( pattern[i], TQT_SIGNAL( clicked( PatternSelect* ) ), - this, TQT_SLOT( slotUnselect2( PatternSelect* ) ) ); - } - - for (int i = BorderType_Top; i < BorderType_END; i++) - { - connect( borderButtons[i], TQT_SIGNAL( clicked (BorderButton *) ), - this, TQT_SLOT( changeState( BorderButton *) ) ); - } - - for (int i = BorderShortcutType_Remove; i < BorderShortcutType_END; i++) - { - connect( shortcutButtons[i], TQT_SIGNAL( clicked(BorderButton *) ), - this, TQT_SLOT( preselect(BorderButton *) ) ); - } - - connect( area ,TQT_SIGNAL( redraw()),this,TQT_SLOT(draw())); - connect( area ,TQT_SIGNAL( choosearea(TQMouseEvent * )), - this,TQT_SLOT( slotPressEvent(TQMouseEvent *))); - - connect( style, TQT_SIGNAL( activated(int)), this, TQT_SLOT(slotChangeStyle(int))); - connect( size, TQT_SIGNAL( textChanged(const TQString &)), - this, TQT_SLOT(slotChangeStyle(const TQString &))); - connect( size ,TQT_SIGNAL( activated(int)), this, TQT_SLOT(slotChangeStyle(int))); -} - -void CellFormatPageBorder::cutomize_chosen_slot() -{ - if ( customize->isChecked() ) - { - style->setEnabled( true ); - size->setEnabled( true ); - slotUnselect2( preview ); - } - else - { - style->setEnabled( false ); - size->setEnabled( false ); - pattern[2]->slotSelect(); - preview->setPattern( black , 1, Qt::SolidLine ); - } -} - -void CellFormatPageBorder::slotChangeStyle(const TQString &) -{ - /* if they try putting text in the size box, then erase the line */ - slotChangeStyle(0); -} - -void CellFormatPageBorder::slotChangeStyle(int) -{ - int index = style->currentItem(); - TQString tmp; - int penSize = size->currentText().toInt(); - if ( !penSize) - { - preview->setPattern( preview->getColor(), penSize, Qt::NoPen ); - } - else - { - switch(index) - { - case 0: - preview->setPattern( preview->getColor(), penSize, Qt::DotLine ); - break; - case 1: - preview->setPattern( preview->getColor(), penSize, Qt::DashLine ); - break; - case 2: - preview->setPattern( preview->getColor(), penSize, Qt::DashDotLine ); - break; - case 3: - preview->setPattern( preview->getColor(), penSize, Qt::DashDotDotLine ); - break; - case 4: - preview->setPattern( preview->getColor(), penSize, Qt::SolidLine ); - break; - default: - kdDebug(36001)<<"Error in combobox\n"; - break; - } - } - slotUnselect2(preview); -} - -TQPixmap CellFormatPageBorder::paintFormatPixmap(PenStyle _style) -{ - TQPixmap pixmap( style->width(), 14 ); - TQPainter painter; - TQPen pen; - pen=TQPen( colorGroup().text(),1,_style); - painter.begin( &pixmap ); - painter.fillRect( 0, 0, style->width(), 14, colorGroup().background() ); - painter.setPen( pen ); - painter.drawLine( 0, 7, style->width(), 7 ); - painter.end(); - return pixmap; -} - -void CellFormatPageBorder::loadIcon( TQString _pix, BorderButton *_button) -{ - _button->setPixmap( TQPixmap( BarIcon(_pix, Factory::global()) ) ); -} - -void CellFormatPageBorder::apply(FormatManipulator* obj) -{ - if (borderButtons[BorderType_Horizontal]->isChanged()) - applyHorizontalOutline(obj); - - if (borderButtons[BorderType_Vertical]->isChanged()) - applyVerticalOutline(obj); - - if ( borderButtons[BorderType_Left]->isChanged() ) - applyLeftOutline(obj); - - if ( borderButtons[BorderType_Right]->isChanged() ) - applyRightOutline(obj); - - if ( borderButtons[BorderType_Top]->isChanged() ) - applyTopOutline(obj); - - if ( borderButtons[BorderType_Bottom]->isChanged() ) - applyBottomOutline(obj); - - if ( borderButtons[BorderType_RisingDiagonal]->isChanged() || - borderButtons[BorderType_FallingDiagonal]->isChanged() ) - applyDiagonalOutline(obj); -} - -void CellFormatPageBorder::applyTopOutline(FormatManipulator* obj) -{ - BorderButton * top = borderButtons[BorderType_Top]; - - TQPen tmpPen( top->getColor(), top->getPenWidth(), top->getPenStyle()); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeTopBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Top]->isChanged()) - obj->setTopBorderPen( tmpPen ); - } -} - -void CellFormatPageBorder::applyBottomOutline(FormatManipulator* obj) -{ - BorderButton * bottom = borderButtons[BorderType_Bottom]; - - TQPen tmpPen( bottom->getColor(), bottom->getPenWidth(), bottom->getPenStyle() ); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeBottomBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Bottom]->isChanged()) - obj->setBottomBorderPen( tmpPen ); - } -} - -void CellFormatPageBorder::applyLeftOutline(FormatManipulator* obj) -{ - BorderButton * left = borderButtons[BorderType_Left]; - TQPen tmpPen( left->getColor(), left->getPenWidth(), left->getPenStyle() ); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeLeftBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Left]->isChanged()) - obj->setLeftBorderPen( tmpPen ); - } -} - -void CellFormatPageBorder::applyRightOutline(FormatManipulator* obj) -{ - BorderButton* right = borderButtons[BorderType_Right]; - TQPen tmpPen( right->getColor(), right->getPenWidth(), right->getPenStyle() ); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeRightBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Right]->isChanged()) - obj->setRightBorderPen( tmpPen ); - } -} - -void CellFormatPageBorder::applyDiagonalOutline(FormatManipulator* obj) -{ - BorderButton * fallDiagonal = borderButtons[BorderType_FallingDiagonal]; - BorderButton * goUpDiagonal = borderButtons[BorderType_RisingDiagonal]; - TQPen tmpPenFall( fallDiagonal->getColor(), fallDiagonal->getPenWidth(), - fallDiagonal->getPenStyle()); - TQPen tmpPenGoUp( goUpDiagonal->getColor(), goUpDiagonal->getPenWidth(), - goUpDiagonal->getPenStyle()); - - if ( dlg->getStyle() ) - { - if ( fallDiagonal->isChanged() ) - dlg->getStyle()->changeFallBorderPen( tmpPenFall ); - if ( goUpDiagonal->isChanged() ) - dlg->getStyle()->changeGoUpBorderPen( tmpPenGoUp ); - } - else - { - if ( fallDiagonal->isChanged() ) - obj->setFallDiagonalPen( tmpPenFall ); - if ( goUpDiagonal->isChanged() ) - obj->setGoUpDiagonalPen( tmpPenGoUp ); - } -} - -void CellFormatPageBorder::applyHorizontalOutline(FormatManipulator* obj) -{ - TQPen tmpPen( borderButtons[BorderType_Horizontal]->getColor(), - borderButtons[BorderType_Horizontal]->getPenWidth(), - borderButtons[BorderType_Horizontal]->getPenStyle()); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeTopBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Horizontal]->isChanged()) - obj->setHorizontalPen( tmpPen ); - } -} - -void CellFormatPageBorder::applyVerticalOutline(FormatManipulator* obj) -{ - BorderButton* vertical = borderButtons[BorderType_Vertical]; - TQPen tmpPen( vertical->getColor(), vertical->getPenWidth(), - vertical->getPenStyle()); - - if ( dlg->getStyle() ) - { - dlg->getStyle()->changeLeftBorderPen( tmpPen ); - } - else - { - if (borderButtons[BorderType_Vertical]->isChanged()) - obj->setVerticalPen( tmpPen ); - } -} - - -void CellFormatPageBorder::slotSetColorButton( const TQColor &_color ) -{ - currentColor = _color; - - for ( int i = 0; i < NUM_BORDER_PATTERNS; ++i ) - { - pattern[i]->setColor( currentColor ); - } - preview->setColor( currentColor ); -} - -void CellFormatPageBorder::slotUnselect2( PatternSelect *_p ) -{ - for ( int i = 0; i < NUM_BORDER_PATTERNS; ++i ) - { - if ( pattern[i] != _p ) - { - pattern[i]->slotUnselect(); - } - } - preview->setPattern( _p->getColor(), _p->getPenWidth(), _p->getPenStyle() ); -} - -void CellFormatPageBorder::preselect( BorderButton *_p ) -{ - BorderButton* top = borderButtons[BorderType_Top]; - BorderButton* bottom = borderButtons[BorderType_Bottom]; - BorderButton* left = borderButtons[BorderType_Left]; - BorderButton* right = borderButtons[BorderType_Right]; - BorderButton* vertical = borderButtons[BorderType_Vertical]; - BorderButton* horizontal = borderButtons[BorderType_Horizontal]; - BorderButton* remove = shortcutButtons[BorderShortcutType_Remove]; - BorderButton* outline = shortcutButtons[BorderShortcutType_Outline]; - BorderButton* all = shortcutButtons[BorderShortcutType_All]; - - _p->setOn(false); - if (_p == remove) - { - for (int i=BorderType_Top; i < BorderType_END; i++) - { - if (borderButtons[i]->isOn()) - { - borderButtons[i]->unselect(); - } - } - } - if (_p==outline) - { - top->setOn(true); - top->setPenWidth(preview->getPenWidth()); - top->setPenStyle(preview->getPenStyle()); - top->setColor( currentColor ); - top->setChanged(true); - bottom->setOn(true); - bottom->setPenWidth(preview->getPenWidth()); - bottom->setPenStyle(preview->getPenStyle()); - bottom->setColor( currentColor ); - bottom->setChanged(true); - left->setOn(true); - left->setPenWidth(preview->getPenWidth()); - left->setPenStyle(preview->getPenStyle()); - left->setColor( currentColor ); - left->setChanged(true); - right->setOn(true); - right->setPenWidth(preview->getPenWidth()); - right->setPenStyle(preview->getPenStyle()); - right->setColor( currentColor ); - right->setChanged(true); - } - if (_p==all) - { - if (dlg->oneRow==false) - { - horizontal->setOn(true); - horizontal->setPenWidth(preview->getPenWidth()); - horizontal->setPenStyle(preview->getPenStyle()); - horizontal->setColor( currentColor ); - horizontal->setChanged(true); - } - if (dlg->oneCol==false) - { - vertical->setOn(true); - vertical->setPenWidth(preview->getPenWidth()); - vertical->setPenStyle(preview->getPenStyle()); - vertical->setColor( currentColor ); - vertical->setChanged(true); - } - } - area->repaint(); -} - -void CellFormatPageBorder::changeState( BorderButton *_p) -{ - _p->setChanged(true); - - if (_p->isOn()) - { - _p->setPenWidth(preview->getPenWidth()); - _p->setPenStyle(preview->getPenStyle()); - _p->setColor( currentColor ); - } - else - { - _p->setPenWidth(1); - _p->setPenStyle(Qt::NoPen); - _p->setColor( colorGroup().text() ); - } - - area->repaint(); -} - -void CellFormatPageBorder::draw() -{ - BorderButton* top = borderButtons[BorderType_Top]; - BorderButton* bottom = borderButtons[BorderType_Bottom]; - BorderButton* left = borderButtons[BorderType_Left]; - BorderButton* right = borderButtons[BorderType_Right]; - BorderButton* risingDiagonal = borderButtons[BorderType_RisingDiagonal]; - BorderButton* fallingDiagonal = borderButtons[BorderType_FallingDiagonal]; - BorderButton* vertical = borderButtons[BorderType_Vertical]; - BorderButton* horizontal = borderButtons[BorderType_Horizontal]; - TQPen pen; - TQPainter painter; - painter.begin( area ); - - if ((bottom->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( bottom->getColor(), bottom->getPenWidth(),bottom->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX, area->height()-OFFSETY, area->width()-OFFSETX , area->height()-OFFSETY ); - } - if ((top->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( top->getColor(), top->getPenWidth(),top->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX, OFFSETY, area->width() -OFFSETX, OFFSETY ); - } - if ((left->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( left->getColor(), left->getPenWidth(),left->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX, OFFSETY, OFFSETX , area->height()-OFFSETY ); - } - if ((right->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( right->getColor(), right->getPenWidth(),right->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( area->width()-OFFSETX, OFFSETY, area->width()-OFFSETX, - area->height()-OFFSETY ); - - } - if ((fallingDiagonal->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( fallingDiagonal->getColor(), fallingDiagonal->getPenWidth(), - fallingDiagonal->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX, OFFSETY, area->width()-OFFSETX, - area->height()-OFFSETY ); - if (dlg->oneCol==false&& dlg->oneRow==false) - { - painter.drawLine( area->width()/2, OFFSETY, area->width()-OFFSETX, - area->height()/2 ); - painter.drawLine( OFFSETX,area->height()/2 , area->width()/2, - area->height()-OFFSETY ); - } - } - if ((risingDiagonal->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( risingDiagonal->getColor(), risingDiagonal->getPenWidth(), - risingDiagonal->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX, area->height()-OFFSETY , area->width()-OFFSETX , - OFFSETY ); - if (dlg->oneCol==false&& dlg->oneRow==false) - { - painter.drawLine( area->width()/2, OFFSETY, OFFSETX, area->height()/2 ); - painter.drawLine( area->width()/2,area->height()-OFFSETY , - area->width()-OFFSETX, area->height()/2 ); - } - - } - if ((vertical->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( vertical->getColor(), vertical->getPenWidth(), - vertical->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( area->width()/2, 5 , area->width()/2 , area->height()-5 ); - } - if ((horizontal->getPenStyle())!=TQt::NoPen) - { - pen=TQPen( horizontal->getColor(), horizontal->getPenWidth(), - horizontal->getPenStyle()); - painter.setPen( pen ); - painter.drawLine( OFFSETX,area->height()/2,area->width()-OFFSETX, - area->height()/2 ); - } - painter.end(); -} - -void CellFormatPageBorder::invertState(BorderButton *_p) -{ - if (_p->isOn()) - { - _p->unselect(); - } - else - { - _p->setOn(true); - _p->setPenWidth(preview->getPenWidth()); - _p->setPenStyle(preview->getPenStyle()); - _p->setColor( currentColor ); - _p->setChanged(true); - } -} - -void CellFormatPageBorder::slotPressEvent(TQMouseEvent *_ev) -{ - BorderButton* top = borderButtons[BorderType_Top]; - BorderButton* bottom = borderButtons[BorderType_Bottom]; - BorderButton* left = borderButtons[BorderType_Left]; - BorderButton* right = borderButtons[BorderType_Right]; - BorderButton* vertical = borderButtons[BorderType_Vertical]; - BorderButton* horizontal = borderButtons[BorderType_Horizontal]; - - - TQRect rect(OFFSETX,OFFSETY-8,area->width()-OFFSETX,OFFSETY+8); - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((top->getPenWidth()!=preview->getPenWidth()) || - (top->getColor()!=currentColor) || - (top->getPenStyle()!=preview->getPenStyle())) - && top->isOn()) - { - top->setPenWidth(preview->getPenWidth()); - top->setPenStyle(preview->getPenStyle()); - top->setColor( currentColor ); - top->setChanged(true); - } - else - invertState(top); - } - rect.setCoords(OFFSETX,area->height()-OFFSETY-8,area->width()-OFFSETX, - area->height()-OFFSETY+8); - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((bottom->getPenWidth()!=preview->getPenWidth()) || - (bottom->getColor()!=currentColor) || - (bottom->getPenStyle()!=preview->getPenStyle())) - && bottom->isOn()) - { - bottom->setPenWidth(preview->getPenWidth()); - bottom->setPenStyle(preview->getPenStyle()); - bottom->setColor( currentColor ); - bottom->setChanged(true); - } - else - invertState(bottom); - } - - rect.setCoords(OFFSETX-8,OFFSETY,OFFSETX+8,area->height()-OFFSETY); - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((left->getPenWidth()!=preview->getPenWidth()) || - (left->getColor()!=currentColor) || - (left->getPenStyle()!=preview->getPenStyle())) - && left->isOn()) - { - left->setPenWidth(preview->getPenWidth()); - left->setPenStyle(preview->getPenStyle()); - left->setColor( currentColor ); - left->setChanged(true); - } - else - invertState(left); - } - rect.setCoords(area->width()-OFFSETX-8,OFFSETY,area->width()-OFFSETX+8, - area->height()-OFFSETY); - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((right->getPenWidth()!=preview->getPenWidth()) || - (right->getColor()!=currentColor) || - (right->getPenStyle()!=preview->getPenStyle())) - && right->isOn()) - { - right->setPenWidth(preview->getPenWidth()); - right->setPenStyle(preview->getPenStyle()); - right->setColor( currentColor ); - right->setChanged(true); - } - else - invertState(right); - } - -//don't work because I don't know how create a rectangle -//for diagonal -/*rect.setCoords(OFFSETX,OFFSETY,XLEN-OFFSETX,YHEI-OFFSETY); -if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - invertState(fallDiagonal); - } -rect.setCoords(OFFSETX,YHEI-OFFSETY,XLEN-OFFSETX,OFFSETY); -if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - invertState(goUpDiagonal); - } */ - - if (dlg->oneCol==false) - { - rect.setCoords(area->width()/2-8,OFFSETY,area->width()/2+8, - area->height()-OFFSETY); - - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((vertical->getPenWidth()!=preview->getPenWidth()) || - (vertical->getColor()!=currentColor) || - (vertical->getPenStyle()!=preview->getPenStyle())) - && vertical->isOn()) - { - vertical->setPenWidth(preview->getPenWidth()); - vertical->setPenStyle(preview->getPenStyle()); - vertical->setColor( currentColor ); - vertical->setChanged(true); - } - else - invertState(vertical); - } - } - if (dlg->oneRow==false) - { - rect.setCoords(OFFSETX,area->height()/2-8,area->width()-OFFSETX, - area->height()/2+8); - if (rect.contains(TQPoint(_ev->x(),_ev->y()))) - { - if (((horizontal->getPenWidth()!=preview->getPenWidth()) || - (horizontal->getColor()!=currentColor) || - (horizontal->getPenStyle()!=preview->getPenStyle())) - && horizontal->isOn()) - { - horizontal->setPenWidth(preview->getPenWidth()); - horizontal->setPenStyle(preview->getPenStyle()); - horizontal->setColor( currentColor ); - horizontal->setChanged(true); - } - else - invertState(horizontal); - } - } - - area->repaint(); -} - - - -/*************************************************************************** - * - * BrushSelect - * - ***************************************************************************/ - -BrushSelect::BrushSelect( TQWidget *parent, const char * ) : TQFrame( parent ) -{ - brushStyle = Qt::NoBrush; - brushColor = TQt::red; - selected = false; -} - -void BrushSelect::setPattern( const TQColor &_color,Qt::BrushStyle _style ) -{ - brushStyle = _style; - brushColor = _color; - repaint(); -} - - -void BrushSelect::paintEvent( TQPaintEvent *_ev ) -{ - TQFrame::paintEvent( _ev ); - - TQPainter painter; - TQBrush brush(brushColor,brushStyle); - painter.begin( this ); - painter.setPen( TQt::NoPen ); - painter.setBrush( brush); - painter.drawRect( 2, 2, width()-4, height()-4); - painter.end(); -} - -void BrushSelect::mousePressEvent( TQMouseEvent * ) -{ - slotSelect(); - - emit clicked( this ); -} - -void BrushSelect::slotUnselect() -{ - selected = false; - - setLineWidth( 1 ); - setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - repaint(); -} - -void BrushSelect::slotSelect() -{ - selected = true; - - setLineWidth( 2 ); - setFrameStyle( TQFrame::Panel | TQFrame::Plain ); - repaint(); -} - - - -/*************************************************************************** - * - * CellFormatPagePattern - * - ***************************************************************************/ - -CellFormatPagePattern::CellFormatPagePattern( TQWidget* parent, CellFormatDialog *_dlg ) : TQWidget( parent ) -{ - dlg = _dlg; - - bBgColorUndefined = !dlg->bBgColor; - - TQGridLayout *grid = new TQGridLayout(this,5,2,KDialog::marginHint(), KDialog::spacingHint()); - - TQGroupBox* tmpTQGroupBox; - tmpTQGroupBox = new TQGroupBox( this, "GroupBox_20" ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setTitle( i18n("Pattern") ); - tmpTQGroupBox->setAlignment( AlignLeft ); - - TQGridLayout *grid2 = new TQGridLayout(tmpTQGroupBox,8,3,KDialog::marginHint(), KDialog::spacingHint()); - int fHeight = tmpTQGroupBox->fontMetrics().height(); - grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title - - - brush1 = new BrushSelect( tmpTQGroupBox, "Frame_1" ); - brush1->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush1,1,0); - - brush2 = new BrushSelect( tmpTQGroupBox, "Frame_2" ); - brush2->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush2,1,1); - - brush3 = new BrushSelect( tmpTQGroupBox, "Frame_3" ); - brush3->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush3,1,2); - - brush4 = new BrushSelect( tmpTQGroupBox, "Frame_4" ); - brush4->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush4,2,0); - - brush5 = new BrushSelect( tmpTQGroupBox, "Frame_5" ); - brush5->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush5,2,1); - - brush6 = new BrushSelect( tmpTQGroupBox, "Frame_6" ); - brush6->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush6,2,2); - - brush7 = new BrushSelect( tmpTQGroupBox, "Frame_7" ); - brush7->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush7,3,0); - - brush8 = new BrushSelect( tmpTQGroupBox, "Frame_8" ); - brush8->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush8,3,1); - - brush9 = new BrushSelect( tmpTQGroupBox, "Frame_9" ); - brush9->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush9,3,2); - - brush10 = new BrushSelect( tmpTQGroupBox, "Frame_10" ); - brush10->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush10,4,0); - - brush11 = new BrushSelect( tmpTQGroupBox, "Frame_11" ); - brush11->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush11,4,1); - - brush12 = new BrushSelect( tmpTQGroupBox, "Frame_12" ); - brush12->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush12,4,2); - - brush13 = new BrushSelect( tmpTQGroupBox, "Frame_13" ); - brush13->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush13,5,0); - - brush14 = new BrushSelect( tmpTQGroupBox, "Frame_14" ); - brush14->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush14,5,1); - - brush15 = new BrushSelect( tmpTQGroupBox, "Frame_15" ); - brush15->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(brush15,5,2); - - TQGridLayout *grid3 = new TQGridLayout( 1, 2 ); - color = new KColorButton (tmpTQGroupBox, "ColorButton_1" ); - grid3->addWidget(color,0,1); - - TQLabel *tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_1" ); - tmpTQLabel->setText( i18n("Color:") ); - grid3->addWidget(tmpTQLabel,0,0); - - grid2->addMultiCell(grid3,6,6,0,2); - - grid3 = new TQGridLayout( 1, 3 ); - grid3->setSpacing(KDialog::spacingHint()); - - tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_2" ); - grid3->addWidget(tmpTQLabel,0,0); - tmpTQLabel->setText( i18n("Background color:") ); - - bgColorButton = new KColorButton( tmpTQGroupBox, "ColorButton" ); - grid3->addWidget(bgColorButton,0,1); - if ( dlg->bBgColor ) - bgColor = dlg->bgColor; - else - bgColor = colorGroup().base(); - - if (!bgColor.isValid()) - bgColor = colorGroup().base(); - - bgColorButton->setColor( bgColor ); - connect( bgColorButton, TQT_SIGNAL( changed( const TQColor & ) ), - this, TQT_SLOT( slotSetBackgroundColor( const TQColor & ) ) ); - - notAnyColor=new TQPushButton(i18n("No Color"),tmpTQGroupBox); - grid3->addWidget(notAnyColor,0,2); - connect( notAnyColor, TQT_SIGNAL( clicked( ) ), - this, TQT_SLOT( slotNotAnyColor( ) ) ); - b_notAnyColor=false; - - grid2->addMultiCell(grid3,7,7,0,2); - - grid->addMultiCellWidget(tmpTQGroupBox,0,3,0,0); - - tmpTQGroupBox = new TQGroupBox( this, "GroupBox1" ); - tmpTQGroupBox->setTitle( i18n("Preview") ); - tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); - tmpTQGroupBox->setAlignment( AlignLeft ); - - grid2 = new TQGridLayout(tmpTQGroupBox,2,1,KDialog::marginHint(), KDialog::spacingHint()); - fHeight = tmpTQGroupBox->fontMetrics().height(); - grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title - - current = new BrushSelect( tmpTQGroupBox, "Current" ); - current->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); - grid2->addWidget(current,1,0); - grid->addWidget( tmpTQGroupBox,4,0); - - connect( brush1, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush2, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush3, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush4, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush5, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush6, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush7, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush8, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush9, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush10, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush11, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush12, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush13, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush14, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - connect( brush15, TQT_SIGNAL( clicked( BrushSelect* ) ), - this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); - - brush1->setPattern( TQt::red,Qt::VerPattern ); - brush2->setPattern( TQt::red,Qt::HorPattern ); - brush3->setPattern( TQt::red,Qt::Dense1Pattern ); - brush4->setPattern( TQt::red,Qt::Dense2Pattern ); - brush5->setPattern( TQt::red,Qt::Dense3Pattern ); - brush6->setPattern( TQt::red,Qt::Dense4Pattern ); - brush7->setPattern( TQt::red,Qt::Dense5Pattern ); - brush8->setPattern( TQt::red,Qt::Dense6Pattern ); - brush9->setPattern( TQt::red,Qt::Dense7Pattern ); - brush10->setPattern( TQt::red,Qt::CrossPattern ); - brush11->setPattern( TQt::red,Qt::BDiagPattern ); - brush12->setPattern( TQt::red,Qt::FDiagPattern ); - brush13->setPattern( TQt::red,Qt::VerPattern ); - brush14->setPattern( TQt::red,Qt::DiagCrossPattern ); - brush15->setPattern( TQt::red,Qt::NoBrush ); - - current->setPattern(dlg->brushColor,dlg->brushStyle); - current->slotSelect(); - selectedBrush=current; - color->setColor(dlg->brushColor); - current->setBackgroundColor( bgColor ); - - connect( color, TQT_SIGNAL( changed( const TQColor & ) ), - this, TQT_SLOT( slotSetColorButton( const TQColor & ) ) ); - - slotSetColorButton( dlg->brushColor ); - init(); - this->resize( 400, 400 ); -} - -void CellFormatPagePattern::slotNotAnyColor() -{ - b_notAnyColor = true; - bgColorButton->setColor( colorGroup().base() ); - current->setBackgroundColor( colorGroup().base() ); -} - -void CellFormatPagePattern::slotSetBackgroundColor( const TQColor &_color ) -{ - bgColor =_color; - current->setBackgroundColor( bgColor ); - bBgColorUndefined = false; - b_notAnyColor = false; -} - -void CellFormatPagePattern::init() -{ - if (dlg->brushStyle == TQt::VerPattern) - { - brush1->slotSelect(); - } - else if (dlg->brushStyle == TQt::HorPattern) - { - brush2->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense1Pattern) - { - brush3->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense2Pattern) - { - brush4->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense3Pattern) - { - brush5->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense4Pattern) - { - brush6->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense5Pattern) - { - brush7->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense6Pattern) - { - brush8->slotSelect(); - } - else if (dlg->brushStyle == TQt::Dense7Pattern) - { - brush9->slotSelect(); - } - else if (dlg->brushStyle == TQt::CrossPattern) - { - brush10->slotSelect(); - } - else if (dlg->brushStyle == TQt::BDiagPattern) - { - brush11->slotSelect(); - } - else if (dlg->brushStyle == TQt::FDiagPattern) - { - brush12->slotSelect(); - } - else if (dlg->brushStyle == TQt::VerPattern) - { - brush13->slotSelect(); - } - else if (dlg->brushStyle == TQt::DiagCrossPattern) - { - brush14->slotSelect(); - } - else if (dlg->brushStyle == TQt::NoBrush) - { - brush15->slotSelect(); - } - else - kdDebug(36001) << "Error in brushStyle" << endl; -} - -void CellFormatPagePattern::slotSetColorButton( const TQColor &_color ) -{ - currentColor = _color; - - brush1->setBrushColor( currentColor ); - brush2->setBrushColor( currentColor ); - brush3->setBrushColor( currentColor ); - brush4->setBrushColor( currentColor ); - brush5->setBrushColor( currentColor ); - brush6->setBrushColor( currentColor ); - brush7->setBrushColor( currentColor ); - brush8->setBrushColor( currentColor ); - brush9->setBrushColor( currentColor ); - brush10->setBrushColor( currentColor ); - brush11->setBrushColor( currentColor ); - brush12->setBrushColor( currentColor ); - brush13->setBrushColor( currentColor ); - brush14->setBrushColor( currentColor ); - brush15->setBrushColor( currentColor ); - current->setBrushColor( currentColor ); -} - -void CellFormatPagePattern::slotUnselect2( BrushSelect *_p ) -{ - selectedBrush = _p; - - if ( brush1 != _p ) - brush1->slotUnselect(); - if ( brush2 != _p ) - brush2->slotUnselect(); - if ( brush3 != _p ) - brush3->slotUnselect(); - if ( brush4 != _p ) - brush4->slotUnselect(); - if ( brush5 != _p ) - brush5->slotUnselect(); - if ( brush6 != _p ) - brush6->slotUnselect(); - if ( brush7 != _p ) - brush7->slotUnselect(); - if ( brush8 != _p ) - brush8->slotUnselect(); - if ( brush9 != _p ) - brush9->slotUnselect(); - if ( brush10 != _p ) - brush10->slotUnselect(); - if ( brush11 != _p ) - brush11->slotUnselect(); - if ( brush12 != _p ) - brush12->slotUnselect(); - if ( brush13 != _p ) - brush13->slotUnselect(); - if ( brush14 != _p ) - brush14->slotUnselect(); - if ( brush15 != _p ) - brush15->slotUnselect(); - - current->setBrushStyle( selectedBrush->getBrushStyle() ); -} - -void CellFormatPagePattern::apply( CustomStyle * style ) -{ - if ( selectedBrush != 0L - && ( dlg->brushStyle != selectedBrush->getBrushStyle() - || dlg->brushColor != selectedBrush->getBrushColor() ) ) - style->changeBackGroundBrush( TQBrush( selectedBrush->getBrushColor(), selectedBrush->getBrushStyle() ) ); - - /* - TODO: check... - if ( b_notAnyColor) - style->changeBgColor( TQColor() ); - else - */ - if ( bgColor != dlg->getStyle()->bgColor() ) - style->changeBgColor( bgColor ); -} - -void CellFormatPagePattern::apply(FormatManipulator *_obj) -{ - if ( selectedBrush != 0L - && ( dlg->brushStyle != selectedBrush->getBrushStyle() - || dlg->brushColor != selectedBrush->getBrushColor() ) ) - _obj->setBackgroundBrush( TQBrush( selectedBrush->getBrushColor(), selectedBrush->getBrushStyle() ) ); - - if ( bgColor == dlg->bgColor ) - return; - - if ( b_notAnyColor) - _obj->setBackgroundColor( TQColor() ); - else if ( !bBgColorUndefined ) - _obj->setBackgroundColor( bgColor ); -} - -#include "kspread_dlg_layout.moc" - diff --git a/kspread/dialogs/kspread_dlg_layout.cpp b/kspread/dialogs/kspread_dlg_layout.cpp new file mode 100644 index 00000000..ad876b3b --- /dev/null +++ b/kspread/dialogs/kspread_dlg_layout.cpp @@ -0,0 +1,3928 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Stefan Nikolaus + (C) 2004 Tomas Mecir + (C) 2002-2004 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 2001-2003 Philipp Mueller + (C) 2002 John Dailey + (C) 1999-2002 Laurent Montel + (C) 1999-2002 Harri Porten + (C) 2000-2001 David Faure + (C) 1998-2000 Torben Weis + (C) 2000 Werner Trobin + (C) 1999 Reginald Stadlbauer + (C) 1998-1999 Stephan Kulow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kspread_canvas.h" +#include "kspread_dlg_layout.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_undo.h" +#include "kspread_util.h" +#include "manipulator.h" +#include "selection.h" +#include "valueformatter.h" + +using namespace KSpread; + +/*************************************************************************** + * + * PatternSelect + * + ***************************************************************************/ + +PatternSelect::PatternSelect( TQWidget *parent, const char * ) + : TQFrame( parent ) +{ + penStyle = Qt::NoPen; + penWidth = 1; + penColor = colorGroup().text(); + selected = false; + undefined = false; +} + +void PatternSelect::setPattern( const TQColor &_color, int _width, Qt::PenStyle _style ) +{ + penStyle = _style; + penColor = _color; + penWidth = _width; + repaint(); +} + +void PatternSelect::setUndefined() +{ + undefined = true; +} + +void PatternSelect::paintEvent( TQPaintEvent *_ev ) +{ + TQFrame::paintEvent( _ev ); + + TQPainter painter( this ); + + if ( !undefined ) + { + TQPen pen( penColor, penWidth, penStyle); + painter.setPen( pen ); + painter.drawLine( 6, height()/2, width() - 6,height()/2 ); + } + else + { + painter.fillRect( 2, 2, width() - 4, height() - 4, BDiagPattern ); + } +} + +void PatternSelect::mousePressEvent( TQMouseEvent * ) +{ + slotSelect(); + + emit clicked( this ); +} + +void PatternSelect::slotUnselect() +{ + selected = false; + + setLineWidth( 1 ); + setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + repaint(); +} + +void PatternSelect::slotSelect() +{ + selected = true; + + setLineWidth( 2 ); + setFrameStyle( TQFrame::Panel | TQFrame::Plain ); + repaint(); +} + + + +/*************************************************************************** + * + * GeneralTab + * + ***************************************************************************/ + +GeneralTab::GeneralTab( TQWidget* parent, CellFormatDialog * dlg ) + : TQWidget( parent ), + m_dlg( dlg ) +{ + TQGridLayout * layout = new TQGridLayout( this, 1, 1, KDialog::marginHint(), KDialog::spacingHint(), "layout"); + + TQGroupBox * groupBox = new TQGroupBox( this, "groupBox1" ); + groupBox->setColumnLayout(0, Qt::Vertical ); + groupBox->setTitle( i18n( "Style" ) ); + groupBox->layout()->setSpacing( KDialog::spacingHint() ); + groupBox->layout()->setMargin( KDialog::marginHint() ); + + TQGridLayout * groupBoxLayout = new TQGridLayout( groupBox->layout() ); + groupBoxLayout->setAlignment( TQt::AlignTop ); + + TQLabel * label1 = new TQLabel( groupBox, "label1" ); + label1->setText( i18n( "Name:" ) ); + groupBoxLayout->addWidget( label1, 0, 0 ); + + m_nameEdit = new KLineEdit( groupBox, "m_nameEdit" ); + m_nameEdit->setText( m_dlg->styleName ); + groupBoxLayout->addWidget( m_nameEdit, 0, 1 ); + + TQLabel * label2 = new TQLabel( groupBox, "label2" ); + label2->setText( i18n( "Inherit style:" ) ); + groupBoxLayout->addWidget( label2, 1, 0 ); + + m_parentBox = new KComboBox( false, groupBox, "m_parentBox" ); + m_parentBox->clear(); + m_parentBox->insertItem( i18n( "" ) ); + TQStringList tmp = m_dlg->getStyleManager()->styleNames(); + tmp.remove( m_dlg->styleName ); + m_parentBox->insertStringList( tmp ); + + if ( m_dlg->getStyle()->parent() ) + m_parentBox->setCurrentText( m_dlg->getStyle()->parentName() ); + else + { + m_parentBox->setCurrentText( i18n( "" ) ); + + if ( m_dlg->getStyle()->definesAll() ) + m_parentBox->setEnabled( false ); + } + + connect( m_parentBox, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SLOT( slotNewParent( const TQString & ) ) ); + connect( m_nameEdit, TQT_SIGNAL( lostFocus() ), this, TQT_SLOT( slotNameChanged() ) ); + + groupBoxLayout->addWidget( m_parentBox, 1, 1 ); + + TQSpacerItem * spacer = new TQSpacerItem( 20, 260, TQSizePolicy::Minimum, TQSizePolicy::Expanding ); + + layout->addWidget( groupBox, 0, 0 ); + layout->addItem( spacer, 1, 0 ); + + if ( m_dlg->getStyle()->type() == Style::BUILTIN ) + { + m_nameEdit->setEnabled( false ); + m_parentBox->setEnabled( false ); + } + + resize( TQSize( 534, 447 ).expandedTo(minimumSizeHint()) ); +} + +GeneralTab::~GeneralTab() +{ +} + +void GeneralTab::slotNameChanged() +{ + checkName(); +} + +void GeneralTab::slotNewParent( const TQString & parentName ) +{ + kdDebug() << "New Parent" << endl; + if ( !checkParent( parentName ) ) + return; + + if ( parentName.isEmpty() || parentName == i18n( "" ) ) + m_dlg->getStyle()->setParent( 0 ); + else + m_dlg->getStyle()->setParent( m_dlg->getStyleManager()->style( parentName ) ); + + // Set difference to new parent, set GUI to parent values, add changes made before + // m_dlg->initGUI(); +} + +bool GeneralTab::checkName() +{ + if ( m_nameEdit->isEnabled() ) + { + if ( !m_dlg->getStyleManager()->validateStyleName( m_nameEdit->text(), m_dlg->getStyle() ) ) + { + KMessageBox::sorry( this, i18n( "A style with this name already exists." ) ); + return false; + } + } + + return true; +} + +bool GeneralTab::checkParent( const TQString & parentName ) +{ + if ( m_dlg->getStyle()->parentName() != parentName + && m_parentBox->isEnabled() && parentName != i18n( "" ) && !parentName.isEmpty() ) + { + if ( m_nameEdit->text() == parentName ) + { + KMessageBox::sorry( this, i18n( "A style cannot inherit from itself." ) ); + return false; + } + if ( !m_dlg->checkCircle( m_nameEdit->text(), parentName ) ) + { + KMessageBox::sorry( this, + i18n( "The style cannot inherit from '%1' because of recursive references." ) + .arg( m_parentBox->currentText() ) ); + return false; + } + + CustomStyle * p = m_dlg->getStyleManager()->style( parentName ); + + if ( !p ) + { + KMessageBox::sorry( this, i18n( "The parent style does not exist." ) ); + return false; + } + } + + return true; +} + +bool GeneralTab::apply( CustomStyle * style ) +{ + if ( !checkParent( m_parentBox->currentText() ) ) + return false; + + if ( !checkName() ) + return false; + + if ( m_nameEdit->isEnabled() ) + { + if ( style->type() != Style::BUILTIN ) + { + TQString name( style->name() ); + style->setName( m_nameEdit->text() ); + if ( m_parentBox->isEnabled() ) + { + if ( m_parentBox->currentText() == i18n( "None" ) || m_parentBox->currentText().isEmpty() ) + style->setParent( 0 ); + else + style->setParent( m_dlg->getStyleManager()->style( m_parentBox->currentText() ) ); + } + m_dlg->getStyleManager()->changeName( name, m_nameEdit->text() ); + } + } + + if ( style->type() == Style::TENTATIVE ) + style->setType( Style::CUSTOM ); + + return true; +} + + + +/*************************************************************************** + * + * CellFormatDialog + * + ***************************************************************************/ + +CellFormatDialog::CellFormatDialog( View * _view, Sheet * _sheet ) + : TQObject(), + m_doc( _sheet->doc() ), + m_sheet( _sheet ), + m_pView( _view ), + m_style( 0 ) +{ + initMembers(); + + //We need both conditions quite often, so store the condition here too + isRowSelected = _view->selectionInfo()->isRowSelected(); + isColumnSelected = _view->selectionInfo()->isColumnSelected(); + + TQRect range = _view->selectionInfo()->selection(); + left = range.left(); + top = range.top(); + right = range.right(); + bottom = range.bottom(); + + if ( left == right ) + oneCol = true; + else + oneCol = false; + + if ( top == bottom ) + oneRow = true; + else + oneRow = false; + + Cell* obj = m_sheet->cellAt( left, top ); + oneCell = (left == right && top == bottom && + !obj->doesMergeCells()); + + isMerged = ((obj->doesMergeCells() && + left + obj->extraXCells() >= right && + top + obj->extraYCells() >= bottom)); + + // Initialize with the upper left object. + borders[BorderType_Left].style = obj->format()->leftBorderStyle( left, top ); + borders[BorderType_Left].width = obj->format()->leftBorderWidth( left, top ); + borders[BorderType_Left].color = obj->format()->leftBorderColor( left, top ); + borders[BorderType_Top].style = obj->format()->topBorderStyle( left, top ); + borders[BorderType_Top].width = obj->format()->topBorderWidth( left, top ); + borders[BorderType_Top].color = obj->format()->topBorderColor( left, top ); + borders[BorderType_FallingDiagonal].style = + obj->format()->fallDiagonalStyle( left, top ); + borders[BorderType_FallingDiagonal].width = + obj->format()->fallDiagonalWidth( left, top ); + borders[BorderType_FallingDiagonal].color = + obj->format()->fallDiagonalColor( left, top ); + borders[BorderType_RisingDiagonal].style = + obj->format()->goUpDiagonalStyle( left, top ); + borders[BorderType_RisingDiagonal].width = + obj->format()->goUpDiagonalWidth( left, top ); + borders[BorderType_RisingDiagonal].color = + obj->format()->goUpDiagonalColor( left, top ); + + // Look at the upper right one for the right border. + obj = m_sheet->cellAt( right, top ); + borders[BorderType_Right].style = obj->format()->rightBorderStyle( right, top ); + borders[BorderType_Right].width = obj->format()->rightBorderWidth( right, top ); + borders[BorderType_Right].color = obj->format()->rightBorderColor( right, top ); + + // Look at the bottom left cell for the bottom border. + obj = m_sheet->cellAt( left, bottom ); + borders[BorderType_Bottom].style = obj->format()->bottomBorderStyle( left, bottom ); + borders[BorderType_Bottom].width = obj->format()->bottomBorderWidth( left, bottom ); + borders[BorderType_Bottom].color = obj->format()->bottomBorderColor( left, bottom ); + + // Just an assumption + obj = m_sheet->cellAt( right, top ); + if ( obj->isPartOfMerged() ) + { + obj = obj->obscuringCells().first(); + int moveX = obj->column(); + int moveY = top; + int moveX2 = right; + int moveY2 = obj->row(); + borders[BorderType_Vertical].style = obj->format()->leftBorderStyle( moveX, moveY ); + borders[BorderType_Vertical].width = obj->format()->leftBorderWidth( moveX, moveY ); + borders[BorderType_Vertical].color = obj->format()->leftBorderColor( moveX, moveY ); + + obj = m_sheet->cellAt( moveX2, moveY2 ); + borders[BorderType_Horizontal].style = obj->format()->topBorderStyle( moveX2, moveY2 ); + borders[BorderType_Horizontal].width = obj->format()->topBorderWidth( moveX2, moveY2 ); + borders[BorderType_Horizontal].color = obj->format()->topBorderColor( moveX2, moveY2 ); + } + else + { + borders[BorderType_Vertical].style = obj->format()->leftBorderStyle( right, top ); + borders[BorderType_Vertical].width = obj->format()->leftBorderWidth( right, top ); + borders[BorderType_Vertical].color = obj->format()->leftBorderColor( right, top ); + borders[BorderType_Horizontal].style = obj->format()->topBorderStyle(right, bottom); + borders[BorderType_Horizontal].width = obj->format()->topBorderWidth(right, bottom); + borders[BorderType_Horizontal].color = obj->format()->topBorderColor(right, bottom); + } + + obj = m_sheet->cellAt( left, top ); + prefix = obj->format()->prefix( left, top ); + postfix = obj->format()->postfix( left, top ); + precision = obj->format()->precision( left, top ); + floatFormat = obj->format()->floatFormat( left, top ); + floatColor = obj->format()->floatColor( left, top ); + alignX = obj->format()->align( left, top ); + alignY = obj->format()->alignY( left, top ); + textColor = obj->format()->textColor( left, top ); + bgColor = obj->bgColor( left, top ); + textFontSize = obj->format()->textFontSize( left, top ); + textFontFamily = obj->format()->textFontFamily( left, top ); + textFontBold = obj->format()->textFontBold( left, top ); + textFontItalic = obj->format()->textFontItalic( left, top ); + strike=obj->format()->textFontStrike( left, top ); + underline = obj->format()->textFontUnderline( left, top ); + // Needed to initialize the font correctly ( bug in TQt ) + textFont = obj->format()->textFont( left, top ); + obj->format()->currencyInfo( cCurrency ); + + brushColor = obj->format()->backGroundBrushColor( left, top ); + brushStyle = obj->format()->backGroundBrushStyle( left,top ); + + bMultiRow = obj->format()->multiRow( left, top ); + bVerticalText = obj->format()->verticalText( left, top ); + textRotation = obj->format()->getAngle(left, top); + formatType = obj->format()->getFormatType(left, top); + + bDontPrintText = obj->format()->getDontprintText( left, top ); + bHideFormula = obj->format()->isHideFormula( left, top ); + bHideAll = obj->format()->isHideAll( left, top ); + bIsProtected = !obj->format()->notProtected( left, top ); + + indent = obj->format()->getIndent(left, top); + + value = obj->value(); + + RowFormat *rl; + ColumnFormat *cl; + widthSize = 0.0; + heightSize = 0.0; + + if ( !isRowSelected ) + { + for ( int x = left; x <= right; x++ ) + { + cl = m_pView->activeSheet()->columnFormat( x ); + widthSize = TQMAX( cl->dblWidth(), widthSize ); + } + } + + if ( !isColumnSelected ) + { + for ( int y = top; y <= bottom; y++ ) + { + rl = m_pView->activeSheet()->rowFormat(y); + heightSize = TQMAX( rl->dblHeight(), heightSize ); + } + } + + //select column(s) + if ( isColumnSelected ) + { + int y = 1; + Cell* cell = NULL; + for (int x = left;x <= right; x++) + { + ColumnFormat *obj = m_sheet->nonDefaultColumnFormat(x); + initParameters( obj,x,y); + + for (cell = m_sheet->getFirstCellColumn(x); cell != NULL; + cell = m_sheet->getNextCellDown(cell->column(), cell->row())) + { + initParameters( cell->format(), x, cell->row()); + } + } + + } + else if ( isRowSelected ) + { + int x = 1; + Cell* c = NULL; + for ( int y = top;y<=bottom;y++) + { + RowFormat *obj = m_sheet->nonDefaultRowFormat(y); + initParameters( obj,x,y); + + for (c = m_sheet->getFirstCellRow(y); c != NULL; + c = m_sheet->getNextCellRight(c->column(), c->row()) ) + { + initParameters( c->format(), c->column(), c->row()); + } + } + } + else + { + // Do the other objects have the same values ? + for ( int x = left; x <= right; x++ ) + { + for ( int y = top; y <= bottom; y++ ) + { + Cell *obj = m_sheet->cellAt( x, y ); + + if ( obj->isPartOfMerged() ) + continue; + + initParameters( obj->format(),x,y); + } + } + } + if ( !bTextRotation ) + textRotation = 0; + + if ( isColumnSelected ) + { + int y=1; + ColumnFormat *obj=m_sheet->nonDefaultColumnFormat(left); + checkBorderLeft( obj,left, y); + + Cell* c = NULL; + for (c = m_sheet->getFirstCellColumn(left); c != NULL; + c = m_sheet->getNextCellDown(c->column(), c->row()) ) + { + checkBorderLeft(c->format(), c->column(), c->row()); + } + + + obj=m_sheet->nonDefaultColumnFormat(right); + checkBorderRight(obj,right,y); + c = NULL; + for (c = m_sheet->getFirstCellColumn(right); c != NULL; + c = m_sheet->getNextCellDown(c->column(), c->row()) ) + { + checkBorderRight(c->format(), c->column(), c->row()); + } + + for ( int x = left; x <= right; x++ ) + { + Cell *obj = m_sheet->cellAt( x, top ); + checkBorderTop(obj->format(),x, top); + obj = m_sheet->cellAt( x, bottom ); + checkBorderBottom(obj->format(),x, bottom); + if ( x > left ) + { + ColumnFormat *obj = m_sheet->nonDefaultColumnFormat(x); + checkBorderHorizontal(obj,x, y); + checkBorderVertical(obj,x, y); + } + } + } + else if ( isRowSelected ) + { + int x=1; + for ( int y = top; y <= bottom; y++ ) + { + Cell *obj = m_sheet->cellAt( right, y ); + checkBorderRight(obj->format(),right,y); + obj = m_sheet->cellAt( left, y ); + checkBorderLeft( obj->format(),left, y); + if ( y > top ) + { + RowFormat* obj = m_sheet->nonDefaultRowFormat(y); + checkBorderHorizontal(obj,x, y); + checkBorderVertical(obj,x, y); + } + } + + RowFormat *obj=m_sheet->nonDefaultRowFormat(top); + checkBorderTop(obj,x, top); + obj=m_sheet->nonDefaultRowFormat(bottom); + checkBorderBottom(obj,x, bottom); + } + else + { + for ( int y = top; y <= bottom; y++ ) + { + Cell *obj = m_sheet->cellAt( left, y ); + checkBorderLeft( obj->format(),left, y); + obj = m_sheet->cellAt( right, y ); + checkBorderRight(obj->format(),right,y); + } + + for ( int x = left; x <= right; x++ ) + { + Cell *obj = m_sheet->cellAt( x, top ); + checkBorderTop( obj->format(), x, top ); + obj = m_sheet->cellAt( x, bottom ); + checkBorderBottom( obj->format(), x, bottom ); + } + + // Look for the Outline + for ( int x = left; x <= right; x++ ) + { + for ( int y = top+1; y <= bottom; y++ ) + { + Cell *obj = m_sheet->cellAt( x, y ); + checkBorderHorizontal(obj->format(),x, y); + } + } + + for ( int x = left+1; x <= right; x++ ) + { + for ( int y = top; y <= bottom; y++ ) + { + Cell *obj = m_sheet->cellAt( x, y ); + checkBorderVertical(obj->format(),x,y); + } + } + } + + init(); +} + +CellFormatDialog::CellFormatDialog( View * _view, CustomStyle * _style, + StyleManager * _manager, Doc * doc ) + : TQObject(), + m_doc( doc ), + m_sheet( 0 ), + m_pView( _view ), + m_style( _style ), + m_styleManager( _manager ) +{ + initMembers(); + initGUI(); + init(); +} + +void CellFormatDialog::initGUI() +{ + isRowSelected = false; + isColumnSelected = false; + styleName = m_style->name(); + + borders[BorderType_Left].style = m_style->leftBorderPen().style(); + borders[BorderType_Left].width = m_style->leftBorderPen().width(); + borders[BorderType_Left].color = m_style->leftBorderPen().color(); + + borders[BorderType_Top].style = m_style->topBorderPen().style(); + borders[BorderType_Top].width = m_style->topBorderPen().width(); + borders[BorderType_Top].color = m_style->topBorderPen().color(); + + borders[BorderType_Right].style = m_style->rightBorderPen().style(); + borders[BorderType_Right].width = m_style->rightBorderPen().width(); + borders[BorderType_Right].color = m_style->rightBorderPen().color(); + + borders[BorderType_Bottom].style = m_style->bottomBorderPen().style(); + borders[BorderType_Bottom].width = m_style->bottomBorderPen().width(); + borders[BorderType_Bottom].color = m_style->bottomBorderPen().color(); + + borders[BorderType_FallingDiagonal].style = m_style->fallDiagonalPen().style(); + borders[BorderType_FallingDiagonal].width = m_style->fallDiagonalPen().width(); + borders[BorderType_FallingDiagonal].color = m_style->fallDiagonalPen().color(); + + borders[BorderType_RisingDiagonal].style = m_style->goUpDiagonalPen().style(); + borders[BorderType_RisingDiagonal].width = m_style->goUpDiagonalPen().width(); + borders[BorderType_RisingDiagonal].color = m_style->goUpDiagonalPen().color(); + + borders[BorderType_Vertical].style = m_style->leftBorderPen().style(); + borders[BorderType_Vertical].width = m_style->leftBorderPen().width(); + borders[BorderType_Vertical].color = m_style->leftBorderPen().color(); + borders[BorderType_Horizontal].style = m_style->topBorderPen().style(); + borders[BorderType_Horizontal].width = m_style->topBorderPen().width(); + borders[BorderType_Horizontal].color = m_style->topBorderPen().color(); + + prefix = m_style->prefix(); + postfix = m_style->postfix(); + precision = m_style->precision(); + floatFormat = m_style->floatFormat(); + floatColor = m_style->floatColor(); + alignX = m_style->alignX(); + alignY = m_style->alignY(); + textColor = m_style->pen().color(); + bgColor = m_style->bgColor(); + textFontSize = m_style->fontSize(); + textFontFamily = m_style->fontFamily(); + + uint flags = m_style->fontFlags(); + textFontBold = ( flags & (uint) Style::FBold ); + textFontItalic = ( flags & (uint) Style::FItalic ); + strike = ( flags & (uint) Style::FStrike ); + underline = ( flags & (uint) Style::FUnderline ); + + // Needed to initialize the font correctly ( bug in TQt ) + textFont = m_style->font(); + cCurrency = m_style->currency(); + brushColor = m_style->backGroundBrush().color(); + brushStyle = m_style->backGroundBrush().style(); + + bMultiRow = m_style->hasProperty( Style::PMultiRow ); + bVerticalText = m_style->hasProperty( Style::PVerticalText ); + textRotation = m_style->rotateAngle(); + formatType = m_style->formatType(); + indent = m_style->indent(); + + bDontPrintText = m_style->hasProperty( Style::PDontPrintText ); + bHideFormula = m_style->hasProperty( Style::PHideFormula ); + bHideAll = m_style->hasProperty( Style::PHideAll ); + bIsProtected = !m_style->hasProperty( Style::PNotProtected ); + + widthSize = defaultWidthSize; + heightSize = defaultHeightSize; +} + +CellFormatDialog::~CellFormatDialog() +{ + delete formatOnlyNegSignedPixmap; + delete formatRedOnlyNegSignedPixmap; + delete formatRedNeverSignedPixmap; + delete formatAlwaysSignedPixmap; + delete formatRedAlwaysSignedPixmap; +} + +void CellFormatDialog::initMembers() +{ + formatOnlyNegSignedPixmap = 0L; + formatRedOnlyNegSignedPixmap = 0L; + formatRedNeverSignedPixmap = 0L; + formatAlwaysSignedPixmap = 0L; + formatRedAlwaysSignedPixmap = 0L; + + // We assume, that all other objects have the same values + for ( int i = 0; i < BorderType_END; ++i ) + { + borders[i].bStyle = true; + borders[i].bColor = true; + } + bFloatFormat = true; + bFloatColor = true; + bTextColor = true; + bBgColor = true; + bTextFontFamily = true; + bTextFontSize = true; + bTextFontBold = true; + bTextFontItalic = true; + bStrike = true; + bUnderline = true; + bTextRotation = true; + bFormatType = true; + bCurrency = true; + bDontPrintText = false; + bHideFormula = false; + bHideAll = false; + bIsProtected = true; + + cCurrency.symbol = locale()->currencySymbol(); + cCurrency.type = 0; + + Sheet* sheet = m_pView->activeSheet(); + defaultWidthSize = sheet ? sheet->columnFormat(0)->dblWidth() : 0; + defaultHeightSize = sheet ? sheet->rowFormat(0)->dblHeight() : 0; +} + +bool CellFormatDialog::checkCircle( TQString const & name, TQString const & parent ) +{ + return m_styleManager->checkCircle( name, parent ); +} + +void CellFormatDialog::checkBorderRight(Format *obj,int x,int y) +{ + if ( borders[BorderType_Right].style != obj->rightBorderStyle( x, y ) || + borders[BorderType_Right].width != obj->rightBorderWidth( x, y ) ) + borders[BorderType_Right].bStyle = false; + if ( borders[BorderType_Right].color != obj->rightBorderColor( x, y ) ) + borders[BorderType_Right].bColor = false; +} + +void CellFormatDialog::checkBorderLeft(Format *obj,int x,int y) +{ + if ( borders[BorderType_Left].style != obj->leftBorderStyle( x, y ) || + borders[BorderType_Left].width != obj->leftBorderWidth( x, y ) ) + borders[BorderType_Left].bStyle = false; + if ( borders[BorderType_Left].color != obj->leftBorderColor( x, y ) ) + borders[BorderType_Left].bColor = false; +} + +void CellFormatDialog::checkBorderTop(Format *obj,int x,int y) +{ + if ( borders[BorderType_Top].style != obj->topBorderStyle( x, y ) || + borders[BorderType_Top].width != obj->topBorderWidth( x, y ) ) + borders[BorderType_Top].bStyle = false; + if ( borders[BorderType_Top].color != obj->topBorderColor( x, y ) ) + borders[BorderType_Top].bColor = false; +} + +void CellFormatDialog::checkBorderBottom(Format *obj,int x,int y) +{ + if ( borders[BorderType_Bottom].style != obj->bottomBorderStyle( x, y ) || + borders[BorderType_Bottom].width != obj->bottomBorderWidth( x, y ) ) + borders[BorderType_Bottom].bStyle = false; + if ( borders[BorderType_Bottom].color != obj->bottomBorderColor( x, y ) ) + borders[BorderType_Bottom].bColor = false; +} + +void CellFormatDialog::checkBorderVertical(Format *obj,int x,int y) +{ + if (borders[BorderType_Vertical].style != obj->leftBorderStyle( x, y ) || + borders[BorderType_Vertical].width != obj->leftBorderWidth( x, y )) + borders[BorderType_Vertical].bStyle = false; + if ( borders[BorderType_Vertical].color != obj->leftBorderColor( x, y ) ) + borders[BorderType_Vertical].bColor = false; +} + +void CellFormatDialog::checkBorderHorizontal(Format *obj,int x,int y) +{ + if ( borders[BorderType_Horizontal].style != obj->topBorderStyle( x, y ) || + borders[BorderType_Horizontal].width != obj->topBorderWidth( x, y ) ) + borders[BorderType_Horizontal].bStyle = false; + if ( borders[BorderType_Horizontal].color != obj->topBorderColor( x, y ) ) + borders[BorderType_Horizontal].bColor = false; +} + + +void CellFormatDialog::initParameters(Format *obj,int x,int y) +{ + if (borders[BorderType_FallingDiagonal].style != obj->fallDiagonalStyle( x, y )) + borders[BorderType_FallingDiagonal].bStyle = false; + if (borders[BorderType_FallingDiagonal].width != obj->fallDiagonalWidth( x, y )) + borders[BorderType_FallingDiagonal].bStyle = false; + if (borders[BorderType_FallingDiagonal].color != obj->fallDiagonalColor( x, y )) + borders[BorderType_FallingDiagonal].bColor = false; + + if (borders[BorderType_RisingDiagonal].style != obj->goUpDiagonalStyle( x, y )) + borders[BorderType_RisingDiagonal].bStyle = false; + if (borders[BorderType_RisingDiagonal].width != obj->goUpDiagonalWidth( x, y )) + borders[BorderType_RisingDiagonal].bStyle = false; + if (borders[BorderType_RisingDiagonal].color != obj->goUpDiagonalColor( x, y )) + borders[BorderType_RisingDiagonal].bColor = false; + if ( strike != obj->textFontStrike( x, y ) ) + bStrike = false; + if ( underline != obj->textFontUnderline( x, y ) ) + bUnderline = false; + if ( prefix != obj->prefix( x, y ) ) + prefix = TQString(); + if ( postfix != obj->postfix( x, y ) ) + postfix = TQString(); + if ( floatFormat != obj->floatFormat( x, y ) ) + bFloatFormat = false; + if ( floatColor != obj->floatColor( x, y ) ) + bFloatColor = false; + if ( textColor != obj->textColor( x, y ) ) + bTextColor = false; + if ( textFontFamily != obj->textFontFamily( x, y ) ) + bTextFontFamily = false; + if ( textFontSize != obj->textFontSize( x, y ) ) + bTextFontSize = false; + if ( textFontBold != obj->textFontBold( x, y ) ) + bTextFontBold = false; + if ( textFontItalic != obj->textFontItalic( x, y ) ) + bTextFontItalic = false; + if ( bgColor != obj->bgColor( x, y ) ) + bBgColor = false; + if ( textRotation != obj->getAngle(left, top) ) + bTextRotation = false; + if ( formatType != obj->getFormatType(left, top) ) + bFormatType = false; + if ( bMultiRow != obj->multiRow( left, top ) ) + bMultiRow = false; + if ( bVerticalText!=obj->verticalText( left, top ) ) + bVerticalText = false; + if ( bDontPrintText!=obj->getDontprintText( left, top ) ) + bDontPrintText= false; + + Format::Currency cur; + if (!obj->currencyInfo(cur)) + bCurrency = false; + else + if (cur.symbol != cCurrency.symbol) + bCurrency = false; +} + +void CellFormatDialog::init() +{ + TQColorGroup colorGroup = TQApplication::palette().active(); + + // Did we initialize the bitmaps ? + if ( formatOnlyNegSignedPixmap == 0L ) + { + TQColor black = colorGroup.text(); // not necessarily black :) + formatOnlyNegSignedPixmap = paintFormatPixmap( "123.456", black, "-123.456", black ); + formatRedOnlyNegSignedPixmap = paintFormatPixmap( "123.456", black, "-123.456", TQt::red ); + formatRedNeverSignedPixmap = paintFormatPixmap( "123.456", black, "123.456", TQt::red ); + formatAlwaysSignedPixmap = paintFormatPixmap( "+123.456", black, "-123.456", black ); + formatRedAlwaysSignedPixmap = paintFormatPixmap( "+123.456", black, "-123.456", TQt::red ); + } + + tab = new TQTabDialog( (TQWidget*)m_pView, 0L, true ); + //tab->setGeometry( tab->x(), tab->y(), 420, 400 ); + + if ( m_style ) + { + generalPage = new GeneralTab( tab, this ); + tab->addTab( generalPage, i18n( "&General" ) ); + } + + floatPage = new CellFormatPageFloat( tab, this ); + tab->addTab( floatPage, i18n("&Data Format") ); + + fontPage = new CellFormatPageFont( tab, this ); + tab->addTab( fontPage, i18n("&Font") ); + + // miscPage = new CellFormatPageMisc( tab, this ); + // tab->addTab( miscPage, i18n("&Misc") ); + + positionPage = new CellFormatPagePosition( tab, this); + tab->addTab( positionPage, i18n("&Position") ); + + borderPage = new CellFormatPageBorder( tab, this ); + tab->addTab( borderPage, i18n("&Border") ); + + patternPage=new CellFormatPagePattern(tab,this); + tab->addTab( patternPage,i18n("Back&ground")); + + protectPage = new CellFormatPageProtection( tab, this ); + tab->addTab( protectPage, i18n("&Cell Protection") ); + + tab->setCancelButton( i18n( "&Cancel" ) ); + tab->setOkButton( i18n( "&OK" ) ); + + tab->setCaption( i18n( "Cell Format" ) ); + + tab->adjustSize(); + + connect( tab, TQT_SIGNAL( applyButtonPressed() ), this, TQT_SLOT( slotApply() ) ); + + tab->exec(); +} + +TQPixmap * CellFormatDialog::paintFormatPixmap( const char * _string1, const TQColor & _color1, + const char *_string2, const TQColor & _color2 ) +{ + TQPixmap * pixmap = new TQPixmap( 150, 14 ); + + TQPainter painter; + painter.begin( pixmap ); + painter.fillRect( 0, 0, 150, 14, TQApplication::palette().active().base() ); + painter.setPen( _color1 ); + painter.drawText( 2, 11, TQString(_string1) ); + painter.setPen( _color2 ); + painter.drawText( 75, 11, TQString(_string2) ); + painter.end(); + + TQBitmap bm( pixmap->size() ); + bm.fill( color0 ); + painter.begin( &bm ); + painter.setPen( color1 ); + painter.drawText( 2, 11, TQString(_string1) ); + painter.drawText( 75, 11, TQString(_string2) ); + painter.end(); + pixmap->setMask( bm ); + + return pixmap; +} + +int CellFormatDialog::exec() +{ + return ( tab->exec() ); +} + +void CellFormatDialog::applyStyle() +{ + generalPage->apply( m_style ); + + borderPage->apply(0); + floatPage->apply( m_style ); + // miscPage->apply( m_style ); + fontPage->apply( m_style ); + positionPage->apply( m_style ); + patternPage->apply( m_style ); + protectPage->apply( m_style ); + m_pView->refreshView(); +} + +void CellFormatDialog::slotApply() +{ + if ( m_style ) + { + applyStyle(); + return; + } + + // (Tomas) TODO: this will be slow !!! + // We need to create a manipulator that would act as KMacroCommand, + // but which would also ensure that updates are not painted until everything + // is updated properly ... + KMacroCommand* macroCommand = new KMacroCommand( i18n("Change Format") ); + + if ( isMerged != positionPage->getMergedCellState() ) + { + if ( positionPage->getMergedCellState() ) + { + Manipulator* manipulator = new MergeManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setRegisterUndo(false); + manipulator->add(*m_pView->selectionInfo()); + macroCommand->addCommand( manipulator ); + } + else + { + //dissociate cells + Manipulator* manipulator = new MergeManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setReverse(true); + manipulator->setRegisterUndo(false); + manipulator->add(*m_pView->selectionInfo()); + macroCommand->addCommand( manipulator ); + } + } + + FormatManipulator* manipulator = new FormatManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setRegisterUndo(false); + manipulator->add(*m_pView->selectionInfo()); + borderPage->apply(manipulator); + floatPage->apply(manipulator); + fontPage->apply(manipulator); + positionPage->apply(manipulator); + patternPage->apply(manipulator); + protectPage->apply(manipulator); + + if (!manipulator->isEmpty()) + { + macroCommand->addCommand( manipulator ); + } + else + { + delete manipulator; + } + + if ( int( positionPage->getSizeHeight() ) != int( heightSize ) ) + { + ResizeRowManipulator* manipulator = new ResizeRowManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setSize(positionPage->getSizeHeight()); + // TODO Stefan: + manipulator->setOldSize(heightSize); + manipulator->add(*m_pView->selectionInfo()); + macroCommand->addCommand( manipulator ); + } + if ( int( positionPage->getSizeWidth() ) != int( widthSize ) ) + { + ResizeColumnManipulator* manipulator = new ResizeColumnManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setSize(positionPage->getSizeWidth()); + // TODO Stefan: + manipulator->setOldSize(widthSize); + manipulator->add(*m_pView->selectionInfo()); + macroCommand->addCommand( manipulator ); + } + + macroCommand->execute(); + m_doc->addCommand( macroCommand ); + + // Update the toolbar (bold/italic/font...) + m_pView->updateEditWidget(); +} + + + +/*************************************************************************** + * + * CellFormatPageFloat + * + ***************************************************************************/ + +CellFormatPageFloat::CellFormatPageFloat( TQWidget* parent, CellFormatDialog *_dlg ) + : TQWidget ( parent ), + dlg( _dlg ) +{ + TQVBoxLayout* layout = new TQVBoxLayout( this, 6,10 ); + + TQButtonGroup *grp = new TQButtonGroup( i18n("Format"),this); + TQGridLayout *grid = new TQGridLayout(grp,11,2,KDialog::marginHint(), KDialog::spacingHint()); + + int fHeight = grp->fontMetrics().height(); + grid->addRowSpacing( 0, fHeight/2 ); // groupbox title + + grp->setRadioButtonExclusive( true ); + generic=new TQRadioButton(i18n("Generic"),grp); + TQWhatsThis::add(generic, i18n( "This is the default format and KSpread autodetects the actual data type depending on the current cell data. By default, KSpread right justifies numbers, dates and times within a cell and left justifies anything else." ) ); + grid->addWidget(generic,1,0); + + number=new TQRadioButton(i18n("Number"),grp); + TQWhatsThis::add(number, i18n( "The number notation uses the notation you globally choose in KControl -> Regional & Accessibility -> Numbers tab. Numbers are right justified by default." ) ); + grid->addWidget(number,2,0); + + percent=new TQRadioButton(i18n("Percent"),grp); + TQWhatsThis::add(percent, i18n( "When you have a number in the current cell and you switch from the dcell format from Generic to Percent, the current cell number will be multiplied by 100%.\nFor example if you enter 12 and set the cell format to Percent, the number will then be 1,200 %. Switching back to Generic cell format will bring it back to 12.\nYou can also use the Percent icon in the Format Toolbar." ) ); + grid->addWidget(percent,3,0); + + money=new TQRadioButton(i18n("Money"),grp); + TQWhatsThis::add(money, i18n( "The Money format converts your number into money notation using the settings globally fixed in KControl in Regional & Accessibility -> Money. The currency symbol will be displayed and the precision will be the one set in KControl.\nYou can also use the Currency icon in the Format Toolbar to set the cell formatting to look like your current currency." ) ); + grid->addWidget(money,4,0); + + scientific=new TQRadioButton(i18n("Scientific"),grp); + TQWhatsThis::add(scientific, i18n( "The scientific format changes your number using the scientific notation. For example, 0.0012 will be changed to 1.2E-03. Going back using Generic cell format will display 0.0012 again." ) ); + grid->addWidget(scientific,5,0); + + fraction=new TQRadioButton(i18n("Fraction"),grp); + TQWhatsThis::add(fraction, i18n( "The fraction format changes your number into a fraction. For example, 0.1 can be changed to 1/8, 2/16, 1/10, etc. You define the type of fraction by choosing it in the field on the right. If the exact fraction is not possible in the fraction mode you choose, the nearest closest match is chosen.\n For example: when we have 1.5 as number, we choose Fraction and Sixteenths 1/16 the text displayed into cell is \"1 8/16\" which is an exact fraction. If you have 1.4 as number in your cell and you choose Fraction and Sixteenths 1/16 then the cell will display \"1 6/16\" which is the nearest closest Sixteenth fraction." ) ); + grid->addWidget(fraction,6,0); + + date=new TQRadioButton(i18n("Date format"),grp); + TQWhatsThis::add(date, i18n( "To enter a date, you should enter it in one of the formats set in KControl in Regional & Accessibility ->Time & Dates. There are two formats set here: the date format and the short date format.\nJust like you can drag down numbers you can also drag down dates and the next cells will also get dates." ) ); + grid->addWidget(date,7,0); + + time=new TQRadioButton(i18n("Time format"),grp); + TQWhatsThis::add(time, i18n( "This formats your cell content as a time. To enter a time, you should enter it in the Time format set in KControl in Regional & Accessibility ->Time & Dates. In the Cell Format dialog box you can set how the time should be displayed by choosing one of the available time format options. The default format is the system format set in KControl. When the number in the cell does not make sense as a time, KSpread will display 00:00 in the global format you have in KControl." ) ); + grid->addWidget(time,8,0); + + textFormat=new TQRadioButton(i18n("Text"),grp); + TQWhatsThis::add(textFormat, i18n( "This formats your cell content as text. This can be useful if you want a number treated as text instead as a number, for example for a ZIP code. Setting a number as text format will left justify it. When numbers are formatted as text, they cannot be used in calculations or formulas. It also change the way the cell is justified." ) ); + grid->addWidget(textFormat,9,0); + + customFormat=new TQRadioButton(i18n("Custom"),grp); + TQWhatsThis::add(customFormat, i18n( "The custom format does not work yet. To be enabled in the next release." ) ); + grid->addWidget(customFormat,10,0); + customFormat->setEnabled( false ); + + TQGroupBox *box2 = new TQGroupBox( grp, "Box"); + box2->setTitle(i18n("Preview")); + TQGridLayout *grid3 = new TQGridLayout(box2,1,3,KDialog::marginHint(), KDialog::spacingHint()); + + exampleLabel=new TQLabel(box2); + TQWhatsThis::add(exampleLabel, i18n( "This will display a preview of your choice so you can know what it does before clicking the OK button to validate it." ) ); + grid3->addWidget(exampleLabel,0,1); + + grid->addMultiCellWidget(box2,9,10,1,1); + + customFormatEdit = new TQLineEdit( grp ); + grid->addMultiCellWidget( customFormatEdit, 1, 1, 1, 1 ); + customFormatEdit->setHidden( true ); + + listFormat=new TQListBox(grp); + grid->addMultiCellWidget(listFormat,2,7,1,1); + TQWhatsThis::add(listFormat, i18n( "Displays choices of format for the fraction, date or time formats." ) ); + layout->addWidget(grp); + + /* *** */ + + TQGroupBox *box = new TQGroupBox( this, "Box"); + + grid = new TQGridLayout(box,3,4,KDialog::marginHint(), KDialog::spacingHint()); + + postfix = new TQLineEdit( box, "LineEdit_1" ); + TQWhatsThis::add(postfix, i18n( "You can add here a Postfix such as a $HK symbol to the end of each cell content in the checked format." ) ); + grid->addWidget(postfix,2,1); + precision = new KIntNumInput( dlg->precision, box, 10 ); + precision->setSpecialValueText(i18n("variable")); + precision->setRange(-1,10,1,false); + TQWhatsThis::add(precision, i18n( "You can control how many digits are displayed after the decimal point for numeric values. This can also be changed using the Increase precision or Decrease precision icons in the Format toolbar. " ) ); + grid->addWidget(precision,1,1); + + prefix = new TQLineEdit( box, "LineEdit_3" ); + TQWhatsThis::add(prefix, i18n( "You can add here a Prefix such as a $ symbol at the start of each cell content in the checked format." ) ); + grid->addWidget(prefix,0,1); + + format = new TQComboBox( box, "ListBox_1" ); + TQWhatsThis::add(format, i18n( "You can choose whether positive values are displayed with a leading + sign and whether negative values are shown in red." ) ); + grid->addWidget(format,0,3); + + TQLabel* tmpTQLabel; + tmpTQLabel = new TQLabel( box, "Label_1" ); + grid->addWidget(tmpTQLabel,2,0); + tmpTQLabel->setText( i18n("Postfix:") ); + + postfix->setText( dlg->postfix ); + + tmpTQLabel = new TQLabel( box, "Label_2" ); + grid->addWidget(tmpTQLabel,0,0); + + tmpTQLabel->setText( i18n("Prefix:") ); + tmpTQLabel = new TQLabel( box, "Label_3" ); + grid->addWidget(tmpTQLabel,1,0); + tmpTQLabel->setText( i18n("Precision:") ); + + prefix->setText( dlg->prefix ); + + format->insertItem( *_dlg->formatOnlyNegSignedPixmap, 0 ); + format->insertItem( *_dlg->formatRedOnlyNegSignedPixmap, 1 ); + format->insertItem( *_dlg->formatRedNeverSignedPixmap, 2 ); + format->insertItem( *_dlg->formatAlwaysSignedPixmap, 3 ); + format->insertItem( *_dlg->formatRedAlwaysSignedPixmap, 4 ); + + tmpTQLabel = new TQLabel( box, "Label_4" ); + grid->addWidget(tmpTQLabel, 0, 2); + tmpTQLabel->setText( i18n("Format:") ); + + currencyLabel = new TQLabel( box, "LabelCurrency" ); + grid->addWidget(currencyLabel, 1, 2); + currencyLabel->setText( i18n("Currency:") ); + + currency = new TQComboBox( box, "ComboCurrency" ); + grid->addWidget(currency, 1, 3); + + currency->insertItem( i18n("Automatic") ); + + int index = 2; //ignore first two in the list + bool ok = true; + TQString text; + + while ( ok ) + { + text = Currency::getChooseString( index, ok ); + if ( ok ) + { + currency->insertItem( text ); + } + else + { + break; + } + + ++index; + } + + currency->setCurrentItem( 0 ); + currency->hide(); + currencyLabel->hide(); + + if ( !dlg->bFloatFormat || !dlg->bFloatColor ) + format->setCurrentItem( 5 ); + else if ( dlg->floatFormat == Format::OnlyNegSigned && dlg->floatColor == Format::AllBlack ) + format->setCurrentItem( 0 ); + else if ( dlg->floatFormat == Format::OnlyNegSigned && dlg->floatColor == Format::NegRed ) + format->setCurrentItem( 1 ); + else if ( dlg->floatFormat == Format::AlwaysUnsigned && dlg->floatColor == Format::NegRed ) + format->setCurrentItem( 2 ); + else if ( dlg->floatFormat == Format::AlwaysSigned && dlg->floatColor == Format::AllBlack ) + format->setCurrentItem( 3 ); + else if ( dlg->floatFormat == Format::AlwaysSigned && dlg->floatColor == Format::NegRed ) + format->setCurrentItem( 4 ); + layout->addWidget(box); + + cellFormatType=dlg->formatType; + newFormatType = cellFormatType; + + if (!cellFormatType) + generic->setChecked(true); + else + { + if (cellFormatType==Number_format) + number->setChecked(true); + else if (cellFormatType==Percentage_format) + percent->setChecked(true); + else if (cellFormatType==Money_format) + { + money->setChecked(true); + currencyLabel->show(); + currency->show(); + if (dlg->bCurrency) + { + TQString tmp; + if (dlg->cCurrency.type != 1) + { + Currency curr(dlg->cCurrency.type); + bool ok = true; + tmp = Currency::getChooseString(dlg->cCurrency.type, ok); + if ( !ok ) + tmp = dlg->cCurrency.symbol; + } + else + tmp = dlg->cCurrency.symbol; + currency->setCurrentText( tmp ); + } + } + else if ( cellFormatType == Scientific_format ) + scientific->setChecked(true); + else if ( formatIsDate (cellFormatType) ) + date->setChecked(true); + else if ( formatIsTime (cellFormatType) ) + time->setChecked(true); + else if ( formatIsFraction (cellFormatType) ) + fraction->setChecked(true); + else if (cellFormatType == Text_format) + textFormat->setChecked(true); + else if (cellFormatType == Custom_format) + customFormat->setChecked(true); + } + + connect(generic,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(fraction,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(money,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(date,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(scientific,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(number,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(percent,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(time,TQT_SIGNAL(clicked ()),this,TQT_SLOT(slotChangeState())); + connect(textFormat,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotChangeState())); + connect(customFormat,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotChangeState())); + + connect(listFormat,TQT_SIGNAL(selectionChanged ()),this,TQT_SLOT(makeformat())); + connect(precision,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(slotChangeValue(int))); + connect(prefix,TQT_SIGNAL(textChanged ( const TQString & ) ),this,TQT_SLOT(makeformat())); + connect(postfix,TQT_SIGNAL(textChanged ( const TQString & ) ),this,TQT_SLOT(makeformat())); + connect(currency,TQT_SIGNAL(activated ( const TQString & ) ),this, TQT_SLOT(currencyChanged(const TQString &))); + connect(format,TQT_SIGNAL(activated ( int ) ),this,TQT_SLOT(formatChanged(int))); + connect(format, TQT_SIGNAL(activated(int)), this, TQT_SLOT(makeformat())); + slotChangeState(); + m_bFormatColorChanged=false; + m_bFormatTypeChanged=false; + this->resize( 400, 400 ); +} + +void CellFormatPageFloat::formatChanged(int) +{ + m_bFormatColorChanged=true; +} + +void CellFormatPageFloat::slotChangeValue(int) +{ + makeformat(); +} +void CellFormatPageFloat::slotChangeState() +{ + TQStringList list; + listFormat->clear(); + currency->hide(); + currencyLabel->hide(); + + // start with enabled, they get disabled when inappropriate further down + precision->setEnabled(true); + prefix->setEnabled(true); + postfix->setEnabled(true); + format->setEnabled(true); + + if (generic->isChecked() || number->isChecked() || percent->isChecked() || + scientific->isChecked() || textFormat->isChecked()) + listFormat->setEnabled(false); + else if (money->isChecked()) + { + listFormat->setEnabled(false); + precision->setValue(2); + currency->show(); + currencyLabel->show(); + } + else if (date->isChecked()) + { + format->setEnabled(false); + precision->setEnabled(false); + prefix->setEnabled(false); + postfix->setEnabled(false); + listFormat->setEnabled(true); + init(); + } + else if (fraction->isChecked()) + { + precision->setEnabled(false); + listFormat->setEnabled(true); + list+=i18n("Halves 1/2"); + list+=i18n("Quarters 1/4"); + list+=i18n("Eighths 1/8"); + list+=i18n("Sixteenths 1/16"); + list+=i18n("Tenths 1/10"); + list+=i18n("Hundredths 1/100"); + list+=i18n("One digit 5/9"); + list+=i18n("Two digits 15/22"); + list+=i18n("Three digits 153/652"); + listFormat->insertStringList(list); + if (cellFormatType == fraction_half) + listFormat->setCurrentItem(0); + else if (cellFormatType == fraction_quarter) + listFormat->setCurrentItem(1); + else if (cellFormatType == fraction_eighth ) + listFormat->setCurrentItem(2); + else if (cellFormatType == fraction_sixteenth ) + listFormat->setCurrentItem(3); + else if (cellFormatType == fraction_tenth ) + listFormat->setCurrentItem(4); + else if (cellFormatType == fraction_hundredth ) + listFormat->setCurrentItem(5); + else if (cellFormatType == fraction_one_digit ) + listFormat->setCurrentItem(6); + else if (cellFormatType == fraction_two_digits ) + listFormat->setCurrentItem(7); + else if (cellFormatType == fraction_three_digits ) + listFormat->setCurrentItem(8); + else + listFormat->setCurrentItem(0); + } + else if (time->isChecked()) + { + precision->setEnabled(false); + prefix->setEnabled(false); + postfix->setEnabled(false); + format->setEnabled(false); + listFormat->setEnabled(true); + + + list+=i18n("System: ")+dlg->locale()->formatTime(TQTime::currentTime(),false); + list+=i18n("System: ")+dlg->locale()->formatTime(TQTime::currentTime(),true); + TQDateTime tmpTime (TQDate (1, 1, 1900), TQTime (10, 35, 25)); + + + ValueFormatter *fmt = dlg->getDoc()->formatter(); + list+= fmt->timeFormat(tmpTime, Time_format1); + list+= fmt->timeFormat(tmpTime, Time_format2); + list+= fmt->timeFormat(tmpTime, Time_format3); + list+= fmt->timeFormat(tmpTime, Time_format4); + list+= fmt->timeFormat(tmpTime, Time_format5); + list+= ( fmt->timeFormat(tmpTime, Time_format6) + i18n(" (=[mm]::ss)") ); + list+= ( fmt->timeFormat(tmpTime, Time_format7) + i18n(" (=[hh]::mm::ss)") ); + list+= ( fmt->timeFormat(tmpTime, Time_format8) + i18n(" (=[hh]::mm)") ); + listFormat->insertStringList(list); + + if ( cellFormatType == Time_format ) + listFormat->setCurrentItem(0); + else if (cellFormatType == SecondeTime_format) + listFormat->setCurrentItem(1); + else if (cellFormatType == Time_format1) + listFormat->setCurrentItem(2); + else if (cellFormatType == Time_format2) + listFormat->setCurrentItem(3); + else if (cellFormatType == Time_format3) + listFormat->setCurrentItem(4); + else if (cellFormatType == Time_format4) + listFormat->setCurrentItem(5); + else if (cellFormatType == Time_format5) + listFormat->setCurrentItem(6); + else if (cellFormatType == Time_format6) + listFormat->setCurrentItem(7); + else if (cellFormatType == Time_format7) + listFormat->setCurrentItem(8); + else if (cellFormatType == Time_format8) + listFormat->setCurrentItem(9); + else + listFormat->setCurrentItem(0); + } + + if (customFormat->isChecked()) + { + customFormatEdit->setHidden( false ); + precision->setEnabled(false); + prefix->setEnabled(false); + postfix->setEnabled(false); + format->setEnabled(false); + listFormat->setEnabled(true); + } + else + customFormatEdit->setHidden( true ); + + m_bFormatTypeChanged=true; + + makeformat(); +} + +void CellFormatPageFloat::init() +{ + TQStringList list; + TQString tmp; + TQString tmp2; + TQDate tmpDate( 2000,2,18); + list+=i18n("System: ")+dlg->locale()->formatDate (TQDate::currentDate(), true); + list+=i18n("System: ")+dlg->locale()->formatDate (TQDate::currentDate(), false); + + ValueFormatter *fmt = dlg->getDoc()->formatter(); + + /*18-Feb-00*/ + list+=fmt->dateFormat( tmpDate, date_format1); + /*18-Feb-1999*/ + list+=fmt->dateFormat( tmpDate, date_format2); + /*18-Feb*/ + list+=fmt->dateFormat( tmpDate, date_format3); + /*18-2*/ + list+=fmt->dateFormat( tmpDate, date_format4); + /*18/2/00*/ + list+=fmt->dateFormat( tmpDate, date_format5); + /*18/5/1999*/ + list+=fmt->dateFormat( tmpDate, date_format6); + /*Feb-99*/ + list+=fmt->dateFormat( tmpDate, date_format7); + /*February-99*/ + list+=fmt->dateFormat( tmpDate, date_format8); + /*February-1999*/ + list+=fmt->dateFormat( tmpDate, date_format9); + /*F-99*/ + list+=fmt->dateFormat( tmpDate, date_format10); + /*18/Feb*/ + list+=fmt->dateFormat( tmpDate, date_format11); + /*18/2*/ + list+=fmt->dateFormat( tmpDate, date_format12); + /*18/Feb/1999*/ + list+=fmt->dateFormat( tmpDate, date_format13); + /*2000/Feb/18*/ + list+=fmt->dateFormat( tmpDate, date_format14); + /*2000-Feb-18*/ + list+=fmt->dateFormat( tmpDate, date_format15); + /*2000-2-18*/ + list+=fmt->dateFormat( tmpDate, date_format16); + /*2 february 2000*/ + list+=fmt->dateFormat( tmpDate, date_format17); + list+=fmt->dateFormat( tmpDate, date_format18); + list+=fmt->dateFormat( tmpDate, date_format19); + list+=fmt->dateFormat( tmpDate, date_format20); + list+=fmt->dateFormat( tmpDate, date_format21); + list+=fmt->dateFormat( tmpDate, date_format22); + list+=fmt->dateFormat( tmpDate, date_format23); + list+=fmt->dateFormat( tmpDate, date_format24); + list+=fmt->dateFormat( tmpDate, date_format25); + list+=fmt->dateFormat( tmpDate, date_format26); + + listFormat->insertStringList(list); + if ( cellFormatType == ShortDate_format ) + listFormat->setCurrentItem(0); + else if (cellFormatType == TextDate_format) + listFormat->setCurrentItem(1); + else if (cellFormatType == date_format1) + listFormat->setCurrentItem(2); + else if (cellFormatType == date_format2) + listFormat->setCurrentItem(3); + else if (cellFormatType == date_format3) + listFormat->setCurrentItem(4); + else if (cellFormatType == date_format4) + listFormat->setCurrentItem(5); + else if (cellFormatType == date_format5) + listFormat->setCurrentItem(6); + else if (cellFormatType == date_format6) + listFormat->setCurrentItem(7); + else if (cellFormatType == date_format7) + listFormat->setCurrentItem(8); + else if (cellFormatType == date_format8) + listFormat->setCurrentItem(9); + else if (cellFormatType == date_format9) + listFormat->setCurrentItem(10); + else if (cellFormatType == date_format10) + listFormat->setCurrentItem(11); + else if (cellFormatType == date_format11) + listFormat->setCurrentItem(12); + else if (cellFormatType == date_format12) + listFormat->setCurrentItem(13); + else if (cellFormatType == date_format13) + listFormat->setCurrentItem(14); + else if (cellFormatType == date_format14) + listFormat->setCurrentItem(15); + else if (cellFormatType == date_format15) + listFormat->setCurrentItem(16); + else if (cellFormatType == date_format16) + listFormat->setCurrentItem(17); + else if (cellFormatType == date_format17) + listFormat->setCurrentItem(18); + else if (cellFormatType == date_format18) + listFormat->setCurrentItem(19); + else if (cellFormatType == date_format19) + listFormat->setCurrentItem(20); + else if (cellFormatType == date_format20) + listFormat->setCurrentItem(21); + else if (cellFormatType == date_format21) + listFormat->setCurrentItem(22); + else if (cellFormatType == date_format22) + listFormat->setCurrentItem(23); + else if (cellFormatType == date_format23) + listFormat->setCurrentItem(24); + else if (cellFormatType == date_format24) + listFormat->setCurrentItem(25); + else if (cellFormatType == date_format25) + listFormat->setCurrentItem(26); + else if (cellFormatType == date_format26) + listFormat->setCurrentItem(27); + else + listFormat->setCurrentItem(0); + +} + +void CellFormatPageFloat::currencyChanged(const TQString &) +{ + int index = currency->currentItem(); + if (index > 0) + ++index; + dlg->cCurrency.symbol = Currency::getDisplaySymbol(index); + dlg->cCurrency.type = index; + + makeformat(); +} + +void CellFormatPageFloat::updateFormatType () +{ + if (generic->isChecked()) + newFormatType = Generic_format; + else if (number->isChecked()) + newFormatType = Number_format; + else if (percent->isChecked()) + newFormatType = Percentage_format; + else if (date->isChecked()) + { + newFormatType=ShortDate_format; + switch (listFormat->currentItem()) + { + case 0: newFormatType=ShortDate_format; break; + case 1: newFormatType=TextDate_format; break; + case 2: newFormatType=date_format1; break; /*18-Feb-99*/ + case 3: newFormatType=date_format2; break; /*18-Feb-1999*/ + case 4: newFormatType=date_format3; break; /*18-Feb*/ + case 5: newFormatType=date_format4; break; /*18-05*/ + case 6: newFormatType=date_format5; break; /*18/05/00*/ + case 7: newFormatType=date_format6; break; /*18/05/1999*/ + case 8: newFormatType=date_format7; break;/*Feb-99*/ + case 9: newFormatType=date_format8; break; /*February-99*/ + case 10: newFormatType=date_format9; break; /*February-1999*/ + case 11: newFormatType=date_format10; break; /*F-99*/ + case 12: newFormatType=date_format11; break; /*18/Feb*/ + case 13: newFormatType=date_format12; break; /*18/02*/ + case 14: newFormatType=date_format13; break; /*18/Feb/1999*/ + case 15: newFormatType=date_format14; break; /*2000/Feb/18*/ + case 16: newFormatType=date_format15; break;/*2000-Feb-18*/ + case 17: newFormatType=date_format16; break;/*2000-02-18*/ + case 18: newFormatType=date_format17; break; /*2000-02-18*/ + case 19: newFormatType=date_format18; break; + case 20: newFormatType=date_format19; break; + case 21: newFormatType=date_format20; break; + case 22: newFormatType=date_format21; break; + case 23: newFormatType=date_format22; break; + case 24: newFormatType=date_format23; break; + case 25: newFormatType=date_format24; break; + case 26: newFormatType=date_format25; break; + case 27: newFormatType=date_format26; break; + } + } + else if (money->isChecked()) + newFormatType = Money_format; + else if (scientific->isChecked()) + newFormatType = Scientific_format; + else if (fraction->isChecked()) + { + newFormatType=fraction_half; + switch (listFormat->currentItem()) + { + case 0: newFormatType=fraction_half; break; + case 1: newFormatType=fraction_quarter; break; + case 2: newFormatType=fraction_eighth; break; + case 3: newFormatType=fraction_sixteenth; break; + case 4: newFormatType=fraction_tenth; break; + case 5: newFormatType=fraction_hundredth; break; + case 6: newFormatType=fraction_one_digit; break; + case 7: newFormatType=fraction_two_digits; break; + case 8: newFormatType=fraction_three_digits; break; + } + } + else if (time->isChecked()) + { + newFormatType=Time_format; + switch (listFormat->currentItem()) + { + case 0: newFormatType=Time_format; break; + case 1: newFormatType=SecondeTime_format; break; + case 2: newFormatType=Time_format1; break; + case 3: newFormatType=Time_format2; break; + case 4: newFormatType=Time_format3; break; + case 5: newFormatType=Time_format4; break; + case 6: newFormatType=Time_format5; break; + case 7: newFormatType=Time_format6; break; + case 8: newFormatType=Time_format7; break; + case 9: newFormatType=Time_format8; break; + } + } + else if (textFormat->isChecked()) + newFormatType = Text_format; + else if (customFormat->isChecked()) + newFormatType = Custom_format; +} + +void CellFormatPageFloat::makeformat() +{ + m_bFormatTypeChanged=true; + TQString tmp; + + updateFormatType(); + TQColor color; + Format::FloatFormat floatFormat = Format::OnlyNegSigned; + switch( format->currentItem() ) + { + case 0: + floatFormat = Format::OnlyNegSigned; + color = black; + break; + case 1: + floatFormat = Format::OnlyNegSigned; + color = TQt::red; + break; + case 2: + floatFormat = Format::AlwaysUnsigned; + color = TQt::red; + break; + case 3: + floatFormat = Format::AlwaysSigned; + color = black; + break; + case 4: + floatFormat = Format::AlwaysSigned; + color = TQt::red; + break; + } + if (!dlg->value.isNumber() || dlg->value.asFloat() >= 0 || !format->isEnabled()) + { + color = black; + } + ValueFormatter *fmt = dlg->getDoc()->formatter(); + tmp = fmt->formatText(dlg->value, newFormatType, precision->value(), + floatFormat, + prefix->isEnabled() ? prefix->text() : TQString(), + postfix->isEnabled() ? postfix->text() : TQString(), + newFormatType == Money_format ? dlg->cCurrency.symbol : TQString()); + if (tmp.length() > 50) + tmp = tmp.left (50); + exampleLabel->setText(tmp.prepend("").append("")); +} + +void CellFormatPageFloat::apply( CustomStyle * style ) +{ + if ( postfix->text() != dlg->postfix ) + { + if ( postfix->isEnabled()) + style->changePostfix( postfix->text() ); + else + style->changePostfix( "" ); + } + if ( prefix->text() != dlg->prefix ) + { + if (prefix->isEnabled()) + style->changePrefix( prefix->text() ); + else + style->changePrefix( "" ); + } + + if ( dlg->precision != precision->value() ) + style->changePrecision( precision->value() ); + + if ( m_bFormatColorChanged ) + { + switch( format->currentItem() ) + { + case 0: + style->changeFloatFormat( Format::OnlyNegSigned ); + style->changeFloatColor( Format::AllBlack ); + break; + case 1: + style->changeFloatFormat( Format::OnlyNegSigned ); + style->changeFloatColor( Format::NegRed ); + break; + case 2: + style->changeFloatFormat( Format::AlwaysUnsigned ); + style->changeFloatColor( Format::NegRed ); + break; + case 3: + style->changeFloatFormat( Format::AlwaysSigned ); + style->changeFloatColor( Format::AllBlack ); + break; + case 4: + style->changeFloatFormat( Format::AlwaysSigned ); + style->changeFloatColor( Format::NegRed ); + break; + } + } + if ( m_bFormatTypeChanged ) + { + style->changeFormatType (newFormatType); + if ( money->isChecked() ) + { + Format::Currency cur; + int index = currency->currentItem(); + if (index == 0) + { + if ( currency->currentText() == i18n( "Automatic" ) ) + { + cur.symbol = dlg->locale()->currencySymbol(); + cur.type = 0; + } + else + { + cur.type = 1; + cur.symbol = currency->currentText(); + } + } + else + { + cur.type = ++index; + cur.symbol = Currency::getDisplaySymbol( index ); + } + + style->changeCurrency( cur ); + } + } +} + +void CellFormatPageFloat::apply(FormatManipulator* _obj) +{ + if ( postfix->text() != dlg->postfix ) + if ( postfix->isEnabled()) + { + // If we are in here it *never* can be disabled - FIXME (Werner)! + if ( postfix->isEnabled()) + _obj->setPostfix( postfix->text() ); + else + _obj->setPostfix( "" ); + } + if ( prefix->text() != dlg->prefix ) + if (prefix->isEnabled()) + _obj->setPrefix( prefix->text() ); + else + _obj->setPrefix( "" ); + + if ( dlg->precision != precision->value() ) + _obj->setPrecision( precision->value() ); + + if (m_bFormatColorChanged) + { + switch( format->currentItem() ) + { + case 0: + _obj->setFloatFormat( Format::OnlyNegSigned ); + _obj->setFloatColor( Format::AllBlack ); + break; + case 1: + _obj->setFloatFormat( Format::OnlyNegSigned ); + _obj->setFloatColor( Format::NegRed ); + break; + case 2: + _obj->setFloatFormat( Format::AlwaysUnsigned ); + _obj->setFloatColor( Format::NegRed ); + break; + case 3: + _obj->setFloatFormat( Format::AlwaysSigned ); + _obj->setFloatColor( Format::AllBlack ); + break; + case 4: + _obj->setFloatFormat( Format::AlwaysSigned ); + _obj->setFloatColor( Format::NegRed ); + break; + } + } + if (m_bFormatTypeChanged) + { + _obj->setFormatType (newFormatType); + if (money->isChecked()) + { + Format::Currency cur; + int index = currency->currentItem(); + if (index == 0) + { + if ( currency->currentText() == i18n( "Automatic" ) ) + { + cur.symbol = dlg->locale()->currencySymbol(); + cur.type = 0; + } + else + { + cur.type = 1; + cur.symbol = currency->currentText(); + } + } + else + { + cur.type = ++index; + cur.symbol = Currency::getDisplaySymbol( index ); + } + + _obj->setCurrency( cur.type, cur.symbol ); + } + } +} + + + +/*************************************************************************** + * + * CellFormatPageProtection + * + ***************************************************************************/ + +CellFormatPageProtection::CellFormatPageProtection( TQWidget* parent, CellFormatDialog * _dlg ) + : ProtectionTab( parent ), + m_dlg( _dlg ) +{ + m_bDontPrint->setChecked( m_dlg->bDontPrintText ); + m_bHideAll->setChecked( m_dlg->bHideAll ); + m_bHideFormula->setChecked( m_dlg->bHideFormula ); + m_bIsProtected->setChecked( m_dlg->bIsProtected ); +} + +CellFormatPageProtection::~CellFormatPageProtection() +{ +} + +void CellFormatPageProtection::apply( CustomStyle * style ) +{ + if ( m_dlg->bDontPrintText != m_bDontPrint->isChecked() ) + { + if ( m_bDontPrint->isChecked() ) + style->addProperty( Style::PDontPrintText ); + else + style->removeProperty( Style::PDontPrintText ); + } + + if ( m_dlg->bIsProtected != m_bIsProtected->isChecked() ) + { + if ( !m_bIsProtected->isChecked() ) + style->addProperty( Style::PNotProtected ); + else + style->removeProperty( Style::PNotProtected ); + } + + if ( m_dlg->bHideAll != m_bHideAll->isChecked() ) + { + if ( m_bHideAll->isChecked() ) + style->addProperty( Style::PHideAll ); + else + style->removeProperty( Style::PHideAll ); + } + + if ( m_dlg->bHideFormula != m_bHideFormula->isChecked() ) + { + if ( m_bHideFormula->isChecked() ) + style->addProperty( Style::PHideFormula ); + else + style->removeProperty( Style::PHideFormula ); + } +} + +void CellFormatPageProtection::apply(FormatManipulator* _obj) +{ + if ( m_dlg->bDontPrintText != m_bDontPrint->isChecked()) + _obj->setDontPrintText( m_bDontPrint->isChecked() ); + + if ( m_dlg->bIsProtected != m_bIsProtected->isChecked()) + _obj->setNotProtected( !m_bIsProtected->isChecked() ); + + if ( m_dlg->bHideAll != m_bHideAll->isChecked()) + _obj->setHideAll( m_bHideAll->isChecked() ); + + if ( m_dlg->bHideFormula != m_bHideFormula->isChecked()) + _obj->setHideFormula( m_bHideFormula->isChecked() ); +} + + + +/*************************************************************************** + * + * CellFormatPageFont + * + ***************************************************************************/ + +CellFormatPageFont::CellFormatPageFont( TQWidget* parent, CellFormatDialog *_dlg ) : FontTab( parent ) +{ + dlg = _dlg; + + bTextColorUndefined = !dlg->bTextColor; + + connect( textColorButton, TQT_SIGNAL( changed( const TQColor & ) ), + this, TQT_SLOT( slotSetTextColor( const TQColor & ) ) ); + + + TQStringList tmpListFont; + TQFontDatabase *fontDataBase = new TQFontDatabase(); + tmpListFont = fontDataBase->families(); + delete fontDataBase; + + family_combo->insertStringList( tmpListFont); + selFont = dlg->textFont; + + if ( dlg->bTextFontFamily ) + { + selFont.setFamily( dlg->textFontFamily ); + kdDebug(36001) << "Family = " << dlg->textFontFamily << endl; + + if ( !family_combo->findItem(dlg->textFontFamily)) + { + family_combo->insertItem("",0); + family_combo->setCurrentItem(0); + } + else + family_combo->setCurrentItem(family_combo->index(family_combo->findItem(dlg->textFontFamily))); + } + else + { + family_combo->insertItem("",0); + family_combo->setCurrentItem(0); + } + + connect( family_combo, TQT_SIGNAL(highlighted(const TQString &)), + TQT_SLOT(family_chosen_slot(const TQString &)) ); + + TQStringList lst; + lst.append(""); + for ( unsigned int i = 1; i < 100; ++i ) + lst.append( TQString( "%1" ).arg( i ) ); + + size_combo->insertStringList( lst ); + + + size_combo->setInsertionPolicy(TQComboBox::NoInsertion); + + connect( size_combo, TQT_SIGNAL(activated(const TQString &)), + TQT_SLOT(size_chosen_slot(const TQString &)) ); + connect( size_combo ,TQT_SIGNAL( textChanged(const TQString &)), + this,TQT_SLOT(size_chosen_slot(const TQString &))); + + connect( weight_combo, TQT_SIGNAL(activated(const TQString &)), + TQT_SLOT(weight_chosen_slot(const TQString &)) ); + + connect( style_combo, TQT_SIGNAL(activated(const TQString &)), + TQT_SLOT(style_chosen_slot(const TQString &)) ); + + strike->setChecked(dlg->strike); + connect( strike, TQT_SIGNAL( clicked()), + TQT_SLOT(strike_chosen_slot()) ); + + underline->setChecked(dlg->underline); + connect( underline, TQT_SIGNAL( clicked()), + TQT_SLOT(underline_chosen_slot()) ); + + example_label->setText(i18n("Dolor Ipse")); + + connect(this,TQT_SIGNAL(fontSelected( const TQFont& )), + this,TQT_SLOT(display_example( const TQFont&))); + + setCombos(); + display_example( selFont ); + fontChanged=false; + this->resize( 400, 400 ); +} + +void CellFormatPageFont::slotSetTextColor( const TQColor &_color ) +{ + textColor = _color; + bTextColorUndefined = false; +} + +void CellFormatPageFont::apply( CustomStyle * style ) +{ + if ( !bTextColorUndefined && textColor != dlg->textColor ) + style->changeTextColor( textColor ); + + if ( ( size_combo->currentItem() != 0 ) + && ( dlg->textFontSize != selFont.pointSize() ) ) + style->changeFontSize( selFont.pointSize() ); + + if ( ( selFont.family() != dlg->textFontFamily ) + && !family_combo->currentText().isEmpty() ) + style->changeFontFamily( selFont.family() ); + + uint flags = 0; + + if ( weight_combo->currentItem() != 0 && selFont.bold() ) + flags |= Style::FBold; + else + flags &= ~(uint) Style::FBold; + + if ( style_combo->currentItem() != 0 && selFont.italic() ) + flags |= Style::FItalic; + else + flags &= ~(uint) Style::FItalic; + + if ( strike->isChecked() ) + flags |= Style::FStrike; + else + flags &= ~(uint) Style::FStrike; + + if ( underline->isChecked() ) + flags |= Style::FUnderline; + else + flags &= ~(uint) Style::FUnderline; + + style->changeFontFlags( flags ); +} + +void CellFormatPageFont::apply(FormatManipulator* _obj) +{ + if ( !bTextColorUndefined && textColor != dlg->textColor ) + _obj->setTextColor( textColor ); + if (fontChanged) + { + if ( ( size_combo->currentItem() != 0 ) + && ( dlg->textFontSize != selFont.pointSize() ) ) + _obj->setFontSize( selFont.pointSize() ); + if ( ( selFont.family() != dlg->textFontFamily ) && ( !family_combo->currentText().isEmpty() ) ) + _obj->setFontFamily( selFont.family() ); + if ( weight_combo->currentItem() != 0 ) + _obj->setFontBold( selFont.bold() ); + if ( style_combo->currentItem() != 0 ) + _obj->setFontItalic( selFont.italic() ); + _obj->setFontStrike( strike->isChecked() ); + _obj->setFontUnderline(underline->isChecked() ); + } +} + +void CellFormatPageFont::underline_chosen_slot() +{ + selFont.setUnderline( underline->isChecked() ); + emit fontSelected(selFont); +} + +void CellFormatPageFont::strike_chosen_slot() +{ + selFont.setStrikeOut( strike->isChecked() ); + emit fontSelected(selFont); +} + +void CellFormatPageFont::family_chosen_slot(const TQString & family) +{ + selFont.setFamily(family); + emit fontSelected(selFont); +} + +void CellFormatPageFont::size_chosen_slot(const TQString & size) +{ + TQString size_string = size; + + selFont.setPointSize(size_string.toInt()); + emit fontSelected(selFont); +} + +void CellFormatPageFont::weight_chosen_slot(const TQString & weight) +{ + TQString weight_string = weight; + + if ( weight_string == i18n("Normal")) + selFont.setBold(false); + if ( weight_string == i18n("Bold")) + selFont.setBold(true); + emit fontSelected(selFont); +} + +void CellFormatPageFont::style_chosen_slot(const TQString & style) +{ + TQString style_string = style; + + if ( style_string == i18n("Roman")) + selFont.setItalic(false); + if ( style_string == i18n("Italic")) + selFont.setItalic(true); + emit fontSelected(selFont); +} + + +void CellFormatPageFont::display_example(const TQFont& font) +{ + TQString string; + fontChanged=true; + example_label->setFont(font); + example_label->repaint(); +} + +void CellFormatPageFont::setCombos() +{ + TQString string; + TQComboBox* combo; + int number_of_entries; + bool found; + + if ( dlg->bTextColor ) + textColor = dlg->textColor; + else + textColor = colorGroup().text(); + + if ( !textColor.isValid() ) + textColor =colorGroup().text(); + + textColorButton->setColor( textColor ); + + + combo = size_combo; + if ( dlg->bTextFontSize ) + { + kdDebug(36001) << "SIZE=" << dlg->textFontSize << endl; + selFont.setPointSize( dlg->textFontSize ); + number_of_entries = size_combo->count(); + string.setNum( dlg->textFontSize ); + found = false; + + for (int i = 0; i < number_of_entries ; i++){ + if ( string == (TQString) combo->text(i)){ + combo->setCurrentItem(i); + found = true; + // kdDebug(36001) << "Found Size " << string.data() << " setting to item " i << endl; + break; + } + } + } + else + combo->setCurrentItem( 0 ); + + if ( !dlg->bTextFontBold ) + weight_combo->setCurrentItem(0); + else if ( dlg->textFontBold ) + { + selFont.setBold( dlg->textFontBold ); + weight_combo->setCurrentItem(2); + } + else + { + selFont.setBold( dlg->textFontBold ); + weight_combo->setCurrentItem(1); + } + + if ( !dlg->bTextFontItalic ) + weight_combo->setCurrentItem(0); + else if ( dlg->textFontItalic ) + { + selFont.setItalic( dlg->textFontItalic ); + style_combo->setCurrentItem(2); + } + else + { + selFont.setItalic( dlg->textFontItalic ); + style_combo->setCurrentItem(1); + } +} + + + +/*************************************************************************** + * + * CellFormatPagePosition + * + ***************************************************************************/ + +CellFormatPagePosition::CellFormatPagePosition( TQWidget* parent, CellFormatDialog *_dlg ) + : PositionTab(parent ), + dlg( _dlg ) +{ + if ( dlg->alignX == Format::Left ) + left->setChecked( true ); + else if ( dlg->alignX == Format::Center ) + center->setChecked( true ); + else if ( dlg->alignX == Format::Right ) + right->setChecked( true ); + else if ( dlg->alignX == Format::Undefined ) + standard->setChecked( true ); + + connect(horizontalGroup, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotStateChanged(int))); + + if ( dlg->alignY ==Format::Top ) + top->setChecked( true ); + else if ( dlg->alignY ==Format::Middle ) + middle->setChecked(true ); + else if ( dlg->alignY ==Format::Bottom ) + bottom->setChecked( true ); + + multi->setChecked(dlg->bMultiRow); + + vertical->setChecked(dlg->bVerticalText); + + angleRotation->setValue(-dlg->textRotation);//annma + spinBox3->setValue(-dlg->textRotation); + if ( dlg->textRotation != 0 ) + { + multi->setEnabled(false ); + vertical->setEnabled(false); + } + + mergeCell->setChecked(dlg->isMerged); + mergeCell->setEnabled(!dlg->oneCell && ((!dlg->isRowSelected) && (!dlg->isColumnSelected))); + + TQGridLayout *grid2 = new TQGridLayout(indentGroup, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); + grid2->addRowSpacing( 0, indentGroup->fontMetrics().height()/8 ); // groupbox title + m_indent = new KoUnitDoubleSpinBox( indentGroup, 0.0, 400.0, 10.0,dlg->indent,dlg->getDoc()->unit() ); + grid2->addWidget(m_indent, 0, 0); + + width = new KoUnitDoubleSpinBox( m_widthPanel ); + TQGridLayout *gridWidth = new TQGridLayout(m_widthPanel, 1, 1, 0, 0); + gridWidth->addWidget(width, 0, 0); + width->setValue ( dlg->widthSize ); + width->setUnit( dlg->getDoc()->unit() ); + //to ensure, that we don't get rounding problems, we store the displayed value (for later check for changes) + dlg->widthSize = width->value(); + + if ( dlg->isRowSelected ) + width->setEnabled(false); + + defaultWidth->setText(i18n("Default width (%1 %2)").arg(KoUnit::toUserValue(dlg->defaultWidthSize, dlg->getDoc()->unit()), 0, 'f', 2).arg(dlg->getDoc()->unitName())); + if ( dlg->isRowSelected ) + defaultWidth->setEnabled(false); + + height=new KoUnitDoubleSpinBox( m_heightPanel ); + TQGridLayout *gridHeight = new TQGridLayout(m_heightPanel, 1, 1, 0, 0); + gridHeight->addWidget(height, 0, 0); + height->setValue( dlg->heightSize ); + height->setUnit( dlg->getDoc()->unit() ); + //to ensure, that we don't get rounding problems, we store the displayed value (for later check for changes) + dlg->heightSize = height->value(); + + if ( dlg->isColumnSelected ) + height->setEnabled(false); + + defaultHeight->setText(i18n("Default height (%1 %2)").arg(KoUnit::toUserValue(dlg->defaultHeightSize, dlg->getDoc()->unit()), 0, 'f', 2).arg(dlg->getDoc()->unitName())); //annma + if ( dlg->isColumnSelected ) + defaultHeight->setEnabled(false); + + // in case we're editing a style, we disable the cell size settings + if (dlg->getStyle()) + { + defaultHeight->setEnabled(false); + defaultWidth->setEnabled(false); + } + + connect(defaultWidth , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeWidthState())); + connect(defaultHeight , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeHeightState())); + connect(vertical , TQT_SIGNAL(clicked() ),this, TQT_SLOT(slotChangeVerticalState())); + connect(multi , TQT_SIGNAL(clicked() ), this, TQT_SLOT(slotChangeMultiState())); + connect(angleRotation, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotChangeAngle(int))); + + slotStateChanged( 0 ); + m_bOptionText = false; + this->resize( 400, 400 ); +} + +void CellFormatPagePosition::slotChangeMultiState() +{ + m_bOptionText = true; + if (vertical->isChecked()) + { + vertical->setChecked(false); + } +} + +void CellFormatPagePosition::slotChangeVerticalState() +{ + m_bOptionText=true; + if (multi->isChecked()) + { + multi->setChecked(false); + } + +} + +void CellFormatPagePosition::slotStateChanged(int) +{ + if (right->isChecked() || center->isChecked()) + m_indent->setEnabled(false); + else + m_indent->setEnabled(true); +} + +bool CellFormatPagePosition::getMergedCellState() const +{ + return mergeCell->isChecked(); +} + +void CellFormatPagePosition::slotChangeWidthState() +{ + if ( defaultWidth->isChecked()) + width->setEnabled(false); + else + width->setEnabled(true); +} + +void CellFormatPagePosition::slotChangeHeightState() +{ + if ( defaultHeight->isChecked()) + height->setEnabled(false); + else + height->setEnabled(true); +} + +void CellFormatPagePosition::slotChangeAngle(int _angle) +{ + if ( _angle == 0 ) + { + multi->setEnabled( true ); + vertical->setEnabled( true ); + } + else + { + multi->setEnabled( false ); + vertical->setEnabled( false ); + } +} + +void CellFormatPagePosition::apply( CustomStyle * style ) +{ + if ( top->isChecked() && dlg->alignY != Format::Top ) + style->changeAlignY( Format::Top ); + else if ( bottom->isChecked() && dlg->alignY != Format::Bottom ) + style->changeAlignY( Format::Bottom ); + else if ( middle->isChecked() && dlg->alignY != Format::Middle ) + style->changeAlignY( Format::Middle ); + + if ( left->isChecked() && dlg->alignX != Format::Left ) + style->changeAlignX( Format::Left ); + else if ( right->isChecked() && dlg->alignX != Format::Right ) + style->changeAlignX( Format::Right ); + else if ( center->isChecked() && dlg->alignX != Format::Center ) + style->changeAlignX( Format::Center ); + else if ( standard->isChecked() && dlg->alignX != Format::Undefined ) + style->changeAlignX( Format::Undefined ); + + if ( m_bOptionText ) + { + if ( multi->isEnabled() ) + { + if ( multi->isChecked() ) + style->addProperty( Style::PMultiRow ); + else + style->removeProperty( Style::PMultiRow ); + } + } + + if ( m_bOptionText ) + { + if ( vertical->isEnabled() ) + { + if ( vertical->isChecked() ) + style->addProperty( Style::PVerticalText ); + else + style->removeProperty( Style::PVerticalText ); + } + } + + if ( dlg->textRotation != angleRotation->value() ) + style->changeRotateAngle( (-angleRotation->value()) ); + + if ( m_indent->isEnabled() + && dlg->indent != m_indent->value() ) + style->changeIndent( m_indent->value() ); + + // setting the default column width and row height + if ( dlg->getStyle()->type() == Style::BUILTIN && dlg->getStyle()->name() == "Default" ) + { + if ( (int) height->value() != (int) dlg->heightSize ) + { + Format::setGlobalRowHeight( height->value() ); + } + if ( (int) width->value() != (int) dlg->widthSize ) + { + Format::setGlobalColWidth( width->value() ); + } + } +} + +void CellFormatPagePosition::apply(FormatManipulator* _obj) +{ + Format::Align ax; + Format::AlignY ay; + + if ( top->isChecked() ) + ay = Format::Top; + else if ( bottom->isChecked() ) + ay = Format::Bottom; + else if ( middle->isChecked() ) + ay = Format::Middle; + else + ay = Format::Middle; // Default, just in case + + if ( left->isChecked() ) + ax = Format::Left; + else if ( right->isChecked() ) + ax = Format::Right; + else if ( center->isChecked() ) + ax = Format::Center; + else if ( standard->isChecked() ) + ax = Format::Undefined; + else + ax = Format::Undefined; //Default, just in case + + if ( top->isChecked() && ay != dlg->alignY ) + _obj->setVerticalAlignment( Format::Top ); + else if ( bottom->isChecked() && ay != dlg->alignY ) + _obj->setVerticalAlignment( Format::Bottom ); + else if ( middle->isChecked() && ay != dlg->alignY ) + _obj->setVerticalAlignment( Format::Middle ); + + if ( left->isChecked() && ax != dlg->alignX ) + _obj->setHorizontalAlignment( Format::Left ); + else if ( right->isChecked() && ax != dlg->alignX ) + _obj->setHorizontalAlignment( Format::Right ); + else if ( center->isChecked() && ax != dlg->alignX ) + _obj->setHorizontalAlignment( Format::Center ); + else if ( standard->isChecked() && ax != dlg->alignX ) + _obj->setHorizontalAlignment( Format::Undefined ); + + if ( m_bOptionText ) + { + if ( multi->isEnabled() ) + _obj->setMultiRow( multi->isChecked() ); + else + _obj->setMultiRow( false ); + } + + if ( m_bOptionText ) + { + if ( vertical->isEnabled() ) + _obj->setVerticalText( vertical->isChecked() ); + else + _obj->setVerticalText( false ); + } + + if ( dlg->textRotation!=angleRotation->value() ) + _obj->setAngle( (-angleRotation->value() ) ); + if ( m_indent->isEnabled() + && dlg->indent != m_indent->value() ) + _obj->setIndent( m_indent->value() ); +} + +double CellFormatPagePosition::getSizeHeight() const +{ + if ( defaultHeight->isChecked() ) + return dlg->defaultHeightSize; // guess who calls this! + else + return height->value(); +} + +double CellFormatPagePosition::getSizeWidth() const +{ + if ( defaultWidth->isChecked() ) + return dlg->defaultWidthSize; // guess who calls this! + else + return width->value(); +} + + + +/*************************************************************************** + * + * BorderButton + * + ***************************************************************************/ + +BorderButton::BorderButton( TQWidget *parent, const char *_name ) : TQPushButton(parent,_name) +{ + penStyle = Qt::NoPen; + penWidth = 1; + penColor = colorGroup().text(); + setToggleButton( true ); + setOn( false); + setChanged(false); +} +void BorderButton::mousePressEvent( TQMouseEvent * ) +{ + + this->setOn(!isOn()); + emit clicked( this ); +} + +void BorderButton::setUndefined() +{ + setPenStyle(Qt::SolidLine ); + setPenWidth(1); + setColor(colorGroup().midlight()); +} + + +void BorderButton::unselect() +{ + setOn(false); + setPenWidth(1); + setPenStyle(Qt::NoPen); + setColor( colorGroup().text() ); + setChanged(true); +} + + + +/*************************************************************************** + * + * Border + * + ***************************************************************************/ + +Border::Border( TQWidget *parent, const char *_name,bool _oneCol, bool _oneRow ) + : TQFrame( parent, _name ) +{ + oneCol=_oneCol; + oneRow=_oneRow; +} + + +#define OFFSETX 5 +#define OFFSETY 5 +void Border::paintEvent( TQPaintEvent *_ev ) +{ + TQFrame::paintEvent( _ev ); + TQPen pen; + TQPainter painter; + painter.begin( this ); + pen=TQPen( colorGroup().midlight(),2,SolidLine); + painter.setPen( pen ); + + painter.drawLine( OFFSETX-5, OFFSETY, OFFSETX , OFFSETY ); + painter.drawLine( OFFSETX, OFFSETY-5, OFFSETX , OFFSETY ); + painter.drawLine( width()-OFFSETX, OFFSETY, width() , OFFSETY ); + painter.drawLine( width()-OFFSETX, OFFSETY-5, width()-OFFSETX , OFFSETY ); + + painter.drawLine( OFFSETX, height()-OFFSETY, OFFSETX , height() ); + painter.drawLine( OFFSETX-5, height()-OFFSETY, OFFSETX , height()-OFFSETY ); + + painter.drawLine( width()-OFFSETX, height()-OFFSETY, width() , height()-OFFSETY ); + painter.drawLine( width()-OFFSETX, height()-OFFSETY, width()-OFFSETX , height() ); + if (oneCol==false) + { + painter.drawLine( width()/2, OFFSETY-5, width()/2 , OFFSETY ); + painter.drawLine( width()/2-5, OFFSETY, width()/2+5 , OFFSETY ); + painter.drawLine( width()/2, height()-OFFSETY, width()/2 , height() ); + painter.drawLine( width()/2-5, height()-OFFSETY, width()/2+5 , height()-OFFSETY ); + } + if (oneRow==false) + { + painter.drawLine( OFFSETX-5, height()/2, OFFSETX , height()/2 ); + painter.drawLine( OFFSETX, height()/2-5, OFFSETX , height()/2+5 ); + painter.drawLine( width()-OFFSETX, height()/2, width(), height()/2 ); + painter.drawLine( width()-OFFSETX, height()/2-5, width()-OFFSETX , height()/2+5 ); + } + painter.end(); + emit redraw(); +} + +void Border::mousePressEvent( TQMouseEvent* _ev ) +{ + emit choosearea(_ev); +} + + + +/*************************************************************************** + * + * CellFormatPageBorder + * + ***************************************************************************/ + +CellFormatPageBorder::CellFormatPageBorder( TQWidget* parent, CellFormatDialog *_dlg ) + : TQWidget( parent ), + dlg( _dlg ) +{ + sheet = dlg->getSheet(); + + InitializeGrids(); + InitializeBorderButtons(); + InitializePatterns(); + SetConnections(); + + preview->slotSelect(); + pattern[2]->slotSelect(); + + style->setEnabled(false); + size->setEnabled(false); + preview->setPattern( black , 1, Qt::SolidLine ); + this->resize( 400, 400 ); +} + +void CellFormatPageBorder::InitializeGrids() +{ + TQGridLayout *grid = new TQGridLayout(this,5,2,KDialog::marginHint(), KDialog::spacingHint()); + TQGridLayout *grid2 = NULL; + TQGroupBox* tmpTQGroupBox = NULL; + + /***********************/ + /* here is the data to initialize all the border buttons with */ + const char borderButtonNames[BorderType_END][20] = + {"top", "bottom", "left", "right", "vertical", "fall", "go", "horizontal"}; + + const char shortcutButtonNames[BorderShortcutType_END][20] = + {"remove", "all", "outline"}; + + TQString borderButtonIconNames[BorderType_END] = + {"border_top", "border_bottom", "border_left", "border_right", + "border_vertical", "border_horizontal", "border_fall", "border_up"}; + + TQString shortcutButtonIconNames[BorderShortcutType_END] = + { "border_remove", "", "border_outline"}; + + int borderButtonPositions[BorderType_END][2] = + {{0,2}, {4,2}, {2,0}, {2,4}, {4,4}, {4,0}, {0,0}, {0,4}}; + + int shortcutButtonPositions[BorderShortcutType_END][2] = + { {0,0}, {0,1},{0,2} }; + /***********************/ + + /* set up a layout box for most of the border setting buttons */ + tmpTQGroupBox = new TQGroupBox( this, "GroupBox_1" ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setTitle( i18n("Border") ); + tmpTQGroupBox->setAlignment( AlignLeft ); + grid2 = new TQGridLayout(tmpTQGroupBox,6,5,KDialog::marginHint(), KDialog::spacingHint()); + int fHeight = tmpTQGroupBox->fontMetrics().height(); + grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title + + area=new Border(tmpTQGroupBox,"area",dlg->oneCol,dlg->oneRow); + grid2->addMultiCellWidget(area,2,4,1,3); + area->setBackgroundColor( colorGroup().base() ); + + /* initailize the buttons that are in this box */ + for (int i=BorderType_Top; i < BorderType_END; i++) + { + borderButtons[i] = new BorderButton(tmpTQGroupBox, + borderButtonNames[i]); + loadIcon(borderButtonIconNames[i], borderButtons[i]); + grid2->addWidget(borderButtons[i], borderButtonPositions[i][0] + 1, + borderButtonPositions[i][1]); + } + + grid->addMultiCellWidget(tmpTQGroupBox,0,2,0,0); + + /* the remove, all, and outline border buttons are in a second box down + below.*/ + + tmpTQGroupBox = new TQGroupBox( this, "GroupBox_3" ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setTitle( i18n("Preselect") ); + tmpTQGroupBox->setAlignment( AlignLeft ); + + grid2 = new TQGridLayout(tmpTQGroupBox,1,3,KDialog::marginHint(), KDialog::spacingHint()); + + /* the "all" button is different depending on what kind of region is currently + selected */ + if ((dlg->oneRow==true)&&(dlg->oneCol==false)) + { + shortcutButtonIconNames[BorderShortcutType_All] = "border_vertical"; + } + else if ((dlg->oneRow==false)&&(dlg->oneCol==true)) + { + shortcutButtonIconNames[BorderShortcutType_All] = "border_horizontal"; + } + else + { + shortcutButtonIconNames[BorderShortcutType_All] = "border_inside"; + } + + for (int i=BorderShortcutType_Remove; i < BorderShortcutType_END; i++) + { + shortcutButtons[i] = new BorderButton(tmpTQGroupBox, + shortcutButtonNames[i]); + loadIcon(shortcutButtonIconNames[i], shortcutButtons[i]); + grid2->addWidget(shortcutButtons[i], shortcutButtonPositions[i][0], + shortcutButtonPositions[i][1]); + } + + if (dlg->oneRow && dlg->oneCol) + { + shortcutButtons[BorderShortcutType_All]->setEnabled(false); + } + + grid->addMultiCellWidget(tmpTQGroupBox,3,4,0,0); + + /* now set up the group box with the pattern selector */ + tmpTQGroupBox = new TQGroupBox( this, "GroupBox_10" ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setTitle( i18n("Pattern") ); + tmpTQGroupBox->setAlignment( AlignLeft ); + + grid2 = new TQGridLayout(tmpTQGroupBox,7,2,KDialog::marginHint(), KDialog::spacingHint()); + fHeight = tmpTQGroupBox->fontMetrics().height(); + grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title + + char name[] = "PatternXX"; + Q_ASSERT(NUM_BORDER_PATTERNS < 100); + + for (int i=0; i < NUM_BORDER_PATTERNS; i++) + { + name[7] = '0' + (i+1) / 10; + name[8] = '0' + (i+1) % 10; + pattern[i] = new PatternSelect( tmpTQGroupBox, name ); + pattern[i]->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(pattern[i], i % 5 + 1, i / 5); + /* this puts them in the pattern: + 1 6 + 2 7 + 3 8 + 4 9 + 5 10 + */ + } + + color = new KColorButton (tmpTQGroupBox, "PushButton_1" ); + grid2->addWidget(color,7,1); + + TQLabel *tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_6" ); + tmpTQLabel->setText( i18n("Color:") ); + grid2->addWidget(tmpTQLabel,7,0); + + /* tack on the 'customize' border pattern selector */ + TQGridLayout *grid3 = new TQGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint() ); + customize = new TQCheckBox(i18n("Customize"),tmpTQGroupBox); + grid3->addWidget(customize,0,0); + connect( customize, TQT_SIGNAL( clicked()), TQT_SLOT(cutomize_chosen_slot()) ); + + size=new TQComboBox(true,tmpTQGroupBox); + grid3->addWidget(size,1,1); + size->setValidator(new KIntValidator( size )); + TQString tmp; + for ( int i=0;i<10;i++) + { + tmp=tmp.setNum(i); + size->insertItem(tmp); + } + size->setCurrentItem(1); + + style=new TQComboBox(tmpTQGroupBox); + grid3->addWidget(style,1,0); + style->insertItem(paintFormatPixmap(DotLine),0 ); + style->insertItem(paintFormatPixmap(DashLine) ,1); + style->insertItem(paintFormatPixmap(DashDotLine),2 ); + style->insertItem(paintFormatPixmap(DashDotDotLine),3 ); + style->insertItem(paintFormatPixmap(SolidLine),4); + style->setBackgroundColor( colorGroup().background() ); + + grid2->addMultiCell(grid3,6,6,0,1); + grid->addMultiCellWidget(tmpTQGroupBox,0,3,1,1); + + /* Now the preview box is put together */ + tmpTQGroupBox = new TQGroupBox(this, "GroupBox_4" ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setTitle( i18n("Preview") ); + tmpTQGroupBox->setAlignment( AlignLeft ); + + grid2 = new TQGridLayout(tmpTQGroupBox,1,1,KDialog::marginHint(), KDialog::spacingHint()); + fHeight = tmpTQGroupBox->fontMetrics().height(); + grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title + + preview = new PatternSelect( tmpTQGroupBox, "Pattern_preview" ); + preview->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(preview,1,0); + + grid->addWidget(tmpTQGroupBox,4,1); +} + +void CellFormatPageBorder::InitializeBorderButtons() +{ + for (int i=BorderType_Top; i < BorderType_END; i++) + { + if (dlg->borders[i].style != TQt::NoPen || + !dlg->borders[i].bStyle ) + { + /* the horozontil and vertical buttons might be disabled depending on what + kind of area is selected so check that first. */ + if ((dlg->oneRow == true && i == BorderType_Horizontal) || + (dlg->oneCol == true && i == BorderType_Vertical)) + { + borderButtons[i]->setEnabled(false); + } + else if ( dlg->borders[i].bColor && dlg->borders[i].bStyle ) + { + borderButtons[i]->setPenStyle(dlg->borders[i].style ); + borderButtons[i]->setPenWidth(dlg->borders[i].width); + borderButtons[i]->setColor(dlg->borders[i].color); + borderButtons[i]->setOn(true); + } + else + { + borderButtons[i]->setUndefined(); + } + } + } + + +} + +void CellFormatPageBorder::InitializePatterns() +{ + pattern[0]->setPattern( black, 1, Qt::DotLine ); + pattern[1]->setPattern( black, 1, Qt::DashLine ); + pattern[2]->setPattern( black, 1, Qt::SolidLine ); + pattern[3]->setPattern( black, 1, Qt::DashDotLine ); + pattern[4]->setPattern( black, 1, Qt::DashDotDotLine ); + pattern[5]->setPattern( black, 2, Qt::SolidLine ); + pattern[6]->setPattern( black, 3, Qt::SolidLine ); + pattern[7]->setPattern( black, 4, Qt::SolidLine ); + pattern[8]->setPattern( black, 5, Qt::SolidLine ); + pattern[9]->setPattern( black, 1, Qt::NoPen ); + + slotSetColorButton( black ); +} + +void CellFormatPageBorder::SetConnections() +{ + connect( color, TQT_SIGNAL( changed( const TQColor & ) ), + this, TQT_SLOT( slotSetColorButton( const TQColor & ) ) ); + + for (int i=0; i < NUM_BORDER_PATTERNS; i++) + { + connect( pattern[i], TQT_SIGNAL( clicked( PatternSelect* ) ), + this, TQT_SLOT( slotUnselect2( PatternSelect* ) ) ); + } + + for (int i = BorderType_Top; i < BorderType_END; i++) + { + connect( borderButtons[i], TQT_SIGNAL( clicked (BorderButton *) ), + this, TQT_SLOT( changeState( BorderButton *) ) ); + } + + for (int i = BorderShortcutType_Remove; i < BorderShortcutType_END; i++) + { + connect( shortcutButtons[i], TQT_SIGNAL( clicked(BorderButton *) ), + this, TQT_SLOT( preselect(BorderButton *) ) ); + } + + connect( area ,TQT_SIGNAL( redraw()),this,TQT_SLOT(draw())); + connect( area ,TQT_SIGNAL( choosearea(TQMouseEvent * )), + this,TQT_SLOT( slotPressEvent(TQMouseEvent *))); + + connect( style, TQT_SIGNAL( activated(int)), this, TQT_SLOT(slotChangeStyle(int))); + connect( size, TQT_SIGNAL( textChanged(const TQString &)), + this, TQT_SLOT(slotChangeStyle(const TQString &))); + connect( size ,TQT_SIGNAL( activated(int)), this, TQT_SLOT(slotChangeStyle(int))); +} + +void CellFormatPageBorder::cutomize_chosen_slot() +{ + if ( customize->isChecked() ) + { + style->setEnabled( true ); + size->setEnabled( true ); + slotUnselect2( preview ); + } + else + { + style->setEnabled( false ); + size->setEnabled( false ); + pattern[2]->slotSelect(); + preview->setPattern( black , 1, Qt::SolidLine ); + } +} + +void CellFormatPageBorder::slotChangeStyle(const TQString &) +{ + /* if they try putting text in the size box, then erase the line */ + slotChangeStyle(0); +} + +void CellFormatPageBorder::slotChangeStyle(int) +{ + int index = style->currentItem(); + TQString tmp; + int penSize = size->currentText().toInt(); + if ( !penSize) + { + preview->setPattern( preview->getColor(), penSize, Qt::NoPen ); + } + else + { + switch(index) + { + case 0: + preview->setPattern( preview->getColor(), penSize, Qt::DotLine ); + break; + case 1: + preview->setPattern( preview->getColor(), penSize, Qt::DashLine ); + break; + case 2: + preview->setPattern( preview->getColor(), penSize, Qt::DashDotLine ); + break; + case 3: + preview->setPattern( preview->getColor(), penSize, Qt::DashDotDotLine ); + break; + case 4: + preview->setPattern( preview->getColor(), penSize, Qt::SolidLine ); + break; + default: + kdDebug(36001)<<"Error in combobox\n"; + break; + } + } + slotUnselect2(preview); +} + +TQPixmap CellFormatPageBorder::paintFormatPixmap(PenStyle _style) +{ + TQPixmap pixmap( style->width(), 14 ); + TQPainter painter; + TQPen pen; + pen=TQPen( colorGroup().text(),1,_style); + painter.begin( &pixmap ); + painter.fillRect( 0, 0, style->width(), 14, colorGroup().background() ); + painter.setPen( pen ); + painter.drawLine( 0, 7, style->width(), 7 ); + painter.end(); + return pixmap; +} + +void CellFormatPageBorder::loadIcon( TQString _pix, BorderButton *_button) +{ + _button->setPixmap( TQPixmap( BarIcon(_pix, Factory::global()) ) ); +} + +void CellFormatPageBorder::apply(FormatManipulator* obj) +{ + if (borderButtons[BorderType_Horizontal]->isChanged()) + applyHorizontalOutline(obj); + + if (borderButtons[BorderType_Vertical]->isChanged()) + applyVerticalOutline(obj); + + if ( borderButtons[BorderType_Left]->isChanged() ) + applyLeftOutline(obj); + + if ( borderButtons[BorderType_Right]->isChanged() ) + applyRightOutline(obj); + + if ( borderButtons[BorderType_Top]->isChanged() ) + applyTopOutline(obj); + + if ( borderButtons[BorderType_Bottom]->isChanged() ) + applyBottomOutline(obj); + + if ( borderButtons[BorderType_RisingDiagonal]->isChanged() || + borderButtons[BorderType_FallingDiagonal]->isChanged() ) + applyDiagonalOutline(obj); +} + +void CellFormatPageBorder::applyTopOutline(FormatManipulator* obj) +{ + BorderButton * top = borderButtons[BorderType_Top]; + + TQPen tmpPen( top->getColor(), top->getPenWidth(), top->getPenStyle()); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeTopBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Top]->isChanged()) + obj->setTopBorderPen( tmpPen ); + } +} + +void CellFormatPageBorder::applyBottomOutline(FormatManipulator* obj) +{ + BorderButton * bottom = borderButtons[BorderType_Bottom]; + + TQPen tmpPen( bottom->getColor(), bottom->getPenWidth(), bottom->getPenStyle() ); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeBottomBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Bottom]->isChanged()) + obj->setBottomBorderPen( tmpPen ); + } +} + +void CellFormatPageBorder::applyLeftOutline(FormatManipulator* obj) +{ + BorderButton * left = borderButtons[BorderType_Left]; + TQPen tmpPen( left->getColor(), left->getPenWidth(), left->getPenStyle() ); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeLeftBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Left]->isChanged()) + obj->setLeftBorderPen( tmpPen ); + } +} + +void CellFormatPageBorder::applyRightOutline(FormatManipulator* obj) +{ + BorderButton* right = borderButtons[BorderType_Right]; + TQPen tmpPen( right->getColor(), right->getPenWidth(), right->getPenStyle() ); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeRightBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Right]->isChanged()) + obj->setRightBorderPen( tmpPen ); + } +} + +void CellFormatPageBorder::applyDiagonalOutline(FormatManipulator* obj) +{ + BorderButton * fallDiagonal = borderButtons[BorderType_FallingDiagonal]; + BorderButton * goUpDiagonal = borderButtons[BorderType_RisingDiagonal]; + TQPen tmpPenFall( fallDiagonal->getColor(), fallDiagonal->getPenWidth(), + fallDiagonal->getPenStyle()); + TQPen tmpPenGoUp( goUpDiagonal->getColor(), goUpDiagonal->getPenWidth(), + goUpDiagonal->getPenStyle()); + + if ( dlg->getStyle() ) + { + if ( fallDiagonal->isChanged() ) + dlg->getStyle()->changeFallBorderPen( tmpPenFall ); + if ( goUpDiagonal->isChanged() ) + dlg->getStyle()->changeGoUpBorderPen( tmpPenGoUp ); + } + else + { + if ( fallDiagonal->isChanged() ) + obj->setFallDiagonalPen( tmpPenFall ); + if ( goUpDiagonal->isChanged() ) + obj->setGoUpDiagonalPen( tmpPenGoUp ); + } +} + +void CellFormatPageBorder::applyHorizontalOutline(FormatManipulator* obj) +{ + TQPen tmpPen( borderButtons[BorderType_Horizontal]->getColor(), + borderButtons[BorderType_Horizontal]->getPenWidth(), + borderButtons[BorderType_Horizontal]->getPenStyle()); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeTopBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Horizontal]->isChanged()) + obj->setHorizontalPen( tmpPen ); + } +} + +void CellFormatPageBorder::applyVerticalOutline(FormatManipulator* obj) +{ + BorderButton* vertical = borderButtons[BorderType_Vertical]; + TQPen tmpPen( vertical->getColor(), vertical->getPenWidth(), + vertical->getPenStyle()); + + if ( dlg->getStyle() ) + { + dlg->getStyle()->changeLeftBorderPen( tmpPen ); + } + else + { + if (borderButtons[BorderType_Vertical]->isChanged()) + obj->setVerticalPen( tmpPen ); + } +} + + +void CellFormatPageBorder::slotSetColorButton( const TQColor &_color ) +{ + currentColor = _color; + + for ( int i = 0; i < NUM_BORDER_PATTERNS; ++i ) + { + pattern[i]->setColor( currentColor ); + } + preview->setColor( currentColor ); +} + +void CellFormatPageBorder::slotUnselect2( PatternSelect *_p ) +{ + for ( int i = 0; i < NUM_BORDER_PATTERNS; ++i ) + { + if ( pattern[i] != _p ) + { + pattern[i]->slotUnselect(); + } + } + preview->setPattern( _p->getColor(), _p->getPenWidth(), _p->getPenStyle() ); +} + +void CellFormatPageBorder::preselect( BorderButton *_p ) +{ + BorderButton* top = borderButtons[BorderType_Top]; + BorderButton* bottom = borderButtons[BorderType_Bottom]; + BorderButton* left = borderButtons[BorderType_Left]; + BorderButton* right = borderButtons[BorderType_Right]; + BorderButton* vertical = borderButtons[BorderType_Vertical]; + BorderButton* horizontal = borderButtons[BorderType_Horizontal]; + BorderButton* remove = shortcutButtons[BorderShortcutType_Remove]; + BorderButton* outline = shortcutButtons[BorderShortcutType_Outline]; + BorderButton* all = shortcutButtons[BorderShortcutType_All]; + + _p->setOn(false); + if (_p == remove) + { + for (int i=BorderType_Top; i < BorderType_END; i++) + { + if (borderButtons[i]->isOn()) + { + borderButtons[i]->unselect(); + } + } + } + if (_p==outline) + { + top->setOn(true); + top->setPenWidth(preview->getPenWidth()); + top->setPenStyle(preview->getPenStyle()); + top->setColor( currentColor ); + top->setChanged(true); + bottom->setOn(true); + bottom->setPenWidth(preview->getPenWidth()); + bottom->setPenStyle(preview->getPenStyle()); + bottom->setColor( currentColor ); + bottom->setChanged(true); + left->setOn(true); + left->setPenWidth(preview->getPenWidth()); + left->setPenStyle(preview->getPenStyle()); + left->setColor( currentColor ); + left->setChanged(true); + right->setOn(true); + right->setPenWidth(preview->getPenWidth()); + right->setPenStyle(preview->getPenStyle()); + right->setColor( currentColor ); + right->setChanged(true); + } + if (_p==all) + { + if (dlg->oneRow==false) + { + horizontal->setOn(true); + horizontal->setPenWidth(preview->getPenWidth()); + horizontal->setPenStyle(preview->getPenStyle()); + horizontal->setColor( currentColor ); + horizontal->setChanged(true); + } + if (dlg->oneCol==false) + { + vertical->setOn(true); + vertical->setPenWidth(preview->getPenWidth()); + vertical->setPenStyle(preview->getPenStyle()); + vertical->setColor( currentColor ); + vertical->setChanged(true); + } + } + area->repaint(); +} + +void CellFormatPageBorder::changeState( BorderButton *_p) +{ + _p->setChanged(true); + + if (_p->isOn()) + { + _p->setPenWidth(preview->getPenWidth()); + _p->setPenStyle(preview->getPenStyle()); + _p->setColor( currentColor ); + } + else + { + _p->setPenWidth(1); + _p->setPenStyle(Qt::NoPen); + _p->setColor( colorGroup().text() ); + } + + area->repaint(); +} + +void CellFormatPageBorder::draw() +{ + BorderButton* top = borderButtons[BorderType_Top]; + BorderButton* bottom = borderButtons[BorderType_Bottom]; + BorderButton* left = borderButtons[BorderType_Left]; + BorderButton* right = borderButtons[BorderType_Right]; + BorderButton* risingDiagonal = borderButtons[BorderType_RisingDiagonal]; + BorderButton* fallingDiagonal = borderButtons[BorderType_FallingDiagonal]; + BorderButton* vertical = borderButtons[BorderType_Vertical]; + BorderButton* horizontal = borderButtons[BorderType_Horizontal]; + TQPen pen; + TQPainter painter; + painter.begin( area ); + + if ((bottom->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( bottom->getColor(), bottom->getPenWidth(),bottom->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX, area->height()-OFFSETY, area->width()-OFFSETX , area->height()-OFFSETY ); + } + if ((top->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( top->getColor(), top->getPenWidth(),top->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX, OFFSETY, area->width() -OFFSETX, OFFSETY ); + } + if ((left->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( left->getColor(), left->getPenWidth(),left->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX, OFFSETY, OFFSETX , area->height()-OFFSETY ); + } + if ((right->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( right->getColor(), right->getPenWidth(),right->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( area->width()-OFFSETX, OFFSETY, area->width()-OFFSETX, + area->height()-OFFSETY ); + + } + if ((fallingDiagonal->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( fallingDiagonal->getColor(), fallingDiagonal->getPenWidth(), + fallingDiagonal->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX, OFFSETY, area->width()-OFFSETX, + area->height()-OFFSETY ); + if (dlg->oneCol==false&& dlg->oneRow==false) + { + painter.drawLine( area->width()/2, OFFSETY, area->width()-OFFSETX, + area->height()/2 ); + painter.drawLine( OFFSETX,area->height()/2 , area->width()/2, + area->height()-OFFSETY ); + } + } + if ((risingDiagonal->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( risingDiagonal->getColor(), risingDiagonal->getPenWidth(), + risingDiagonal->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX, area->height()-OFFSETY , area->width()-OFFSETX , + OFFSETY ); + if (dlg->oneCol==false&& dlg->oneRow==false) + { + painter.drawLine( area->width()/2, OFFSETY, OFFSETX, area->height()/2 ); + painter.drawLine( area->width()/2,area->height()-OFFSETY , + area->width()-OFFSETX, area->height()/2 ); + } + + } + if ((vertical->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( vertical->getColor(), vertical->getPenWidth(), + vertical->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( area->width()/2, 5 , area->width()/2 , area->height()-5 ); + } + if ((horizontal->getPenStyle())!=TQt::NoPen) + { + pen=TQPen( horizontal->getColor(), horizontal->getPenWidth(), + horizontal->getPenStyle()); + painter.setPen( pen ); + painter.drawLine( OFFSETX,area->height()/2,area->width()-OFFSETX, + area->height()/2 ); + } + painter.end(); +} + +void CellFormatPageBorder::invertState(BorderButton *_p) +{ + if (_p->isOn()) + { + _p->unselect(); + } + else + { + _p->setOn(true); + _p->setPenWidth(preview->getPenWidth()); + _p->setPenStyle(preview->getPenStyle()); + _p->setColor( currentColor ); + _p->setChanged(true); + } +} + +void CellFormatPageBorder::slotPressEvent(TQMouseEvent *_ev) +{ + BorderButton* top = borderButtons[BorderType_Top]; + BorderButton* bottom = borderButtons[BorderType_Bottom]; + BorderButton* left = borderButtons[BorderType_Left]; + BorderButton* right = borderButtons[BorderType_Right]; + BorderButton* vertical = borderButtons[BorderType_Vertical]; + BorderButton* horizontal = borderButtons[BorderType_Horizontal]; + + + TQRect rect(OFFSETX,OFFSETY-8,area->width()-OFFSETX,OFFSETY+8); + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((top->getPenWidth()!=preview->getPenWidth()) || + (top->getColor()!=currentColor) || + (top->getPenStyle()!=preview->getPenStyle())) + && top->isOn()) + { + top->setPenWidth(preview->getPenWidth()); + top->setPenStyle(preview->getPenStyle()); + top->setColor( currentColor ); + top->setChanged(true); + } + else + invertState(top); + } + rect.setCoords(OFFSETX,area->height()-OFFSETY-8,area->width()-OFFSETX, + area->height()-OFFSETY+8); + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((bottom->getPenWidth()!=preview->getPenWidth()) || + (bottom->getColor()!=currentColor) || + (bottom->getPenStyle()!=preview->getPenStyle())) + && bottom->isOn()) + { + bottom->setPenWidth(preview->getPenWidth()); + bottom->setPenStyle(preview->getPenStyle()); + bottom->setColor( currentColor ); + bottom->setChanged(true); + } + else + invertState(bottom); + } + + rect.setCoords(OFFSETX-8,OFFSETY,OFFSETX+8,area->height()-OFFSETY); + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((left->getPenWidth()!=preview->getPenWidth()) || + (left->getColor()!=currentColor) || + (left->getPenStyle()!=preview->getPenStyle())) + && left->isOn()) + { + left->setPenWidth(preview->getPenWidth()); + left->setPenStyle(preview->getPenStyle()); + left->setColor( currentColor ); + left->setChanged(true); + } + else + invertState(left); + } + rect.setCoords(area->width()-OFFSETX-8,OFFSETY,area->width()-OFFSETX+8, + area->height()-OFFSETY); + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((right->getPenWidth()!=preview->getPenWidth()) || + (right->getColor()!=currentColor) || + (right->getPenStyle()!=preview->getPenStyle())) + && right->isOn()) + { + right->setPenWidth(preview->getPenWidth()); + right->setPenStyle(preview->getPenStyle()); + right->setColor( currentColor ); + right->setChanged(true); + } + else + invertState(right); + } + +//don't work because I don't know how create a rectangle +//for diagonal +/*rect.setCoords(OFFSETX,OFFSETY,XLEN-OFFSETX,YHEI-OFFSETY); +if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + invertState(fallDiagonal); + } +rect.setCoords(OFFSETX,YHEI-OFFSETY,XLEN-OFFSETX,OFFSETY); +if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + invertState(goUpDiagonal); + } */ + + if (dlg->oneCol==false) + { + rect.setCoords(area->width()/2-8,OFFSETY,area->width()/2+8, + area->height()-OFFSETY); + + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((vertical->getPenWidth()!=preview->getPenWidth()) || + (vertical->getColor()!=currentColor) || + (vertical->getPenStyle()!=preview->getPenStyle())) + && vertical->isOn()) + { + vertical->setPenWidth(preview->getPenWidth()); + vertical->setPenStyle(preview->getPenStyle()); + vertical->setColor( currentColor ); + vertical->setChanged(true); + } + else + invertState(vertical); + } + } + if (dlg->oneRow==false) + { + rect.setCoords(OFFSETX,area->height()/2-8,area->width()-OFFSETX, + area->height()/2+8); + if (rect.contains(TQPoint(_ev->x(),_ev->y()))) + { + if (((horizontal->getPenWidth()!=preview->getPenWidth()) || + (horizontal->getColor()!=currentColor) || + (horizontal->getPenStyle()!=preview->getPenStyle())) + && horizontal->isOn()) + { + horizontal->setPenWidth(preview->getPenWidth()); + horizontal->setPenStyle(preview->getPenStyle()); + horizontal->setColor( currentColor ); + horizontal->setChanged(true); + } + else + invertState(horizontal); + } + } + + area->repaint(); +} + + + +/*************************************************************************** + * + * BrushSelect + * + ***************************************************************************/ + +BrushSelect::BrushSelect( TQWidget *parent, const char * ) : TQFrame( parent ) +{ + brushStyle = Qt::NoBrush; + brushColor = TQt::red; + selected = false; +} + +void BrushSelect::setPattern( const TQColor &_color,Qt::BrushStyle _style ) +{ + brushStyle = _style; + brushColor = _color; + repaint(); +} + + +void BrushSelect::paintEvent( TQPaintEvent *_ev ) +{ + TQFrame::paintEvent( _ev ); + + TQPainter painter; + TQBrush brush(brushColor,brushStyle); + painter.begin( this ); + painter.setPen( TQt::NoPen ); + painter.setBrush( brush); + painter.drawRect( 2, 2, width()-4, height()-4); + painter.end(); +} + +void BrushSelect::mousePressEvent( TQMouseEvent * ) +{ + slotSelect(); + + emit clicked( this ); +} + +void BrushSelect::slotUnselect() +{ + selected = false; + + setLineWidth( 1 ); + setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + repaint(); +} + +void BrushSelect::slotSelect() +{ + selected = true; + + setLineWidth( 2 ); + setFrameStyle( TQFrame::Panel | TQFrame::Plain ); + repaint(); +} + + + +/*************************************************************************** + * + * CellFormatPagePattern + * + ***************************************************************************/ + +CellFormatPagePattern::CellFormatPagePattern( TQWidget* parent, CellFormatDialog *_dlg ) : TQWidget( parent ) +{ + dlg = _dlg; + + bBgColorUndefined = !dlg->bBgColor; + + TQGridLayout *grid = new TQGridLayout(this,5,2,KDialog::marginHint(), KDialog::spacingHint()); + + TQGroupBox* tmpTQGroupBox; + tmpTQGroupBox = new TQGroupBox( this, "GroupBox_20" ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setTitle( i18n("Pattern") ); + tmpTQGroupBox->setAlignment( AlignLeft ); + + TQGridLayout *grid2 = new TQGridLayout(tmpTQGroupBox,8,3,KDialog::marginHint(), KDialog::spacingHint()); + int fHeight = tmpTQGroupBox->fontMetrics().height(); + grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title + + + brush1 = new BrushSelect( tmpTQGroupBox, "Frame_1" ); + brush1->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush1,1,0); + + brush2 = new BrushSelect( tmpTQGroupBox, "Frame_2" ); + brush2->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush2,1,1); + + brush3 = new BrushSelect( tmpTQGroupBox, "Frame_3" ); + brush3->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush3,1,2); + + brush4 = new BrushSelect( tmpTQGroupBox, "Frame_4" ); + brush4->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush4,2,0); + + brush5 = new BrushSelect( tmpTQGroupBox, "Frame_5" ); + brush5->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush5,2,1); + + brush6 = new BrushSelect( tmpTQGroupBox, "Frame_6" ); + brush6->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush6,2,2); + + brush7 = new BrushSelect( tmpTQGroupBox, "Frame_7" ); + brush7->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush7,3,0); + + brush8 = new BrushSelect( tmpTQGroupBox, "Frame_8" ); + brush8->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush8,3,1); + + brush9 = new BrushSelect( tmpTQGroupBox, "Frame_9" ); + brush9->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush9,3,2); + + brush10 = new BrushSelect( tmpTQGroupBox, "Frame_10" ); + brush10->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush10,4,0); + + brush11 = new BrushSelect( tmpTQGroupBox, "Frame_11" ); + brush11->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush11,4,1); + + brush12 = new BrushSelect( tmpTQGroupBox, "Frame_12" ); + brush12->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush12,4,2); + + brush13 = new BrushSelect( tmpTQGroupBox, "Frame_13" ); + brush13->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush13,5,0); + + brush14 = new BrushSelect( tmpTQGroupBox, "Frame_14" ); + brush14->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush14,5,1); + + brush15 = new BrushSelect( tmpTQGroupBox, "Frame_15" ); + brush15->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(brush15,5,2); + + TQGridLayout *grid3 = new TQGridLayout( 1, 2 ); + color = new KColorButton (tmpTQGroupBox, "ColorButton_1" ); + grid3->addWidget(color,0,1); + + TQLabel *tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_1" ); + tmpTQLabel->setText( i18n("Color:") ); + grid3->addWidget(tmpTQLabel,0,0); + + grid2->addMultiCell(grid3,6,6,0,2); + + grid3 = new TQGridLayout( 1, 3 ); + grid3->setSpacing(KDialog::spacingHint()); + + tmpTQLabel = new TQLabel( tmpTQGroupBox, "Label_2" ); + grid3->addWidget(tmpTQLabel,0,0); + tmpTQLabel->setText( i18n("Background color:") ); + + bgColorButton = new KColorButton( tmpTQGroupBox, "ColorButton" ); + grid3->addWidget(bgColorButton,0,1); + if ( dlg->bBgColor ) + bgColor = dlg->bgColor; + else + bgColor = colorGroup().base(); + + if (!bgColor.isValid()) + bgColor = colorGroup().base(); + + bgColorButton->setColor( bgColor ); + connect( bgColorButton, TQT_SIGNAL( changed( const TQColor & ) ), + this, TQT_SLOT( slotSetBackgroundColor( const TQColor & ) ) ); + + notAnyColor=new TQPushButton(i18n("No Color"),tmpTQGroupBox); + grid3->addWidget(notAnyColor,0,2); + connect( notAnyColor, TQT_SIGNAL( clicked( ) ), + this, TQT_SLOT( slotNotAnyColor( ) ) ); + b_notAnyColor=false; + + grid2->addMultiCell(grid3,7,7,0,2); + + grid->addMultiCellWidget(tmpTQGroupBox,0,3,0,0); + + tmpTQGroupBox = new TQGroupBox( this, "GroupBox1" ); + tmpTQGroupBox->setTitle( i18n("Preview") ); + tmpTQGroupBox->setFrameStyle( TQFrame::Box | TQFrame::Sunken ); + tmpTQGroupBox->setAlignment( AlignLeft ); + + grid2 = new TQGridLayout(tmpTQGroupBox,2,1,KDialog::marginHint(), KDialog::spacingHint()); + fHeight = tmpTQGroupBox->fontMetrics().height(); + grid2->addRowSpacing( 0, fHeight/2 ); // groupbox title + + current = new BrushSelect( tmpTQGroupBox, "Current" ); + current->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + grid2->addWidget(current,1,0); + grid->addWidget( tmpTQGroupBox,4,0); + + connect( brush1, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush2, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush3, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush4, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush5, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush6, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush7, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush8, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush9, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush10, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush11, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush12, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush13, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush14, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + connect( brush15, TQT_SIGNAL( clicked( BrushSelect* ) ), + this, TQT_SLOT( slotUnselect2( BrushSelect* ) ) ); + + brush1->setPattern( TQt::red,Qt::VerPattern ); + brush2->setPattern( TQt::red,Qt::HorPattern ); + brush3->setPattern( TQt::red,Qt::Dense1Pattern ); + brush4->setPattern( TQt::red,Qt::Dense2Pattern ); + brush5->setPattern( TQt::red,Qt::Dense3Pattern ); + brush6->setPattern( TQt::red,Qt::Dense4Pattern ); + brush7->setPattern( TQt::red,Qt::Dense5Pattern ); + brush8->setPattern( TQt::red,Qt::Dense6Pattern ); + brush9->setPattern( TQt::red,Qt::Dense7Pattern ); + brush10->setPattern( TQt::red,Qt::CrossPattern ); + brush11->setPattern( TQt::red,Qt::BDiagPattern ); + brush12->setPattern( TQt::red,Qt::FDiagPattern ); + brush13->setPattern( TQt::red,Qt::VerPattern ); + brush14->setPattern( TQt::red,Qt::DiagCrossPattern ); + brush15->setPattern( TQt::red,Qt::NoBrush ); + + current->setPattern(dlg->brushColor,dlg->brushStyle); + current->slotSelect(); + selectedBrush=current; + color->setColor(dlg->brushColor); + current->setBackgroundColor( bgColor ); + + connect( color, TQT_SIGNAL( changed( const TQColor & ) ), + this, TQT_SLOT( slotSetColorButton( const TQColor & ) ) ); + + slotSetColorButton( dlg->brushColor ); + init(); + this->resize( 400, 400 ); +} + +void CellFormatPagePattern::slotNotAnyColor() +{ + b_notAnyColor = true; + bgColorButton->setColor( colorGroup().base() ); + current->setBackgroundColor( colorGroup().base() ); +} + +void CellFormatPagePattern::slotSetBackgroundColor( const TQColor &_color ) +{ + bgColor =_color; + current->setBackgroundColor( bgColor ); + bBgColorUndefined = false; + b_notAnyColor = false; +} + +void CellFormatPagePattern::init() +{ + if (dlg->brushStyle == TQt::VerPattern) + { + brush1->slotSelect(); + } + else if (dlg->brushStyle == TQt::HorPattern) + { + brush2->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense1Pattern) + { + brush3->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense2Pattern) + { + brush4->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense3Pattern) + { + brush5->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense4Pattern) + { + brush6->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense5Pattern) + { + brush7->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense6Pattern) + { + brush8->slotSelect(); + } + else if (dlg->brushStyle == TQt::Dense7Pattern) + { + brush9->slotSelect(); + } + else if (dlg->brushStyle == TQt::CrossPattern) + { + brush10->slotSelect(); + } + else if (dlg->brushStyle == TQt::BDiagPattern) + { + brush11->slotSelect(); + } + else if (dlg->brushStyle == TQt::FDiagPattern) + { + brush12->slotSelect(); + } + else if (dlg->brushStyle == TQt::VerPattern) + { + brush13->slotSelect(); + } + else if (dlg->brushStyle == TQt::DiagCrossPattern) + { + brush14->slotSelect(); + } + else if (dlg->brushStyle == TQt::NoBrush) + { + brush15->slotSelect(); + } + else + kdDebug(36001) << "Error in brushStyle" << endl; +} + +void CellFormatPagePattern::slotSetColorButton( const TQColor &_color ) +{ + currentColor = _color; + + brush1->setBrushColor( currentColor ); + brush2->setBrushColor( currentColor ); + brush3->setBrushColor( currentColor ); + brush4->setBrushColor( currentColor ); + brush5->setBrushColor( currentColor ); + brush6->setBrushColor( currentColor ); + brush7->setBrushColor( currentColor ); + brush8->setBrushColor( currentColor ); + brush9->setBrushColor( currentColor ); + brush10->setBrushColor( currentColor ); + brush11->setBrushColor( currentColor ); + brush12->setBrushColor( currentColor ); + brush13->setBrushColor( currentColor ); + brush14->setBrushColor( currentColor ); + brush15->setBrushColor( currentColor ); + current->setBrushColor( currentColor ); +} + +void CellFormatPagePattern::slotUnselect2( BrushSelect *_p ) +{ + selectedBrush = _p; + + if ( brush1 != _p ) + brush1->slotUnselect(); + if ( brush2 != _p ) + brush2->slotUnselect(); + if ( brush3 != _p ) + brush3->slotUnselect(); + if ( brush4 != _p ) + brush4->slotUnselect(); + if ( brush5 != _p ) + brush5->slotUnselect(); + if ( brush6 != _p ) + brush6->slotUnselect(); + if ( brush7 != _p ) + brush7->slotUnselect(); + if ( brush8 != _p ) + brush8->slotUnselect(); + if ( brush9 != _p ) + brush9->slotUnselect(); + if ( brush10 != _p ) + brush10->slotUnselect(); + if ( brush11 != _p ) + brush11->slotUnselect(); + if ( brush12 != _p ) + brush12->slotUnselect(); + if ( brush13 != _p ) + brush13->slotUnselect(); + if ( brush14 != _p ) + brush14->slotUnselect(); + if ( brush15 != _p ) + brush15->slotUnselect(); + + current->setBrushStyle( selectedBrush->getBrushStyle() ); +} + +void CellFormatPagePattern::apply( CustomStyle * style ) +{ + if ( selectedBrush != 0L + && ( dlg->brushStyle != selectedBrush->getBrushStyle() + || dlg->brushColor != selectedBrush->getBrushColor() ) ) + style->changeBackGroundBrush( TQBrush( selectedBrush->getBrushColor(), selectedBrush->getBrushStyle() ) ); + + /* + TODO: check... + if ( b_notAnyColor) + style->changeBgColor( TQColor() ); + else + */ + if ( bgColor != dlg->getStyle()->bgColor() ) + style->changeBgColor( bgColor ); +} + +void CellFormatPagePattern::apply(FormatManipulator *_obj) +{ + if ( selectedBrush != 0L + && ( dlg->brushStyle != selectedBrush->getBrushStyle() + || dlg->brushColor != selectedBrush->getBrushColor() ) ) + _obj->setBackgroundBrush( TQBrush( selectedBrush->getBrushColor(), selectedBrush->getBrushStyle() ) ); + + if ( bgColor == dlg->bgColor ) + return; + + if ( b_notAnyColor) + _obj->setBackgroundColor( TQColor() ); + else if ( !bBgColorUndefined ) + _obj->setBackgroundColor( bgColor ); +} + +#include "kspread_dlg_layout.moc" + diff --git a/kspread/dialogs/kspread_dlg_list.cc b/kspread/dialogs/kspread_dlg_list.cc deleted file mode 100644 index 254470e1..00000000 --- a/kspread/dialogs/kspread_dlg_list.cc +++ /dev/null @@ -1,321 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Ariya Hidayat - (C) 2001-2003 Laurent Montel - (C) 1998, 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_autofill.h" -#include "kspread_factory.h" -#include "kspread_locale.h" - -#include "kspread_dlg_list.h" - -using namespace KSpread; - -ListDialog::ListDialog( TQWidget* parent, const char* name ) - : KDialogBase( parent, name, true, i18n("Custom Lists"), Ok|Cancel ) -{ - TQWidget* page = new TQWidget( this ); - setMainWidget( page ); - - TQGridLayout *grid1 = new TQGridLayout( page,10,3,KDialog::marginHint(), KDialog::spacingHint()); - - TQLabel *lab=new TQLabel(page); - lab->setText(i18n("List:" )); - grid1->addWidget(lab,0,0); - - list=new TQListBox(page); - grid1->addMultiCellWidget(list,1,8,0,0); - - - lab=new TQLabel(page); - lab->setText(i18n("Entry:" )); - grid1->addWidget(lab,0,1); - - entryList=new TQMultiLineEdit(page); - grid1->addMultiCellWidget(entryList,1,8,1,1); - - m_pRemove=new TQPushButton(i18n("&Remove"),page); - grid1->addWidget(m_pRemove,3,2); - - m_pAdd=new TQPushButton(i18n("&Add"),page); - grid1->addWidget(m_pAdd,1,2); - - m_pNew=new TQPushButton(i18n("&New"),page); - grid1->addWidget(m_pNew,2,2); - - m_pModify=new TQPushButton(i18n("&Modify"),page); - grid1->addWidget(m_pModify,4,2); - - m_pCopy=new TQPushButton(i18n("Co&py"),page); - grid1->addWidget(m_pCopy,5,2); - - m_pAdd->setEnabled(false); - - connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); - connect( m_pAdd, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdd() ) ); - connect( m_pNew, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotNew() ) ); - connect( m_pModify, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotModify() ) ); - connect( m_pCopy, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotCopy() ) ); - connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); - connect( list, TQT_SIGNAL(clicked ( TQListBoxItem * )),this,TQT_SLOT(slotTextClicked(TQListBoxItem * ))); - init(); - entryList->setEnabled(false); - m_pModify->setEnabled(false); - if(list->count()<=2) - m_pRemove->setEnabled(false); - resize( 600, 250 ); - m_bChanged=false; -} - - -void ListDialog::slotTextClicked(TQListBoxItem*) -{ - //we can't remove the two first item - bool state=list->currentItem()>1; - m_pRemove->setEnabled(state); - m_pModify->setEnabled(state); - -} - -void ListDialog::init() -{ - TQString month; - month+=i18n("January")+", "; - month+=i18n("February")+", "; - month+=i18n("March") +", "; - month+=i18n("April")+", "; - month+=i18n("May")+", "; - month+=i18n("June")+", "; - month+=i18n("July")+", "; - month+=i18n("August")+", "; - month+=i18n("September")+", "; - month+=i18n("October")+", "; - month+=i18n("November")+", "; - month+=i18n("December"); - TQStringList lst; - lst.append(month); - - TQString smonth; - smonth+=i18n("Jan")+", "; - smonth+=i18n("Feb")+", "; - smonth+=i18n("Mar") +", "; - smonth+=i18n("Apr")+", "; - smonth+=i18n("May")+", "; - smonth+=i18n("Jun")+", "; - smonth+=i18n("Jul")+", "; - smonth+=i18n("Aug")+", "; - smonth+=i18n("Sep")+", "; - smonth+=i18n("Oct")+", "; - smonth+=i18n("Nov")+", "; - smonth+=i18n("Dec"); - lst.append(smonth); - - TQString day=i18n("Monday")+", "; - day+=i18n("Tuesday")+", "; - day+=i18n("Wednesday")+", "; - day+=i18n("Thursday")+", "; - day+=i18n("Friday")+", "; - day+=i18n("Saturday")+", "; - day+=i18n("Sunday"); - lst.append(day); - - TQString sday=i18n("Mon")+", "; - sday+=i18n("Tue")+", "; - sday+=i18n("Wed")+", "; - sday+=i18n("Thu")+", "; - sday+=i18n("Fri")+", "; - sday+=i18n("Sat")+", "; - sday+=i18n("Sun"); - lst.append(sday); - - config = Factory::global()->config(); - config->setGroup( "Parameters" ); - TQStringList other=config->readListEntry("Other list"); - TQString tmp; - for ( TQStringList::Iterator it = other.begin(); it != other.end();++it ) - { - if((*it)!="\\") - tmp+=(*it)+", "; - else if( it!=other.begin()) - { - tmp=tmp.left(tmp.length()-2); - lst.append(tmp); - tmp=""; - } - } - list->insertStringList(lst); -} - -void ListDialog::slotDoubleClicked(TQListBoxItem *) -{ - //we can't modify the two first item - if(list->currentItem()<2) - return; - TQString tmp=list->currentText(); - entryList->setText(""); - TQStringList result=result.split(", ",tmp); - int index=0; - for ( TQStringList::Iterator it = result.begin(); it != result.end();++it ) - { - entryList->insertLine((*it),index); - index++; - } - entryList->setEnabled(true); - m_pModify->setEnabled(true); -} - -void ListDialog::slotAdd() -{ - m_pAdd->setEnabled(false); - list->setEnabled(true); - TQString tmp; - for(int i=0;inumLines();i++) - { - if(!entryList->textLine(i).isEmpty()) - { - if(tmp.isEmpty()) - tmp=entryList->textLine(i); - else - tmp+=", "+entryList->textLine(i); - } - } - if(!tmp.isEmpty()) - list->insertItem(tmp,list->count()); - - entryList->setText(""); - entryList->setEnabled(false); - entryList->setFocus(); - slotTextClicked(0L); - m_bChanged=true; -} - -void ListDialog::slotNew() -{ - m_pAdd->setEnabled(true); - list->setEnabled(false); - entryList->setText(""); - entryList->setEnabled(true); - entryList->setFocus(); -} - -void ListDialog::slotRemove() -{ - if(list->currentItem()==-1) - return; - //don't remove the two first line - if(list->currentItem()<2) - return; - int ret = KMessageBox::warningContinueCancel( this, i18n("Do you really want to remove this list?"),i18n("Remove List"),KStdGuiItem::del()); - if(ret==Cancel) // reponse = No - return; - list->removeItem(list->currentItem ()); - entryList->setEnabled(false); - entryList->setText(""); - if(list->count()<=2) - m_pRemove->setEnabled(false); - m_bChanged=true; -} - -void ListDialog::slotOk() -{ - if(!entryList->text().isEmpty()) - { - int ret = KMessageBox::warningYesNo( this, i18n("Entry area is not empty.\nDo you want to continue?")); - if(ret==4) // reponse = No - return; - } - if(m_bChanged) - { - TQStringList result; - result.append("\\"); - - //don't save the two first line - for(unsigned int i=2;icount();i++) - { - TQStringList tmp=result.split(", ",list->text(i)); - if ( !tmp.isEmpty() ) - { - result+=tmp; - result+="\\"; - } - } - config->setGroup( "Parameters" ); - config->writeEntry("Other list",result); - //todo refresh AutoFillSequenceItem::other - // I don't know how to do for the moment - if(AutoFillSequenceItem::other!=0L) - { - delete(AutoFillSequenceItem::other); - AutoFillSequenceItem::other=0L; - } - } - accept(); -} - -void ListDialog::slotModify() -{ - //you can modify list but not the two first list - if(list->currentItem ()>1 && !entryList->text().isEmpty()) - { - TQString tmp; - for(int i=0;inumLines();i++) - { - if(!entryList->textLine(i).isEmpty()) - { - if(tmp.isEmpty()) - tmp=entryList->textLine(i); - else - tmp+=", "+entryList->textLine(i); - } - } - list->insertItem(tmp,list->currentItem()); - list->removeItem(list->currentItem()); - - - entryList->setText(""); - m_bChanged=true; - - } - entryList->setEnabled(false); - m_pModify->setEnabled(false); - -} - -void ListDialog::slotCopy() -{ - if(list->currentItem()!=-1) - { - list->insertItem(list->currentText(),list->count()); - } -} - - -#include "kspread_dlg_list.moc" diff --git a/kspread/dialogs/kspread_dlg_list.cpp b/kspread/dialogs/kspread_dlg_list.cpp new file mode 100644 index 00000000..254470e1 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_list.cpp @@ -0,0 +1,321 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Ariya Hidayat + (C) 2001-2003 Laurent Montel + (C) 1998, 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_autofill.h" +#include "kspread_factory.h" +#include "kspread_locale.h" + +#include "kspread_dlg_list.h" + +using namespace KSpread; + +ListDialog::ListDialog( TQWidget* parent, const char* name ) + : KDialogBase( parent, name, true, i18n("Custom Lists"), Ok|Cancel ) +{ + TQWidget* page = new TQWidget( this ); + setMainWidget( page ); + + TQGridLayout *grid1 = new TQGridLayout( page,10,3,KDialog::marginHint(), KDialog::spacingHint()); + + TQLabel *lab=new TQLabel(page); + lab->setText(i18n("List:" )); + grid1->addWidget(lab,0,0); + + list=new TQListBox(page); + grid1->addMultiCellWidget(list,1,8,0,0); + + + lab=new TQLabel(page); + lab->setText(i18n("Entry:" )); + grid1->addWidget(lab,0,1); + + entryList=new TQMultiLineEdit(page); + grid1->addMultiCellWidget(entryList,1,8,1,1); + + m_pRemove=new TQPushButton(i18n("&Remove"),page); + grid1->addWidget(m_pRemove,3,2); + + m_pAdd=new TQPushButton(i18n("&Add"),page); + grid1->addWidget(m_pAdd,1,2); + + m_pNew=new TQPushButton(i18n("&New"),page); + grid1->addWidget(m_pNew,2,2); + + m_pModify=new TQPushButton(i18n("&Modify"),page); + grid1->addWidget(m_pModify,4,2); + + m_pCopy=new TQPushButton(i18n("Co&py"),page); + grid1->addWidget(m_pCopy,5,2); + + m_pAdd->setEnabled(false); + + connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); + connect( m_pAdd, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdd() ) ); + connect( m_pNew, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotNew() ) ); + connect( m_pModify, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotModify() ) ); + connect( m_pCopy, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotCopy() ) ); + connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); + connect( list, TQT_SIGNAL(clicked ( TQListBoxItem * )),this,TQT_SLOT(slotTextClicked(TQListBoxItem * ))); + init(); + entryList->setEnabled(false); + m_pModify->setEnabled(false); + if(list->count()<=2) + m_pRemove->setEnabled(false); + resize( 600, 250 ); + m_bChanged=false; +} + + +void ListDialog::slotTextClicked(TQListBoxItem*) +{ + //we can't remove the two first item + bool state=list->currentItem()>1; + m_pRemove->setEnabled(state); + m_pModify->setEnabled(state); + +} + +void ListDialog::init() +{ + TQString month; + month+=i18n("January")+", "; + month+=i18n("February")+", "; + month+=i18n("March") +", "; + month+=i18n("April")+", "; + month+=i18n("May")+", "; + month+=i18n("June")+", "; + month+=i18n("July")+", "; + month+=i18n("August")+", "; + month+=i18n("September")+", "; + month+=i18n("October")+", "; + month+=i18n("November")+", "; + month+=i18n("December"); + TQStringList lst; + lst.append(month); + + TQString smonth; + smonth+=i18n("Jan")+", "; + smonth+=i18n("Feb")+", "; + smonth+=i18n("Mar") +", "; + smonth+=i18n("Apr")+", "; + smonth+=i18n("May")+", "; + smonth+=i18n("Jun")+", "; + smonth+=i18n("Jul")+", "; + smonth+=i18n("Aug")+", "; + smonth+=i18n("Sep")+", "; + smonth+=i18n("Oct")+", "; + smonth+=i18n("Nov")+", "; + smonth+=i18n("Dec"); + lst.append(smonth); + + TQString day=i18n("Monday")+", "; + day+=i18n("Tuesday")+", "; + day+=i18n("Wednesday")+", "; + day+=i18n("Thursday")+", "; + day+=i18n("Friday")+", "; + day+=i18n("Saturday")+", "; + day+=i18n("Sunday"); + lst.append(day); + + TQString sday=i18n("Mon")+", "; + sday+=i18n("Tue")+", "; + sday+=i18n("Wed")+", "; + sday+=i18n("Thu")+", "; + sday+=i18n("Fri")+", "; + sday+=i18n("Sat")+", "; + sday+=i18n("Sun"); + lst.append(sday); + + config = Factory::global()->config(); + config->setGroup( "Parameters" ); + TQStringList other=config->readListEntry("Other list"); + TQString tmp; + for ( TQStringList::Iterator it = other.begin(); it != other.end();++it ) + { + if((*it)!="\\") + tmp+=(*it)+", "; + else if( it!=other.begin()) + { + tmp=tmp.left(tmp.length()-2); + lst.append(tmp); + tmp=""; + } + } + list->insertStringList(lst); +} + +void ListDialog::slotDoubleClicked(TQListBoxItem *) +{ + //we can't modify the two first item + if(list->currentItem()<2) + return; + TQString tmp=list->currentText(); + entryList->setText(""); + TQStringList result=result.split(", ",tmp); + int index=0; + for ( TQStringList::Iterator it = result.begin(); it != result.end();++it ) + { + entryList->insertLine((*it),index); + index++; + } + entryList->setEnabled(true); + m_pModify->setEnabled(true); +} + +void ListDialog::slotAdd() +{ + m_pAdd->setEnabled(false); + list->setEnabled(true); + TQString tmp; + for(int i=0;inumLines();i++) + { + if(!entryList->textLine(i).isEmpty()) + { + if(tmp.isEmpty()) + tmp=entryList->textLine(i); + else + tmp+=", "+entryList->textLine(i); + } + } + if(!tmp.isEmpty()) + list->insertItem(tmp,list->count()); + + entryList->setText(""); + entryList->setEnabled(false); + entryList->setFocus(); + slotTextClicked(0L); + m_bChanged=true; +} + +void ListDialog::slotNew() +{ + m_pAdd->setEnabled(true); + list->setEnabled(false); + entryList->setText(""); + entryList->setEnabled(true); + entryList->setFocus(); +} + +void ListDialog::slotRemove() +{ + if(list->currentItem()==-1) + return; + //don't remove the two first line + if(list->currentItem()<2) + return; + int ret = KMessageBox::warningContinueCancel( this, i18n("Do you really want to remove this list?"),i18n("Remove List"),KStdGuiItem::del()); + if(ret==Cancel) // reponse = No + return; + list->removeItem(list->currentItem ()); + entryList->setEnabled(false); + entryList->setText(""); + if(list->count()<=2) + m_pRemove->setEnabled(false); + m_bChanged=true; +} + +void ListDialog::slotOk() +{ + if(!entryList->text().isEmpty()) + { + int ret = KMessageBox::warningYesNo( this, i18n("Entry area is not empty.\nDo you want to continue?")); + if(ret==4) // reponse = No + return; + } + if(m_bChanged) + { + TQStringList result; + result.append("\\"); + + //don't save the two first line + for(unsigned int i=2;icount();i++) + { + TQStringList tmp=result.split(", ",list->text(i)); + if ( !tmp.isEmpty() ) + { + result+=tmp; + result+="\\"; + } + } + config->setGroup( "Parameters" ); + config->writeEntry("Other list",result); + //todo refresh AutoFillSequenceItem::other + // I don't know how to do for the moment + if(AutoFillSequenceItem::other!=0L) + { + delete(AutoFillSequenceItem::other); + AutoFillSequenceItem::other=0L; + } + } + accept(); +} + +void ListDialog::slotModify() +{ + //you can modify list but not the two first list + if(list->currentItem ()>1 && !entryList->text().isEmpty()) + { + TQString tmp; + for(int i=0;inumLines();i++) + { + if(!entryList->textLine(i).isEmpty()) + { + if(tmp.isEmpty()) + tmp=entryList->textLine(i); + else + tmp+=", "+entryList->textLine(i); + } + } + list->insertItem(tmp,list->currentItem()); + list->removeItem(list->currentItem()); + + + entryList->setText(""); + m_bChanged=true; + + } + entryList->setEnabled(false); + m_pModify->setEnabled(false); + +} + +void ListDialog::slotCopy() +{ + if(list->currentItem()!=-1) + { + list->insertItem(list->currentText(),list->count()); + } +} + + +#include "kspread_dlg_list.moc" diff --git a/kspread/dialogs/kspread_dlg_paperlayout.cc b/kspread/dialogs/kspread_dlg_paperlayout.cc deleted file mode 100644 index 3305963e..00000000 --- a/kspread/dialogs/kspread_dlg_paperlayout.cc +++ /dev/null @@ -1,554 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005 Raphael Langerhorst - (C) 2002-2003 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 2002-2003 Philipp Mueller - (C) 2002 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_dlg_paperlayout.h" -#include -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace KSpread; - -PaperLayout::PaperLayout( TQWidget * parent, const char * name, - const KoPageLayout & layout, - const KoHeadFoot & headfoot, - int tabs, KoUnit::Unit unit, - Sheet * sheet, View * view) - : KoPageLayoutDia( parent, name, layout, headfoot, tabs, unit, false /*no modal*/), - m_pSheet( sheet ), - m_pView( view ) -{ - initTab(); - connect(view->selectionInfo(), TQT_SIGNAL(changed(const Region&)), - this, TQT_SLOT(slotSelectionChanged())); - tqApp->installEventFilter( this ); - m_focus= 0L; -} - -void PaperLayout::initTab() -{ - SheetPrint* print = m_pSheet->print(); - - TQWidget *tab = addPage(i18n( "Options" )); - TQVBoxLayout *vbox = new TQVBoxLayout( tab, KDialog::marginHint(), KDialog::spacingHint() ); - - pApplyToAll = new TQCheckBox ( i18n( "&Apply to all sheets" ), tab ); - pApplyToAll->setChecked( print->printGrid() ); - vbox->addWidget( pApplyToAll ); - - //Range properties - initGeneralOptions( tab, vbox ); - - //Range properties - initRanges( tab, vbox ); - - //Scale properties - initScaleOptions( tab, vbox ); - - vbox->addStretch( 1 ); -} - -void PaperLayout::initGeneralOptions( TQWidget * tab, TQVBoxLayout * vbox ) -{ - SheetPrint* print = m_pSheet->print(); - - TQGroupBox *group = new TQGroupBox( i18n("General Options"), tab ); - TQGridLayout *l = new TQGridLayout( group, 2, 3 ); - - pPrintGrid = new TQCheckBox ( i18n("Print &grid"), group ); - pPrintGrid->setChecked( print->printGrid() ); - l->addWidget( pPrintGrid, 0, 0 ); - - pPrintCommentIndicator = new TQCheckBox ( i18n("Print &comment indicator"), group ); - pPrintCommentIndicator->setChecked( print->printCommentIndicator() ); - l->addWidget( pPrintCommentIndicator, 0, 1 ); - - pPrintFormulaIndicator = new TQCheckBox ( i18n("Print &formula indicator"), group ); - pPrintFormulaIndicator->setChecked( print->printFormulaIndicator() ); - l->addWidget( pPrintFormulaIndicator, 0, 2 ); - - pPrintObjects = new TQCheckBox ( i18n("Print &objects"), group ); - pPrintObjects->setChecked( print->printObjects() ); - l->addWidget( pPrintObjects, 1, 0 ); - - pPrintCharts = new TQCheckBox ( i18n("Print &charts"), group ); - pPrintCharts->setChecked( print->printCharts() ); - l->addWidget( pPrintCharts, 1, 1 ); - -// Not used yet unless someone implement some kind of drawing object -// pPrintGraphics = new TQCheckBox ( i18n("Print &drawings"), group ); -// pPrintGraphics->setChecked( print->printGraphics() ); -// l->addWidget( pPrintGraphics, 1, 2 ); - - vbox->addWidget( group ); -} - -void PaperLayout::initRanges( TQWidget * tab, TQVBoxLayout * vbox ) -{ - SheetPrint* print = m_pSheet->print(); - - TQGroupBox *rangeGroup = new TQGroupBox( i18n("Ranges"), tab ); - rangeGroup->setColumnLayout( 0, Qt::Vertical ); - rangeGroup->setMargin( KDialog::marginHint() ); - vbox->addWidget( rangeGroup ); - - TQGridLayout *grid = new TQGridLayout( rangeGroup->layout(), 3, 2, KDialog::spacingHint() ); - - TQLabel *pPrintRange = new TQLabel ( i18n("Print range:"), rangeGroup ); - grid->addWidget( pPrintRange, 0, 0 ); - - ePrintRange = new TQLineEdit( rangeGroup ); - ePrintRange->setText( util_rangeName( print->printRange() ) ); - grid->addWidget( ePrintRange, 0, 1 ); - - TQLabel *pRepeatCols = new TQLabel ( i18n("Repeat columns on each page:"), rangeGroup ); - grid->addWidget( pRepeatCols, 1, 0 ); - - eRepeatCols = new TQLineEdit( rangeGroup ); - if ( print->printRepeatColumns().first != 0 ) - eRepeatCols->setText( Cell::columnName( print->printRepeatColumns().first ) + ":" + - Cell::columnName( print->printRepeatColumns().second ) ); - grid->addWidget( eRepeatCols, 1, 1 ); - - TQLabel *pRepeatRows = new TQLabel ( i18n("Repeat rows on each page:"), rangeGroup ); - grid->addWidget( pRepeatRows, 2, 0 ); - - eRepeatRows = new TQLineEdit( rangeGroup ); - if ( print->printRepeatRows().first != 0 ) - eRepeatRows->setText( TQString().setNum( print->printRepeatRows().first ) + - ":" + - TQString().setNum( print->printRepeatRows().second ) ); - grid->addWidget( eRepeatRows, 2, 1 ); - - grid->addColSpacing( 0, pPrintRange->width() ); - grid->addColSpacing( 0, pRepeatRows->width() ); - grid->addColSpacing( 0, pRepeatCols->width() ); - grid->addColSpacing( 1, ePrintRange->width() ); - grid->addColSpacing( 1, eRepeatRows->width() ); - grid->addColSpacing( 1, eRepeatCols->width() ); - - grid->addRowSpacing( 0, pPrintRange->height() ); - grid->addRowSpacing( 0, ePrintRange->height() ); - grid->addRowSpacing( 1, pRepeatRows->height() ); - grid->addRowSpacing( 1, eRepeatRows->height() ); - grid->addRowSpacing( 2, pRepeatCols->height() ); - grid->addRowSpacing( 2, eRepeatCols->height() ); -} - -void PaperLayout::initScaleOptions( TQWidget * tab, TQVBoxLayout * vbox ) -{ - SheetPrint* print = m_pSheet->print(); - - TQButtonGroup *zoomGroup = new TQButtonGroup( i18n("Scale Printout"), tab ); - zoomGroup->setColumnLayout( 0, Qt::Vertical ); - zoomGroup->setMargin( KDialog::marginHint() ); - vbox->addWidget( zoomGroup ); - - TQGridLayout *grid = new TQGridLayout( zoomGroup->layout(), 2, 6, - KDialog::spacingHint() ); - - m_rScalingZoom = new TQRadioButton ( i18n("Zoom:"), zoomGroup ); - grid->addWidget( m_rScalingZoom, 0, 0 ); - - m_cZoom = new TQComboBox( true, zoomGroup, "Zoom" ); - grid->addMultiCellWidget( m_cZoom, 0, 0, 1, 5, TQt::AlignLeft ); - - TQStringList lst; - for( int i = 5; i < 500; i += 5 ) - { - lst.append( TQString( i18n( "%1%" ) ).arg( i ) ); - if( tqRound( print->zoom() * 100 ) > i && - tqRound( print->zoom() * 100 ) < i + 5 ) - { - lst.append( TQString( i18n( "%1%" ) ).arg( tqRound( print->zoom() * 100 ) ) ); - } - } - m_cZoom->insertStringList( lst ); - - int number_of_entries = m_cZoom->count(); - TQString string = TQString( i18n( "%1%" ) ).arg( tqRound( print->zoom() * 100 ) ); - for (int i = 0; i < number_of_entries ; i++) - { - if ( string == (TQString) m_cZoom->text(i) ) - { - m_cZoom->setCurrentItem( i ); - break; - } - } - - m_rScalingLimitPages = new TQRadioButton ( i18n("Limit pages:"), zoomGroup ); - grid->addWidget( m_rScalingLimitPages, 1, 0 ); - - TQLabel *pLimitPagesX = new TQLabel ( i18n("X:"), zoomGroup ); - grid->addWidget( pLimitPagesX, 1, 1 ); - - m_cLimitPagesX = new TQComboBox( true, zoomGroup, "pagesX" ); - grid->addWidget( m_cLimitPagesX, 1, 2 ); - - TQStringList lstX; - lstX.append( i18n( "No Limit" ) ); - for( int i = 1; i <= 20; i += 1 ) - { - lstX.append( TQString( "%1" ).arg( i ) ); - } - if( print->pageLimitX() > 20 ) - { - lstX.append( TQString( "%1" ).arg( print->pageLimitX() ) ); - } - m_cLimitPagesX->insertStringList( lstX ); - - if ( print->pageLimitX() <= 20 ) - m_cLimitPagesX->setCurrentItem( print->pageLimitX() ); - else - m_cLimitPagesX->setCurrentItem( 21 ); - - TQLabel *pLimitPagesY = new TQLabel ( i18n("Y:"), zoomGroup ); - grid->addWidget( pLimitPagesY, 1, 3 ); - - m_cLimitPagesY = new TQComboBox( true, zoomGroup, "pagesY" ); - grid->addWidget( m_cLimitPagesY, 1, 4 ); - - TQStringList lstY; - lstY.append( i18n( "No Limit" ) ); - for( int i = 1; i <= 20; i += 1 ) - { - lstY.append( TQString( "%1" ).arg( i ) ); - } - if( print->pageLimitY() > 20 ) - { - lstY.append( TQString( "%1" ).arg( print->pageLimitY() ) ); - } - m_cLimitPagesY->insertStringList( lstY ); - - if ( print->pageLimitY() <= 20 ) - m_cLimitPagesY->setCurrentItem( print->pageLimitY() ); - else - m_cLimitPagesY->setCurrentItem( 21 ); - - if ( print->pageLimitY() != 0 || print->pageLimitX() != 0 ) - { - m_rScalingLimitPages->setChecked( true ); - } - else - { - m_rScalingZoom->setChecked( true ); - } - - connect( m_cZoom, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChooseZoom( int ) ) ); - connect( m_cLimitPagesX, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChoosePageLimit( int ) ) ); - connect( m_cLimitPagesY, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChoosePageLimit( int ) ) ); -} - -void PaperLayout::slotChooseZoom( int /*index*/ ) -{ - m_rScalingZoom->setChecked( true ); -} - -void PaperLayout::slotChoosePageLimit( int /*index*/ ) -{ - m_rScalingLimitPages->setChecked( true ); -} - -void PaperLayout::slotOk() -{ - if ( !m_pSheet->doc()->undoLocked() ) - { - UndoAction* undo = new UndoPaperLayout( m_pSheet->doc(), m_pSheet ); - m_pSheet->doc()->addCommand( undo ); - } - - // get new values for borders - Map * map = 0; - Sheet * sheet = 0; - - if ( pApplyToAll->isChecked() ) - map = m_pSheet->doc()->map(); - - if ( map ) - sheet = map->firstSheet(); - else - sheet = m_pSheet; - - m_pView->doc()->emitBeginOperation( false ); - while ( sheet ) - { - SheetPrint *print = sheet->print(); - - KoPageLayout pl = layout(); - KoHeadFoot hf = headFoot(); - KoUnit::Unit unit = sheet->doc()->unit(); - print->setPrintGrid( pPrintGrid->isChecked() ); - print->setPrintCommentIndicator( pPrintCommentIndicator->isChecked() ); - print->setPrintFormulaIndicator( pPrintFormulaIndicator->isChecked() ); - print->setPrintObjects( pPrintObjects->isChecked() ); - print->setPrintCharts( pPrintCharts->isChecked() ); -// print->setPrintGraphics( pPrintGraphics->isChecked() ); - TQString tmpPrintRange = ePrintRange->text(); - TQString tmpRepeatCols = eRepeatCols->text(); - TQString tmpRepeatRows = eRepeatRows->text(); - if ( tmpPrintRange.isEmpty() ) - { - print->setPrintRange( TQRect( TQPoint( 1, 1 ), TQPoint( KS_colMax, KS_rowMax ) ) ); - } - else - { - bool error = true; - int first = tmpPrintRange.find(":"); - if ( ( first != -1 ) && ( (int)tmpPrintRange.length() > first ) ) - { - Point point1 ( tmpPrintRange.left( first ) ); - if ( point1.isValid() ) - { - Point point2 ( tmpPrintRange.mid( first+1 ) ); - if ( point2.isValid() ) - { - error = false; - print->setPrintRange ( TQRect( TQPoint( TQMIN( point1.pos().x(), point2.pos().x() ), - TQMIN( point1.pos().y(), point2.pos().y() ) ), - TQPoint( TQMAX( point1.pos().x(), point2.pos().x() ), - TQMAX( point1.pos().y(), point2.pos().y() ) ) ) ); - } - } - } - - if ( error ) KMessageBox::information( 0, i18n( "Print range wrong, changes are ignored." ) ); - } - - if ( tmpRepeatCols.isEmpty() ) - { - print->setPrintRepeatColumns( tqMakePair( 0, 0 ) ); - } - else - { - bool error = true; - int first = tmpRepeatCols.find(":"); - if ( ( first != -1 ) && ( (int)tmpRepeatCols.length() > first ) ) - { - int col1 = util_decodeColumnLabelText( tmpRepeatCols.left( first ) ); - if ( col1 > 0 && col1 <= KS_colMax ) - { - int col2 = util_decodeColumnLabelText( tmpRepeatCols.mid( first+1 ) ); - if ( col2 > 0 && col2 <= KS_colMax ) - { - error = false; - print->setPrintRepeatColumns ( tqMakePair( col1, col2 ) ); - } - } - } - - if ( error ) - KMessageBox::information( 0, i18n( "Repeated columns range wrong, changes are ignored.\nMust be in format column:column (eg. B:C)" ) ); - } - - if ( tmpRepeatRows.isEmpty() ) - { - print->setPrintRepeatRows ( tqMakePair( 0, 0 ) ); - } - else - { - bool error = true; - int first = tmpRepeatRows.find(":"); - if ( ( first != -1 ) && ( (int)tmpRepeatRows.length() > first ) ) - { - int row1 = tmpRepeatRows.left( first ).toInt(); - if ( row1 > 0 && row1 <= KS_rowMax ) - { - int row2 = tmpRepeatRows.mid( first+1 ).toInt(); - if ( row2 > 0 && row2 <= KS_rowMax ) - { - error = false; - print->setPrintRepeatRows ( tqMakePair( row1, row2 ) ); - } - } - } - - if ( error ) - KMessageBox::information( 0, i18n( "Repeated rows range wrong, changes are ignored.\nMust be in format row:row (eg. 2:3)" ) ); - } - - if ( m_rScalingZoom->isChecked() ) - { - kdDebug() << "Zoom is selected" << endl; - if( TQString( "%1%" ).arg( tqRound( print->zoom() * 100 ) ) != m_cZoom->currentText() ) - { - kdDebug() << "New zoom is different than original: " << m_cZoom->currentText() << endl; - TQString zoomtext = m_cZoom->currentText(); - zoomtext.replace("%",""); - bool convertok = false; - double zoomvalue = zoomtext.toDouble(&convertok); - if (!convertok) - { - kdWarning() << "Could not convert zoom text to double value!!!" << endl; - } - else if( zoomvalue != 0.0 ) - { - //reset page limits - print->setPageLimitX(0); - print->setPageLimitY(0); - kdDebug() << "Setting print zoom: " << zoomvalue*0.01 << endl; - print->setZoom( 0.01 * zoomvalue ); - kdDebug() << "New print zoom: " << print->zoom() << endl; - } - else - kdDebug() << "Did not set print zoom" << endl; - } - else - kdDebug() << "new zoom is same as original: " << m_cZoom->currentText() << endl; - } - else if (m_rScalingLimitPages->isChecked()) - { - kdDebug() << "Limit pages is selected" << endl; - kdDebug() << "Current zoom: " << print->zoom() << endl; - - //reset first, otherwise setting the first limit - //would still check against the second limit and - //possibly result in a smaller total zoom - print->setPageLimitX( 0 ); - print->setPageLimitY( 0 ); - - //start with at least 100% - - if (print->zoom() < 1.0) - { - kdDebug() << "Resetting zoom to 1.0" << endl; - print->setZoom(1.0,false); //don't check page limits here - kdDebug() << "Zoom is now: " << print->zoom() << endl; - } - - bool convertok = false; - - int limitX = m_cLimitPagesX->currentText().toInt(&convertok); - if (!convertok) //THIS IS THE CASE WITH "No Limit" - limitX = 0; //0 means no limit - - convertok=false; - int limitY = m_cLimitPagesY->currentText().toInt(&convertok); - if (!convertok) //THIS IS THE CASE WITH "No Limit" - limitY=0; //0 means no limit - - kdDebug() << "Zoom before setting limits: " << print->zoom() << endl; - kdDebug() << "Chosen Limits: x: " << limitX << "; y: " << limitY << endl; - print->setPageLimitX( limitX ); - kdDebug() << "Zoom after setting x limit: " << print->zoom() << endl; - print->setPageLimitY( limitY ); - kdDebug() << "Zoom after setting y limit: " << print->zoom() << endl; - } - else - kdWarning() << "ERROR: unknown zoom option selected" << endl; - - sheet->doc()->setModified( true ); - - if ( pl.format == PG_CUSTOM ) - { - print->setPaperWidth( tqRound( POINT_TO_MM( pl.ptWidth ) *1000 ) / 1000 ); - print->setPaperHeight( tqRound( POINT_TO_MM( pl.ptHeight ) *1000 ) / 1000 ); - } - - print->setPaperLayout( POINT_TO_MM(pl.ptLeft), POINT_TO_MM(pl.ptTop), - POINT_TO_MM(pl.ptRight), POINT_TO_MM(pl.ptBottom), - pl.format, pl.orientation ); - - print->setHeadFootLine( print->delocalizeHeadFootLine( hf.headLeft ), - print->delocalizeHeadFootLine( hf.headMid ), - print->delocalizeHeadFootLine( hf.headRight ), - print->delocalizeHeadFootLine( hf.footLeft ), - print->delocalizeHeadFootLine( hf.footMid ), - print->delocalizeHeadFootLine( hf.footRight ) ); - - sheet->doc()->setUnit( unit ); - - if ( map ) - sheet = map->nextSheet(); - else - sheet = 0; - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void PaperLayout::closeEvent ( TQCloseEvent * ) -{ - delete this; -} - -void PaperLayout::slotSelectionChanged() -{ - // TODO Stefan: check for improvement - if (!m_pView->selectionInfo()->isValid()) - return; - - TQString area = util_rangeName( m_pView->selectionInfo()->lastRange() ); - if ( m_focus ) - { - if ( m_focus == ePrintRange ) - area = util_rangeName( m_pView->selectionInfo()->lastRange() ); - else if ( m_focus == eRepeatRows ) - area = util_rangeRowName( m_pView->selectionInfo()->lastRange() ); - else if ( m_focus == eRepeatCols ) - area = util_rangeColumnName( m_pView->selectionInfo()->lastRange() ); - else - return; - m_focus->setText( area ); - } -} - -void PaperLayout::slotCancel() -{ - reject(); -} - -bool PaperLayout::eventFilter( TQObject* obj, TQEvent* ev ) -{ - if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(ePrintRange) && ev->type() == TQEvent::FocusIn ) - m_focus = ePrintRange; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(eRepeatCols) && ev->type() == TQEvent::FocusIn ) - m_focus = eRepeatCols; - else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(eRepeatRows) && ev->type() == TQEvent::FocusIn ) - m_focus = eRepeatRows; - else - return false; - - return false; -} - - -#include "kspread_dlg_paperlayout.moc" diff --git a/kspread/dialogs/kspread_dlg_paperlayout.cpp b/kspread/dialogs/kspread_dlg_paperlayout.cpp new file mode 100644 index 00000000..3305963e --- /dev/null +++ b/kspread/dialogs/kspread_dlg_paperlayout.cpp @@ -0,0 +1,554 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Raphael Langerhorst + (C) 2002-2003 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 2002-2003 Philipp Mueller + (C) 2002 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_dlg_paperlayout.h" +#include +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace KSpread; + +PaperLayout::PaperLayout( TQWidget * parent, const char * name, + const KoPageLayout & layout, + const KoHeadFoot & headfoot, + int tabs, KoUnit::Unit unit, + Sheet * sheet, View * view) + : KoPageLayoutDia( parent, name, layout, headfoot, tabs, unit, false /*no modal*/), + m_pSheet( sheet ), + m_pView( view ) +{ + initTab(); + connect(view->selectionInfo(), TQT_SIGNAL(changed(const Region&)), + this, TQT_SLOT(slotSelectionChanged())); + tqApp->installEventFilter( this ); + m_focus= 0L; +} + +void PaperLayout::initTab() +{ + SheetPrint* print = m_pSheet->print(); + + TQWidget *tab = addPage(i18n( "Options" )); + TQVBoxLayout *vbox = new TQVBoxLayout( tab, KDialog::marginHint(), KDialog::spacingHint() ); + + pApplyToAll = new TQCheckBox ( i18n( "&Apply to all sheets" ), tab ); + pApplyToAll->setChecked( print->printGrid() ); + vbox->addWidget( pApplyToAll ); + + //Range properties + initGeneralOptions( tab, vbox ); + + //Range properties + initRanges( tab, vbox ); + + //Scale properties + initScaleOptions( tab, vbox ); + + vbox->addStretch( 1 ); +} + +void PaperLayout::initGeneralOptions( TQWidget * tab, TQVBoxLayout * vbox ) +{ + SheetPrint* print = m_pSheet->print(); + + TQGroupBox *group = new TQGroupBox( i18n("General Options"), tab ); + TQGridLayout *l = new TQGridLayout( group, 2, 3 ); + + pPrintGrid = new TQCheckBox ( i18n("Print &grid"), group ); + pPrintGrid->setChecked( print->printGrid() ); + l->addWidget( pPrintGrid, 0, 0 ); + + pPrintCommentIndicator = new TQCheckBox ( i18n("Print &comment indicator"), group ); + pPrintCommentIndicator->setChecked( print->printCommentIndicator() ); + l->addWidget( pPrintCommentIndicator, 0, 1 ); + + pPrintFormulaIndicator = new TQCheckBox ( i18n("Print &formula indicator"), group ); + pPrintFormulaIndicator->setChecked( print->printFormulaIndicator() ); + l->addWidget( pPrintFormulaIndicator, 0, 2 ); + + pPrintObjects = new TQCheckBox ( i18n("Print &objects"), group ); + pPrintObjects->setChecked( print->printObjects() ); + l->addWidget( pPrintObjects, 1, 0 ); + + pPrintCharts = new TQCheckBox ( i18n("Print &charts"), group ); + pPrintCharts->setChecked( print->printCharts() ); + l->addWidget( pPrintCharts, 1, 1 ); + +// Not used yet unless someone implement some kind of drawing object +// pPrintGraphics = new TQCheckBox ( i18n("Print &drawings"), group ); +// pPrintGraphics->setChecked( print->printGraphics() ); +// l->addWidget( pPrintGraphics, 1, 2 ); + + vbox->addWidget( group ); +} + +void PaperLayout::initRanges( TQWidget * tab, TQVBoxLayout * vbox ) +{ + SheetPrint* print = m_pSheet->print(); + + TQGroupBox *rangeGroup = new TQGroupBox( i18n("Ranges"), tab ); + rangeGroup->setColumnLayout( 0, Qt::Vertical ); + rangeGroup->setMargin( KDialog::marginHint() ); + vbox->addWidget( rangeGroup ); + + TQGridLayout *grid = new TQGridLayout( rangeGroup->layout(), 3, 2, KDialog::spacingHint() ); + + TQLabel *pPrintRange = new TQLabel ( i18n("Print range:"), rangeGroup ); + grid->addWidget( pPrintRange, 0, 0 ); + + ePrintRange = new TQLineEdit( rangeGroup ); + ePrintRange->setText( util_rangeName( print->printRange() ) ); + grid->addWidget( ePrintRange, 0, 1 ); + + TQLabel *pRepeatCols = new TQLabel ( i18n("Repeat columns on each page:"), rangeGroup ); + grid->addWidget( pRepeatCols, 1, 0 ); + + eRepeatCols = new TQLineEdit( rangeGroup ); + if ( print->printRepeatColumns().first != 0 ) + eRepeatCols->setText( Cell::columnName( print->printRepeatColumns().first ) + ":" + + Cell::columnName( print->printRepeatColumns().second ) ); + grid->addWidget( eRepeatCols, 1, 1 ); + + TQLabel *pRepeatRows = new TQLabel ( i18n("Repeat rows on each page:"), rangeGroup ); + grid->addWidget( pRepeatRows, 2, 0 ); + + eRepeatRows = new TQLineEdit( rangeGroup ); + if ( print->printRepeatRows().first != 0 ) + eRepeatRows->setText( TQString().setNum( print->printRepeatRows().first ) + + ":" + + TQString().setNum( print->printRepeatRows().second ) ); + grid->addWidget( eRepeatRows, 2, 1 ); + + grid->addColSpacing( 0, pPrintRange->width() ); + grid->addColSpacing( 0, pRepeatRows->width() ); + grid->addColSpacing( 0, pRepeatCols->width() ); + grid->addColSpacing( 1, ePrintRange->width() ); + grid->addColSpacing( 1, eRepeatRows->width() ); + grid->addColSpacing( 1, eRepeatCols->width() ); + + grid->addRowSpacing( 0, pPrintRange->height() ); + grid->addRowSpacing( 0, ePrintRange->height() ); + grid->addRowSpacing( 1, pRepeatRows->height() ); + grid->addRowSpacing( 1, eRepeatRows->height() ); + grid->addRowSpacing( 2, pRepeatCols->height() ); + grid->addRowSpacing( 2, eRepeatCols->height() ); +} + +void PaperLayout::initScaleOptions( TQWidget * tab, TQVBoxLayout * vbox ) +{ + SheetPrint* print = m_pSheet->print(); + + TQButtonGroup *zoomGroup = new TQButtonGroup( i18n("Scale Printout"), tab ); + zoomGroup->setColumnLayout( 0, Qt::Vertical ); + zoomGroup->setMargin( KDialog::marginHint() ); + vbox->addWidget( zoomGroup ); + + TQGridLayout *grid = new TQGridLayout( zoomGroup->layout(), 2, 6, + KDialog::spacingHint() ); + + m_rScalingZoom = new TQRadioButton ( i18n("Zoom:"), zoomGroup ); + grid->addWidget( m_rScalingZoom, 0, 0 ); + + m_cZoom = new TQComboBox( true, zoomGroup, "Zoom" ); + grid->addMultiCellWidget( m_cZoom, 0, 0, 1, 5, TQt::AlignLeft ); + + TQStringList lst; + for( int i = 5; i < 500; i += 5 ) + { + lst.append( TQString( i18n( "%1%" ) ).arg( i ) ); + if( tqRound( print->zoom() * 100 ) > i && + tqRound( print->zoom() * 100 ) < i + 5 ) + { + lst.append( TQString( i18n( "%1%" ) ).arg( tqRound( print->zoom() * 100 ) ) ); + } + } + m_cZoom->insertStringList( lst ); + + int number_of_entries = m_cZoom->count(); + TQString string = TQString( i18n( "%1%" ) ).arg( tqRound( print->zoom() * 100 ) ); + for (int i = 0; i < number_of_entries ; i++) + { + if ( string == (TQString) m_cZoom->text(i) ) + { + m_cZoom->setCurrentItem( i ); + break; + } + } + + m_rScalingLimitPages = new TQRadioButton ( i18n("Limit pages:"), zoomGroup ); + grid->addWidget( m_rScalingLimitPages, 1, 0 ); + + TQLabel *pLimitPagesX = new TQLabel ( i18n("X:"), zoomGroup ); + grid->addWidget( pLimitPagesX, 1, 1 ); + + m_cLimitPagesX = new TQComboBox( true, zoomGroup, "pagesX" ); + grid->addWidget( m_cLimitPagesX, 1, 2 ); + + TQStringList lstX; + lstX.append( i18n( "No Limit" ) ); + for( int i = 1; i <= 20; i += 1 ) + { + lstX.append( TQString( "%1" ).arg( i ) ); + } + if( print->pageLimitX() > 20 ) + { + lstX.append( TQString( "%1" ).arg( print->pageLimitX() ) ); + } + m_cLimitPagesX->insertStringList( lstX ); + + if ( print->pageLimitX() <= 20 ) + m_cLimitPagesX->setCurrentItem( print->pageLimitX() ); + else + m_cLimitPagesX->setCurrentItem( 21 ); + + TQLabel *pLimitPagesY = new TQLabel ( i18n("Y:"), zoomGroup ); + grid->addWidget( pLimitPagesY, 1, 3 ); + + m_cLimitPagesY = new TQComboBox( true, zoomGroup, "pagesY" ); + grid->addWidget( m_cLimitPagesY, 1, 4 ); + + TQStringList lstY; + lstY.append( i18n( "No Limit" ) ); + for( int i = 1; i <= 20; i += 1 ) + { + lstY.append( TQString( "%1" ).arg( i ) ); + } + if( print->pageLimitY() > 20 ) + { + lstY.append( TQString( "%1" ).arg( print->pageLimitY() ) ); + } + m_cLimitPagesY->insertStringList( lstY ); + + if ( print->pageLimitY() <= 20 ) + m_cLimitPagesY->setCurrentItem( print->pageLimitY() ); + else + m_cLimitPagesY->setCurrentItem( 21 ); + + if ( print->pageLimitY() != 0 || print->pageLimitX() != 0 ) + { + m_rScalingLimitPages->setChecked( true ); + } + else + { + m_rScalingZoom->setChecked( true ); + } + + connect( m_cZoom, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChooseZoom( int ) ) ); + connect( m_cLimitPagesX, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChoosePageLimit( int ) ) ); + connect( m_cLimitPagesY, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotChoosePageLimit( int ) ) ); +} + +void PaperLayout::slotChooseZoom( int /*index*/ ) +{ + m_rScalingZoom->setChecked( true ); +} + +void PaperLayout::slotChoosePageLimit( int /*index*/ ) +{ + m_rScalingLimitPages->setChecked( true ); +} + +void PaperLayout::slotOk() +{ + if ( !m_pSheet->doc()->undoLocked() ) + { + UndoAction* undo = new UndoPaperLayout( m_pSheet->doc(), m_pSheet ); + m_pSheet->doc()->addCommand( undo ); + } + + // get new values for borders + Map * map = 0; + Sheet * sheet = 0; + + if ( pApplyToAll->isChecked() ) + map = m_pSheet->doc()->map(); + + if ( map ) + sheet = map->firstSheet(); + else + sheet = m_pSheet; + + m_pView->doc()->emitBeginOperation( false ); + while ( sheet ) + { + SheetPrint *print = sheet->print(); + + KoPageLayout pl = layout(); + KoHeadFoot hf = headFoot(); + KoUnit::Unit unit = sheet->doc()->unit(); + print->setPrintGrid( pPrintGrid->isChecked() ); + print->setPrintCommentIndicator( pPrintCommentIndicator->isChecked() ); + print->setPrintFormulaIndicator( pPrintFormulaIndicator->isChecked() ); + print->setPrintObjects( pPrintObjects->isChecked() ); + print->setPrintCharts( pPrintCharts->isChecked() ); +// print->setPrintGraphics( pPrintGraphics->isChecked() ); + TQString tmpPrintRange = ePrintRange->text(); + TQString tmpRepeatCols = eRepeatCols->text(); + TQString tmpRepeatRows = eRepeatRows->text(); + if ( tmpPrintRange.isEmpty() ) + { + print->setPrintRange( TQRect( TQPoint( 1, 1 ), TQPoint( KS_colMax, KS_rowMax ) ) ); + } + else + { + bool error = true; + int first = tmpPrintRange.find(":"); + if ( ( first != -1 ) && ( (int)tmpPrintRange.length() > first ) ) + { + Point point1 ( tmpPrintRange.left( first ) ); + if ( point1.isValid() ) + { + Point point2 ( tmpPrintRange.mid( first+1 ) ); + if ( point2.isValid() ) + { + error = false; + print->setPrintRange ( TQRect( TQPoint( TQMIN( point1.pos().x(), point2.pos().x() ), + TQMIN( point1.pos().y(), point2.pos().y() ) ), + TQPoint( TQMAX( point1.pos().x(), point2.pos().x() ), + TQMAX( point1.pos().y(), point2.pos().y() ) ) ) ); + } + } + } + + if ( error ) KMessageBox::information( 0, i18n( "Print range wrong, changes are ignored." ) ); + } + + if ( tmpRepeatCols.isEmpty() ) + { + print->setPrintRepeatColumns( tqMakePair( 0, 0 ) ); + } + else + { + bool error = true; + int first = tmpRepeatCols.find(":"); + if ( ( first != -1 ) && ( (int)tmpRepeatCols.length() > first ) ) + { + int col1 = util_decodeColumnLabelText( tmpRepeatCols.left( first ) ); + if ( col1 > 0 && col1 <= KS_colMax ) + { + int col2 = util_decodeColumnLabelText( tmpRepeatCols.mid( first+1 ) ); + if ( col2 > 0 && col2 <= KS_colMax ) + { + error = false; + print->setPrintRepeatColumns ( tqMakePair( col1, col2 ) ); + } + } + } + + if ( error ) + KMessageBox::information( 0, i18n( "Repeated columns range wrong, changes are ignored.\nMust be in format column:column (eg. B:C)" ) ); + } + + if ( tmpRepeatRows.isEmpty() ) + { + print->setPrintRepeatRows ( tqMakePair( 0, 0 ) ); + } + else + { + bool error = true; + int first = tmpRepeatRows.find(":"); + if ( ( first != -1 ) && ( (int)tmpRepeatRows.length() > first ) ) + { + int row1 = tmpRepeatRows.left( first ).toInt(); + if ( row1 > 0 && row1 <= KS_rowMax ) + { + int row2 = tmpRepeatRows.mid( first+1 ).toInt(); + if ( row2 > 0 && row2 <= KS_rowMax ) + { + error = false; + print->setPrintRepeatRows ( tqMakePair( row1, row2 ) ); + } + } + } + + if ( error ) + KMessageBox::information( 0, i18n( "Repeated rows range wrong, changes are ignored.\nMust be in format row:row (eg. 2:3)" ) ); + } + + if ( m_rScalingZoom->isChecked() ) + { + kdDebug() << "Zoom is selected" << endl; + if( TQString( "%1%" ).arg( tqRound( print->zoom() * 100 ) ) != m_cZoom->currentText() ) + { + kdDebug() << "New zoom is different than original: " << m_cZoom->currentText() << endl; + TQString zoomtext = m_cZoom->currentText(); + zoomtext.replace("%",""); + bool convertok = false; + double zoomvalue = zoomtext.toDouble(&convertok); + if (!convertok) + { + kdWarning() << "Could not convert zoom text to double value!!!" << endl; + } + else if( zoomvalue != 0.0 ) + { + //reset page limits + print->setPageLimitX(0); + print->setPageLimitY(0); + kdDebug() << "Setting print zoom: " << zoomvalue*0.01 << endl; + print->setZoom( 0.01 * zoomvalue ); + kdDebug() << "New print zoom: " << print->zoom() << endl; + } + else + kdDebug() << "Did not set print zoom" << endl; + } + else + kdDebug() << "new zoom is same as original: " << m_cZoom->currentText() << endl; + } + else if (m_rScalingLimitPages->isChecked()) + { + kdDebug() << "Limit pages is selected" << endl; + kdDebug() << "Current zoom: " << print->zoom() << endl; + + //reset first, otherwise setting the first limit + //would still check against the second limit and + //possibly result in a smaller total zoom + print->setPageLimitX( 0 ); + print->setPageLimitY( 0 ); + + //start with at least 100% + + if (print->zoom() < 1.0) + { + kdDebug() << "Resetting zoom to 1.0" << endl; + print->setZoom(1.0,false); //don't check page limits here + kdDebug() << "Zoom is now: " << print->zoom() << endl; + } + + bool convertok = false; + + int limitX = m_cLimitPagesX->currentText().toInt(&convertok); + if (!convertok) //THIS IS THE CASE WITH "No Limit" + limitX = 0; //0 means no limit + + convertok=false; + int limitY = m_cLimitPagesY->currentText().toInt(&convertok); + if (!convertok) //THIS IS THE CASE WITH "No Limit" + limitY=0; //0 means no limit + + kdDebug() << "Zoom before setting limits: " << print->zoom() << endl; + kdDebug() << "Chosen Limits: x: " << limitX << "; y: " << limitY << endl; + print->setPageLimitX( limitX ); + kdDebug() << "Zoom after setting x limit: " << print->zoom() << endl; + print->setPageLimitY( limitY ); + kdDebug() << "Zoom after setting y limit: " << print->zoom() << endl; + } + else + kdWarning() << "ERROR: unknown zoom option selected" << endl; + + sheet->doc()->setModified( true ); + + if ( pl.format == PG_CUSTOM ) + { + print->setPaperWidth( tqRound( POINT_TO_MM( pl.ptWidth ) *1000 ) / 1000 ); + print->setPaperHeight( tqRound( POINT_TO_MM( pl.ptHeight ) *1000 ) / 1000 ); + } + + print->setPaperLayout( POINT_TO_MM(pl.ptLeft), POINT_TO_MM(pl.ptTop), + POINT_TO_MM(pl.ptRight), POINT_TO_MM(pl.ptBottom), + pl.format, pl.orientation ); + + print->setHeadFootLine( print->delocalizeHeadFootLine( hf.headLeft ), + print->delocalizeHeadFootLine( hf.headMid ), + print->delocalizeHeadFootLine( hf.headRight ), + print->delocalizeHeadFootLine( hf.footLeft ), + print->delocalizeHeadFootLine( hf.footMid ), + print->delocalizeHeadFootLine( hf.footRight ) ); + + sheet->doc()->setUnit( unit ); + + if ( map ) + sheet = map->nextSheet(); + else + sheet = 0; + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void PaperLayout::closeEvent ( TQCloseEvent * ) +{ + delete this; +} + +void PaperLayout::slotSelectionChanged() +{ + // TODO Stefan: check for improvement + if (!m_pView->selectionInfo()->isValid()) + return; + + TQString area = util_rangeName( m_pView->selectionInfo()->lastRange() ); + if ( m_focus ) + { + if ( m_focus == ePrintRange ) + area = util_rangeName( m_pView->selectionInfo()->lastRange() ); + else if ( m_focus == eRepeatRows ) + area = util_rangeRowName( m_pView->selectionInfo()->lastRange() ); + else if ( m_focus == eRepeatCols ) + area = util_rangeColumnName( m_pView->selectionInfo()->lastRange() ); + else + return; + m_focus->setText( area ); + } +} + +void PaperLayout::slotCancel() +{ + reject(); +} + +bool PaperLayout::eventFilter( TQObject* obj, TQEvent* ev ) +{ + if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(ePrintRange) && ev->type() == TQEvent::FocusIn ) + m_focus = ePrintRange; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(eRepeatCols) && ev->type() == TQEvent::FocusIn ) + m_focus = eRepeatCols; + else if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(eRepeatRows) && ev->type() == TQEvent::FocusIn ) + m_focus = eRepeatRows; + else + return false; + + return false; +} + + +#include "kspread_dlg_paperlayout.moc" diff --git a/kspread/dialogs/kspread_dlg_pasteinsert.cc b/kspread/dialogs/kspread_dlg_pasteinsert.cc deleted file mode 100644 index 93d67b06..00000000 --- a/kspread/dialogs/kspread_dlg_pasteinsert.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 2000-2002 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "kspread_dlg_pasteinsert.h" -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "selection.h" - -using namespace KSpread; - -PasteInsertDialog::PasteInsertDialog( View* parent, const char* name,const TQRect &_rect) - : KDialogBase( parent, name, TRUE,i18n("Paste Inserting Cells"),Ok|Cancel ) -{ - m_pView = parent; - rect=_rect; - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Insert"),page); - grp->setRadioButtonExclusive( TRUE ); - grp->layout(); - lay1->addWidget(grp); - rb1 = new TQRadioButton( i18n("Move towards right"), grp ); - rb2 = new TQRadioButton( i18n("Move towards bottom"), grp ); - rb1->setChecked(true); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); -} - -void PasteInsertDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - if( rb1->isChecked() ) - m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), - true, Paste::Normal, Paste::OverWrite, - true, -1 ); - else if( rb2->isChecked() ) - m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), - true, Paste::Normal, Paste::OverWrite, - true, +1 ); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -#include "kspread_dlg_pasteinsert.moc" diff --git a/kspread/dialogs/kspread_dlg_pasteinsert.cpp b/kspread/dialogs/kspread_dlg_pasteinsert.cpp new file mode 100644 index 00000000..93d67b06 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_pasteinsert.cpp @@ -0,0 +1,77 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 2000-2002 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "kspread_dlg_pasteinsert.h" +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "selection.h" + +using namespace KSpread; + +PasteInsertDialog::PasteInsertDialog( View* parent, const char* name,const TQRect &_rect) + : KDialogBase( parent, name, TRUE,i18n("Paste Inserting Cells"),Ok|Cancel ) +{ + m_pView = parent; + rect=_rect; + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Insert"),page); + grp->setRadioButtonExclusive( TRUE ); + grp->layout(); + lay1->addWidget(grp); + rb1 = new TQRadioButton( i18n("Move towards right"), grp ); + rb2 = new TQRadioButton( i18n("Move towards bottom"), grp ); + rb1->setChecked(true); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); +} + +void PasteInsertDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + if( rb1->isChecked() ) + m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), + true, Paste::Normal, Paste::OverWrite, + true, -1 ); + else if( rb2->isChecked() ) + m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), + true, Paste::Normal, Paste::OverWrite, + true, +1 ); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +#include "kspread_dlg_pasteinsert.moc" diff --git a/kspread/dialogs/kspread_dlg_preference.cc b/kspread/dialogs/kspread_dlg_preference.cc deleted file mode 100644 index d82af591..00000000 --- a/kspread/dialogs/kspread_dlg_preference.cc +++ /dev/null @@ -1,1042 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005 Raphael Langerhorst - (C) 2002-2004 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 2000-2005 Laurent Montel - (C) 2002 John Dailey - (C) 2002 Philipp Mueller - (C) 2001-2002 David Faure - (C) 2001 Werner Trobin - (C) 2000 Bernd Johannes Wuebben - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include "kspread_doc.h" -#include "kspread_canvas.h" -#include "kspread_view.h" -#include "kspread_locale.h" -#include "kspread_editors.h" - -#include "kspread_dlg_preference.h" - -using namespace KSpread; - -PreferenceDialog::PreferenceDialog( View* parent, const char* /*name*/) - : KDialogBase(KDialogBase::IconList,i18n("Configure KSpread") , - KDialogBase::Ok | KDialogBase::Cancel| KDialogBase::Default, - KDialogBase::Ok) - -{ - m_pView=parent; - - connect(this, TQT_SIGNAL(okClicked()),this,TQT_SLOT(slotApply())); - - TQVBox *page2=addVBoxPage(i18n("Locale Settings"), TQString(),BarIcon("go-home",TDEIcon::SizeMedium)); - _localePage=new parameterLocale(parent,page2 ); - - TQVBox *page3=addVBoxPage(i18n("Interface"), TQString(),BarIcon("signature", TDEIcon::SizeMedium) ); - _configure = new configure(parent,page3 ); - - TQVBox * page4=addVBoxPage(i18n("Misc"), TQString(),BarIcon("misc",TDEIcon::SizeMedium) ); - _miscParameter = new miscParameters(parent,page4 ); - - TQVBox *page5=addVBoxPage(i18n("Color"), TQString(),BarIcon("colorize",TDEIcon::SizeMedium) ); - _colorParameter=new colorParameters(parent,page5 ); - - TQVBox *page6=addVBoxPage(i18n("Page Layout"), TQString(),BarIcon("edit",TDEIcon::SizeMedium) ); - _layoutPage=new configureLayoutPage(parent,page6 ); - - TQVBox *page7 = addVBoxPage( i18n("Spelling"), i18n("Spell Checker Behavior"), - BarIcon("tools-check-spelling", TDEIcon::SizeMedium) ); - _spellPage=new configureSpellPage(parent,page7); - - if (KoSpeaker::isKttsdInstalled()) { - TQVBox *page8 = addVBoxPage( i18n("Abbreviation for Text-to-Speech", "TTS"), - i18n("Text-to-Speech Settings"), BarIcon("access", TDEIcon::SizeMedium) ); - _ttsPage=new configureTTSPage(parent, page8); - } else _ttsPage = 0; - -} - -void PreferenceDialog::openPage(int flags) -{ - if(flags & KS_LOCALE) - showPage( 0 ); - else if(flags & KS_INTERFACE) - showPage( 1 ); - else if(flags & KS_MISC) - showPage( 2 ); - else if(flags & KS_COLOR) - showPage( 3 ); - else if(flags & KS_LAYOUT) - showPage( 4 ); - else if(flags & KS_SPELLING) - showPage( 5 ); -} - -void PreferenceDialog::slotApply() -{ - m_pView->doc()->emitBeginOperation( false ); - _configure->apply(); - _miscParameter->apply(); - _colorParameter->apply(); - _layoutPage->apply(); - _spellPage->apply(); - _localePage->apply(); - if (_ttsPage) _ttsPage->apply(); - m_pView->doc()->refreshInterface(); - m_pView->slotUpdateView( m_pView->activeSheet() ); -} - -void PreferenceDialog::slotDefault() -{ - switch(activePageIndex()) - { - case 1: - _configure->slotDefault(); - break; - case 2: - _miscParameter->slotDefault(); - break; - case 3: - _colorParameter->slotDefault(); - break; - case 4: - _layoutPage->slotDefault(); - break; - case 5: - _spellPage->slotDefault(); - break; - case 6: - _ttsPage->slotDefault(); - break; - default: - break; - } -} - - -parameterLocale::parameterLocale( View* _view, TQVBox *box , char *name ) - :TQObject ( box->parent(),name) -{ - m_pView = _view; - m_bUpdateLocale=false; - TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Settings"), box, "GroupBox" ); - - TDELocale* locale=_view->doc()->locale(); - - m_language=new TQLabel( tmpTQGroupBox,"label"); - m_number=new TQLabel( tmpTQGroupBox,"label6"); - m_date=new TQLabel( tmpTQGroupBox,"label1"); - m_shortDate=new TQLabel( tmpTQGroupBox,"label5"); - m_time=new TQLabel( tmpTQGroupBox,"label2"); - m_money=new TQLabel( tmpTQGroupBox,"label3"); - - updateToMatchLocale(locale); - - m_updateButton=new TQPushButton ( i18n("&Update Locale Settings"), tmpTQGroupBox); - connect(m_updateButton, TQT_SIGNAL(clicked()),this,TQT_SLOT(updateDefaultSystemConfig())); -} - -void parameterLocale::apply() -{ - if (m_bUpdateLocale) - { - m_pView->doc()->emitBeginOperation( false ); - m_pView->doc()->refreshLocale(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - } -} - -void parameterLocale::updateDefaultSystemConfig() -{ - m_bUpdateLocale=true; - static_cast(m_pView->doc()->locale())->defaultSystemConfig( ); - TDELocale* locale=m_pView->doc()->locale(); - updateToMatchLocale( locale ); -} - -void parameterLocale::updateToMatchLocale(TDELocale* locale) -{ - m_language->setText( i18n("Language: %1").arg( locale->language() )); - m_number->setText( i18n("Default number format: %1").arg( locale->formatNumber(12.55) )); - m_date->setText( i18n("Long date format: %1").arg( locale->formatDate( TQDate::currentDate() ))); - m_shortDate->setText( i18n("Short date format: %1").arg( locale->formatDate( TQDate::currentDate() ,true) )); - m_time->setText( i18n("Time format: %1").arg( locale->formatTime( TQTime::currentTime() ) )); - m_money->setText( i18n("Currency format: %1").arg( locale->formatMoney(12.55) )); -} - -configure::configure( View* _view, TQVBox *box , char *name ) - :TQObject ( box->parent(),name) - { - m_pView = _view; - - bool vertical=true; - bool horizontal=true; - bool rowHeader=true; - bool colHeader=true; - bool tabbar=true; - bool formulaBar=true; - bool statusBar=true; - m_oldBackupFile = true; - - TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Settings"), box, "GroupBox" ); - - config = Factory::global()->config(); - int _page=1; - - oldRecent=10; - oldAutoSaveValue=KoDocument::defaultAutoSave()/60; - - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - _page=config->readNumEntry( "NbPage" ,1) ; - horizontal=config->readBoolEntry("Horiz ScrollBar",true); - vertical=config->readBoolEntry("Vert ScrollBar",true); - colHeader=config->readBoolEntry("Column Header",true); - rowHeader=config->readBoolEntry("Row Header",true); - tabbar=config->readBoolEntry("Tabbar",true); - formulaBar=config->readBoolEntry("Formula bar",true); - statusBar=config->readBoolEntry("Status bar",true); - oldRecent=config->readNumEntry( "NbRecentFile" ,10); - oldAutoSaveValue=config->readNumEntry("AutoSave",KoDocument::defaultAutoSave()/60); - m_oldBackupFile=config->readBoolEntry("BackupFile",m_oldBackupFile); - } - nbPage=new KIntNumInput(_page, tmpTQGroupBox , 10); - nbPage->setRange(1, 10, 1); - nbPage->setLabel(i18n("Number of sheets open at the &beginning:")); - TQWhatsThis::add(nbPage, i18n( "Controls how many worksheets will be created if the option Start with an empty document is chosen when KSpread is started." ) ); - - nbRecentFile=new KIntNumInput(oldRecent, tmpTQGroupBox , 10); - nbRecentFile->setRange(1, 20, 1); - nbRecentFile->setLabel(i18n("&Number of files to show in Recent Files list:")); - TQWhatsThis::add(nbRecentFile, i18n( "Controls the maximum number of filenames that are shown when you select File-> Open Recent." ) ); - - autoSaveDelay=new KIntNumInput(oldAutoSaveValue, tmpTQGroupBox , 10); - autoSaveDelay->setRange(0, 60, 1); - autoSaveDelay->setLabel(i18n("Au&tosave delay (minutes):")); - autoSaveDelay->setSpecialValueText(i18n("Do not save automatically")); - autoSaveDelay->setSuffix(i18n("min")); - TQWhatsThis::add(autoSaveDelay, i18n( "Here you can select the time between autosaves, or disable this feature altogether by choosing Do not save automatically (drag the slider to the far left)." ) ); - - m_createBackupFile = new TQCheckBox( i18n("Create backup files"), tmpTQGroupBox ); - m_createBackupFile->setChecked( m_oldBackupFile ); - TQWhatsThis::add(m_createBackupFile, i18n( "Check this box if you want some backup files created. This is checked per default." ) ); - - showVScrollBar=new TQCheckBox(i18n("Show &vertical scrollbar"),tmpTQGroupBox); - showVScrollBar->setChecked(vertical); - TQWhatsThis::add(showVScrollBar, i18n( "Check or uncheck this box to show or hide the vertical scrollbar in all sheets." ) ); - - showHScrollBar=new TQCheckBox(i18n("Show &horizontal scrollbar"),tmpTQGroupBox); - showHScrollBar->setChecked(horizontal); - TQWhatsThis::add(showHScrollBar, i18n( "Check or uncheck this box to show or hide the horizontal scrollbar in all sheets." ) ); - - showColHeader=new TQCheckBox(i18n("Show c&olumn header"),tmpTQGroupBox); - showColHeader->setChecked(colHeader); - TQWhatsThis::add(showColHeader, i18n( "Check this box to show the column letters across the top of each worksheet." ) ); - showRowHeader=new TQCheckBox(i18n("Show &row header"),tmpTQGroupBox); - showRowHeader->setChecked(rowHeader); - TQWhatsThis::add(showRowHeader, i18n( "Check this box to show the row numbers down the left side." ) ); - - showTabBar =new TQCheckBox(i18n("Show ta&bs"),tmpTQGroupBox); - showTabBar->setChecked(tabbar); - TQWhatsThis::add(showTabBar, i18n( "This check box controls whether the sheet tabs are shown at the bottom of the worksheet." ) ); - - showFormulaBar =new TQCheckBox(i18n("Sho&w formula toolbar"),tmpTQGroupBox); - showFormulaBar->setChecked(formulaBar); - TQWhatsThis::add(showFormulaBar, i18n( "Here is where you can choose to show or hide the Formula bar." ) ); - - showStatusBar =new TQCheckBox(i18n("Show stat&us bar"),tmpTQGroupBox); - showStatusBar->setChecked(statusBar); - TQWhatsThis::add(showStatusBar, i18n( "Uncheck this box if you want to hide the status bar." ) ); -} - - -void configure::slotDefault() -{ - showHScrollBar->setChecked(true); - showRowHeader->setChecked(true); - showVScrollBar->setChecked(true); - showColHeader->setChecked(true); - showTabBar->setChecked(true); - showFormulaBar->setChecked(true); - showStatusBar->setChecked(true); - nbPage->setValue(1); - nbRecentFile->setValue(10); - autoSaveDelay->setValue(KoDocument::defaultAutoSave()/60); - m_createBackupFile->setChecked( true ); -} - - -void configure::apply() -{ - m_pView->doc()->emitBeginOperation( false ); - config->setGroup( "Parameters" ); - config->writeEntry( "NbPage", nbPage->value()); - Doc *doc =m_pView->doc(); - bool active=true; - active=showHScrollBar->isChecked(); - if( m_pView->horzScrollBar()->isVisible()!=active) - { - config->writeEntry( "Horiz ScrollBar",active); - if( active) - m_pView->horzScrollBar()->show(); - else - m_pView->horzScrollBar()->hide(); - doc->setShowHorizontalScrollBar(active); - } - active=showVScrollBar->isChecked(); - if( m_pView->vertScrollBar()->isVisible()!=active) - { - config->writeEntry( "Vert ScrollBar", active); - if(active) - m_pView->vertScrollBar()->show(); - else - m_pView->vertScrollBar()->hide(); - doc->setShowVerticalScrollBar(active); - - } - active=showColHeader->isChecked(); - if( m_pView->hBorderWidget()->isVisible()!=active) - { - config->writeEntry( "Column Header", active); - if( active) - m_pView->hBorderWidget()->show(); - else - m_pView->hBorderWidget()->hide(); - doc->setShowColHeader(active); - } - - active=showRowHeader->isChecked(); - if( m_pView->vBorderWidget()->isVisible()!=active) - { - config->writeEntry( "Row Header", active); - if( active) - m_pView->vBorderWidget()->show(); - else - m_pView->vBorderWidget()->hide(); - doc->setShowRowHeader(active); - } - - active=showTabBar->isChecked(); - if(m_pView->tabBar()->isVisible()!=active) - { - config->writeEntry( "Tabbar", active); - if(active) - m_pView->tabBar()->show(); - else - m_pView->tabBar()->hide(); - doc->setShowTabBar(active); - } - - active=showFormulaBar->isChecked(); - if(m_pView->posWidget()->isVisible()!=active) - { - config->writeEntry( "Formula bar",active); - m_pView->editWidget()->showEditWidget(active); - if(active) - m_pView->posWidget()->show(); - else - m_pView->posWidget()->hide(); - doc->setShowFormulaBar(active); - } - - active=showStatusBar->isChecked(); - config->writeEntry( "Status bar",active); - m_pView->showStatusBar( active ); - - int val=nbRecentFile->value(); - if( oldRecent!= val) - { - config->writeEntry( "NbRecentFile",val); - m_pView->changeNbOfRecentFiles(val); - } - val=autoSaveDelay->value(); - if(val!=oldAutoSaveValue) - { - config->writeEntry( "AutoSave", val ); - doc->setAutoSave(val*60); - } - - bool state =m_createBackupFile->isChecked(); - if(state!=m_oldBackupFile) - { - config->writeEntry( "BackupFile", state ); - doc->setBackupFile( state); - m_oldBackupFile=state; - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); -} - - -miscParameters::miscParameters( View* _view,TQVBox *box, char *name ) - :TQObject ( box->parent(),name) - { - m_pView = _view; - - - TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Misc"), box, "GroupBox" ); - - config = Factory::global()->config(); - indentUnit = _view->doc()->unit(); - double _indent = KoUnit::toUserValue( 10.0, indentUnit); - bool m_bMsgError=false; - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - _indent = config->readDoubleNumEntry( "Indent" , _indent ) ; - m_bMsgError=config->readBoolEntry( "Msg error" ,false) ; - } - - if( config->hasGroup("Misc") ) - { - config->setGroup( "Misc" ); - m_oldNbRedo=config->readNumEntry("UndoRedo",m_oldNbRedo); - } - - m_undoRedoLimit=new KIntNumInput( m_oldNbRedo, tmpTQGroupBox ); - m_undoRedoLimit->setLabel(i18n("Undo/redo limit:")); - m_undoRedoLimit->setRange(10, 60, 1); - - - TQLabel *label=new TQLabel(i18n("&Completion mode:"), tmpTQGroupBox); - - typeCompletion=new TQComboBox(tmpTQGroupBox); - label->setBuddy(typeCompletion); - TQWhatsThis::add(typeCompletion, i18n( "Lets you choose the (auto) text completion mode from a range of options in the drop down selection box." ) ); - TQStringList listType; - listType+=i18n("None"); - listType+=i18n("Manual"); - listType+=i18n("Popup"); - listType+=i18n("Automatic"); - listType+=i18n("Semi-Automatic"); - typeCompletion->insertStringList(listType); - typeCompletion->setCurrentItem(0); - comboChanged=false; - connect(typeCompletion,TQT_SIGNAL(activated( const TQString & )),this,TQT_SLOT(slotTextComboChanged(const TQString &))); - - label=new TQLabel(i18n("&Pressing enter moves cell cursor:"), tmpTQGroupBox); - typeOfMove=new TQComboBox( tmpTQGroupBox); - label->setBuddy(typeOfMove); - listType.clear(); - listType+=i18n("Down"); - listType+=i18n("Up"); - listType+=i18n("Right"); - listType+=i18n("Left"); - listType+=i18n("Down, First Column"); - typeOfMove->insertStringList(listType); - typeOfMove->setCurrentItem(0); - TQWhatsThis::add(typeOfMove, i18n( "When you have selected a cell, pressing the Enter key will move the cell cursor one cell left, right, up or down, as determined by this setting." ) ); - - label=new TQLabel(i18n("&Method of calc:"), tmpTQGroupBox); - - typeCalc=new TQComboBox( tmpTQGroupBox); - label->setBuddy(typeCalc); - TQStringList listTypeCalc; - listTypeCalc+=i18n("Sum"); - listTypeCalc+=i18n("Min"); - listTypeCalc+=i18n("Max"); - listTypeCalc+=i18n("Average"); - listTypeCalc+=i18n("Count"); - listTypeCalc+=i18n("CountA"); - listTypeCalc+=i18n("None"); - typeCalc->insertStringList(listTypeCalc); - typeCalc->setCurrentItem(0); - TQWhatsThis::add(typeCalc, i18n( "This drop down selection box can be used to choose the calculation performed by the Statusbar Summary function." ) ); - -// valIndent = new KDoubleNumInput( _indent, tmpTQGroupBox , 10.0 ); - valIndent = new KDoubleNumInput( tmpTQGroupBox ); - valIndent->setRange( KoUnit::toUserValue( 0.0, indentUnit ), - KoUnit::toUserValue( 400.0, indentUnit ), - KoUnit::toUserValue( 10.0, indentUnit) ); -// valIndent->setRange( 0.0, 100.0, 10.0 ); - valIndent->setValue ( KoUnit::toUserValue( _indent, indentUnit ) ); - TQWhatsThis::add(valIndent, i18n( "Lets you define the amount of indenting used by the Increase Indent and Decrease Indent option in the Format menu." ) ); - valIndent->setLabel(i18n("&Indentation step (%1):").arg(KoUnit::unitName(indentUnit))); - - msgError= new TQCheckBox(i18n("&Show error message for invalid formulae"),tmpTQGroupBox); - msgError->setChecked(m_bMsgError); - TQWhatsThis::add(msgError, i18n( "If this box is checked a message box will pop up when what you have entered into a cell cannot be understood by KSpread." ) ); - - initComboBox(); -} - -void miscParameters::slotTextComboChanged(const TQString &) -{ - comboChanged=true; -} - -void miscParameters::initComboBox() -{ - TDEGlobalSettings::Completion tmpCompletion=TDEGlobalSettings::CompletionAuto; - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - tmpCompletion=( TDEGlobalSettings::Completion)config->readNumEntry( "Completion Mode" ,TDEGlobalSettings::CompletionAuto) ; - config->writeEntry( "Completion Mode", (int)tmpCompletion); - } -switch(tmpCompletion ) - { - case TDEGlobalSettings::CompletionNone: - typeCompletion->setCurrentItem(0); - break; - case TDEGlobalSettings::CompletionAuto: - typeCompletion->setCurrentItem(3); - break; - case TDEGlobalSettings::CompletionMan: - typeCompletion->setCurrentItem(4); - break; - case TDEGlobalSettings::CompletionShell: - typeCompletion->setCurrentItem(1); - break; - case TDEGlobalSettings::CompletionPopup: - typeCompletion->setCurrentItem(2); - break; - default : - typeCompletion->setCurrentItem(0); - break; - } -switch( m_pView->doc()->getMoveToValue( )) - { - case KSpread::Bottom: - typeOfMove->setCurrentItem(0); - break; - case KSpread::Left: - typeOfMove->setCurrentItem(3); - break; - case KSpread::Top: - typeOfMove->setCurrentItem(1); - break; - case KSpread::Right: - typeOfMove->setCurrentItem(2); - break; - case KSpread::BottomFirst: - typeOfMove->setCurrentItem(4); - break; - default : - typeOfMove->setCurrentItem(0); - break; - } - -switch( m_pView->doc()->getTypeOfCalc()) - { - case SumOfNumber: - typeCalc->setCurrentItem(0); - break; - case Min: - typeCalc->setCurrentItem(1); - break; - case Max: - typeCalc->setCurrentItem(2); - break; - case Average: - typeCalc->setCurrentItem(3); - break; - case Count: - typeCalc->setCurrentItem(4); - break; - case CountA: - typeCalc->setCurrentItem(5); - break; - case NoneCalc: - typeCalc->setCurrentItem(6); - break; - default : - typeCalc->setCurrentItem(0); - break; - } - -} - -void miscParameters::slotDefault() -{ - m_undoRedoLimit->setValue(30); - valIndent->setValue( KoUnit::toUserValue( 10.0, indentUnit) ); - typeCompletion->setCurrentItem(3); - typeOfMove->setCurrentItem(0); - msgError->setChecked(false); - typeCalc->setCurrentItem(0); -} - - -void miscParameters::apply() -{ - kdDebug() << "Applying misc preferences" << endl; - - config->setGroup( "Misc" ); - int const newUndo=m_undoRedoLimit->value(); - if( newUndo!=m_oldNbRedo ) - { - config->writeEntry("UndoRedo",newUndo); - m_pView->doc()->setUndoRedoLimit(newUndo); - m_oldNbRedo=newUndo; - } - - config->setGroup( "Parameters" ); - TDEGlobalSettings::Completion tmpCompletion=TDEGlobalSettings::CompletionNone; - - switch(typeCompletion->currentItem()) - { - case 0: - tmpCompletion=TDEGlobalSettings::CompletionNone; - break; - case 1: - tmpCompletion=TDEGlobalSettings::CompletionShell; - break; - case 2: - tmpCompletion=TDEGlobalSettings::CompletionPopup; - break; - case 3: - tmpCompletion=TDEGlobalSettings::CompletionAuto; - break; - case 4: - tmpCompletion=TDEGlobalSettings::CompletionMan; - break; - } - - - if(comboChanged) - { - m_pView->doc()->setCompletionMode(tmpCompletion); - config->writeEntry( "Completion Mode", (int)tmpCompletion); - } - - KSpread::MoveTo tmpMoveTo=KSpread::Bottom; - switch(typeOfMove->currentItem()) - { - case 0: - tmpMoveTo=KSpread::Bottom; - break; - case 1: - tmpMoveTo=KSpread::Top; - break; - case 2: - tmpMoveTo=KSpread::Right; - break; - case 3: - tmpMoveTo=KSpread::Left; - break; - case 4: - tmpMoveTo=KSpread::BottomFirst; - break; - } - if(tmpMoveTo!=m_pView->doc()->getMoveToValue()) - { - m_pView->doc()->setMoveToValue(tmpMoveTo); - config->writeEntry( "Move", (int)tmpMoveTo); - } - - MethodOfCalc tmpMethodCalc=SumOfNumber; - switch(typeCalc->currentItem()) - { - case 0: - tmpMethodCalc =SumOfNumber; - break; - case 1: - tmpMethodCalc=Min; - break; - case 2: - tmpMethodCalc=Max; - break; - case 3: - tmpMethodCalc=Average; - break; - case 4: - tmpMethodCalc=Count; - break; - case 5: - tmpMethodCalc=CountA; - break; - case 6: - tmpMethodCalc=NoneCalc; - break; - - } - if(tmpMethodCalc!=m_pView->doc()->getTypeOfCalc()) - { - m_pView->doc()->setTypeOfCalc(tmpMethodCalc); - config->writeEntry( "Method of Calc", (int)tmpMethodCalc); - m_pView->calcStatusBarOp(); - m_pView->initCalcMenu(); - } - - double val = valIndent->value(); - if( val != m_pView->doc()->getIndentValue() ) - { - KoUnit::Unit oldUnit = m_pView->doc()->unit(); - m_pView->doc()->setUnit(indentUnit); - m_pView->doc()->setIndentValue( val ); - m_pView->doc()->setUnit(oldUnit); - config->writeEntry( "Indent", KoUnit::fromUserValue( val, indentUnit ) ); - } - - bool active=msgError->isChecked(); - if(active!=m_pView->doc()->getShowMessageError()) - { - m_pView->doc()->setShowMessageError( active); - config->writeEntry( "Msg error" ,(int)active); - } -} - - - -colorParameters::colorParameters( View* _view,TQVBox *box , char *name ) - :TQObject ( box->parent(),name) -{ - m_pView = _view; - config = Factory::global()->config(); - - TQColor _gridColor(TQt::lightGray); - - if ( config->hasGroup("KSpread Color" ) ) - { - config->setGroup( "KSpread Color" ); - _gridColor = config->readColorEntry("GridColor",&_gridColor); - } - - TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Color"), box, "GroupBox" ); - - TQLabel *label = new TQLabel(i18n("&Grid color:"), tmpTQGroupBox,"label20" ); - - gridColor = new KColorButton( _gridColor, - TQt::lightGray, - tmpTQGroupBox ); - TQWhatsThis::add(gridColor, i18n( "Click here to change the grid color ie the color of the borders of each cell." ) ); - label->setBuddy(gridColor); - - TQColor _pbColor(TQt::red); - if ( config->hasGroup("KSpread Color" ) ) - { - config->setGroup( "KSpread Color" ); - _pbColor = config->readColorEntry("PageBorderColor", &_pbColor); - } - - TQLabel * label2 = new TQLabel( i18n("&Page borders:"), tmpTQGroupBox, "label21" ); - - pageBorderColor = new KColorButton( _pbColor, - TQt::red, - tmpTQGroupBox ); - TQWhatsThis::add(pageBorderColor, i18n( "When the View ->Show Page Borders menu item is checked, the page borders are displayed. Click here to choose another color for the borders than the default red." ) ); - - label2->setBuddy(pageBorderColor); -} - -void colorParameters::apply() -{ - TQColor _col = gridColor->color(); - if ( m_pView->doc()->gridColor() != _col ) - { - m_pView->doc()->setGridColor( _col ); - config->setGroup( "KSpread Color" ); - config->writeEntry( "GridColor", _col ); - } - - TQColor _pbColor = pageBorderColor->color(); - if ( m_pView->doc()->pageBorderColor() != _pbColor ) - { - m_pView->doc()->changePageBorderColor( _pbColor ); - config->setGroup( "KSpread Color" ); - config->writeEntry( "PageBorderColor", _pbColor ); - } -} - -void colorParameters::slotDefault() -{ - gridColor->setColor( lightGray ); - pageBorderColor->setColor( red ); -} - - - -configureLayoutPage::configureLayoutPage( View* _view,TQVBox *box , char *name ) - :TQObject ( box->parent(),name) -{ - m_pView = _view; - - TQGroupBox* tmpTQGroupBox = new TQGroupBox( 0, Qt::Vertical, i18n("Default Parameters"), box, "GroupBox" ); - tmpTQGroupBox->layout()->setSpacing(KDialog::spacingHint()); - tmpTQGroupBox->layout()->setMargin(KDialog::marginHint()); - - TQGridLayout *grid1 = new TQGridLayout(tmpTQGroupBox->layout(),8,1); - grid1->addRowSpacing( 0, KDialog::marginHint() ); - grid1->setRowStretch( 7, 10 ); - - config = Factory::global()->config(); - - TQLabel *label=new TQLabel(i18n("Default page &size:"), tmpTQGroupBox); - - grid1->addWidget(label,0,0); - - defaultSizePage=new TQComboBox( tmpTQGroupBox); - label->setBuddy(defaultSizePage); - defaultSizePage->insertStringList( KoPageFormat::allFormats() ); - defaultSizePage->setCurrentItem(1); - TQWhatsThis::add(defaultSizePage, i18n( "Choose the default page size for your worksheet among all the most common page sizes.\nNote that you can overwrite the page size for the current sheet using the Format -> Page Layout... dialog." ) ); - grid1->addWidget(defaultSizePage,1,0); - - label=new TQLabel(i18n("Default page &orientation:"), tmpTQGroupBox); - grid1->addWidget(label,2,0); - - defaultOrientationPage=new TQComboBox( tmpTQGroupBox); - label->setBuddy(defaultOrientationPage); - - TQStringList listType; - listType+=i18n( "Portrait" ); - listType+=i18n( "Landscape" ); - defaultOrientationPage->insertStringList(listType); - defaultOrientationPage->setCurrentItem(0); - TQWhatsThis::add(defaultOrientationPage, i18n( "Choose the sheet orientation: portrait or lanscape.\nNote that you can overwrite the orientation for the current sheet using the Format -> Page Layout... dialog." ) ); - grid1->addWidget(defaultOrientationPage,3,0); - - label=new TQLabel(tmpTQGroupBox); - label->setText(i18n("Default page &unit:")); - grid1->addWidget(label,4,0); - defaultUnit=new TQComboBox( tmpTQGroupBox); - label->setBuddy(defaultUnit); - - defaultUnit->insertStringList(KoUnit::listOfUnitName()); - defaultUnit->setCurrentItem(0); - TQWhatsThis::add(defaultUnit, i18n( "Choose the default unit that will be used in your sheet.\nNote that you can overwrite the unit for the current sheet using the Format -> Page Layout... dialog." ) ); - grid1->addWidget(defaultUnit,5,0); - initCombo(); - -} - -void configureLayoutPage::slotDefault() -{ - defaultSizePage->setCurrentItem(1); - defaultOrientationPage->setCurrentItem(0); - defaultUnit->setCurrentItem(0); -} - -void configureLayoutPage::initCombo() -{ - paper=1; - orientation=0; - unit=0; - if( config->hasGroup("KSpread Page Layout" )) - { - config->setGroup( "KSpread Page Layout" ); - paper=config->readNumEntry( "Default size page" ,1); - orientation=config->readNumEntry( "Default orientation page" ,0); - unit=config->readNumEntry( "Default unit page" ,0); - } - - defaultUnit->setCurrentItem(m_pView->doc()->unit()); - defaultSizePage->setCurrentItem(paper); - defaultOrientationPage->setCurrentItem(orientation); -} - - -void configureLayoutPage::apply() -{ - m_pView->doc()->emitBeginOperation( false ); - config->setGroup( "KSpread Page Layout" ); - - if( paper != defaultSizePage->currentItem() ) - { - unsigned int sizePage = defaultSizePage->currentItem(); - config->writeEntry( "Default size page", sizePage ); - m_pView->activeSheet()->print()->setPaperFormat( (KoFormat)sizePage ); - } - if( orientation != defaultOrientationPage->currentItem() ) - { - unsigned int orientationPage = defaultOrientationPage->currentItem(); - config->writeEntry( "Default orientation page", orientationPage ); - m_pView->activeSheet()->print()->setPaperOrientation( (KoOrientation)orientationPage ); - } - if( unit != defaultUnit->currentItem() ) - { - unsigned int unitPage = defaultUnit->currentItem(); - config->writeEntry( "Default unit page", unitPage ); - m_pView->doc()->setUnit( (KoUnit::Unit)unitPage ); - } - m_pView->slotUpdateView( m_pView->activeSheet() ); -} - -configureSpellPage::configureSpellPage( View* _view,TQVBox *box , char *name ) - :TQObject ( box->parent(),name) -{ - m_pView = _view; - - config = Factory::global()->config(); - - - m_spellConfigWidget = new KSpellConfig( box, "spell_check",m_pView->doc()->getKSpellConfig()/*, false*/); - dontCheckUpperWord = new TQCheckBox( i18n("Skip all uppercase words"),box); - TQWhatsThis::add(dontCheckUpperWord, i18n( "If checked, the words written in uppercase letters are not spell checked. This might be useful if you have a lot of acronyms such as TDE for example." ) ); - dontCheckTitleCase = new TQCheckBox( i18n("Do not check title case"),box); - TQWhatsThis::add(dontCheckTitleCase, i18n( "Check this box if you want the spellchecker to ignore the title case, for example My Own Spreadsheet or My own spreadsheet. If this is unchecked, the spell checker will ask for a uppercase letter in the title nouns." ) ); - - TQWidget* spacer = new TQWidget( box ); - spacer->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); - - if( config->hasGroup("KSpell kspread") ) - { - config->setGroup( "KSpell kspread" ); - - dontCheckUpperWord->setChecked(config->readBoolEntry("KSpell_dont_check_upper_word",false)); - dontCheckTitleCase->setChecked(config->readBoolEntry("KSpell_dont_check_title_case",false)); - } - //m_spellConfigWidget->addIgnoreList( m_pView->doc()->spellListIgnoreAll() ); -} - - -void configureSpellPage::apply() -{ - m_pView->doc()->emitBeginOperation( false ); - - KSpellConfig *_spellConfig = m_spellConfigWidget; - config->setGroup( "KSpell kspread" ); - config->writeEntry ("KSpell_NoRootAffix",(int) _spellConfig->noRootAffix ()); - config->writeEntry ("KSpell_RunTogether", (int) _spellConfig->runTogether ()); - config->writeEntry ("KSpell_Dictionary", _spellConfig->dictionary ()); - config->writeEntry ("KSpell_DictFromList",(int) _spellConfig->dictFromList()); - config->writeEntry ("KSpell_Encoding", (int) _spellConfig->encoding()); - config->writeEntry ("KSpell_Client", _spellConfig->client()); -// m_spellConfigWidget->saveDictionary(); - Doc* doc = m_pView->doc(); - doc->setKSpellConfig(*_spellConfig); - - bool state=dontCheckUpperWord->isChecked(); - config->writeEntry ("KSpell_dont_check_upper_word",(int)state); - doc->setDontCheckUpperWord(state); - - state=dontCheckTitleCase->isChecked(); - config->writeEntry("KSpell_dont_check_title_case",(int)state); - doc->setDontCheckTitleCase(state); - - //m_pView->doc()->addIgnoreWordAllList( m_spellConfigWidget->ignoreList() ); - - m_pView->slotUpdateView( m_pView->activeSheet() ); -} - -void configureSpellPage::slotDefault() -{ - //FIXME - //m_spellConfigWidget->setDefault(); -} - -//// - -configureTTSPage::configureTTSPage( View *_view, TQVBox *box, char *name ) - : TQObject( box->parent(), name ) -{ - Q_UNUSED(_view); - - m_cbSpeakPointerWidget = new TQCheckBox(i18n("Speak widget under &mouse pointer"), box); - m_cbSpeakFocusWidget = new TQCheckBox(i18n("Speak widget with &focus"), box); - m_gbScreenReaderOptions = new TQVGroupBox("", box); - m_gbScreenReaderOptions->setMargin( KDialog::marginHint() ); - m_gbScreenReaderOptions->setInsideSpacing( KDialog::spacingHint() ); - m_cbSpeakTooltips = new TQCheckBox(i18n("Speak &tool tips"), m_gbScreenReaderOptions); - m_cbSpeakWhatsThis = new TQCheckBox(i18n("Speak &What's This"), m_gbScreenReaderOptions); - m_cbSpeakDisabled = new TQCheckBox(i18n("Verbal indication if widget is disabled (grayed)", - "&Say whether disabled"), m_gbScreenReaderOptions); - m_cbSpeakAccelerators = new TQCheckBox(i18n("Spea&k accelerators"), m_gbScreenReaderOptions); - TQHBox* hbAcceleratorPrefix = new TQHBox(m_gbScreenReaderOptions); - TQWidget* spacer = new TQWidget(hbAcceleratorPrefix); - spacer->setMinimumWidth(2 * KDialog::marginHint()); - m_lblAcceleratorPrefix = - new TQLabel(i18n("A word spoken before another word", "Pr&efaced by the word:"), - hbAcceleratorPrefix); - m_leAcceleratorPrefixWord = new TQLineEdit(i18n("Keyboard accelerator, such as Alt+F", "Accelerator"), - hbAcceleratorPrefix); - m_lblAcceleratorPrefix->setBuddy(m_leAcceleratorPrefixWord); - TQHBox* hbPollingInterval = new TQHBox(m_gbScreenReaderOptions); - hbPollingInterval->setMargin( 0 ); - TQLabel* lblPollingInterval = new TQLabel(i18n("&Polling interval:"), hbPollingInterval); - m_iniPollingInterval = new KIntNumInput(hbPollingInterval); - m_iniPollingInterval->setSuffix(" ms"); - m_iniPollingInterval->setRange(100, 5000, 100, true); - lblPollingInterval->setBuddy(m_iniPollingInterval); - - config = Factory::global()->config(); - config->setGroup("TTS"); - m_cbSpeakPointerWidget->setChecked(config->readBoolEntry("SpeakPointerWidget", false)); - m_cbSpeakFocusWidget->setChecked(config->readBoolEntry("SpeakFocusWidget", false)); - m_cbSpeakTooltips->setChecked(config->readBoolEntry("SpeakTooltips", true)); - m_cbSpeakWhatsThis->setChecked(config->readBoolEntry("SpeakWhatsThis", false)); - m_cbSpeakDisabled->setChecked(config->readBoolEntry("SpeakDisabled", true)); - m_cbSpeakAccelerators->setChecked(config->readBoolEntry("SpeakAccelerators", true)); - m_leAcceleratorPrefixWord->setText(config->readEntry("AcceleratorPrefixWord", - i18n("Keyboard accelerator, such as Alt+F", "Accelerator"))); - m_iniPollingInterval->setValue(config->readNumEntry("PollingInterval", 600)); - - screenReaderOptionChanged(); - connect(m_cbSpeakPointerWidget, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); - connect(m_cbSpeakFocusWidget, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); - connect(m_cbSpeakAccelerators, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); -} - -void configureTTSPage::slotDefault() -{ - m_cbSpeakPointerWidget->setChecked(false); - m_cbSpeakFocusWidget->setChecked(false); - m_cbSpeakTooltips->setChecked(true); - m_cbSpeakWhatsThis->setChecked(false); - m_cbSpeakDisabled->setChecked(true); - m_cbSpeakAccelerators->setChecked(true); - m_leAcceleratorPrefixWord->setText(i18n("Keyboard accelerator, such as Alt+F", "Accelerator")); - m_iniPollingInterval->setValue(600); -} - -void configureTTSPage::apply() -{ - config->setGroup("TTS"); - config->writeEntry("SpeakPointerWidget", m_cbSpeakPointerWidget->isChecked()); - config->writeEntry("SpeakFocusWidget", m_cbSpeakFocusWidget->isChecked()); - config->writeEntry("SpeakTooltips", m_cbSpeakTooltips->isChecked()); - config->writeEntry("SpeakWhatsThis", m_cbSpeakWhatsThis->isChecked()); - config->writeEntry("SpeakDisabled", m_cbSpeakDisabled->isChecked()); - config->writeEntry("SpeakAccelerators", m_cbSpeakAccelerators->isChecked()); - config->writeEntry("AcceleratorPrefixWord", m_leAcceleratorPrefixWord->text()); - config->writeEntry("PollingInterval", m_iniPollingInterval->value()); - if (kospeaker) kospeaker->readConfig(config); -} - -void configureTTSPage::screenReaderOptionChanged() -{ - m_gbScreenReaderOptions->setEnabled( - m_cbSpeakPointerWidget->isChecked() || m_cbSpeakFocusWidget->isChecked()); - m_leAcceleratorPrefixWord->setEnabled(m_cbSpeakAccelerators->isChecked()); - m_lblAcceleratorPrefix->setEnabled(m_cbSpeakAccelerators->isChecked()); -} - -#include "kspread_dlg_preference.moc" diff --git a/kspread/dialogs/kspread_dlg_preference.cpp b/kspread/dialogs/kspread_dlg_preference.cpp new file mode 100644 index 00000000..d82af591 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_preference.cpp @@ -0,0 +1,1042 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Raphael Langerhorst + (C) 2002-2004 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 2000-2005 Laurent Montel + (C) 2002 John Dailey + (C) 2002 Philipp Mueller + (C) 2001-2002 David Faure + (C) 2001 Werner Trobin + (C) 2000 Bernd Johannes Wuebben + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include "kspread_doc.h" +#include "kspread_canvas.h" +#include "kspread_view.h" +#include "kspread_locale.h" +#include "kspread_editors.h" + +#include "kspread_dlg_preference.h" + +using namespace KSpread; + +PreferenceDialog::PreferenceDialog( View* parent, const char* /*name*/) + : KDialogBase(KDialogBase::IconList,i18n("Configure KSpread") , + KDialogBase::Ok | KDialogBase::Cancel| KDialogBase::Default, + KDialogBase::Ok) + +{ + m_pView=parent; + + connect(this, TQT_SIGNAL(okClicked()),this,TQT_SLOT(slotApply())); + + TQVBox *page2=addVBoxPage(i18n("Locale Settings"), TQString(),BarIcon("go-home",TDEIcon::SizeMedium)); + _localePage=new parameterLocale(parent,page2 ); + + TQVBox *page3=addVBoxPage(i18n("Interface"), TQString(),BarIcon("signature", TDEIcon::SizeMedium) ); + _configure = new configure(parent,page3 ); + + TQVBox * page4=addVBoxPage(i18n("Misc"), TQString(),BarIcon("misc",TDEIcon::SizeMedium) ); + _miscParameter = new miscParameters(parent,page4 ); + + TQVBox *page5=addVBoxPage(i18n("Color"), TQString(),BarIcon("colorize",TDEIcon::SizeMedium) ); + _colorParameter=new colorParameters(parent,page5 ); + + TQVBox *page6=addVBoxPage(i18n("Page Layout"), TQString(),BarIcon("edit",TDEIcon::SizeMedium) ); + _layoutPage=new configureLayoutPage(parent,page6 ); + + TQVBox *page7 = addVBoxPage( i18n("Spelling"), i18n("Spell Checker Behavior"), + BarIcon("tools-check-spelling", TDEIcon::SizeMedium) ); + _spellPage=new configureSpellPage(parent,page7); + + if (KoSpeaker::isKttsdInstalled()) { + TQVBox *page8 = addVBoxPage( i18n("Abbreviation for Text-to-Speech", "TTS"), + i18n("Text-to-Speech Settings"), BarIcon("access", TDEIcon::SizeMedium) ); + _ttsPage=new configureTTSPage(parent, page8); + } else _ttsPage = 0; + +} + +void PreferenceDialog::openPage(int flags) +{ + if(flags & KS_LOCALE) + showPage( 0 ); + else if(flags & KS_INTERFACE) + showPage( 1 ); + else if(flags & KS_MISC) + showPage( 2 ); + else if(flags & KS_COLOR) + showPage( 3 ); + else if(flags & KS_LAYOUT) + showPage( 4 ); + else if(flags & KS_SPELLING) + showPage( 5 ); +} + +void PreferenceDialog::slotApply() +{ + m_pView->doc()->emitBeginOperation( false ); + _configure->apply(); + _miscParameter->apply(); + _colorParameter->apply(); + _layoutPage->apply(); + _spellPage->apply(); + _localePage->apply(); + if (_ttsPage) _ttsPage->apply(); + m_pView->doc()->refreshInterface(); + m_pView->slotUpdateView( m_pView->activeSheet() ); +} + +void PreferenceDialog::slotDefault() +{ + switch(activePageIndex()) + { + case 1: + _configure->slotDefault(); + break; + case 2: + _miscParameter->slotDefault(); + break; + case 3: + _colorParameter->slotDefault(); + break; + case 4: + _layoutPage->slotDefault(); + break; + case 5: + _spellPage->slotDefault(); + break; + case 6: + _ttsPage->slotDefault(); + break; + default: + break; + } +} + + +parameterLocale::parameterLocale( View* _view, TQVBox *box , char *name ) + :TQObject ( box->parent(),name) +{ + m_pView = _view; + m_bUpdateLocale=false; + TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Settings"), box, "GroupBox" ); + + TDELocale* locale=_view->doc()->locale(); + + m_language=new TQLabel( tmpTQGroupBox,"label"); + m_number=new TQLabel( tmpTQGroupBox,"label6"); + m_date=new TQLabel( tmpTQGroupBox,"label1"); + m_shortDate=new TQLabel( tmpTQGroupBox,"label5"); + m_time=new TQLabel( tmpTQGroupBox,"label2"); + m_money=new TQLabel( tmpTQGroupBox,"label3"); + + updateToMatchLocale(locale); + + m_updateButton=new TQPushButton ( i18n("&Update Locale Settings"), tmpTQGroupBox); + connect(m_updateButton, TQT_SIGNAL(clicked()),this,TQT_SLOT(updateDefaultSystemConfig())); +} + +void parameterLocale::apply() +{ + if (m_bUpdateLocale) + { + m_pView->doc()->emitBeginOperation( false ); + m_pView->doc()->refreshLocale(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + } +} + +void parameterLocale::updateDefaultSystemConfig() +{ + m_bUpdateLocale=true; + static_cast(m_pView->doc()->locale())->defaultSystemConfig( ); + TDELocale* locale=m_pView->doc()->locale(); + updateToMatchLocale( locale ); +} + +void parameterLocale::updateToMatchLocale(TDELocale* locale) +{ + m_language->setText( i18n("Language: %1").arg( locale->language() )); + m_number->setText( i18n("Default number format: %1").arg( locale->formatNumber(12.55) )); + m_date->setText( i18n("Long date format: %1").arg( locale->formatDate( TQDate::currentDate() ))); + m_shortDate->setText( i18n("Short date format: %1").arg( locale->formatDate( TQDate::currentDate() ,true) )); + m_time->setText( i18n("Time format: %1").arg( locale->formatTime( TQTime::currentTime() ) )); + m_money->setText( i18n("Currency format: %1").arg( locale->formatMoney(12.55) )); +} + +configure::configure( View* _view, TQVBox *box , char *name ) + :TQObject ( box->parent(),name) + { + m_pView = _view; + + bool vertical=true; + bool horizontal=true; + bool rowHeader=true; + bool colHeader=true; + bool tabbar=true; + bool formulaBar=true; + bool statusBar=true; + m_oldBackupFile = true; + + TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Settings"), box, "GroupBox" ); + + config = Factory::global()->config(); + int _page=1; + + oldRecent=10; + oldAutoSaveValue=KoDocument::defaultAutoSave()/60; + + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + _page=config->readNumEntry( "NbPage" ,1) ; + horizontal=config->readBoolEntry("Horiz ScrollBar",true); + vertical=config->readBoolEntry("Vert ScrollBar",true); + colHeader=config->readBoolEntry("Column Header",true); + rowHeader=config->readBoolEntry("Row Header",true); + tabbar=config->readBoolEntry("Tabbar",true); + formulaBar=config->readBoolEntry("Formula bar",true); + statusBar=config->readBoolEntry("Status bar",true); + oldRecent=config->readNumEntry( "NbRecentFile" ,10); + oldAutoSaveValue=config->readNumEntry("AutoSave",KoDocument::defaultAutoSave()/60); + m_oldBackupFile=config->readBoolEntry("BackupFile",m_oldBackupFile); + } + nbPage=new KIntNumInput(_page, tmpTQGroupBox , 10); + nbPage->setRange(1, 10, 1); + nbPage->setLabel(i18n("Number of sheets open at the &beginning:")); + TQWhatsThis::add(nbPage, i18n( "Controls how many worksheets will be created if the option Start with an empty document is chosen when KSpread is started." ) ); + + nbRecentFile=new KIntNumInput(oldRecent, tmpTQGroupBox , 10); + nbRecentFile->setRange(1, 20, 1); + nbRecentFile->setLabel(i18n("&Number of files to show in Recent Files list:")); + TQWhatsThis::add(nbRecentFile, i18n( "Controls the maximum number of filenames that are shown when you select File-> Open Recent." ) ); + + autoSaveDelay=new KIntNumInput(oldAutoSaveValue, tmpTQGroupBox , 10); + autoSaveDelay->setRange(0, 60, 1); + autoSaveDelay->setLabel(i18n("Au&tosave delay (minutes):")); + autoSaveDelay->setSpecialValueText(i18n("Do not save automatically")); + autoSaveDelay->setSuffix(i18n("min")); + TQWhatsThis::add(autoSaveDelay, i18n( "Here you can select the time between autosaves, or disable this feature altogether by choosing Do not save automatically (drag the slider to the far left)." ) ); + + m_createBackupFile = new TQCheckBox( i18n("Create backup files"), tmpTQGroupBox ); + m_createBackupFile->setChecked( m_oldBackupFile ); + TQWhatsThis::add(m_createBackupFile, i18n( "Check this box if you want some backup files created. This is checked per default." ) ); + + showVScrollBar=new TQCheckBox(i18n("Show &vertical scrollbar"),tmpTQGroupBox); + showVScrollBar->setChecked(vertical); + TQWhatsThis::add(showVScrollBar, i18n( "Check or uncheck this box to show or hide the vertical scrollbar in all sheets." ) ); + + showHScrollBar=new TQCheckBox(i18n("Show &horizontal scrollbar"),tmpTQGroupBox); + showHScrollBar->setChecked(horizontal); + TQWhatsThis::add(showHScrollBar, i18n( "Check or uncheck this box to show or hide the horizontal scrollbar in all sheets." ) ); + + showColHeader=new TQCheckBox(i18n("Show c&olumn header"),tmpTQGroupBox); + showColHeader->setChecked(colHeader); + TQWhatsThis::add(showColHeader, i18n( "Check this box to show the column letters across the top of each worksheet." ) ); + showRowHeader=new TQCheckBox(i18n("Show &row header"),tmpTQGroupBox); + showRowHeader->setChecked(rowHeader); + TQWhatsThis::add(showRowHeader, i18n( "Check this box to show the row numbers down the left side." ) ); + + showTabBar =new TQCheckBox(i18n("Show ta&bs"),tmpTQGroupBox); + showTabBar->setChecked(tabbar); + TQWhatsThis::add(showTabBar, i18n( "This check box controls whether the sheet tabs are shown at the bottom of the worksheet." ) ); + + showFormulaBar =new TQCheckBox(i18n("Sho&w formula toolbar"),tmpTQGroupBox); + showFormulaBar->setChecked(formulaBar); + TQWhatsThis::add(showFormulaBar, i18n( "Here is where you can choose to show or hide the Formula bar." ) ); + + showStatusBar =new TQCheckBox(i18n("Show stat&us bar"),tmpTQGroupBox); + showStatusBar->setChecked(statusBar); + TQWhatsThis::add(showStatusBar, i18n( "Uncheck this box if you want to hide the status bar." ) ); +} + + +void configure::slotDefault() +{ + showHScrollBar->setChecked(true); + showRowHeader->setChecked(true); + showVScrollBar->setChecked(true); + showColHeader->setChecked(true); + showTabBar->setChecked(true); + showFormulaBar->setChecked(true); + showStatusBar->setChecked(true); + nbPage->setValue(1); + nbRecentFile->setValue(10); + autoSaveDelay->setValue(KoDocument::defaultAutoSave()/60); + m_createBackupFile->setChecked( true ); +} + + +void configure::apply() +{ + m_pView->doc()->emitBeginOperation( false ); + config->setGroup( "Parameters" ); + config->writeEntry( "NbPage", nbPage->value()); + Doc *doc =m_pView->doc(); + bool active=true; + active=showHScrollBar->isChecked(); + if( m_pView->horzScrollBar()->isVisible()!=active) + { + config->writeEntry( "Horiz ScrollBar",active); + if( active) + m_pView->horzScrollBar()->show(); + else + m_pView->horzScrollBar()->hide(); + doc->setShowHorizontalScrollBar(active); + } + active=showVScrollBar->isChecked(); + if( m_pView->vertScrollBar()->isVisible()!=active) + { + config->writeEntry( "Vert ScrollBar", active); + if(active) + m_pView->vertScrollBar()->show(); + else + m_pView->vertScrollBar()->hide(); + doc->setShowVerticalScrollBar(active); + + } + active=showColHeader->isChecked(); + if( m_pView->hBorderWidget()->isVisible()!=active) + { + config->writeEntry( "Column Header", active); + if( active) + m_pView->hBorderWidget()->show(); + else + m_pView->hBorderWidget()->hide(); + doc->setShowColHeader(active); + } + + active=showRowHeader->isChecked(); + if( m_pView->vBorderWidget()->isVisible()!=active) + { + config->writeEntry( "Row Header", active); + if( active) + m_pView->vBorderWidget()->show(); + else + m_pView->vBorderWidget()->hide(); + doc->setShowRowHeader(active); + } + + active=showTabBar->isChecked(); + if(m_pView->tabBar()->isVisible()!=active) + { + config->writeEntry( "Tabbar", active); + if(active) + m_pView->tabBar()->show(); + else + m_pView->tabBar()->hide(); + doc->setShowTabBar(active); + } + + active=showFormulaBar->isChecked(); + if(m_pView->posWidget()->isVisible()!=active) + { + config->writeEntry( "Formula bar",active); + m_pView->editWidget()->showEditWidget(active); + if(active) + m_pView->posWidget()->show(); + else + m_pView->posWidget()->hide(); + doc->setShowFormulaBar(active); + } + + active=showStatusBar->isChecked(); + config->writeEntry( "Status bar",active); + m_pView->showStatusBar( active ); + + int val=nbRecentFile->value(); + if( oldRecent!= val) + { + config->writeEntry( "NbRecentFile",val); + m_pView->changeNbOfRecentFiles(val); + } + val=autoSaveDelay->value(); + if(val!=oldAutoSaveValue) + { + config->writeEntry( "AutoSave", val ); + doc->setAutoSave(val*60); + } + + bool state =m_createBackupFile->isChecked(); + if(state!=m_oldBackupFile) + { + config->writeEntry( "BackupFile", state ); + doc->setBackupFile( state); + m_oldBackupFile=state; + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); +} + + +miscParameters::miscParameters( View* _view,TQVBox *box, char *name ) + :TQObject ( box->parent(),name) + { + m_pView = _view; + + + TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Misc"), box, "GroupBox" ); + + config = Factory::global()->config(); + indentUnit = _view->doc()->unit(); + double _indent = KoUnit::toUserValue( 10.0, indentUnit); + bool m_bMsgError=false; + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + _indent = config->readDoubleNumEntry( "Indent" , _indent ) ; + m_bMsgError=config->readBoolEntry( "Msg error" ,false) ; + } + + if( config->hasGroup("Misc") ) + { + config->setGroup( "Misc" ); + m_oldNbRedo=config->readNumEntry("UndoRedo",m_oldNbRedo); + } + + m_undoRedoLimit=new KIntNumInput( m_oldNbRedo, tmpTQGroupBox ); + m_undoRedoLimit->setLabel(i18n("Undo/redo limit:")); + m_undoRedoLimit->setRange(10, 60, 1); + + + TQLabel *label=new TQLabel(i18n("&Completion mode:"), tmpTQGroupBox); + + typeCompletion=new TQComboBox(tmpTQGroupBox); + label->setBuddy(typeCompletion); + TQWhatsThis::add(typeCompletion, i18n( "Lets you choose the (auto) text completion mode from a range of options in the drop down selection box." ) ); + TQStringList listType; + listType+=i18n("None"); + listType+=i18n("Manual"); + listType+=i18n("Popup"); + listType+=i18n("Automatic"); + listType+=i18n("Semi-Automatic"); + typeCompletion->insertStringList(listType); + typeCompletion->setCurrentItem(0); + comboChanged=false; + connect(typeCompletion,TQT_SIGNAL(activated( const TQString & )),this,TQT_SLOT(slotTextComboChanged(const TQString &))); + + label=new TQLabel(i18n("&Pressing enter moves cell cursor:"), tmpTQGroupBox); + typeOfMove=new TQComboBox( tmpTQGroupBox); + label->setBuddy(typeOfMove); + listType.clear(); + listType+=i18n("Down"); + listType+=i18n("Up"); + listType+=i18n("Right"); + listType+=i18n("Left"); + listType+=i18n("Down, First Column"); + typeOfMove->insertStringList(listType); + typeOfMove->setCurrentItem(0); + TQWhatsThis::add(typeOfMove, i18n( "When you have selected a cell, pressing the Enter key will move the cell cursor one cell left, right, up or down, as determined by this setting." ) ); + + label=new TQLabel(i18n("&Method of calc:"), tmpTQGroupBox); + + typeCalc=new TQComboBox( tmpTQGroupBox); + label->setBuddy(typeCalc); + TQStringList listTypeCalc; + listTypeCalc+=i18n("Sum"); + listTypeCalc+=i18n("Min"); + listTypeCalc+=i18n("Max"); + listTypeCalc+=i18n("Average"); + listTypeCalc+=i18n("Count"); + listTypeCalc+=i18n("CountA"); + listTypeCalc+=i18n("None"); + typeCalc->insertStringList(listTypeCalc); + typeCalc->setCurrentItem(0); + TQWhatsThis::add(typeCalc, i18n( "This drop down selection box can be used to choose the calculation performed by the Statusbar Summary function." ) ); + +// valIndent = new KDoubleNumInput( _indent, tmpTQGroupBox , 10.0 ); + valIndent = new KDoubleNumInput( tmpTQGroupBox ); + valIndent->setRange( KoUnit::toUserValue( 0.0, indentUnit ), + KoUnit::toUserValue( 400.0, indentUnit ), + KoUnit::toUserValue( 10.0, indentUnit) ); +// valIndent->setRange( 0.0, 100.0, 10.0 ); + valIndent->setValue ( KoUnit::toUserValue( _indent, indentUnit ) ); + TQWhatsThis::add(valIndent, i18n( "Lets you define the amount of indenting used by the Increase Indent and Decrease Indent option in the Format menu." ) ); + valIndent->setLabel(i18n("&Indentation step (%1):").arg(KoUnit::unitName(indentUnit))); + + msgError= new TQCheckBox(i18n("&Show error message for invalid formulae"),tmpTQGroupBox); + msgError->setChecked(m_bMsgError); + TQWhatsThis::add(msgError, i18n( "If this box is checked a message box will pop up when what you have entered into a cell cannot be understood by KSpread." ) ); + + initComboBox(); +} + +void miscParameters::slotTextComboChanged(const TQString &) +{ + comboChanged=true; +} + +void miscParameters::initComboBox() +{ + TDEGlobalSettings::Completion tmpCompletion=TDEGlobalSettings::CompletionAuto; + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + tmpCompletion=( TDEGlobalSettings::Completion)config->readNumEntry( "Completion Mode" ,TDEGlobalSettings::CompletionAuto) ; + config->writeEntry( "Completion Mode", (int)tmpCompletion); + } +switch(tmpCompletion ) + { + case TDEGlobalSettings::CompletionNone: + typeCompletion->setCurrentItem(0); + break; + case TDEGlobalSettings::CompletionAuto: + typeCompletion->setCurrentItem(3); + break; + case TDEGlobalSettings::CompletionMan: + typeCompletion->setCurrentItem(4); + break; + case TDEGlobalSettings::CompletionShell: + typeCompletion->setCurrentItem(1); + break; + case TDEGlobalSettings::CompletionPopup: + typeCompletion->setCurrentItem(2); + break; + default : + typeCompletion->setCurrentItem(0); + break; + } +switch( m_pView->doc()->getMoveToValue( )) + { + case KSpread::Bottom: + typeOfMove->setCurrentItem(0); + break; + case KSpread::Left: + typeOfMove->setCurrentItem(3); + break; + case KSpread::Top: + typeOfMove->setCurrentItem(1); + break; + case KSpread::Right: + typeOfMove->setCurrentItem(2); + break; + case KSpread::BottomFirst: + typeOfMove->setCurrentItem(4); + break; + default : + typeOfMove->setCurrentItem(0); + break; + } + +switch( m_pView->doc()->getTypeOfCalc()) + { + case SumOfNumber: + typeCalc->setCurrentItem(0); + break; + case Min: + typeCalc->setCurrentItem(1); + break; + case Max: + typeCalc->setCurrentItem(2); + break; + case Average: + typeCalc->setCurrentItem(3); + break; + case Count: + typeCalc->setCurrentItem(4); + break; + case CountA: + typeCalc->setCurrentItem(5); + break; + case NoneCalc: + typeCalc->setCurrentItem(6); + break; + default : + typeCalc->setCurrentItem(0); + break; + } + +} + +void miscParameters::slotDefault() +{ + m_undoRedoLimit->setValue(30); + valIndent->setValue( KoUnit::toUserValue( 10.0, indentUnit) ); + typeCompletion->setCurrentItem(3); + typeOfMove->setCurrentItem(0); + msgError->setChecked(false); + typeCalc->setCurrentItem(0); +} + + +void miscParameters::apply() +{ + kdDebug() << "Applying misc preferences" << endl; + + config->setGroup( "Misc" ); + int const newUndo=m_undoRedoLimit->value(); + if( newUndo!=m_oldNbRedo ) + { + config->writeEntry("UndoRedo",newUndo); + m_pView->doc()->setUndoRedoLimit(newUndo); + m_oldNbRedo=newUndo; + } + + config->setGroup( "Parameters" ); + TDEGlobalSettings::Completion tmpCompletion=TDEGlobalSettings::CompletionNone; + + switch(typeCompletion->currentItem()) + { + case 0: + tmpCompletion=TDEGlobalSettings::CompletionNone; + break; + case 1: + tmpCompletion=TDEGlobalSettings::CompletionShell; + break; + case 2: + tmpCompletion=TDEGlobalSettings::CompletionPopup; + break; + case 3: + tmpCompletion=TDEGlobalSettings::CompletionAuto; + break; + case 4: + tmpCompletion=TDEGlobalSettings::CompletionMan; + break; + } + + + if(comboChanged) + { + m_pView->doc()->setCompletionMode(tmpCompletion); + config->writeEntry( "Completion Mode", (int)tmpCompletion); + } + + KSpread::MoveTo tmpMoveTo=KSpread::Bottom; + switch(typeOfMove->currentItem()) + { + case 0: + tmpMoveTo=KSpread::Bottom; + break; + case 1: + tmpMoveTo=KSpread::Top; + break; + case 2: + tmpMoveTo=KSpread::Right; + break; + case 3: + tmpMoveTo=KSpread::Left; + break; + case 4: + tmpMoveTo=KSpread::BottomFirst; + break; + } + if(tmpMoveTo!=m_pView->doc()->getMoveToValue()) + { + m_pView->doc()->setMoveToValue(tmpMoveTo); + config->writeEntry( "Move", (int)tmpMoveTo); + } + + MethodOfCalc tmpMethodCalc=SumOfNumber; + switch(typeCalc->currentItem()) + { + case 0: + tmpMethodCalc =SumOfNumber; + break; + case 1: + tmpMethodCalc=Min; + break; + case 2: + tmpMethodCalc=Max; + break; + case 3: + tmpMethodCalc=Average; + break; + case 4: + tmpMethodCalc=Count; + break; + case 5: + tmpMethodCalc=CountA; + break; + case 6: + tmpMethodCalc=NoneCalc; + break; + + } + if(tmpMethodCalc!=m_pView->doc()->getTypeOfCalc()) + { + m_pView->doc()->setTypeOfCalc(tmpMethodCalc); + config->writeEntry( "Method of Calc", (int)tmpMethodCalc); + m_pView->calcStatusBarOp(); + m_pView->initCalcMenu(); + } + + double val = valIndent->value(); + if( val != m_pView->doc()->getIndentValue() ) + { + KoUnit::Unit oldUnit = m_pView->doc()->unit(); + m_pView->doc()->setUnit(indentUnit); + m_pView->doc()->setIndentValue( val ); + m_pView->doc()->setUnit(oldUnit); + config->writeEntry( "Indent", KoUnit::fromUserValue( val, indentUnit ) ); + } + + bool active=msgError->isChecked(); + if(active!=m_pView->doc()->getShowMessageError()) + { + m_pView->doc()->setShowMessageError( active); + config->writeEntry( "Msg error" ,(int)active); + } +} + + + +colorParameters::colorParameters( View* _view,TQVBox *box , char *name ) + :TQObject ( box->parent(),name) +{ + m_pView = _view; + config = Factory::global()->config(); + + TQColor _gridColor(TQt::lightGray); + + if ( config->hasGroup("KSpread Color" ) ) + { + config->setGroup( "KSpread Color" ); + _gridColor = config->readColorEntry("GridColor",&_gridColor); + } + + TQGroupBox* tmpTQGroupBox = new TQVGroupBox( i18n("Color"), box, "GroupBox" ); + + TQLabel *label = new TQLabel(i18n("&Grid color:"), tmpTQGroupBox,"label20" ); + + gridColor = new KColorButton( _gridColor, + TQt::lightGray, + tmpTQGroupBox ); + TQWhatsThis::add(gridColor, i18n( "Click here to change the grid color ie the color of the borders of each cell." ) ); + label->setBuddy(gridColor); + + TQColor _pbColor(TQt::red); + if ( config->hasGroup("KSpread Color" ) ) + { + config->setGroup( "KSpread Color" ); + _pbColor = config->readColorEntry("PageBorderColor", &_pbColor); + } + + TQLabel * label2 = new TQLabel( i18n("&Page borders:"), tmpTQGroupBox, "label21" ); + + pageBorderColor = new KColorButton( _pbColor, + TQt::red, + tmpTQGroupBox ); + TQWhatsThis::add(pageBorderColor, i18n( "When the View ->Show Page Borders menu item is checked, the page borders are displayed. Click here to choose another color for the borders than the default red." ) ); + + label2->setBuddy(pageBorderColor); +} + +void colorParameters::apply() +{ + TQColor _col = gridColor->color(); + if ( m_pView->doc()->gridColor() != _col ) + { + m_pView->doc()->setGridColor( _col ); + config->setGroup( "KSpread Color" ); + config->writeEntry( "GridColor", _col ); + } + + TQColor _pbColor = pageBorderColor->color(); + if ( m_pView->doc()->pageBorderColor() != _pbColor ) + { + m_pView->doc()->changePageBorderColor( _pbColor ); + config->setGroup( "KSpread Color" ); + config->writeEntry( "PageBorderColor", _pbColor ); + } +} + +void colorParameters::slotDefault() +{ + gridColor->setColor( lightGray ); + pageBorderColor->setColor( red ); +} + + + +configureLayoutPage::configureLayoutPage( View* _view,TQVBox *box , char *name ) + :TQObject ( box->parent(),name) +{ + m_pView = _view; + + TQGroupBox* tmpTQGroupBox = new TQGroupBox( 0, Qt::Vertical, i18n("Default Parameters"), box, "GroupBox" ); + tmpTQGroupBox->layout()->setSpacing(KDialog::spacingHint()); + tmpTQGroupBox->layout()->setMargin(KDialog::marginHint()); + + TQGridLayout *grid1 = new TQGridLayout(tmpTQGroupBox->layout(),8,1); + grid1->addRowSpacing( 0, KDialog::marginHint() ); + grid1->setRowStretch( 7, 10 ); + + config = Factory::global()->config(); + + TQLabel *label=new TQLabel(i18n("Default page &size:"), tmpTQGroupBox); + + grid1->addWidget(label,0,0); + + defaultSizePage=new TQComboBox( tmpTQGroupBox); + label->setBuddy(defaultSizePage); + defaultSizePage->insertStringList( KoPageFormat::allFormats() ); + defaultSizePage->setCurrentItem(1); + TQWhatsThis::add(defaultSizePage, i18n( "Choose the default page size for your worksheet among all the most common page sizes.\nNote that you can overwrite the page size for the current sheet using the Format -> Page Layout... dialog." ) ); + grid1->addWidget(defaultSizePage,1,0); + + label=new TQLabel(i18n("Default page &orientation:"), tmpTQGroupBox); + grid1->addWidget(label,2,0); + + defaultOrientationPage=new TQComboBox( tmpTQGroupBox); + label->setBuddy(defaultOrientationPage); + + TQStringList listType; + listType+=i18n( "Portrait" ); + listType+=i18n( "Landscape" ); + defaultOrientationPage->insertStringList(listType); + defaultOrientationPage->setCurrentItem(0); + TQWhatsThis::add(defaultOrientationPage, i18n( "Choose the sheet orientation: portrait or lanscape.\nNote that you can overwrite the orientation for the current sheet using the Format -> Page Layout... dialog." ) ); + grid1->addWidget(defaultOrientationPage,3,0); + + label=new TQLabel(tmpTQGroupBox); + label->setText(i18n("Default page &unit:")); + grid1->addWidget(label,4,0); + defaultUnit=new TQComboBox( tmpTQGroupBox); + label->setBuddy(defaultUnit); + + defaultUnit->insertStringList(KoUnit::listOfUnitName()); + defaultUnit->setCurrentItem(0); + TQWhatsThis::add(defaultUnit, i18n( "Choose the default unit that will be used in your sheet.\nNote that you can overwrite the unit for the current sheet using the Format -> Page Layout... dialog." ) ); + grid1->addWidget(defaultUnit,5,0); + initCombo(); + +} + +void configureLayoutPage::slotDefault() +{ + defaultSizePage->setCurrentItem(1); + defaultOrientationPage->setCurrentItem(0); + defaultUnit->setCurrentItem(0); +} + +void configureLayoutPage::initCombo() +{ + paper=1; + orientation=0; + unit=0; + if( config->hasGroup("KSpread Page Layout" )) + { + config->setGroup( "KSpread Page Layout" ); + paper=config->readNumEntry( "Default size page" ,1); + orientation=config->readNumEntry( "Default orientation page" ,0); + unit=config->readNumEntry( "Default unit page" ,0); + } + + defaultUnit->setCurrentItem(m_pView->doc()->unit()); + defaultSizePage->setCurrentItem(paper); + defaultOrientationPage->setCurrentItem(orientation); +} + + +void configureLayoutPage::apply() +{ + m_pView->doc()->emitBeginOperation( false ); + config->setGroup( "KSpread Page Layout" ); + + if( paper != defaultSizePage->currentItem() ) + { + unsigned int sizePage = defaultSizePage->currentItem(); + config->writeEntry( "Default size page", sizePage ); + m_pView->activeSheet()->print()->setPaperFormat( (KoFormat)sizePage ); + } + if( orientation != defaultOrientationPage->currentItem() ) + { + unsigned int orientationPage = defaultOrientationPage->currentItem(); + config->writeEntry( "Default orientation page", orientationPage ); + m_pView->activeSheet()->print()->setPaperOrientation( (KoOrientation)orientationPage ); + } + if( unit != defaultUnit->currentItem() ) + { + unsigned int unitPage = defaultUnit->currentItem(); + config->writeEntry( "Default unit page", unitPage ); + m_pView->doc()->setUnit( (KoUnit::Unit)unitPage ); + } + m_pView->slotUpdateView( m_pView->activeSheet() ); +} + +configureSpellPage::configureSpellPage( View* _view,TQVBox *box , char *name ) + :TQObject ( box->parent(),name) +{ + m_pView = _view; + + config = Factory::global()->config(); + + + m_spellConfigWidget = new KSpellConfig( box, "spell_check",m_pView->doc()->getKSpellConfig()/*, false*/); + dontCheckUpperWord = new TQCheckBox( i18n("Skip all uppercase words"),box); + TQWhatsThis::add(dontCheckUpperWord, i18n( "If checked, the words written in uppercase letters are not spell checked. This might be useful if you have a lot of acronyms such as TDE for example." ) ); + dontCheckTitleCase = new TQCheckBox( i18n("Do not check title case"),box); + TQWhatsThis::add(dontCheckTitleCase, i18n( "Check this box if you want the spellchecker to ignore the title case, for example My Own Spreadsheet or My own spreadsheet. If this is unchecked, the spell checker will ask for a uppercase letter in the title nouns." ) ); + + TQWidget* spacer = new TQWidget( box ); + spacer->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); + + if( config->hasGroup("KSpell kspread") ) + { + config->setGroup( "KSpell kspread" ); + + dontCheckUpperWord->setChecked(config->readBoolEntry("KSpell_dont_check_upper_word",false)); + dontCheckTitleCase->setChecked(config->readBoolEntry("KSpell_dont_check_title_case",false)); + } + //m_spellConfigWidget->addIgnoreList( m_pView->doc()->spellListIgnoreAll() ); +} + + +void configureSpellPage::apply() +{ + m_pView->doc()->emitBeginOperation( false ); + + KSpellConfig *_spellConfig = m_spellConfigWidget; + config->setGroup( "KSpell kspread" ); + config->writeEntry ("KSpell_NoRootAffix",(int) _spellConfig->noRootAffix ()); + config->writeEntry ("KSpell_RunTogether", (int) _spellConfig->runTogether ()); + config->writeEntry ("KSpell_Dictionary", _spellConfig->dictionary ()); + config->writeEntry ("KSpell_DictFromList",(int) _spellConfig->dictFromList()); + config->writeEntry ("KSpell_Encoding", (int) _spellConfig->encoding()); + config->writeEntry ("KSpell_Client", _spellConfig->client()); +// m_spellConfigWidget->saveDictionary(); + Doc* doc = m_pView->doc(); + doc->setKSpellConfig(*_spellConfig); + + bool state=dontCheckUpperWord->isChecked(); + config->writeEntry ("KSpell_dont_check_upper_word",(int)state); + doc->setDontCheckUpperWord(state); + + state=dontCheckTitleCase->isChecked(); + config->writeEntry("KSpell_dont_check_title_case",(int)state); + doc->setDontCheckTitleCase(state); + + //m_pView->doc()->addIgnoreWordAllList( m_spellConfigWidget->ignoreList() ); + + m_pView->slotUpdateView( m_pView->activeSheet() ); +} + +void configureSpellPage::slotDefault() +{ + //FIXME + //m_spellConfigWidget->setDefault(); +} + +//// + +configureTTSPage::configureTTSPage( View *_view, TQVBox *box, char *name ) + : TQObject( box->parent(), name ) +{ + Q_UNUSED(_view); + + m_cbSpeakPointerWidget = new TQCheckBox(i18n("Speak widget under &mouse pointer"), box); + m_cbSpeakFocusWidget = new TQCheckBox(i18n("Speak widget with &focus"), box); + m_gbScreenReaderOptions = new TQVGroupBox("", box); + m_gbScreenReaderOptions->setMargin( KDialog::marginHint() ); + m_gbScreenReaderOptions->setInsideSpacing( KDialog::spacingHint() ); + m_cbSpeakTooltips = new TQCheckBox(i18n("Speak &tool tips"), m_gbScreenReaderOptions); + m_cbSpeakWhatsThis = new TQCheckBox(i18n("Speak &What's This"), m_gbScreenReaderOptions); + m_cbSpeakDisabled = new TQCheckBox(i18n("Verbal indication if widget is disabled (grayed)", + "&Say whether disabled"), m_gbScreenReaderOptions); + m_cbSpeakAccelerators = new TQCheckBox(i18n("Spea&k accelerators"), m_gbScreenReaderOptions); + TQHBox* hbAcceleratorPrefix = new TQHBox(m_gbScreenReaderOptions); + TQWidget* spacer = new TQWidget(hbAcceleratorPrefix); + spacer->setMinimumWidth(2 * KDialog::marginHint()); + m_lblAcceleratorPrefix = + new TQLabel(i18n("A word spoken before another word", "Pr&efaced by the word:"), + hbAcceleratorPrefix); + m_leAcceleratorPrefixWord = new TQLineEdit(i18n("Keyboard accelerator, such as Alt+F", "Accelerator"), + hbAcceleratorPrefix); + m_lblAcceleratorPrefix->setBuddy(m_leAcceleratorPrefixWord); + TQHBox* hbPollingInterval = new TQHBox(m_gbScreenReaderOptions); + hbPollingInterval->setMargin( 0 ); + TQLabel* lblPollingInterval = new TQLabel(i18n("&Polling interval:"), hbPollingInterval); + m_iniPollingInterval = new KIntNumInput(hbPollingInterval); + m_iniPollingInterval->setSuffix(" ms"); + m_iniPollingInterval->setRange(100, 5000, 100, true); + lblPollingInterval->setBuddy(m_iniPollingInterval); + + config = Factory::global()->config(); + config->setGroup("TTS"); + m_cbSpeakPointerWidget->setChecked(config->readBoolEntry("SpeakPointerWidget", false)); + m_cbSpeakFocusWidget->setChecked(config->readBoolEntry("SpeakFocusWidget", false)); + m_cbSpeakTooltips->setChecked(config->readBoolEntry("SpeakTooltips", true)); + m_cbSpeakWhatsThis->setChecked(config->readBoolEntry("SpeakWhatsThis", false)); + m_cbSpeakDisabled->setChecked(config->readBoolEntry("SpeakDisabled", true)); + m_cbSpeakAccelerators->setChecked(config->readBoolEntry("SpeakAccelerators", true)); + m_leAcceleratorPrefixWord->setText(config->readEntry("AcceleratorPrefixWord", + i18n("Keyboard accelerator, such as Alt+F", "Accelerator"))); + m_iniPollingInterval->setValue(config->readNumEntry("PollingInterval", 600)); + + screenReaderOptionChanged(); + connect(m_cbSpeakPointerWidget, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); + connect(m_cbSpeakFocusWidget, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); + connect(m_cbSpeakAccelerators, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(screenReaderOptionChanged())); +} + +void configureTTSPage::slotDefault() +{ + m_cbSpeakPointerWidget->setChecked(false); + m_cbSpeakFocusWidget->setChecked(false); + m_cbSpeakTooltips->setChecked(true); + m_cbSpeakWhatsThis->setChecked(false); + m_cbSpeakDisabled->setChecked(true); + m_cbSpeakAccelerators->setChecked(true); + m_leAcceleratorPrefixWord->setText(i18n("Keyboard accelerator, such as Alt+F", "Accelerator")); + m_iniPollingInterval->setValue(600); +} + +void configureTTSPage::apply() +{ + config->setGroup("TTS"); + config->writeEntry("SpeakPointerWidget", m_cbSpeakPointerWidget->isChecked()); + config->writeEntry("SpeakFocusWidget", m_cbSpeakFocusWidget->isChecked()); + config->writeEntry("SpeakTooltips", m_cbSpeakTooltips->isChecked()); + config->writeEntry("SpeakWhatsThis", m_cbSpeakWhatsThis->isChecked()); + config->writeEntry("SpeakDisabled", m_cbSpeakDisabled->isChecked()); + config->writeEntry("SpeakAccelerators", m_cbSpeakAccelerators->isChecked()); + config->writeEntry("AcceleratorPrefixWord", m_leAcceleratorPrefixWord->text()); + config->writeEntry("PollingInterval", m_iniPollingInterval->value()); + if (kospeaker) kospeaker->readConfig(config); +} + +void configureTTSPage::screenReaderOptionChanged() +{ + m_gbScreenReaderOptions->setEnabled( + m_cbSpeakPointerWidget->isChecked() || m_cbSpeakFocusWidget->isChecked()); + m_leAcceleratorPrefixWord->setEnabled(m_cbSpeakAccelerators->isChecked()); + m_lblAcceleratorPrefix->setEnabled(m_cbSpeakAccelerators->isChecked()); +} + +#include "kspread_dlg_preference.moc" diff --git a/kspread/dialogs/kspread_dlg_reference.cc b/kspread/dialogs/kspread_dlg_reference.cc deleted file mode 100644 index 9e747dfb..00000000 --- a/kspread/dialogs/kspread_dlg_reference.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 Harri Porten - (C) 2002 John Dailey - (C) 1999-2002 Laurent Montel - (C) 2001-2002 Philipp Mueller - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - - -#include "kspread_dlg_reference.h" -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_util.h" -#include "kspread_map.h" -#include "kspread_view.h" -#include "kspread_sheet.h" -#include "selection.h" -#include "kspread_locale.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -using namespace KSpread; - -reference::reference( View* parent, const char* name ) - : TQDialog( parent, name,TRUE ) -{ - m_pView = parent; - TQVBoxLayout *lay1 = new TQVBoxLayout( this ); - lay1->setMargin( KDialog::marginHint() ); - lay1->setSpacing( KDialog::spacingHint() ); - m_list = new TQListBox(this); - lay1->addWidget( m_list ); - - setCaption( i18n("Area Name") ); - - m_rangeName = new TQLabel(this); - lay1->addWidget(m_rangeName); - - m_pRemove = new TQPushButton(i18n("&Remove"), this); - lay1->addWidget( m_pRemove ); - //m_pRemove->setEnabled(false); - KButtonBox *bb = new KButtonBox( this ); - // bb->addStretch(); - m_pEdit = bb->addButton( i18n("&Edit...") ); - m_pOk = bb->addButton( KStdGuiItem::ok() ); - m_pCancel = bb->addButton( KStdGuiItem::cancel() ); - m_pOk->setDefault( TRUE ); - bb->layout(); - lay1->addWidget( bb ); - - TQString text; - TQStringList sheetName; - TQPtrListIterator it2 ( m_pView->doc()->map()->sheetList() ); - for( ; it2.current(); ++it2 ) - { - sheetName.append( it2.current()->sheetName()); - } - - TQValueList::Iterator it; - TQValueList area = m_pView->doc()->listArea(); - for ( it = area.begin(); it != area.end(); ++it ) - { - text = (*it).ref_name; - if ( sheetName.contains((*it).sheet_name )) - m_list->insertItem(text); - } - - if ( !m_list->count() ) - { - m_pOk->setEnabled( false ); - m_pRemove->setEnabled( false ); - m_pEdit->setEnabled( false ); - } - - connect( m_pOk, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotOk() ) ); - connect( m_pCancel, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotCancel() ) ); - connect( m_pEdit, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotEdit() ) ); - connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); - connect( m_list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)), this, - TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); - connect( m_list, TQT_SIGNAL(highlighted ( TQListBoxItem * ) ), this, - TQT_SLOT(slotHighlighted(TQListBoxItem * ))); - m_rangeName->setText(i18n("Area: %1").arg("")); - - resize( 250, 200 ); -} - -void reference::displayAreaValues(TQString const & areaName) -{ - TQString tmpName; - TQValueList::Iterator it; - TQValueList area( m_pView->doc()->listArea() ); - for ( it = area.begin(); it != area.end(); ++it ) - { - if ((*it).ref_name == areaName) - { - if (!m_pView->doc()->map()->findSheet( (*it).sheet_name)) - kdDebug(36001) << "(*it).table_name '" << (*it).sheet_name - << "' not found!*********" << endl; - else - tmpName = util_rangeName(m_pView->doc()->map()->findSheet( (*it).sheet_name), - (*it).rect); - break; - } - } - - tmpName = i18n("Area: %1").arg(tmpName); - m_rangeName->setText(tmpName); -} - -void reference::slotHighlighted(TQListBoxItem * ) -{ - TQString tmp = m_list->text(m_list->currentItem()); - displayAreaValues(tmp); -} - -void reference::slotDoubleClicked(TQListBoxItem *) -{ - slotOk(); -} - -void reference::slotRemove() -{ - if (m_list->currentItem() == -1) - return; - - int ret = KMessageBox::warningContinueCancel( this, i18n("Do you really want to remove this area name?"),i18n("Remove Area"),KStdGuiItem::del()); - if (ret == KMessageBox::Cancel) - return; - - TQString textRemove; - if ( m_list->currentItem() != -1) - { - m_pView->doc()->emitBeginOperation( false ); - - TQString textRemove = m_list->text(m_list->currentItem()); - m_pView->doc()->removeArea(textRemove ); - m_pView->doc()->setModified(true); - /* - m_list->clear(); - TQString text; - TQValueList::Iterator it; - TQValueList area=m_pView->doc()->listArea(); - for ( it = area.begin(); it != area.end(); ++it ) - { - text=(*it).ref_name; - m_list->insertItem(text); - } - */ - - m_list->removeItem(m_list->currentItem()); - - Sheet *tbl; - - for ( tbl = m_pView->doc()->map()->firstSheet(); tbl != 0L; tbl = m_pView->doc()->map()->nextSheet() ) - { - tbl->refreshRemoveAreaName(textRemove); - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - } - - if ( !m_list->count() ) - { - m_pOk->setEnabled( false ); - m_pRemove->setEnabled( false ); - m_pEdit->setEnabled( false ); - } -} - -void reference::slotEdit() -{ - TQString name(m_list->text(m_list->currentItem())); - if ( name.isEmpty() ) - return; - EditAreaName editDlg( m_pView, "EditArea", name ); - editDlg.exec(); - - m_rangeName->setText(i18n("Area: %1").arg("")); - TQString tmp = m_list->text(m_list->currentItem()); - if (!tmp.isEmpty()) - displayAreaValues( tmp ); -} - -void reference::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - TQString text; - if (m_list->currentItem() != -1) - { - int index = m_list->currentItem(); - text = m_list->text(index); - TQValueList area = m_pView->doc()->listArea(); - - if (m_pView->activeSheet()->sheetName() != area[ index ].sheet_name) - { - Sheet *sheet = m_pView->doc()->map()->findSheet(area[ index ].sheet_name); - if (sheet) - m_pView->setActiveSheet(sheet); - } - - Region region(m_pView, Cell::fullName(m_pView->activeSheet(), area[index].rect.left(), area[index].rect.top())); - m_pView->selectionInfo()->initialize(region); - m_pView->selectionInfo()->initialize(area[ index ].rect);//, m_pView->activeSheet() ); - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void reference::slotCancel() -{ - reject(); -} - - - -EditAreaName::EditAreaName( View * parent, - const char * name, - TQString const & areaname ) - : KDialogBase( parent, name ,true,i18n( "Edit Area" ) , Ok|Cancel ) -{ - m_pView = parent; - - resize( 350, 142 ); - setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, - (TQSizePolicy::SizeType)4, 0, 0, - sizePolicy().hasHeightForWidth() ) ); - - TQWidget * page = new TQWidget( this ); - setMainWidget(page); - - TQGridLayout * EditAreaNameLayout - = new TQGridLayout( page, 1, 1, 11, 6, "EditAreaNameLayout"); - - TQHBoxLayout * Layout1 = new TQHBoxLayout( 0, 0, 6, "Layout1"); - TQSpacerItem * spacer = new TQSpacerItem( 0, 0, TQSizePolicy::Expanding, - TQSizePolicy::Minimum ); - Layout1->addItem( spacer ); - - EditAreaNameLayout->addMultiCellLayout( Layout1, 3, 3, 0, 1 ); - - TQLabel * TextLabel4 = new TQLabel( page, "TextLabel4" ); - TextLabel4->setText( i18n( "Cells:" ) ); - - EditAreaNameLayout->addWidget( TextLabel4, 2, 0 ); - - m_area = new TQLineEdit( page, "m_area" ); - - EditAreaNameLayout->addWidget( m_area, 2, 1 ); - - TQLabel * TextLabel1 = new TQLabel( page, "TextLabel1" ); - TextLabel1->setText( i18n( "Sheet:" ) ); - - EditAreaNameLayout->addWidget( TextLabel1, 1, 0 ); - - m_sheets = new TQComboBox( FALSE, page, "m_sheets" ); - - EditAreaNameLayout->addWidget( m_sheets, 1, 1 ); - - TQLabel * TextLabel2 = new TQLabel( page, "TextLabel2" ); - TextLabel2->setText( i18n( "Area name:" ) ); - - EditAreaNameLayout->addWidget( TextLabel2, 0, 0 ); - - m_areaName = new TQLabel( page, "m_areaName" ); - m_areaName->setText( areaname ); - - EditAreaNameLayout->addWidget( m_areaName, 0, 1 ); - - TQPtrList sheetList = m_pView->doc()->map()->sheetList(); - for (unsigned int c = 0; c < sheetList.count(); ++c) - { - Sheet * t = sheetList.at(c); - if (!t) - continue; - m_sheets->insertItem( t->sheetName() ); - } - - TQString tmpName; - TQValueList::Iterator it; - TQValueList area(m_pView->doc()->listArea()); - for ( it = area.begin(); it != area.end(); ++it ) - { - if ((*it).ref_name == areaname) - { - if (!m_pView->doc()->map()->findSheet( (*it).sheet_name)) - kdDebug(36001) << "(*it).table_name '" << (*it).sheet_name - << "' not found!*********" << endl; - else - tmpName = util_rangeName( (*it).rect ); - break; - } - } - - m_sheets->setCurrentText( (*it).sheet_name ); - m_area->setText( tmpName ); - -} - -EditAreaName::~EditAreaName() -{ -} - -void EditAreaName::slotOk() -{ - Range range( m_area->text() ); - - if ( !range.isValid() ) - { - Point point( m_area->text() ); - if ( !point.isValid() ) - return; - - m_area->setText( m_area->text() + ":" + m_area->text() ); - - range = Range( m_area->text() ); - } - - m_pView->doc()->emitBeginOperation( false ); - - m_pView->doc()->removeArea( m_areaName->text() ); - m_pView->doc()->addAreaName(range.range(), m_areaName->text(), m_sheets->currentText() ); - - Sheet *sheet; - - for ( sheet = m_pView->doc()->map()->firstSheet(); sheet != 0L; - sheet = m_pView->doc()->map()->nextSheet() ) - { - sheet->refreshChangeAreaName( m_areaName->text() ); - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -#include "kspread_dlg_reference.moc" diff --git a/kspread/dialogs/kspread_dlg_reference.cpp b/kspread/dialogs/kspread_dlg_reference.cpp new file mode 100644 index 00000000..9e747dfb --- /dev/null +++ b/kspread/dialogs/kspread_dlg_reference.cpp @@ -0,0 +1,368 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 Harri Porten + (C) 2002 John Dailey + (C) 1999-2002 Laurent Montel + (C) 2001-2002 Philipp Mueller + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + + +#include "kspread_dlg_reference.h" +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_util.h" +#include "kspread_map.h" +#include "kspread_view.h" +#include "kspread_sheet.h" +#include "selection.h" +#include "kspread_locale.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace KSpread; + +reference::reference( View* parent, const char* name ) + : TQDialog( parent, name,TRUE ) +{ + m_pView = parent; + TQVBoxLayout *lay1 = new TQVBoxLayout( this ); + lay1->setMargin( KDialog::marginHint() ); + lay1->setSpacing( KDialog::spacingHint() ); + m_list = new TQListBox(this); + lay1->addWidget( m_list ); + + setCaption( i18n("Area Name") ); + + m_rangeName = new TQLabel(this); + lay1->addWidget(m_rangeName); + + m_pRemove = new TQPushButton(i18n("&Remove"), this); + lay1->addWidget( m_pRemove ); + //m_pRemove->setEnabled(false); + KButtonBox *bb = new KButtonBox( this ); + // bb->addStretch(); + m_pEdit = bb->addButton( i18n("&Edit...") ); + m_pOk = bb->addButton( KStdGuiItem::ok() ); + m_pCancel = bb->addButton( KStdGuiItem::cancel() ); + m_pOk->setDefault( TRUE ); + bb->layout(); + lay1->addWidget( bb ); + + TQString text; + TQStringList sheetName; + TQPtrListIterator it2 ( m_pView->doc()->map()->sheetList() ); + for( ; it2.current(); ++it2 ) + { + sheetName.append( it2.current()->sheetName()); + } + + TQValueList::Iterator it; + TQValueList area = m_pView->doc()->listArea(); + for ( it = area.begin(); it != area.end(); ++it ) + { + text = (*it).ref_name; + if ( sheetName.contains((*it).sheet_name )) + m_list->insertItem(text); + } + + if ( !m_list->count() ) + { + m_pOk->setEnabled( false ); + m_pRemove->setEnabled( false ); + m_pEdit->setEnabled( false ); + } + + connect( m_pOk, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotOk() ) ); + connect( m_pCancel, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotCancel() ) ); + connect( m_pEdit, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotEdit() ) ); + connect( m_pRemove, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemove() ) ); + connect( m_list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)), this, + TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); + connect( m_list, TQT_SIGNAL(highlighted ( TQListBoxItem * ) ), this, + TQT_SLOT(slotHighlighted(TQListBoxItem * ))); + m_rangeName->setText(i18n("Area: %1").arg("")); + + resize( 250, 200 ); +} + +void reference::displayAreaValues(TQString const & areaName) +{ + TQString tmpName; + TQValueList::Iterator it; + TQValueList area( m_pView->doc()->listArea() ); + for ( it = area.begin(); it != area.end(); ++it ) + { + if ((*it).ref_name == areaName) + { + if (!m_pView->doc()->map()->findSheet( (*it).sheet_name)) + kdDebug(36001) << "(*it).table_name '" << (*it).sheet_name + << "' not found!*********" << endl; + else + tmpName = util_rangeName(m_pView->doc()->map()->findSheet( (*it).sheet_name), + (*it).rect); + break; + } + } + + tmpName = i18n("Area: %1").arg(tmpName); + m_rangeName->setText(tmpName); +} + +void reference::slotHighlighted(TQListBoxItem * ) +{ + TQString tmp = m_list->text(m_list->currentItem()); + displayAreaValues(tmp); +} + +void reference::slotDoubleClicked(TQListBoxItem *) +{ + slotOk(); +} + +void reference::slotRemove() +{ + if (m_list->currentItem() == -1) + return; + + int ret = KMessageBox::warningContinueCancel( this, i18n("Do you really want to remove this area name?"),i18n("Remove Area"),KStdGuiItem::del()); + if (ret == KMessageBox::Cancel) + return; + + TQString textRemove; + if ( m_list->currentItem() != -1) + { + m_pView->doc()->emitBeginOperation( false ); + + TQString textRemove = m_list->text(m_list->currentItem()); + m_pView->doc()->removeArea(textRemove ); + m_pView->doc()->setModified(true); + /* + m_list->clear(); + TQString text; + TQValueList::Iterator it; + TQValueList area=m_pView->doc()->listArea(); + for ( it = area.begin(); it != area.end(); ++it ) + { + text=(*it).ref_name; + m_list->insertItem(text); + } + */ + + m_list->removeItem(m_list->currentItem()); + + Sheet *tbl; + + for ( tbl = m_pView->doc()->map()->firstSheet(); tbl != 0L; tbl = m_pView->doc()->map()->nextSheet() ) + { + tbl->refreshRemoveAreaName(textRemove); + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + } + + if ( !m_list->count() ) + { + m_pOk->setEnabled( false ); + m_pRemove->setEnabled( false ); + m_pEdit->setEnabled( false ); + } +} + +void reference::slotEdit() +{ + TQString name(m_list->text(m_list->currentItem())); + if ( name.isEmpty() ) + return; + EditAreaName editDlg( m_pView, "EditArea", name ); + editDlg.exec(); + + m_rangeName->setText(i18n("Area: %1").arg("")); + TQString tmp = m_list->text(m_list->currentItem()); + if (!tmp.isEmpty()) + displayAreaValues( tmp ); +} + +void reference::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + TQString text; + if (m_list->currentItem() != -1) + { + int index = m_list->currentItem(); + text = m_list->text(index); + TQValueList area = m_pView->doc()->listArea(); + + if (m_pView->activeSheet()->sheetName() != area[ index ].sheet_name) + { + Sheet *sheet = m_pView->doc()->map()->findSheet(area[ index ].sheet_name); + if (sheet) + m_pView->setActiveSheet(sheet); + } + + Region region(m_pView, Cell::fullName(m_pView->activeSheet(), area[index].rect.left(), area[index].rect.top())); + m_pView->selectionInfo()->initialize(region); + m_pView->selectionInfo()->initialize(area[ index ].rect);//, m_pView->activeSheet() ); + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void reference::slotCancel() +{ + reject(); +} + + + +EditAreaName::EditAreaName( View * parent, + const char * name, + TQString const & areaname ) + : KDialogBase( parent, name ,true,i18n( "Edit Area" ) , Ok|Cancel ) +{ + m_pView = parent; + + resize( 350, 142 ); + setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, + (TQSizePolicy::SizeType)4, 0, 0, + sizePolicy().hasHeightForWidth() ) ); + + TQWidget * page = new TQWidget( this ); + setMainWidget(page); + + TQGridLayout * EditAreaNameLayout + = new TQGridLayout( page, 1, 1, 11, 6, "EditAreaNameLayout"); + + TQHBoxLayout * Layout1 = new TQHBoxLayout( 0, 0, 6, "Layout1"); + TQSpacerItem * spacer = new TQSpacerItem( 0, 0, TQSizePolicy::Expanding, + TQSizePolicy::Minimum ); + Layout1->addItem( spacer ); + + EditAreaNameLayout->addMultiCellLayout( Layout1, 3, 3, 0, 1 ); + + TQLabel * TextLabel4 = new TQLabel( page, "TextLabel4" ); + TextLabel4->setText( i18n( "Cells:" ) ); + + EditAreaNameLayout->addWidget( TextLabel4, 2, 0 ); + + m_area = new TQLineEdit( page, "m_area" ); + + EditAreaNameLayout->addWidget( m_area, 2, 1 ); + + TQLabel * TextLabel1 = new TQLabel( page, "TextLabel1" ); + TextLabel1->setText( i18n( "Sheet:" ) ); + + EditAreaNameLayout->addWidget( TextLabel1, 1, 0 ); + + m_sheets = new TQComboBox( FALSE, page, "m_sheets" ); + + EditAreaNameLayout->addWidget( m_sheets, 1, 1 ); + + TQLabel * TextLabel2 = new TQLabel( page, "TextLabel2" ); + TextLabel2->setText( i18n( "Area name:" ) ); + + EditAreaNameLayout->addWidget( TextLabel2, 0, 0 ); + + m_areaName = new TQLabel( page, "m_areaName" ); + m_areaName->setText( areaname ); + + EditAreaNameLayout->addWidget( m_areaName, 0, 1 ); + + TQPtrList sheetList = m_pView->doc()->map()->sheetList(); + for (unsigned int c = 0; c < sheetList.count(); ++c) + { + Sheet * t = sheetList.at(c); + if (!t) + continue; + m_sheets->insertItem( t->sheetName() ); + } + + TQString tmpName; + TQValueList::Iterator it; + TQValueList area(m_pView->doc()->listArea()); + for ( it = area.begin(); it != area.end(); ++it ) + { + if ((*it).ref_name == areaname) + { + if (!m_pView->doc()->map()->findSheet( (*it).sheet_name)) + kdDebug(36001) << "(*it).table_name '" << (*it).sheet_name + << "' not found!*********" << endl; + else + tmpName = util_rangeName( (*it).rect ); + break; + } + } + + m_sheets->setCurrentText( (*it).sheet_name ); + m_area->setText( tmpName ); + +} + +EditAreaName::~EditAreaName() +{ +} + +void EditAreaName::slotOk() +{ + Range range( m_area->text() ); + + if ( !range.isValid() ) + { + Point point( m_area->text() ); + if ( !point.isValid() ) + return; + + m_area->setText( m_area->text() + ":" + m_area->text() ); + + range = Range( m_area->text() ); + } + + m_pView->doc()->emitBeginOperation( false ); + + m_pView->doc()->removeArea( m_areaName->text() ); + m_pView->doc()->addAreaName(range.range(), m_areaName->text(), m_sheets->currentText() ); + + Sheet *sheet; + + for ( sheet = m_pView->doc()->map()->firstSheet(); sheet != 0L; + sheet = m_pView->doc()->map()->nextSheet() ) + { + sheet->refreshChangeAreaName( m_areaName->text() ); + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +#include "kspread_dlg_reference.moc" diff --git a/kspread/dialogs/kspread_dlg_resize2.cc b/kspread/dialogs/kspread_dlg_resize2.cc deleted file mode 100644 index e6d74d26..00000000 --- a/kspread/dialogs/kspread_dlg_resize2.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2004 Ariya Hidayat - (C) 2003 Norbert Andres - (C) 2001-2003 Philipp Mueller - (C) 1999-2002 Laurent Montel - (C) 2002 John Dailey - (C) 2000 David Faure - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "manipulator.h" -#include "selection.h" - -#include "kspread_dlg_resize2.h" - -using namespace KSpread; - -ResizeRow::ResizeRow( View* parent, const char* name ) - : KDialogBase( parent, name, true, i18n("Resize Row"), Ok|Cancel|Default ) -{ - m_pView = parent; - - TQWidget *page = new TQWidget( this ); - setMainWidget( page ); - - TQVBoxLayout *vLay = new TQVBoxLayout( page, 0, spacingHint() ); - TQHBoxLayout *hLay = new TQHBoxLayout( vLay ); - - TQRect selection( m_pView->selectionInfo()->selection() ); - RowFormat* rl = m_pView->activeSheet()->rowFormat( selection.top() ); - rowHeight = rl->dblHeight(); - - TQLabel * label1 = new TQLabel( page, "label1" ); - label1->setText( i18n( "Height:" ) ); - hLay->addWidget( label1 ); - - m_pHeight = new KoUnitDoubleSpinBox( page ); - m_pHeight->setValue( rowHeight ); - m_pHeight->setUnit( m_pView->doc()->unit() ); - - hLay->addWidget( m_pHeight ); - - TQWidget *hSpacer = new TQWidget( page ); - hSpacer->setMinimumSize( spacingHint(), spacingHint() ); - hLay->addWidget( hSpacer ); - - TQWidget *vSpacer = new TQWidget( page ); - vSpacer->setMinimumSize( spacingHint(), spacingHint() ); - vLay->addWidget( vSpacer ); - - m_pHeight->setFocus(); - - //store the visible value, for later check for changes - rowHeight = m_pHeight->value(); -} - -void ResizeRow::slotOk() -{ - double height = m_pHeight->value(); - - //Don't generate a resize, when there isn't a change or the change is only a rounding issue - if ( fabs( height - rowHeight ) > DBL_EPSILON ) - { - ResizeRowManipulator* manipulator = new ResizeRowManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setSize(height); - // TODO Stefan: - manipulator->setOldSize(rowHeight); - manipulator->add(*m_pView->selectionInfo()); - manipulator->execute(); - } - accept(); -} - -void ResizeRow::slotDefault() -{ - Sheet* sheet = m_pView->activeSheet(); - if (!sheet) - return; - double points = sheet->rowFormat(0)->dblHeight(); - m_pHeight->setValue(KoUnit::toUserValue(points, m_pView->doc()->unit())); -} - -ResizeColumn::ResizeColumn( View* parent, const char* name ) - : KDialogBase( parent, name, true, i18n("Resize Column"), Ok|Cancel|Default ) -{ - m_pView = parent; - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - - TQVBoxLayout *vLay = new TQVBoxLayout( page, 0, spacingHint() ); - TQHBoxLayout *hLay = new TQHBoxLayout( vLay ); - - TQRect selection( m_pView->selectionInfo()->selection() ); - ColumnFormat* cl = m_pView->activeSheet()->columnFormat( selection.left() ); - columnWidth = cl->dblWidth(); - - TQLabel * label1 = new TQLabel( page, "label1" ); - label1->setText( i18n( "Width:" ) ); - hLay->addWidget( label1 ); - - m_pWidth = new KoUnitDoubleSpinBox( page ); - m_pWidth->setValue( columnWidth ); - m_pWidth->setUnit( m_pView->doc()->unit() ); - - hLay->addWidget( m_pWidth ); - - TQWidget *hSpacer = new TQWidget( page ); - hSpacer->setMinimumSize( spacingHint(), spacingHint() ); - hLay->addWidget( hSpacer ); - - TQWidget *vSpacer = new TQWidget( page ); - vSpacer->setMinimumSize( spacingHint(), spacingHint() ); - vLay->addWidget( vSpacer ); - - m_pWidth->setFocus(); - - //store the visible value, for later check for changes - columnWidth = m_pWidth->value(); -} - -void ResizeColumn::slotOk() -{ - double width = m_pWidth->value(); - - //Don't generate a resize, when there isn't a change or the change is only a rounding issue - if ( fabs( width - columnWidth ) > DBL_EPSILON ) - { - ResizeColumnManipulator* manipulator = new ResizeColumnManipulator(); - manipulator->setSheet(m_pView->activeSheet()); - manipulator->setSize(width); - // TODO Stefan: - manipulator->setOldSize(columnWidth); - manipulator->add(*m_pView->selectionInfo()); - manipulator->execute(); - } - accept(); -} - -void ResizeColumn::slotDefault() -{ - Sheet* sheet = m_pView->activeSheet(); - if (!sheet) - return; - double points = sheet->columnFormat(0)->dblWidth(); - m_pWidth->setValue(KoUnit::toUserValue(points, m_pView->doc()->unit())); -} - - -#include "kspread_dlg_resize2.moc" diff --git a/kspread/dialogs/kspread_dlg_resize2.cpp b/kspread/dialogs/kspread_dlg_resize2.cpp new file mode 100644 index 00000000..e6d74d26 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_resize2.cpp @@ -0,0 +1,183 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2004 Ariya Hidayat + (C) 2003 Norbert Andres + (C) 2001-2003 Philipp Mueller + (C) 1999-2002 Laurent Montel + (C) 2002 John Dailey + (C) 2000 David Faure + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "manipulator.h" +#include "selection.h" + +#include "kspread_dlg_resize2.h" + +using namespace KSpread; + +ResizeRow::ResizeRow( View* parent, const char* name ) + : KDialogBase( parent, name, true, i18n("Resize Row"), Ok|Cancel|Default ) +{ + m_pView = parent; + + TQWidget *page = new TQWidget( this ); + setMainWidget( page ); + + TQVBoxLayout *vLay = new TQVBoxLayout( page, 0, spacingHint() ); + TQHBoxLayout *hLay = new TQHBoxLayout( vLay ); + + TQRect selection( m_pView->selectionInfo()->selection() ); + RowFormat* rl = m_pView->activeSheet()->rowFormat( selection.top() ); + rowHeight = rl->dblHeight(); + + TQLabel * label1 = new TQLabel( page, "label1" ); + label1->setText( i18n( "Height:" ) ); + hLay->addWidget( label1 ); + + m_pHeight = new KoUnitDoubleSpinBox( page ); + m_pHeight->setValue( rowHeight ); + m_pHeight->setUnit( m_pView->doc()->unit() ); + + hLay->addWidget( m_pHeight ); + + TQWidget *hSpacer = new TQWidget( page ); + hSpacer->setMinimumSize( spacingHint(), spacingHint() ); + hLay->addWidget( hSpacer ); + + TQWidget *vSpacer = new TQWidget( page ); + vSpacer->setMinimumSize( spacingHint(), spacingHint() ); + vLay->addWidget( vSpacer ); + + m_pHeight->setFocus(); + + //store the visible value, for later check for changes + rowHeight = m_pHeight->value(); +} + +void ResizeRow::slotOk() +{ + double height = m_pHeight->value(); + + //Don't generate a resize, when there isn't a change or the change is only a rounding issue + if ( fabs( height - rowHeight ) > DBL_EPSILON ) + { + ResizeRowManipulator* manipulator = new ResizeRowManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setSize(height); + // TODO Stefan: + manipulator->setOldSize(rowHeight); + manipulator->add(*m_pView->selectionInfo()); + manipulator->execute(); + } + accept(); +} + +void ResizeRow::slotDefault() +{ + Sheet* sheet = m_pView->activeSheet(); + if (!sheet) + return; + double points = sheet->rowFormat(0)->dblHeight(); + m_pHeight->setValue(KoUnit::toUserValue(points, m_pView->doc()->unit())); +} + +ResizeColumn::ResizeColumn( View* parent, const char* name ) + : KDialogBase( parent, name, true, i18n("Resize Column"), Ok|Cancel|Default ) +{ + m_pView = parent; + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + + TQVBoxLayout *vLay = new TQVBoxLayout( page, 0, spacingHint() ); + TQHBoxLayout *hLay = new TQHBoxLayout( vLay ); + + TQRect selection( m_pView->selectionInfo()->selection() ); + ColumnFormat* cl = m_pView->activeSheet()->columnFormat( selection.left() ); + columnWidth = cl->dblWidth(); + + TQLabel * label1 = new TQLabel( page, "label1" ); + label1->setText( i18n( "Width:" ) ); + hLay->addWidget( label1 ); + + m_pWidth = new KoUnitDoubleSpinBox( page ); + m_pWidth->setValue( columnWidth ); + m_pWidth->setUnit( m_pView->doc()->unit() ); + + hLay->addWidget( m_pWidth ); + + TQWidget *hSpacer = new TQWidget( page ); + hSpacer->setMinimumSize( spacingHint(), spacingHint() ); + hLay->addWidget( hSpacer ); + + TQWidget *vSpacer = new TQWidget( page ); + vSpacer->setMinimumSize( spacingHint(), spacingHint() ); + vLay->addWidget( vSpacer ); + + m_pWidth->setFocus(); + + //store the visible value, for later check for changes + columnWidth = m_pWidth->value(); +} + +void ResizeColumn::slotOk() +{ + double width = m_pWidth->value(); + + //Don't generate a resize, when there isn't a change or the change is only a rounding issue + if ( fabs( width - columnWidth ) > DBL_EPSILON ) + { + ResizeColumnManipulator* manipulator = new ResizeColumnManipulator(); + manipulator->setSheet(m_pView->activeSheet()); + manipulator->setSize(width); + // TODO Stefan: + manipulator->setOldSize(columnWidth); + manipulator->add(*m_pView->selectionInfo()); + manipulator->execute(); + } + accept(); +} + +void ResizeColumn::slotDefault() +{ + Sheet* sheet = m_pView->activeSheet(); + if (!sheet) + return; + double points = sheet->columnFormat(0)->dblWidth(); + m_pWidth->setValue(KoUnit::toUserValue(points, m_pView->doc()->unit())); +} + + +#include "kspread_dlg_resize2.moc" diff --git a/kspread/dialogs/kspread_dlg_series.cc b/kspread/dialogs/kspread_dlg_series.cc deleted file mode 100644 index ee241617..00000000 --- a/kspread/dialogs/kspread_dlg_series.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2004 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 2002 John Dailey - (C) 1999-2002 Laurent Montel - (C) 2001-2002 Philipp Mueller - (C) 2000-2001 Werner Trobin - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "kspread_dlg_series.h" -#include "kspread_doc.h" -#include "kspread_editors.h" -#include "kspread_sheet.h" -#include "kspread_view.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace KSpread; - -SeriesDlg::SeriesDlg( View* parent, const char* name,const TQPoint &_marker) - : KDialogBase( parent, name,TRUE,i18n("Series"),Ok|Cancel ) -{ - m_pView = parent; - marker=_marker; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - - TQBoxLayout *grid1 = new TQHBoxLayout(page); - grid1->setSpacing( spacingHint() ); - - TQButtonGroup* gb1 = new TQButtonGroup( 2, Qt::Vertical, - i18n("Insert Values"), page ); - column = new TQRadioButton( i18n("Vertical"), gb1 ); - TQWhatsThis::add(column, i18n("Insert the series vertically, one below the other") ); - row = new TQRadioButton( i18n("Horizontal"), gb1 ); - TQWhatsThis::add(row, i18n("Insert the series horizontally, from left to right") ); - - column->setChecked(true); - - TQButtonGroup* gb2 = new TQButtonGroup( 2, Qt::Vertical, - i18n("Type"), page ); - linear = new TQRadioButton( i18n("Linear (2,4,6,...)"), gb2 ); - TQWhatsThis::add(linear, i18n("Generate a series from 'start' to 'end' and for each step add " - "the value provided in step. This creates a series where each value " - "is 'step' larger than the value before it.") ); - geometric = new TQRadioButton( i18n("Geometric (2,4,8,...)"), gb2 ); - TQWhatsThis::add(geometric, i18n("Generate a series from 'start' to 'end' and for each step multiply " - "the value with the value provided in step. Using a step of 5 produces a list like: " - "5, 25, 125, 625 since 5 multiplied by 5 (step) equals 25, and that multiplied by 5 equals 125, " - "which multiplied by the same step-value of 5 equals 625.") ); - - linear->setChecked(true); - - TQGroupBox* gb = new TQGroupBox( 1, Qt::Vertical, i18n("Parameters"), page ); - TQWidget *params = new TQWidget( gb ); - TQGridLayout *params_layout = new TQGridLayout( params, 3, 2 ); - params_layout->setSpacing( spacingHint() ); - params_layout->setAutoAdd( true ); - - new TQLabel( i18n( "Start value:" ), params ); - start=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); - - new TQLabel( i18n( "Stop value:" ), params ); - end=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); - - new TQLabel( i18n( "Step value:" ), params ); - step=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); - - grid1->addWidget(gb); - - grid1->addWidget(gb1); - grid1->addWidget(gb2); - - start->setFocus(); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); -} - - -void SeriesDlg::slotOk() -{ - - Series mode=Column; //same as Qt::Vertical - Series type=Linear; // same as Qt::Horizontal - TQString tmp; - double dstep, dend, dstart; - Sheet * m_pSheet; - m_pSheet = m_pView->activeSheet(); - - if(column->isChecked()) - mode = Column; - else if(row->isChecked()) - mode = Row; - - if (linear->isChecked()) - type = Linear; - else if (geometric->isChecked()) - type = Geometric; - - dstart = start->value(); - dend= end->value(); - dstep = step->value(); - if ( type == Geometric ) - { - if ( dstart < 0 || dend < 0 ) - { - KMessageBox::error( this, i18n("End and start value must be positive.") ); - return; - } - if ( dstart > dend && dstep >= 1) - { - KMessageBox::error( this, i18n("End value must be greater than the start value or the step must be less than '1'.") ); - return; - } - if ( dstart == 0 || dend == 0 || dstep == 0) - { - KMessageBox::error( this, i18n("None of the Start, Stop or Step values may be equal to zero.") ); - return; - } - if ( dstep == 1) - { - KMessageBox::error( this, i18n("Step value must be different from 1") ); - return; - } - } - - if (dstep >= 0) - { - if (linear->isChecked() && dstep == 0) - { - KMessageBox::error( this, i18n("The step value must be greater than zero; " - "otherwise, the linear series is infinite.") ); - step->setFocus(); - return; - } - /* else if (geometric->isChecked() && dstep <= 1) - { - KMessageBox::error( this, i18n("The step value must be greater than one; " - "otherwise, the geometric series is infinite.") ); - step->setFocus(); - return; - } - */ - else if ( type == Linear && dend < dstart ) - { - KMessageBox::error( this, - i18n("If the start value is greater than the end value the step must be less than zero.") ); - return; - } - } - else if (type != Linear) - { - KMessageBox::error( this, i18n("Step is negative.") ); - return; - } - else - { - if (dstart <= dend) - { - KMessageBox::error( this, - i18n("If the step is negative, the start value must be greater then the end value.") ); - return; - } - } - - // double val_end = TQMAX(dend, dstart); - // double val_start = TQMIN(dend, dstart); - m_pView->doc()->emitBeginOperation( false ); - - m_pSheet->setSeries( marker, dstart, dend, dstep, mode, type ); - - Cell * cell = m_pSheet->cellAt( marker.x(), marker.y() ); - if ( cell->text() != 0L ) - m_pView->editWidget()->setText( cell->text() ); - else - m_pView->editWidget()->setText( "" ); - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - - -#include "kspread_dlg_series.moc" diff --git a/kspread/dialogs/kspread_dlg_series.cpp b/kspread/dialogs/kspread_dlg_series.cpp new file mode 100644 index 00000000..ee241617 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_series.cpp @@ -0,0 +1,213 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2004 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 2002 John Dailey + (C) 1999-2002 Laurent Montel + (C) 2001-2002 Philipp Mueller + (C) 2000-2001 Werner Trobin + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "kspread_dlg_series.h" +#include "kspread_doc.h" +#include "kspread_editors.h" +#include "kspread_sheet.h" +#include "kspread_view.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace KSpread; + +SeriesDlg::SeriesDlg( View* parent, const char* name,const TQPoint &_marker) + : KDialogBase( parent, name,TRUE,i18n("Series"),Ok|Cancel ) +{ + m_pView = parent; + marker=_marker; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + + TQBoxLayout *grid1 = new TQHBoxLayout(page); + grid1->setSpacing( spacingHint() ); + + TQButtonGroup* gb1 = new TQButtonGroup( 2, Qt::Vertical, + i18n("Insert Values"), page ); + column = new TQRadioButton( i18n("Vertical"), gb1 ); + TQWhatsThis::add(column, i18n("Insert the series vertically, one below the other") ); + row = new TQRadioButton( i18n("Horizontal"), gb1 ); + TQWhatsThis::add(row, i18n("Insert the series horizontally, from left to right") ); + + column->setChecked(true); + + TQButtonGroup* gb2 = new TQButtonGroup( 2, Qt::Vertical, + i18n("Type"), page ); + linear = new TQRadioButton( i18n("Linear (2,4,6,...)"), gb2 ); + TQWhatsThis::add(linear, i18n("Generate a series from 'start' to 'end' and for each step add " + "the value provided in step. This creates a series where each value " + "is 'step' larger than the value before it.") ); + geometric = new TQRadioButton( i18n("Geometric (2,4,8,...)"), gb2 ); + TQWhatsThis::add(geometric, i18n("Generate a series from 'start' to 'end' and for each step multiply " + "the value with the value provided in step. Using a step of 5 produces a list like: " + "5, 25, 125, 625 since 5 multiplied by 5 (step) equals 25, and that multiplied by 5 equals 125, " + "which multiplied by the same step-value of 5 equals 625.") ); + + linear->setChecked(true); + + TQGroupBox* gb = new TQGroupBox( 1, Qt::Vertical, i18n("Parameters"), page ); + TQWidget *params = new TQWidget( gb ); + TQGridLayout *params_layout = new TQGridLayout( params, 3, 2 ); + params_layout->setSpacing( spacingHint() ); + params_layout->setAutoAdd( true ); + + new TQLabel( i18n( "Start value:" ), params ); + start=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); + + new TQLabel( i18n( "Stop value:" ), params ); + end=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); + + new TQLabel( i18n( "Step value:" ), params ); + step=new KDoubleNumInput(-999999.999, 999999.99, 0.0, 1.0, 3, params); + + grid1->addWidget(gb); + + grid1->addWidget(gb1); + grid1->addWidget(gb2); + + start->setFocus(); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); +} + + +void SeriesDlg::slotOk() +{ + + Series mode=Column; //same as Qt::Vertical + Series type=Linear; // same as Qt::Horizontal + TQString tmp; + double dstep, dend, dstart; + Sheet * m_pSheet; + m_pSheet = m_pView->activeSheet(); + + if(column->isChecked()) + mode = Column; + else if(row->isChecked()) + mode = Row; + + if (linear->isChecked()) + type = Linear; + else if (geometric->isChecked()) + type = Geometric; + + dstart = start->value(); + dend= end->value(); + dstep = step->value(); + if ( type == Geometric ) + { + if ( dstart < 0 || dend < 0 ) + { + KMessageBox::error( this, i18n("End and start value must be positive.") ); + return; + } + if ( dstart > dend && dstep >= 1) + { + KMessageBox::error( this, i18n("End value must be greater than the start value or the step must be less than '1'.") ); + return; + } + if ( dstart == 0 || dend == 0 || dstep == 0) + { + KMessageBox::error( this, i18n("None of the Start, Stop or Step values may be equal to zero.") ); + return; + } + if ( dstep == 1) + { + KMessageBox::error( this, i18n("Step value must be different from 1") ); + return; + } + } + + if (dstep >= 0) + { + if (linear->isChecked() && dstep == 0) + { + KMessageBox::error( this, i18n("The step value must be greater than zero; " + "otherwise, the linear series is infinite.") ); + step->setFocus(); + return; + } + /* else if (geometric->isChecked() && dstep <= 1) + { + KMessageBox::error( this, i18n("The step value must be greater than one; " + "otherwise, the geometric series is infinite.") ); + step->setFocus(); + return; + } + */ + else if ( type == Linear && dend < dstart ) + { + KMessageBox::error( this, + i18n("If the start value is greater than the end value the step must be less than zero.") ); + return; + } + } + else if (type != Linear) + { + KMessageBox::error( this, i18n("Step is negative.") ); + return; + } + else + { + if (dstart <= dend) + { + KMessageBox::error( this, + i18n("If the step is negative, the start value must be greater then the end value.") ); + return; + } + } + + // double val_end = TQMAX(dend, dstart); + // double val_start = TQMIN(dend, dstart); + m_pView->doc()->emitBeginOperation( false ); + + m_pSheet->setSeries( marker, dstart, dend, dstep, mode, type ); + + Cell * cell = m_pSheet->cellAt( marker.x(), marker.y() ); + if ( cell->text() != 0L ) + m_pView->editWidget()->setText( cell->text() ); + else + m_pView->editWidget()->setText( "" ); + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + + +#include "kspread_dlg_series.moc" diff --git a/kspread/dialogs/kspread_dlg_show.cc b/kspread/dialogs/kspread_dlg_show.cc deleted file mode 100644 index 11f55e6d..00000000 --- a/kspread/dialogs/kspread_dlg_show.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999-2004 Laurent Montel - (C) 2002-2004 Ariya Hidayat - (C) 2003 Norbert Andres - (C) 2002 John Dailey - (C) 2001-2002 Philipp Mueller - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include - -#include - -#include "kspread_view.h" -#include "kspread_doc.h" -#include "kspread_map.h" -#include "commands.h" - -#include "kspread_dlg_show.h" - -using namespace KSpread; - -ShowDialog::ShowDialog( View* parent, const char* name ) - : KDialogBase( parent, name,TRUE,i18n("Show Sheet"),Ok|Cancel ) -{ - m_pView = parent; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQLabel *label = new TQLabel( i18n("Select hidden sheets to show:"), page ); - lay1->addWidget( label ); - - list=new TQListBox(page); - lay1->addWidget( list ); - - list->setSelectionMode(TQListBox::Multi); - TQString text; - TQStringList::Iterator it; - TQStringList tabsList=m_pView->doc()->map()->hiddenSheets(); - for ( it = tabsList.begin(); it != tabsList.end(); ++it ) - { - text=*it; - list->insertItem(text); - } - if(!list->count()) - enableButtonOK(false); - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); - resize( 200, 150 ); - setFocus(); -} - -void ShowDialog::slotDoubleClicked(TQListBoxItem *) -{ - slotOk(); -} - - - -void ShowDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - TQStringList listSheet; - - for (int i=0; i < list->numRows(); i++) - { - if (list->isSelected(i)) - { - listSheet.append( list->text(i)); - } - } - - //m_pView->tabBar()->showSheet(listSheet); - - if ( listSheet.count()==0 ) - return; - - Sheet *sheet; - KMacroCommand *macroUndo=new KMacroCommand( i18n("Show Sheet") ); - for ( TQStringList::Iterator it = listSheet.begin(); it != listSheet.end(); ++it ) - { - sheet=m_pView->doc()->map()->findSheet( *it ); - KCommand* command = new ShowSheetCommand( sheet ); - macroUndo->addCommand( command ); - } - m_pView->doc()->addCommand( macroUndo ); - macroUndo->execute(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -#include "kspread_dlg_show.moc" diff --git a/kspread/dialogs/kspread_dlg_show.cpp b/kspread/dialogs/kspread_dlg_show.cpp new file mode 100644 index 00000000..11f55e6d --- /dev/null +++ b/kspread/dialogs/kspread_dlg_show.cpp @@ -0,0 +1,112 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2004 Laurent Montel + (C) 2002-2004 Ariya Hidayat + (C) 2003 Norbert Andres + (C) 2002 John Dailey + (C) 2001-2002 Philipp Mueller + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include + +#include "kspread_view.h" +#include "kspread_doc.h" +#include "kspread_map.h" +#include "commands.h" + +#include "kspread_dlg_show.h" + +using namespace KSpread; + +ShowDialog::ShowDialog( View* parent, const char* name ) + : KDialogBase( parent, name,TRUE,i18n("Show Sheet"),Ok|Cancel ) +{ + m_pView = parent; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQLabel *label = new TQLabel( i18n("Select hidden sheets to show:"), page ); + lay1->addWidget( label ); + + list=new TQListBox(page); + lay1->addWidget( list ); + + list->setSelectionMode(TQListBox::Multi); + TQString text; + TQStringList::Iterator it; + TQStringList tabsList=m_pView->doc()->map()->hiddenSheets(); + for ( it = tabsList.begin(); it != tabsList.end(); ++it ) + { + text=*it; + list->insertItem(text); + } + if(!list->count()) + enableButtonOK(false); + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); + resize( 200, 150 ); + setFocus(); +} + +void ShowDialog::slotDoubleClicked(TQListBoxItem *) +{ + slotOk(); +} + + + +void ShowDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + TQStringList listSheet; + + for (int i=0; i < list->numRows(); i++) + { + if (list->isSelected(i)) + { + listSheet.append( list->text(i)); + } + } + + //m_pView->tabBar()->showSheet(listSheet); + + if ( listSheet.count()==0 ) + return; + + Sheet *sheet; + KMacroCommand *macroUndo=new KMacroCommand( i18n("Show Sheet") ); + for ( TQStringList::Iterator it = listSheet.begin(); it != listSheet.end(); ++it ) + { + sheet=m_pView->doc()->map()->findSheet( *it ); + KCommand* command = new ShowSheetCommand( sheet ); + macroUndo->addCommand( command ); + } + m_pView->doc()->addCommand( macroUndo ); + macroUndo->execute(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +#include "kspread_dlg_show.moc" diff --git a/kspread/dialogs/kspread_dlg_showColRow.cc b/kspread/dialogs/kspread_dlg_showColRow.cc deleted file mode 100644 index 32c4c631..00000000 --- a/kspread/dialogs/kspread_dlg_showColRow.cc +++ /dev/null @@ -1,152 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Norbert Andres - (C) 2000-2002 Laurent Montel - (C) 2001-2002 Philipp Mueller - (C) 2002 John Dailey - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include - -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_util.h" -#include "kspread_view.h" -#include "region.h" - -#include "kspread_dlg_showColRow.h" - -using namespace KSpread; - -ShowColRow::ShowColRow( View* parent, const char* name, Type _type ) - : KDialogBase( parent, name,TRUE,"",Ok|Cancel ) -{ - m_pView = parent; - typeShow=_type; - - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQLabel *label = new TQLabel( page ); - - if(_type==Column) { - setCaption( i18n("Show Columns") ); - label->setText(i18n("Select hidden columns to show:")); - } - else if(_type==Row) { - setCaption( i18n("Show Rows") ); - label->setText(i18n("Select hidden rows to show:")); - } - - list=new TQListBox(page); - - lay1->addWidget( label ); - lay1->addWidget( list ); - - bool showColNumber=m_pView->activeSheet()->getShowColumnNumber(); - if(_type==Column) - { - ColumnFormat *col=m_pView->activeSheet()->firstCol(); - - TQString text; - TQStringList listCol; - for( ; col; col = col->next() ) - { - if(col->isHide()) - listInt.append(col->column()); - } - qHeapSort(listInt); - TQValueList::Iterator it; - for( it = listInt.begin(); it != listInt.end(); ++it ) - { - if(!showColNumber) - listCol+=i18n("Column: %1").arg(Cell::columnName(*it)); - else - listCol+=i18n("Column: %1").arg(text.setNum(*it)); - } - list->insertStringList(listCol); - } - else if(_type==Row) - { - RowFormat *row=m_pView->activeSheet()->firstRow(); - - TQString text; - TQStringList listRow; - for( ; row; row = row->next() ) - { - if(row->isHide()) - listInt.append(row->row()); - } - qHeapSort(listInt); - TQValueList::Iterator it; - for( it = listInt.begin(); it != listInt.end(); ++it ) - listRow+=i18n("Row: %1").arg(text.setNum(*it)); - - list->insertStringList(listRow); - } - - if(!list->count()) - enableButtonOK(false); - - //selection multiple - list->setSelectionMode(TQListBox::Multi); - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); - resize( 200, 150 ); - setFocus(); -} - -void ShowColRow::slotDoubleClicked(TQListBoxItem *) -{ - slotOk(); -} - -void ShowColRow::slotOk() -{ - Region region; - for(unsigned int i=0; i < list->count(); i++) - { - if (list->isSelected(i)) - { - if (typeShow == Column) - { - region.add(TQRect(*listInt.at(i), 1, 1, KS_rowMax)); - } - if (typeShow == Row) - { - region.add(TQRect(1, *listInt.at(i), KS_colMax, 1)); - } - } - } - - if (typeShow == Column) - { - m_pView->activeSheet()->showColumn(region); - } - if (typeShow == Row) - { - m_pView->activeSheet()->showRow(region); - } - - accept(); -} - -#include "kspread_dlg_showColRow.moc" diff --git a/kspread/dialogs/kspread_dlg_showColRow.cpp b/kspread/dialogs/kspread_dlg_showColRow.cpp new file mode 100644 index 00000000..32c4c631 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_showColRow.cpp @@ -0,0 +1,152 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres + (C) 2000-2002 Laurent Montel + (C) 2001-2002 Philipp Mueller + (C) 2002 John Dailey + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include + +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_util.h" +#include "kspread_view.h" +#include "region.h" + +#include "kspread_dlg_showColRow.h" + +using namespace KSpread; + +ShowColRow::ShowColRow( View* parent, const char* name, Type _type ) + : KDialogBase( parent, name,TRUE,"",Ok|Cancel ) +{ + m_pView = parent; + typeShow=_type; + + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQLabel *label = new TQLabel( page ); + + if(_type==Column) { + setCaption( i18n("Show Columns") ); + label->setText(i18n("Select hidden columns to show:")); + } + else if(_type==Row) { + setCaption( i18n("Show Rows") ); + label->setText(i18n("Select hidden rows to show:")); + } + + list=new TQListBox(page); + + lay1->addWidget( label ); + lay1->addWidget( list ); + + bool showColNumber=m_pView->activeSheet()->getShowColumnNumber(); + if(_type==Column) + { + ColumnFormat *col=m_pView->activeSheet()->firstCol(); + + TQString text; + TQStringList listCol; + for( ; col; col = col->next() ) + { + if(col->isHide()) + listInt.append(col->column()); + } + qHeapSort(listInt); + TQValueList::Iterator it; + for( it = listInt.begin(); it != listInt.end(); ++it ) + { + if(!showColNumber) + listCol+=i18n("Column: %1").arg(Cell::columnName(*it)); + else + listCol+=i18n("Column: %1").arg(text.setNum(*it)); + } + list->insertStringList(listCol); + } + else if(_type==Row) + { + RowFormat *row=m_pView->activeSheet()->firstRow(); + + TQString text; + TQStringList listRow; + for( ; row; row = row->next() ) + { + if(row->isHide()) + listInt.append(row->row()); + } + qHeapSort(listInt); + TQValueList::Iterator it; + for( it = listInt.begin(); it != listInt.end(); ++it ) + listRow+=i18n("Row: %1").arg(text.setNum(*it)); + + list->insertStringList(listRow); + } + + if(!list->count()) + enableButtonOK(false); + + //selection multiple + list->setSelectionMode(TQListBox::Multi); + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( list, TQT_SIGNAL(doubleClicked(TQListBoxItem *)),this,TQT_SLOT(slotDoubleClicked(TQListBoxItem *))); + resize( 200, 150 ); + setFocus(); +} + +void ShowColRow::slotDoubleClicked(TQListBoxItem *) +{ + slotOk(); +} + +void ShowColRow::slotOk() +{ + Region region; + for(unsigned int i=0; i < list->count(); i++) + { + if (list->isSelected(i)) + { + if (typeShow == Column) + { + region.add(TQRect(*listInt.at(i), 1, 1, KS_rowMax)); + } + if (typeShow == Row) + { + region.add(TQRect(1, *listInt.at(i), KS_colMax, 1)); + } + } + } + + if (typeShow == Column) + { + m_pView->activeSheet()->showColumn(region); + } + if (typeShow == Row) + { + m_pView->activeSheet()->showRow(region); + } + + accept(); +} + +#include "kspread_dlg_showColRow.moc" diff --git a/kspread/dialogs/kspread_dlg_sort.cc b/kspread/dialogs/kspread_dlg_sort.cc deleted file mode 100644 index 52cda9b6..00000000 --- a/kspread/dialogs/kspread_dlg_sort.cc +++ /dev/null @@ -1,748 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2006 Robert Knight - (C) 2002-2003 Norbert Andres - (C) 2002 Ariya Hidayat - (C) 2002 John Dailey - (C) 2002 Werner Trobin - (C) 2001-2002 Philipp Mueller - (C) 1999-2002 Laurent Montel - (C) 2000 David Faure - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_dlg_sort.h" -#include "kspread_doc.h" -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "kspread_util.h" -#include "selection.h" - -using namespace KSpread; - -SortDialog::SortDialog( View * parent, const char * name, - bool modal ) - : KDialogBase( parent, name, modal,"Sort",Ok|Cancel ), - m_pView( parent ) -{ - if ( !name ) - setName( "SortDialog" ); - - resize( 528, 316 ); - setCaption( i18n( "Sorting" ) ); - //setSizeGripEnabled( true ); - - TQVBox *page = makeVBoxMainWidget(); - - m_tabWidget = new TQTabWidget( page, "m_tabWidget" ); - - m_page1 = new TQWidget( m_tabWidget, "m_page1" ); - TQGridLayout * page1Layout - = new TQGridLayout( m_page1, 1, 1, 11, 6, "page1Layout"); - -//---------------- Sort Layout & Header Row/Column Toggle - - //Sort orientation selector (for selecting Left-To-Right or Top-To-Bottom sorting of the selection) - TQGroupBox* layoutGroup = new TQGroupBox(2 , Qt::Vertical, m_page1, "layoutGroup"); - layoutGroup->setTitle( i18n("Layout") ); - - TQHButtonGroup * orientationGroup = new TQHButtonGroup( layoutGroup, "orientationGroup" ); - orientationGroup->setLineWidth(0); - orientationGroup->setMargin(0); - orientationGroup->layout()->setMargin(0); - - m_sortColumn = new TQRadioButton( orientationGroup, "m_sortColumn" ); - m_sortColumn->setText( i18n( "Sort &Rows" ) ); - - m_sortRow = new TQRadioButton( orientationGroup, "m_sortRow" ); - m_sortRow->setText( i18n( "Sort &Columns" ) ); - - //First row / column contains header toggle - m_firstRowOrColHeader = new TQCheckBox( layoutGroup, "m_copyLayout" ); - //m_firstRowOrColHeader->setText( i18n( "&First row contains headers" ) ); - m_firstRowOrColHeader->setChecked(true); - page1Layout->addWidget(layoutGroup,0,0); - -//---------------- - - page1Layout->addRowSpacing(2,10); - - - TQGroupBox * sort1Box = new TQGroupBox( m_page1, "sort1Box" ); - sort1Box->setTitle( i18n( "Sort By" ) ); - sort1Box->setFlat(true); - sort1Box->setColumnLayout(0, Qt::Vertical ); - sort1Box->layout()->setSpacing( KDialog::spacingHint() ); - sort1Box->layout()->setMargin( KDialog::marginHint() ); - TQHBoxLayout * sort1BoxLayout = new TQHBoxLayout( sort1Box->layout() ); - sort1BoxLayout->setAlignment( TQt::AlignTop ); - - m_sortKey1 = new TQComboBox( false, sort1Box, "m_sortKey1" ); - sort1BoxLayout->addWidget( m_sortKey1 ); - - m_sortOrder1 = new TQComboBox( false, sort1Box, "m_sortOrder1" ); - m_sortOrder1->insertItem( i18n( "Ascending" ) ); - m_sortOrder1->insertItem( i18n( "Descending" ) ); - sort1BoxLayout->addWidget( m_sortOrder1 ); - - page1Layout->addWidget( sort1Box, 3, 0 ); - - TQGroupBox * sort2Box = new TQGroupBox( m_page1, "sort2Box" ); - sort2Box->setTitle( i18n( "Then By" ) ); - sort2Box->setFlat(true); - sort2Box->setColumnLayout(0, Qt::Vertical ); - sort2Box->layout()->setSpacing( KDialog::spacingHint() ); - sort2Box->layout()->setMargin( KDialog::marginHint() ); - TQHBoxLayout * sort2BoxLayout = new TQHBoxLayout( sort2Box->layout() ); - sort2BoxLayout->setAlignment( TQt::AlignTop ); - - m_sortKey2 = new TQComboBox( false, sort2Box, "m_sortKey2" ); - m_sortKey2->insertItem( i18n( "None" ) ); - sort2BoxLayout->addWidget( m_sortKey2 ); - - m_sortOrder2 = new TQComboBox( false, sort2Box, "m_sortOrder2" ); - m_sortOrder2->insertItem( i18n( "Ascending" ) ); - m_sortOrder2->insertItem( i18n( "Descending" ) ); - sort2BoxLayout->addWidget( m_sortOrder2 ); - - page1Layout->addWidget( sort2Box, 4, 0 ); - - TQGroupBox * sort3Box = new TQGroupBox( m_page1, "sort3Box" ); - sort3Box->setTitle( i18n( "Then By" ) ); - sort3Box->setFlat(true); - sort3Box->setColumnLayout(0, Qt::Vertical ); - sort3Box->layout()->setSpacing( KDialog::spacingHint() ); - sort3Box->layout()->setMargin( KDialog::marginHint() ); - TQHBoxLayout * sort3BoxLayout = new TQHBoxLayout( sort3Box->layout() ); - sort3BoxLayout->setAlignment( TQt::AlignTop ); - - m_sortKey3 = new TQComboBox( false, sort3Box, "m_sortKey3" ); - m_sortKey3->insertItem( i18n( "None" ) ); - m_sortKey3->setEnabled( false ); - sort3BoxLayout->addWidget( m_sortKey3 ); - - m_sortOrder3 = new TQComboBox( false, sort3Box, "m_sortOrder3" ); - m_sortOrder3->insertItem( i18n( "Ascending" ) ); - m_sortOrder3->insertItem( i18n( "Descending" ) ); - m_sortOrder3->setEnabled( false ); - sort3BoxLayout->addWidget( m_sortOrder3 ); - - page1Layout->addWidget( sort3Box, 5, 0 ); - m_tabWidget->insertTab( m_page1, i18n( "Sort Criteria" ) ); - - - //---------------- options page - - m_page2 = new TQWidget( m_tabWidget, "m_page2" ); - TQGridLayout * page2Layout = new TQGridLayout( m_page2, 1, 1, 11, 6, "page2Layout"); - page2Layout->setAlignment(TQt::AlignTop); - - TQGroupBox * firstKeyBox = new TQGroupBox( m_page2, "firstKeyBox" ); - firstKeyBox->setTitle( i18n( "First Key" ) ); - firstKeyBox->setColumnLayout(0, Qt::Vertical ); - firstKeyBox->layout()->setSpacing( KDialog::spacingHint() ); - firstKeyBox->layout()->setMargin( KDialog::marginHint() ); - TQVBoxLayout * firstKeyBoxLayout = new TQVBoxLayout( firstKeyBox->layout() ); - firstKeyBoxLayout->setAlignment( TQt::AlignTop ); - - m_useCustomLists = new TQCheckBox( firstKeyBox, "m_useCustomLists_2" ); - m_useCustomLists->setText( i18n( "&Use custom list" ) ); - firstKeyBoxLayout->addWidget( m_useCustomLists ); - - m_customList = new TQComboBox( false, firstKeyBox, "m_customList" ); - m_customList->setEnabled( false ); - m_customList->setMaximumSize( 230, 30 ); - firstKeyBoxLayout->addWidget( m_customList ); - - page2Layout->addWidget( firstKeyBox, 0, 0 ); - - - /* - This doesn't work properly, and as a bug report pointed out, it isn't that useful since it is easy - to just copy and paste the data and then sort the newly pasted data in place. - -- Robert Knight - - TQGroupBox * resultToBox = new TQGroupBox( m_page2, "resultToBox" ); - resultToBox->setTitle( i18n( "Location to Store Sort Results" ) ); - resultToBox->setColumnLayout(0, Qt::Vertical ); - resultToBox->layout()->setSpacing( KDialog::spacingHint() ); - resultToBox->layout()->setMargin( KDialog::marginHint() ); - - - TQHBoxLayout * resultToBoxLayout = new TQHBoxLayout( resultToBox->layout() ); - resultToBoxLayout->setAlignment( TQt::AlignTop ); - - TQLabel * destinationSheet=new TQLabel(resultToBox,"destinationSheet"); - destinationSheet->setText("Destination Sheet:"); - resultToBoxLayout->addWidget(destinationSheet); - - m_outputSheet = new TQComboBox( false, resultToBox, "m_outputSheet" ); - resultToBoxLayout->addWidget( m_outputSheet ); - TQSpacerItem * spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); - resultToBoxLayout->addItem( spacer ); - - TQLabel * startingCellLabel = new TQLabel( resultToBox, "destinationCellLabel" ); - startingCellLabel->setText( i18n( "Destination Cell:" ) ); - resultToBoxLayout->addWidget( startingCellLabel ); - - m_outputCell = new TQLineEdit( resultToBox, "m_outputCell" ); - m_outputCell->setMaximumSize( TQSize( 60, 32767 ) ); - resultToBoxLayout->addWidget( m_outputCell ); - - page2Layout->addWidget( resultToBox, 1,0 );*/ - - - m_tabWidget->insertTab( m_page2, i18n( "Options" ) ); - - TQHBoxLayout * Layout1 = new TQHBoxLayout( 0, 0, 6, "Layout1"); - TQSpacerItem * spacer_2 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, - TQSizePolicy::Minimum ); - Layout1->addItem( spacer_2 ); - - - m_copyLayout = new TQCheckBox( m_page2, "m_copyLayout" ); - m_copyLayout->setText( i18n( "Copy cell &formatting (Borders, Colours, Text Style)" ) ); - - page2Layout->addWidget( m_copyLayout, 1, 0 ); - - m_respectCase = new TQCheckBox( m_page2, "m_copyLayout" ); - m_respectCase->setText( i18n( "Case sensitive sort" ) ); - m_respectCase->setChecked( true ); - - page2Layout->addWidget( m_respectCase, 2,0 ); - - connect( m_sortKey2, TQT_SIGNAL( activated( int ) ), this, - TQT_SLOT( sortKey2textChanged( int ) ) ); - connect( m_useCustomLists, TQT_SIGNAL( stateChanged(int) ), this, - TQT_SLOT( useCustomListsStateChanged(int) ) ); - connect( m_firstRowOrColHeader, TQT_SIGNAL( stateChanged(int) ), this, - TQT_SLOT( firstRowHeaderChanged(int) ) ); - connect( orientationGroup, TQT_SIGNAL( pressed(int) ), this, - TQT_SLOT( slotOrientationChanged(int) ) ); - - init(); -} - -TQRect SortDialog::sourceArea() -{ - return m_pView->selectionInfo()->selection(); -} - -SortDialog::Orientation SortDialog::guessDataOrientation() -{ - const TQRect selection=sourceArea(); - - if (selection.width() >= selection.height()) - return SortColumns; - else - return SortRows; -} - -SortDialog::~SortDialog() -{ - // no need to delete child widgets, TQt does it all for us -} - -void SortDialog::init() -{ - TQStringList lst; - lst<config(); - config->setGroup( "Parameters" ); - TQStringList other = config->readListEntry("Other list"); - TQString tmp; - for ( TQStringList::Iterator it = other.begin(); it != other.end(); ++it ) - { - if((*it) != "\\") - tmp += (*it) + ", "; - else if( it != other.begin()) - { - tmp = tmp.left(tmp.length() - 2); - lst.append(tmp); - tmp = ""; - } - } - m_customList->insertStringList(lst); - - /*TQPtrList sheetList = m_pView->doc()->map()->sheetList(); - for (unsigned int c = 0; c < sheetList.count(); ++c) - { - Sheet * t = sheetList.at(c); - if (!t) - continue; - m_outputSheet->insertItem( t->sheetName() ); - } - m_outputSheet->setCurrentText( m_pView->activeSheet()->sheetName() );*/ - - TQRect r = sourceArea(); - /*TQString cellArea; - cellArea += Cell::columnName(r.left()); - cellArea += TQString::number( r.top() ); - m_outputCell->setText( cellArea );*/ - - //If the top-most row or left-most column all contain text items (as opposed to numbers, dates etc.) - //then the dialog will guess that the top row (or left column) is a header. - //The user can always change this if we get this wrong. - bool selectionMayHaveHeader = true; - - // Entire columns selected ? - if ( util_isColumnSelected(r) ) - { - m_sortRow->setEnabled(false); - m_sortColumn->setChecked(true); - - int right = r.right(); - for (int i = r.left(); i <= right; ++i) - { - TQString guessName=m_pView->activeSheet()->guessColumnTitle(r,i); - TQString colName=i18n(" (Column %1)").arg(Cell::columnName(i)); - - if (!guessName.isEmpty()) - { - m_listColumn += guessName + colName; - } - else - { - m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); - - if ( i == r.left() ) - selectionMayHaveHeader=false; - } - } - // m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); - } - // Entire rows selected ? - else if ( util_isRowSelected(r) ) - { - m_sortColumn->setEnabled(false); - m_sortRow->setChecked(true); - - int bottom = r.bottom(); - for (int i = r.top(); i <= bottom; ++i) - { - TQString guessName=m_pView->activeSheet()->guessRowTitle(r,i); - TQString rowName=i18n(" (Row %1)").arg(i); - - if (!guessName.isEmpty()) - { - m_listRow += guessName + rowName; - } - else - { - m_listRow += i18n("Row %1").arg(i); - - if ( i == r.top() ) - selectionMayHaveHeader=false; - } - } - } - else - { - // Selection is only one row - if ( r.top() == r.bottom() ) - { - m_sortColumn->setEnabled(false); - m_sortRow->setChecked(true); - } - // only one column - else if (r.left() == r.right()) - { - m_sortRow->setEnabled(false); - m_sortColumn->setChecked(true); - } - else - { - if (guessDataOrientation() == SortColumns) - m_sortRow->setChecked(true); - else - m_sortColumn->setChecked(true); - } - - int right = r.right(); - int bottom = r.bottom(); - for (int i = r.left(); i <= right; ++i) - { - TQString guessName=m_pView->activeSheet()->guessColumnTitle(r,i); - TQString colName=i18n(" (Column %1)").arg(Cell::columnName(i)); - - if (!guessName.isEmpty()) - m_listColumn += guessName + colName; - else - { - m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); - - if (i == r.left()) - selectionMayHaveHeader=false; - } - } - - for (int i = r.top(); i <= bottom; ++i) - { - TQString guessName=m_pView->activeSheet()->guessRowTitle(r,i); - TQString rowName=i18n(" (Row %1)").arg(i); - - if (!guessName.isEmpty()) - m_listRow += guessName + rowName; - else - { - m_listRow += i18n("Row %1").arg(i); - - if (i == r.top()) - selectionMayHaveHeader=false; - } - } - } - - if ( selectionMayHaveHeader ) - m_firstRowOrColHeader->setChecked( true ); - else - m_firstRowOrColHeader->setChecked( false ); - - // Initialize the combo box - if ( m_sortRow->isChecked() ) - { - slotOrientationChanged( SortRows ); - } - else - { - slotOrientationChanged( SortColumns ); - } -} - -void SortDialog::slotOrientationChanged(int id) -{ - switch( id ) - { - case SortColumns : - m_sortKey1->clear(); - m_sortKey2->clear(); - m_sortKey3->clear(); - m_sortKey1->insertStringList(m_listColumn); - m_sortKey2->insertItem( i18n("None") ); - m_sortKey2->insertStringList(m_listColumn); - m_sortKey3->insertItem( i18n("None") ); - m_sortKey3->insertStringList(m_listColumn); - m_firstRowOrColHeader->setText( i18n( "&First row contains headers" ) ); - break; - - case SortRows : - m_sortKey1->clear(); - m_sortKey2->clear(); - m_sortKey3->clear(); - m_sortKey1->insertStringList(m_listRow); - m_sortKey2->insertItem( i18n("None") ); - m_sortKey2->insertStringList(m_listRow); - m_sortKey3->insertItem( i18n("None") ); - m_sortKey3->insertStringList(m_listRow); - m_firstRowOrColHeader->setText( i18n( "&First column contains headers" ) ); - - /*if (m_firstRowOrColHeader->isChecked()) - { - int k1 = m_sortKey1->currentItem(); - int k2 = m_sortKey2->currentItem(); - int k3 = m_sortKey3->currentItem(); - m_sortKey1->removeItem( 0 ); - m_sortKey2->removeItem( 1 ); // because there is "None" in there - m_sortKey3->removeItem( 1 ); - if (k1 > 0) - m_sortKey1->setCurrentItem(--k1); - else - m_sortKey1->setCurrentItem( 0 ); - if (k2 > 0) - m_sortKey2->setCurrentItem(--k2); - if (k3 > 0) - m_sortKey3->setCurrentItem(--k3); - }*/ - - break; - - default : - kdDebug(36001) << "Error in signal : pressed(int id)" << endl; - break; - } -} - -void SortDialog::slotOk() -{ - m_pView->doc()->emitBeginOperation( false ); - - Orientation sortOrientation; - if (m_sortRow->isChecked()) - sortOrientation=SortColumns; - else - sortOrientation=SortRows; - - Sheet * sheet = m_pView->activeSheet(); - /*m_pView->doc()->map()->findSheet( m_outputSheet->currentText() ); - if ( !sheet ) - { - KMessageBox::error( this, i18n("The destination sheet does not exist.") ); - m_outputSheet->setFocus(); - m_tabWidget->setTabEnabled(m_page2, true); - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - } */ - - /*if ( !outputPoint.isValid() || outputPoint.isSheetKnown() ) - { - KMessageBox::error( this, i18n("The destination cell does not exist.") ); - m_outputCell->setFocus(); - m_tabWidget->setTabEnabled(m_page2, true); - m_pView->slotUpdateView( m_pView->activeSheet() ); - return; - }*/ - //outputPoint.setSheet(sheet); - - TQRect sortArea = sourceArea(); - Point outputPoint; - outputPoint.setPos(sortArea.topLeft()); - outputPoint.setSheet(sheet); - bool hasHeader=m_firstRowOrColHeader->isChecked(); - - if ( hasHeader ) - { - if (sortOrientation == SortColumns) - { - sortArea.setLeft( sortArea.left()+1 ); - outputPoint.setColumn( outputPoint.column()+1 ); - } - else - { - sortArea.setTop( sortArea.top()+1 ); - outputPoint.setRow( outputPoint.row()+1 ); - } - } - - /*if ( sortArea.topLeft() != outputPoint.pos() ) - { - int h = outputPoint.pos().y() + sortArea.height(); - int w = outputPoint.pos().x() + sortArea.width(); - - if ( sortArea.contains(outputPoint.pos()) - || ( w >= sortArea.left() && w <= sortArea.right() ) - || ( h >= sortArea.top() && h <= sortArea.bottom() ) ) - { - KMessageBox::error( this, i18n("If the destination and source regions are different, they must not overlap.") ); - m_outputCell->setFocus(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - // TODO: set right tab - return; - } - }*/ - - int key1 = 1; - int key2 = 0; - int key3 = 0; - TQStringList * firstKey = 0L; - Sheet::SortingOrder order1; - Sheet::SortingOrder order2; - Sheet::SortingOrder order3; - - order1 = ( m_sortOrder1->currentItem() == 0 ? Sheet::Increase - : Sheet::Decrease ); - order2 = ( m_sortOrder2->currentItem() == 0 ? Sheet::Increase - : Sheet::Decrease ); - order3 = ( m_sortOrder3->currentItem() == 0 ? Sheet::Increase - : Sheet::Decrease ); - - if ( m_sortRow->isChecked() ) - { - key1 = m_sortKey1->currentItem() + sortArea.top(); - if (m_sortKey2->currentItem() > 0) - key2 = m_sortKey2->currentItem() + sortArea.top() - 1; // cause there is "None" - if (m_sortKey3->currentItem() > 0) - key3 = m_sortKey3->currentItem() + sortArea.top() - 1; // cause there is "None" - } - else - { - key1 = m_sortKey1->currentItem() + sortArea.left(); - if (m_sortKey2->currentItem() > 0) - key2 = m_sortKey2->currentItem() + sortArea.left() - 1; // cause there is "None" - if (m_sortKey3->currentItem() > 0) - key3 = m_sortKey3->currentItem() + sortArea.left() - 1; // cause there is "None" - - } - /* - if (m_firstRowOrColHeader->isChecked()) - { - if (key1 >= 0) - ++key1; - if (key2 > 0) - ++key2; - if (key3 > 0) - ++key3; - }*/ - - if ( m_useCustomLists->isChecked() ) - { - firstKey = new TQStringList(); - TQString list = m_customList->currentText(); - TQString tmp; - int l = list.length(); - for ( int i = 0; i < l; ++i ) - { - if ( list[i] == ',' ) - { - firstKey->append( tmp.stripWhiteSpace() ); - tmp = ""; - } - else - tmp += list[i]; - } - } - - - - if (key1 == key2) - key2 = 0; - - if (key1 == key3) - key3 = 0; - - if (key2 == 0 && key3 > 0) - { - key2 = key3; - key3 = 0; - } - - - - if ( m_sortRow->isChecked() ) - { - m_pView->activeSheet()->sortByRow( sortArea/*sourceArea*/, key1, key2, key3, - order1, order2, order3, - firstKey, m_copyLayout->isChecked(), - false /*m_firstRowOrColHeader->isChecked()*/, - outputPoint, m_respectCase->isChecked() ); - } - else if (m_sortColumn->isChecked()) - { - m_pView->activeSheet()->sortByColumn( sortArea /*sourceArea*/, key1, key2, key3, - order1, order2, order3, - firstKey, m_copyLayout->isChecked(), - false/*m_firstRowOrColHeader->isChecked()*/, - outputPoint, m_respectCase->isChecked() ); - } - else - { - kdDebug(36001) << "Err in radiobutton" << endl; - } - - delete firstKey; - firstKey = 0L; - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void SortDialog::sortKey2textChanged( int i ) -{ - m_sortKey3->setEnabled( ( i!=0 ) ); - m_sortOrder3->setEnabled( ( i!=0 ) ); -} - -void SortDialog::useCustomListsStateChanged( int state ) -{ - if (state == 0) - m_customList->setEnabled(false); - else if (state == 2) - m_customList->setEnabled(true); -} - -void SortDialog::firstRowHeaderChanged( int /*state*/ ) -{ - /* if (m_sortColumn->isChecked()) - return; - - if (state == 0) // off - { - int k1 = m_sortKey1->currentItem(); - int k2 = m_sortKey2->currentItem(); - int k3 = m_sortKey3->currentItem(); - m_sortKey1->clear(); - m_sortKey2->clear(); - m_sortKey3->clear(); - m_sortKey1->insertStringList( m_listRow ); - m_sortKey2->insertItem( i18n("None") ); - m_sortKey2->insertStringList( m_listRow ); - m_sortKey3->insertItem( i18n("None") ); - m_sortKey3->insertStringList( m_listRow ); - - m_sortKey1->setCurrentItem(++k1); - m_sortKey2->setCurrentItem(++k2); - m_sortKey3->setCurrentItem(++k3); - } - else if (state == 2) // on - { - int k1 = m_sortKey1->currentItem(); - int k2 = m_sortKey2->currentItem(); - int k3 = m_sortKey3->currentItem(); - m_sortKey1->removeItem( 0 ); - m_sortKey2->removeItem( 1 ); // because there is "None" in there - m_sortKey3->removeItem( 1 ); - if (k1 > 0) - m_sortKey1->setCurrentItem(--k1); - if (k2 > 0) - m_sortKey2->setCurrentItem(--k2); - if (k3 > 0) - m_sortKey3->setCurrentItem(--k3); - }*/ -} - -#include "kspread_dlg_sort.moc" diff --git a/kspread/dialogs/kspread_dlg_sort.cpp b/kspread/dialogs/kspread_dlg_sort.cpp new file mode 100644 index 00000000..52cda9b6 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_sort.cpp @@ -0,0 +1,748 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Robert Knight + (C) 2002-2003 Norbert Andres + (C) 2002 Ariya Hidayat + (C) 2002 John Dailey + (C) 2002 Werner Trobin + (C) 2001-2002 Philipp Mueller + (C) 1999-2002 Laurent Montel + (C) 2000 David Faure + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_dlg_sort.h" +#include "kspread_doc.h" +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "kspread_util.h" +#include "selection.h" + +using namespace KSpread; + +SortDialog::SortDialog( View * parent, const char * name, + bool modal ) + : KDialogBase( parent, name, modal,"Sort",Ok|Cancel ), + m_pView( parent ) +{ + if ( !name ) + setName( "SortDialog" ); + + resize( 528, 316 ); + setCaption( i18n( "Sorting" ) ); + //setSizeGripEnabled( true ); + + TQVBox *page = makeVBoxMainWidget(); + + m_tabWidget = new TQTabWidget( page, "m_tabWidget" ); + + m_page1 = new TQWidget( m_tabWidget, "m_page1" ); + TQGridLayout * page1Layout + = new TQGridLayout( m_page1, 1, 1, 11, 6, "page1Layout"); + +//---------------- Sort Layout & Header Row/Column Toggle + + //Sort orientation selector (for selecting Left-To-Right or Top-To-Bottom sorting of the selection) + TQGroupBox* layoutGroup = new TQGroupBox(2 , Qt::Vertical, m_page1, "layoutGroup"); + layoutGroup->setTitle( i18n("Layout") ); + + TQHButtonGroup * orientationGroup = new TQHButtonGroup( layoutGroup, "orientationGroup" ); + orientationGroup->setLineWidth(0); + orientationGroup->setMargin(0); + orientationGroup->layout()->setMargin(0); + + m_sortColumn = new TQRadioButton( orientationGroup, "m_sortColumn" ); + m_sortColumn->setText( i18n( "Sort &Rows" ) ); + + m_sortRow = new TQRadioButton( orientationGroup, "m_sortRow" ); + m_sortRow->setText( i18n( "Sort &Columns" ) ); + + //First row / column contains header toggle + m_firstRowOrColHeader = new TQCheckBox( layoutGroup, "m_copyLayout" ); + //m_firstRowOrColHeader->setText( i18n( "&First row contains headers" ) ); + m_firstRowOrColHeader->setChecked(true); + page1Layout->addWidget(layoutGroup,0,0); + +//---------------- + + page1Layout->addRowSpacing(2,10); + + + TQGroupBox * sort1Box = new TQGroupBox( m_page1, "sort1Box" ); + sort1Box->setTitle( i18n( "Sort By" ) ); + sort1Box->setFlat(true); + sort1Box->setColumnLayout(0, Qt::Vertical ); + sort1Box->layout()->setSpacing( KDialog::spacingHint() ); + sort1Box->layout()->setMargin( KDialog::marginHint() ); + TQHBoxLayout * sort1BoxLayout = new TQHBoxLayout( sort1Box->layout() ); + sort1BoxLayout->setAlignment( TQt::AlignTop ); + + m_sortKey1 = new TQComboBox( false, sort1Box, "m_sortKey1" ); + sort1BoxLayout->addWidget( m_sortKey1 ); + + m_sortOrder1 = new TQComboBox( false, sort1Box, "m_sortOrder1" ); + m_sortOrder1->insertItem( i18n( "Ascending" ) ); + m_sortOrder1->insertItem( i18n( "Descending" ) ); + sort1BoxLayout->addWidget( m_sortOrder1 ); + + page1Layout->addWidget( sort1Box, 3, 0 ); + + TQGroupBox * sort2Box = new TQGroupBox( m_page1, "sort2Box" ); + sort2Box->setTitle( i18n( "Then By" ) ); + sort2Box->setFlat(true); + sort2Box->setColumnLayout(0, Qt::Vertical ); + sort2Box->layout()->setSpacing( KDialog::spacingHint() ); + sort2Box->layout()->setMargin( KDialog::marginHint() ); + TQHBoxLayout * sort2BoxLayout = new TQHBoxLayout( sort2Box->layout() ); + sort2BoxLayout->setAlignment( TQt::AlignTop ); + + m_sortKey2 = new TQComboBox( false, sort2Box, "m_sortKey2" ); + m_sortKey2->insertItem( i18n( "None" ) ); + sort2BoxLayout->addWidget( m_sortKey2 ); + + m_sortOrder2 = new TQComboBox( false, sort2Box, "m_sortOrder2" ); + m_sortOrder2->insertItem( i18n( "Ascending" ) ); + m_sortOrder2->insertItem( i18n( "Descending" ) ); + sort2BoxLayout->addWidget( m_sortOrder2 ); + + page1Layout->addWidget( sort2Box, 4, 0 ); + + TQGroupBox * sort3Box = new TQGroupBox( m_page1, "sort3Box" ); + sort3Box->setTitle( i18n( "Then By" ) ); + sort3Box->setFlat(true); + sort3Box->setColumnLayout(0, Qt::Vertical ); + sort3Box->layout()->setSpacing( KDialog::spacingHint() ); + sort3Box->layout()->setMargin( KDialog::marginHint() ); + TQHBoxLayout * sort3BoxLayout = new TQHBoxLayout( sort3Box->layout() ); + sort3BoxLayout->setAlignment( TQt::AlignTop ); + + m_sortKey3 = new TQComboBox( false, sort3Box, "m_sortKey3" ); + m_sortKey3->insertItem( i18n( "None" ) ); + m_sortKey3->setEnabled( false ); + sort3BoxLayout->addWidget( m_sortKey3 ); + + m_sortOrder3 = new TQComboBox( false, sort3Box, "m_sortOrder3" ); + m_sortOrder3->insertItem( i18n( "Ascending" ) ); + m_sortOrder3->insertItem( i18n( "Descending" ) ); + m_sortOrder3->setEnabled( false ); + sort3BoxLayout->addWidget( m_sortOrder3 ); + + page1Layout->addWidget( sort3Box, 5, 0 ); + m_tabWidget->insertTab( m_page1, i18n( "Sort Criteria" ) ); + + + //---------------- options page + + m_page2 = new TQWidget( m_tabWidget, "m_page2" ); + TQGridLayout * page2Layout = new TQGridLayout( m_page2, 1, 1, 11, 6, "page2Layout"); + page2Layout->setAlignment(TQt::AlignTop); + + TQGroupBox * firstKeyBox = new TQGroupBox( m_page2, "firstKeyBox" ); + firstKeyBox->setTitle( i18n( "First Key" ) ); + firstKeyBox->setColumnLayout(0, Qt::Vertical ); + firstKeyBox->layout()->setSpacing( KDialog::spacingHint() ); + firstKeyBox->layout()->setMargin( KDialog::marginHint() ); + TQVBoxLayout * firstKeyBoxLayout = new TQVBoxLayout( firstKeyBox->layout() ); + firstKeyBoxLayout->setAlignment( TQt::AlignTop ); + + m_useCustomLists = new TQCheckBox( firstKeyBox, "m_useCustomLists_2" ); + m_useCustomLists->setText( i18n( "&Use custom list" ) ); + firstKeyBoxLayout->addWidget( m_useCustomLists ); + + m_customList = new TQComboBox( false, firstKeyBox, "m_customList" ); + m_customList->setEnabled( false ); + m_customList->setMaximumSize( 230, 30 ); + firstKeyBoxLayout->addWidget( m_customList ); + + page2Layout->addWidget( firstKeyBox, 0, 0 ); + + + /* + This doesn't work properly, and as a bug report pointed out, it isn't that useful since it is easy + to just copy and paste the data and then sort the newly pasted data in place. + -- Robert Knight + + TQGroupBox * resultToBox = new TQGroupBox( m_page2, "resultToBox" ); + resultToBox->setTitle( i18n( "Location to Store Sort Results" ) ); + resultToBox->setColumnLayout(0, Qt::Vertical ); + resultToBox->layout()->setSpacing( KDialog::spacingHint() ); + resultToBox->layout()->setMargin( KDialog::marginHint() ); + + + TQHBoxLayout * resultToBoxLayout = new TQHBoxLayout( resultToBox->layout() ); + resultToBoxLayout->setAlignment( TQt::AlignTop ); + + TQLabel * destinationSheet=new TQLabel(resultToBox,"destinationSheet"); + destinationSheet->setText("Destination Sheet:"); + resultToBoxLayout->addWidget(destinationSheet); + + m_outputSheet = new TQComboBox( false, resultToBox, "m_outputSheet" ); + resultToBoxLayout->addWidget( m_outputSheet ); + TQSpacerItem * spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + resultToBoxLayout->addItem( spacer ); + + TQLabel * startingCellLabel = new TQLabel( resultToBox, "destinationCellLabel" ); + startingCellLabel->setText( i18n( "Destination Cell:" ) ); + resultToBoxLayout->addWidget( startingCellLabel ); + + m_outputCell = new TQLineEdit( resultToBox, "m_outputCell" ); + m_outputCell->setMaximumSize( TQSize( 60, 32767 ) ); + resultToBoxLayout->addWidget( m_outputCell ); + + page2Layout->addWidget( resultToBox, 1,0 );*/ + + + m_tabWidget->insertTab( m_page2, i18n( "Options" ) ); + + TQHBoxLayout * Layout1 = new TQHBoxLayout( 0, 0, 6, "Layout1"); + TQSpacerItem * spacer_2 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, + TQSizePolicy::Minimum ); + Layout1->addItem( spacer_2 ); + + + m_copyLayout = new TQCheckBox( m_page2, "m_copyLayout" ); + m_copyLayout->setText( i18n( "Copy cell &formatting (Borders, Colours, Text Style)" ) ); + + page2Layout->addWidget( m_copyLayout, 1, 0 ); + + m_respectCase = new TQCheckBox( m_page2, "m_copyLayout" ); + m_respectCase->setText( i18n( "Case sensitive sort" ) ); + m_respectCase->setChecked( true ); + + page2Layout->addWidget( m_respectCase, 2,0 ); + + connect( m_sortKey2, TQT_SIGNAL( activated( int ) ), this, + TQT_SLOT( sortKey2textChanged( int ) ) ); + connect( m_useCustomLists, TQT_SIGNAL( stateChanged(int) ), this, + TQT_SLOT( useCustomListsStateChanged(int) ) ); + connect( m_firstRowOrColHeader, TQT_SIGNAL( stateChanged(int) ), this, + TQT_SLOT( firstRowHeaderChanged(int) ) ); + connect( orientationGroup, TQT_SIGNAL( pressed(int) ), this, + TQT_SLOT( slotOrientationChanged(int) ) ); + + init(); +} + +TQRect SortDialog::sourceArea() +{ + return m_pView->selectionInfo()->selection(); +} + +SortDialog::Orientation SortDialog::guessDataOrientation() +{ + const TQRect selection=sourceArea(); + + if (selection.width() >= selection.height()) + return SortColumns; + else + return SortRows; +} + +SortDialog::~SortDialog() +{ + // no need to delete child widgets, TQt does it all for us +} + +void SortDialog::init() +{ + TQStringList lst; + lst<config(); + config->setGroup( "Parameters" ); + TQStringList other = config->readListEntry("Other list"); + TQString tmp; + for ( TQStringList::Iterator it = other.begin(); it != other.end(); ++it ) + { + if((*it) != "\\") + tmp += (*it) + ", "; + else if( it != other.begin()) + { + tmp = tmp.left(tmp.length() - 2); + lst.append(tmp); + tmp = ""; + } + } + m_customList->insertStringList(lst); + + /*TQPtrList sheetList = m_pView->doc()->map()->sheetList(); + for (unsigned int c = 0; c < sheetList.count(); ++c) + { + Sheet * t = sheetList.at(c); + if (!t) + continue; + m_outputSheet->insertItem( t->sheetName() ); + } + m_outputSheet->setCurrentText( m_pView->activeSheet()->sheetName() );*/ + + TQRect r = sourceArea(); + /*TQString cellArea; + cellArea += Cell::columnName(r.left()); + cellArea += TQString::number( r.top() ); + m_outputCell->setText( cellArea );*/ + + //If the top-most row or left-most column all contain text items (as opposed to numbers, dates etc.) + //then the dialog will guess that the top row (or left column) is a header. + //The user can always change this if we get this wrong. + bool selectionMayHaveHeader = true; + + // Entire columns selected ? + if ( util_isColumnSelected(r) ) + { + m_sortRow->setEnabled(false); + m_sortColumn->setChecked(true); + + int right = r.right(); + for (int i = r.left(); i <= right; ++i) + { + TQString guessName=m_pView->activeSheet()->guessColumnTitle(r,i); + TQString colName=i18n(" (Column %1)").arg(Cell::columnName(i)); + + if (!guessName.isEmpty()) + { + m_listColumn += guessName + colName; + } + else + { + m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); + + if ( i == r.left() ) + selectionMayHaveHeader=false; + } + } + // m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); + } + // Entire rows selected ? + else if ( util_isRowSelected(r) ) + { + m_sortColumn->setEnabled(false); + m_sortRow->setChecked(true); + + int bottom = r.bottom(); + for (int i = r.top(); i <= bottom; ++i) + { + TQString guessName=m_pView->activeSheet()->guessRowTitle(r,i); + TQString rowName=i18n(" (Row %1)").arg(i); + + if (!guessName.isEmpty()) + { + m_listRow += guessName + rowName; + } + else + { + m_listRow += i18n("Row %1").arg(i); + + if ( i == r.top() ) + selectionMayHaveHeader=false; + } + } + } + else + { + // Selection is only one row + if ( r.top() == r.bottom() ) + { + m_sortColumn->setEnabled(false); + m_sortRow->setChecked(true); + } + // only one column + else if (r.left() == r.right()) + { + m_sortRow->setEnabled(false); + m_sortColumn->setChecked(true); + } + else + { + if (guessDataOrientation() == SortColumns) + m_sortRow->setChecked(true); + else + m_sortColumn->setChecked(true); + } + + int right = r.right(); + int bottom = r.bottom(); + for (int i = r.left(); i <= right; ++i) + { + TQString guessName=m_pView->activeSheet()->guessColumnTitle(r,i); + TQString colName=i18n(" (Column %1)").arg(Cell::columnName(i)); + + if (!guessName.isEmpty()) + m_listColumn += guessName + colName; + else + { + m_listColumn += i18n("Column %1").arg(Cell::columnName(i)); + + if (i == r.left()) + selectionMayHaveHeader=false; + } + } + + for (int i = r.top(); i <= bottom; ++i) + { + TQString guessName=m_pView->activeSheet()->guessRowTitle(r,i); + TQString rowName=i18n(" (Row %1)").arg(i); + + if (!guessName.isEmpty()) + m_listRow += guessName + rowName; + else + { + m_listRow += i18n("Row %1").arg(i); + + if (i == r.top()) + selectionMayHaveHeader=false; + } + } + } + + if ( selectionMayHaveHeader ) + m_firstRowOrColHeader->setChecked( true ); + else + m_firstRowOrColHeader->setChecked( false ); + + // Initialize the combo box + if ( m_sortRow->isChecked() ) + { + slotOrientationChanged( SortRows ); + } + else + { + slotOrientationChanged( SortColumns ); + } +} + +void SortDialog::slotOrientationChanged(int id) +{ + switch( id ) + { + case SortColumns : + m_sortKey1->clear(); + m_sortKey2->clear(); + m_sortKey3->clear(); + m_sortKey1->insertStringList(m_listColumn); + m_sortKey2->insertItem( i18n("None") ); + m_sortKey2->insertStringList(m_listColumn); + m_sortKey3->insertItem( i18n("None") ); + m_sortKey3->insertStringList(m_listColumn); + m_firstRowOrColHeader->setText( i18n( "&First row contains headers" ) ); + break; + + case SortRows : + m_sortKey1->clear(); + m_sortKey2->clear(); + m_sortKey3->clear(); + m_sortKey1->insertStringList(m_listRow); + m_sortKey2->insertItem( i18n("None") ); + m_sortKey2->insertStringList(m_listRow); + m_sortKey3->insertItem( i18n("None") ); + m_sortKey3->insertStringList(m_listRow); + m_firstRowOrColHeader->setText( i18n( "&First column contains headers" ) ); + + /*if (m_firstRowOrColHeader->isChecked()) + { + int k1 = m_sortKey1->currentItem(); + int k2 = m_sortKey2->currentItem(); + int k3 = m_sortKey3->currentItem(); + m_sortKey1->removeItem( 0 ); + m_sortKey2->removeItem( 1 ); // because there is "None" in there + m_sortKey3->removeItem( 1 ); + if (k1 > 0) + m_sortKey1->setCurrentItem(--k1); + else + m_sortKey1->setCurrentItem( 0 ); + if (k2 > 0) + m_sortKey2->setCurrentItem(--k2); + if (k3 > 0) + m_sortKey3->setCurrentItem(--k3); + }*/ + + break; + + default : + kdDebug(36001) << "Error in signal : pressed(int id)" << endl; + break; + } +} + +void SortDialog::slotOk() +{ + m_pView->doc()->emitBeginOperation( false ); + + Orientation sortOrientation; + if (m_sortRow->isChecked()) + sortOrientation=SortColumns; + else + sortOrientation=SortRows; + + Sheet * sheet = m_pView->activeSheet(); + /*m_pView->doc()->map()->findSheet( m_outputSheet->currentText() ); + if ( !sheet ) + { + KMessageBox::error( this, i18n("The destination sheet does not exist.") ); + m_outputSheet->setFocus(); + m_tabWidget->setTabEnabled(m_page2, true); + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + } */ + + /*if ( !outputPoint.isValid() || outputPoint.isSheetKnown() ) + { + KMessageBox::error( this, i18n("The destination cell does not exist.") ); + m_outputCell->setFocus(); + m_tabWidget->setTabEnabled(m_page2, true); + m_pView->slotUpdateView( m_pView->activeSheet() ); + return; + }*/ + //outputPoint.setSheet(sheet); + + TQRect sortArea = sourceArea(); + Point outputPoint; + outputPoint.setPos(sortArea.topLeft()); + outputPoint.setSheet(sheet); + bool hasHeader=m_firstRowOrColHeader->isChecked(); + + if ( hasHeader ) + { + if (sortOrientation == SortColumns) + { + sortArea.setLeft( sortArea.left()+1 ); + outputPoint.setColumn( outputPoint.column()+1 ); + } + else + { + sortArea.setTop( sortArea.top()+1 ); + outputPoint.setRow( outputPoint.row()+1 ); + } + } + + /*if ( sortArea.topLeft() != outputPoint.pos() ) + { + int h = outputPoint.pos().y() + sortArea.height(); + int w = outputPoint.pos().x() + sortArea.width(); + + if ( sortArea.contains(outputPoint.pos()) + || ( w >= sortArea.left() && w <= sortArea.right() ) + || ( h >= sortArea.top() && h <= sortArea.bottom() ) ) + { + KMessageBox::error( this, i18n("If the destination and source regions are different, they must not overlap.") ); + m_outputCell->setFocus(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + // TODO: set right tab + return; + } + }*/ + + int key1 = 1; + int key2 = 0; + int key3 = 0; + TQStringList * firstKey = 0L; + Sheet::SortingOrder order1; + Sheet::SortingOrder order2; + Sheet::SortingOrder order3; + + order1 = ( m_sortOrder1->currentItem() == 0 ? Sheet::Increase + : Sheet::Decrease ); + order2 = ( m_sortOrder2->currentItem() == 0 ? Sheet::Increase + : Sheet::Decrease ); + order3 = ( m_sortOrder3->currentItem() == 0 ? Sheet::Increase + : Sheet::Decrease ); + + if ( m_sortRow->isChecked() ) + { + key1 = m_sortKey1->currentItem() + sortArea.top(); + if (m_sortKey2->currentItem() > 0) + key2 = m_sortKey2->currentItem() + sortArea.top() - 1; // cause there is "None" + if (m_sortKey3->currentItem() > 0) + key3 = m_sortKey3->currentItem() + sortArea.top() - 1; // cause there is "None" + } + else + { + key1 = m_sortKey1->currentItem() + sortArea.left(); + if (m_sortKey2->currentItem() > 0) + key2 = m_sortKey2->currentItem() + sortArea.left() - 1; // cause there is "None" + if (m_sortKey3->currentItem() > 0) + key3 = m_sortKey3->currentItem() + sortArea.left() - 1; // cause there is "None" + + } + /* + if (m_firstRowOrColHeader->isChecked()) + { + if (key1 >= 0) + ++key1; + if (key2 > 0) + ++key2; + if (key3 > 0) + ++key3; + }*/ + + if ( m_useCustomLists->isChecked() ) + { + firstKey = new TQStringList(); + TQString list = m_customList->currentText(); + TQString tmp; + int l = list.length(); + for ( int i = 0; i < l; ++i ) + { + if ( list[i] == ',' ) + { + firstKey->append( tmp.stripWhiteSpace() ); + tmp = ""; + } + else + tmp += list[i]; + } + } + + + + if (key1 == key2) + key2 = 0; + + if (key1 == key3) + key3 = 0; + + if (key2 == 0 && key3 > 0) + { + key2 = key3; + key3 = 0; + } + + + + if ( m_sortRow->isChecked() ) + { + m_pView->activeSheet()->sortByRow( sortArea/*sourceArea*/, key1, key2, key3, + order1, order2, order3, + firstKey, m_copyLayout->isChecked(), + false /*m_firstRowOrColHeader->isChecked()*/, + outputPoint, m_respectCase->isChecked() ); + } + else if (m_sortColumn->isChecked()) + { + m_pView->activeSheet()->sortByColumn( sortArea /*sourceArea*/, key1, key2, key3, + order1, order2, order3, + firstKey, m_copyLayout->isChecked(), + false/*m_firstRowOrColHeader->isChecked()*/, + outputPoint, m_respectCase->isChecked() ); + } + else + { + kdDebug(36001) << "Err in radiobutton" << endl; + } + + delete firstKey; + firstKey = 0L; + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void SortDialog::sortKey2textChanged( int i ) +{ + m_sortKey3->setEnabled( ( i!=0 ) ); + m_sortOrder3->setEnabled( ( i!=0 ) ); +} + +void SortDialog::useCustomListsStateChanged( int state ) +{ + if (state == 0) + m_customList->setEnabled(false); + else if (state == 2) + m_customList->setEnabled(true); +} + +void SortDialog::firstRowHeaderChanged( int /*state*/ ) +{ + /* if (m_sortColumn->isChecked()) + return; + + if (state == 0) // off + { + int k1 = m_sortKey1->currentItem(); + int k2 = m_sortKey2->currentItem(); + int k3 = m_sortKey3->currentItem(); + m_sortKey1->clear(); + m_sortKey2->clear(); + m_sortKey3->clear(); + m_sortKey1->insertStringList( m_listRow ); + m_sortKey2->insertItem( i18n("None") ); + m_sortKey2->insertStringList( m_listRow ); + m_sortKey3->insertItem( i18n("None") ); + m_sortKey3->insertStringList( m_listRow ); + + m_sortKey1->setCurrentItem(++k1); + m_sortKey2->setCurrentItem(++k2); + m_sortKey3->setCurrentItem(++k3); + } + else if (state == 2) // on + { + int k1 = m_sortKey1->currentItem(); + int k2 = m_sortKey2->currentItem(); + int k3 = m_sortKey3->currentItem(); + m_sortKey1->removeItem( 0 ); + m_sortKey2->removeItem( 1 ); // because there is "None" in there + m_sortKey3->removeItem( 1 ); + if (k1 > 0) + m_sortKey1->setCurrentItem(--k1); + if (k2 > 0) + m_sortKey2->setCurrentItem(--k2); + if (k3 > 0) + m_sortKey3->setCurrentItem(--k3); + }*/ +} + +#include "kspread_dlg_sort.moc" diff --git a/kspread/dialogs/kspread_dlg_special.cc b/kspread/dialogs/kspread_dlg_special.cc deleted file mode 100644 index 2fbeb7eb..00000000 --- a/kspread/dialogs/kspread_dlg_special.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999-2004 Laurent Montel - (C) 2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 2002 John Dailey - (C) 1998-1999 Torben Weis - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include - -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "selection.h" - -#include "kspread_dlg_special.h" - -using namespace KSpread; - -SpecialDialog::SpecialDialog( View* parent, const char* name ) - : KDialogBase( parent, name, TRUE,i18n("Special Paste"),Ok|Cancel ) -{ - m_pView = parent; - TQWidget *page = new TQWidget( this ); - setMainWidget(page); - TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); - - TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n( "Paste What" ),page ); - grp->setRadioButtonExclusive( TRUE ); - grp->layout(); - lay1->addWidget(grp); - rb1 = new TQRadioButton( i18n("Everything"), grp ); - rb2 = new TQRadioButton( i18n("Text"), grp ); - rb3 = new TQRadioButton( i18n("Format"), grp ); - rb10 = new TQRadioButton( i18n("Comment"), grp ); - rb11 = new TQRadioButton( i18n("Result"), grp ); - - rb4 = new TQRadioButton( i18n("Everything without border"), grp ); - rb1->setChecked(true); - - grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Operation"),page); - grp->setRadioButtonExclusive( TRUE ); - grp->layout(); - lay1->addWidget(grp); - - - rb5 = new TQRadioButton( i18n("Overwrite"), grp ); - rb6 = new TQRadioButton( i18n("Addition"), grp ); - rb7 = new TQRadioButton( i18n("Subtraction"), grp ); - rb8 = new TQRadioButton( i18n("Multiplication"), grp ); - rb9 = new TQRadioButton( i18n("Division"), grp ); - rb5->setChecked(true); - - // cb = new TQCheckBox(i18n("Transpose"),this); - // cb->layout(); - // lay1->addWidget(cb); - - connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); - connect( rb3, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotToggled( bool ) ) ); - connect( rb10, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotToggled( bool ) ) ); -} - -void SpecialDialog::slotOk() -{ - Paste::Mode sp = Paste::Normal; - Paste::Operation op = Paste::OverWrite; - - /* if( rb1->isChecked() ) - sp = cb->isChecked() ? NormalAndTranspose : Normal; - else if( rb2->isChecked() ) - sp = cb->isChecked() ? TextAndTranspose : Text; - else if( rb3->isChecked() ) - sp = cb->isChecked() ? FormatAndTranspose : Format; - else if( rb4->isChecked() ) - sp = cb->isChecked() ? NoBorderAndTranspose : NoBorder; */ - - if( rb1->isChecked() ) - sp = Paste::Normal; - else if( rb2->isChecked() ) - sp = Paste::Text; - else if( rb3->isChecked() ) - sp = Paste::Format; - else if( rb4->isChecked() ) - sp = Paste::NoBorder; - else if( rb10->isChecked() ) - sp = Paste::Comment; - else if( rb11->isChecked() ) - sp = Paste::Result; - - if( rb5->isChecked() ) - op = Paste::OverWrite; - if( rb6->isChecked() ) - op = Paste::Add; - if( rb7->isChecked() ) - op = Paste::Sub; - if( rb8->isChecked() ) - op = Paste::Mul; - if( rb9->isChecked() ) - op = Paste::Div; - - m_pView->doc()->emitBeginOperation( false ); - m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), true, sp, op ); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void SpecialDialog::slotToggled( bool b ) -{ - rb5->setEnabled( !b ); - rb6->setEnabled( !b ); - rb7->setEnabled( !b ); - rb8->setEnabled( !b ); - rb9->setEnabled( !b ); -} - -#include "kspread_dlg_special.moc" diff --git a/kspread/dialogs/kspread_dlg_special.cpp b/kspread/dialogs/kspread_dlg_special.cpp new file mode 100644 index 00000000..2fbeb7eb --- /dev/null +++ b/kspread/dialogs/kspread_dlg_special.cpp @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2004 Laurent Montel + (C) 2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 2002 John Dailey + (C) 1998-1999 Torben Weis + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include + +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "selection.h" + +#include "kspread_dlg_special.h" + +using namespace KSpread; + +SpecialDialog::SpecialDialog( View* parent, const char* name ) + : KDialogBase( parent, name, TRUE,i18n("Special Paste"),Ok|Cancel ) +{ + m_pView = parent; + TQWidget *page = new TQWidget( this ); + setMainWidget(page); + TQVBoxLayout *lay1 = new TQVBoxLayout( page, 0, spacingHint() ); + + TQButtonGroup *grp = new TQButtonGroup( 1, Qt::Horizontal, i18n( "Paste What" ),page ); + grp->setRadioButtonExclusive( TRUE ); + grp->layout(); + lay1->addWidget(grp); + rb1 = new TQRadioButton( i18n("Everything"), grp ); + rb2 = new TQRadioButton( i18n("Text"), grp ); + rb3 = new TQRadioButton( i18n("Format"), grp ); + rb10 = new TQRadioButton( i18n("Comment"), grp ); + rb11 = new TQRadioButton( i18n("Result"), grp ); + + rb4 = new TQRadioButton( i18n("Everything without border"), grp ); + rb1->setChecked(true); + + grp = new TQButtonGroup( 1, Qt::Horizontal, i18n("Operation"),page); + grp->setRadioButtonExclusive( TRUE ); + grp->layout(); + lay1->addWidget(grp); + + + rb5 = new TQRadioButton( i18n("Overwrite"), grp ); + rb6 = new TQRadioButton( i18n("Addition"), grp ); + rb7 = new TQRadioButton( i18n("Subtraction"), grp ); + rb8 = new TQRadioButton( i18n("Multiplication"), grp ); + rb9 = new TQRadioButton( i18n("Division"), grp ); + rb5->setChecked(true); + + // cb = new TQCheckBox(i18n("Transpose"),this); + // cb->layout(); + // lay1->addWidget(cb); + + connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotOk() ) ); + connect( rb3, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotToggled( bool ) ) ); + connect( rb10, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotToggled( bool ) ) ); +} + +void SpecialDialog::slotOk() +{ + Paste::Mode sp = Paste::Normal; + Paste::Operation op = Paste::OverWrite; + + /* if( rb1->isChecked() ) + sp = cb->isChecked() ? NormalAndTranspose : Normal; + else if( rb2->isChecked() ) + sp = cb->isChecked() ? TextAndTranspose : Text; + else if( rb3->isChecked() ) + sp = cb->isChecked() ? FormatAndTranspose : Format; + else if( rb4->isChecked() ) + sp = cb->isChecked() ? NoBorderAndTranspose : NoBorder; */ + + if( rb1->isChecked() ) + sp = Paste::Normal; + else if( rb2->isChecked() ) + sp = Paste::Text; + else if( rb3->isChecked() ) + sp = Paste::Format; + else if( rb4->isChecked() ) + sp = Paste::NoBorder; + else if( rb10->isChecked() ) + sp = Paste::Comment; + else if( rb11->isChecked() ) + sp = Paste::Result; + + if( rb5->isChecked() ) + op = Paste::OverWrite; + if( rb6->isChecked() ) + op = Paste::Add; + if( rb7->isChecked() ) + op = Paste::Sub; + if( rb8->isChecked() ) + op = Paste::Mul; + if( rb9->isChecked() ) + op = Paste::Div; + + m_pView->doc()->emitBeginOperation( false ); + m_pView->activeSheet()->paste( m_pView->selectionInfo()->lastRange(), true, sp, op ); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void SpecialDialog::slotToggled( bool b ) +{ + rb5->setEnabled( !b ); + rb6->setEnabled( !b ); + rb7->setEnabled( !b ); + rb8->setEnabled( !b ); + rb9->setEnabled( !b ); +} + +#include "kspread_dlg_special.moc" diff --git a/kspread/dialogs/kspread_dlg_styles.cc b/kspread/dialogs/kspread_dlg_styles.cc deleted file mode 100644 index bf8f4de2..00000000 --- a/kspread/dialogs/kspread_dlg_styles.cc +++ /dev/null @@ -1,332 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003 Laurent Montel - (C) 2003 Norbert Andres - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_canvas.h" -#include "kspread_cell.h" -#include "kspread_dlg_layout.h" -#include "kspread_sheet.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_view.h" - -#include "kspread_dlg_styles.h" - -using namespace KSpread; - -StyleWidget::StyleWidget( TQWidget * parent, const char * name, WFlags fl ) - : TQWidget( parent, name, fl ) -{ - TQVBoxLayout * layout = new TQVBoxLayout( this, 11, 6, "layout"); - - m_styleList = new TDEListView( this, "m_styleList" ); - m_styleList->addColumn( i18n( "Styles" ) ); - m_styleList->setResizeMode( TDEListView::AllColumns ); - layout->addWidget( m_styleList ); - - m_displayBox = new KComboBox( FALSE, this, "m_displayBox" ); - layout->addWidget( m_displayBox ); - - m_styleList->header()->setLabel( 0, i18n( "Styles" ) ); - m_displayBox->clear(); - m_displayBox->insertItem( i18n( "All Styles" ) ); - m_displayBox->insertItem( i18n( "Applied Styles" ) ); - m_displayBox->insertItem( i18n( "Custom Styles" ) ); - m_displayBox->insertItem( i18n( "Hierarchical" ) ); - connect( m_styleList, TQT_SIGNAL(doubleClicked ( TQListViewItem *)),this, TQT_SIGNAL( modifyStyle())); - resize( TQSize(446, 384).expandedTo(minimumSizeHint()) ); -} - -StyleWidget::~StyleWidget() -{ -} - - - -StyleDlg::StyleDlg( View * parent, StyleManager * manager, - const char * name ) - : KDialogBase( parent, name, true, "", - KDialogBase::Ok | KDialogBase::User1 | KDialogBase::User2 | KDialogBase::User3 | KDialogBase::Close, - KDialogBase::Ok, false, KGuiItem( i18n( "&New..." ) ), KGuiItem( i18n( "&Modify..." ) ), KGuiItem( i18n( "&Delete" ) ) ), - m_view( parent ), - m_styleManager( manager ), - m_dlg( new StyleWidget( this ) ) -{ - setCaption( i18n( "Style Manager" ) ); - setButtonBoxOrientation(Qt::Vertical ); - setMainWidget( m_dlg ); - - slotDisplayMode( 0 ); - enableButton( KDialogBase::User1, true ); - enableButton( KDialogBase::User2, true ); - enableButton( KDialogBase::User3, false ); - - connect( m_dlg->m_styleList, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ), - this, TQT_SLOT( slotSelectionChanged( TQListViewItem * ) ) ); - connect( m_dlg->m_displayBox, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotDisplayMode( int ) ) ); - connect( this, TQT_SIGNAL( user3Clicked() ), this, TQT_SLOT( slotUser3() ) ); - connect( m_dlg, TQT_SIGNAL( modifyStyle() ), this, TQT_SLOT( slotUser2())); -} - -StyleDlg::~StyleDlg() -{ -} - -void StyleDlg::fillComboBox() -{ - class Map : public TQMap {}; - Map entries; - - entries.clear(); - entries[m_styleManager->defaultStyle()] = new TDEListViewItem( m_dlg->m_styleList, i18n( "Default" ) ); - - StyleManager::Styles::const_iterator iter = m_styleManager->m_styles.begin(); - StyleManager::Styles::const_iterator end = m_styleManager->m_styles.end(); - uint count = m_styleManager->m_styles.count() + 1; - - while ( entries.count() != count ) - { - if ( entries.find( iter.data() ) == entries.end() ) - { - if ( iter.data()->parent() == 0 ) - entries[iter.data()] = new TDEListViewItem( m_dlg->m_styleList, iter.data()->name() ); - else - { - Map::const_iterator i = entries.find( iter.data()->parent() ); - if ( i != entries.end() ) - entries[iter.data()] = new TDEListViewItem( i.data(), iter.data()->name() ); - } - } - - ++iter; - if ( iter == end ) - iter = m_styleManager->m_styles.begin(); - } - entries.clear(); -} - -void StyleDlg::slotDisplayMode( int mode ) -{ - m_dlg->m_styleList->clear(); - - if ( mode != 3 ) - m_dlg->m_styleList->setRootIsDecorated( false ); - else - { - m_dlg->m_styleList->setRootIsDecorated( true ); - fillComboBox(); - return; - } - - if ( mode != 2 ) - new TDEListViewItem( m_dlg->m_styleList, i18n( "Default" ) ); - - StyleManager::Styles::iterator iter = m_styleManager->m_styles.begin(); - StyleManager::Styles::iterator end = m_styleManager->m_styles.end(); - - while ( iter != end ) - { - CustomStyle * styleData = iter.data(); - if ( !styleData || styleData->name().isEmpty() ) - { - ++iter; - continue; - } - - if ( mode == 2 ) - { - if ( styleData->type() == Style::CUSTOM ) - new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); - } - else if ( mode == 1 ) - { - if ( styleData->usage() > 0 ) - new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); - } - else - new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); - - ++iter; - } -} - -void StyleDlg::slotOk() -{ - TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); - - if ( !item ) - { - accept(); - return; - } - - CustomStyle * s = 0; - - TQString name( item->text( 0 ) ); - if ( name == i18n( "Default" ) ) - s = m_styleManager->defaultStyle(); - else - s = m_styleManager->style( name ); - - if ( !s ) - { - accept(); - return; - } - - if ( m_view ) - { - Sheet * sheet = m_view->activeSheet(); - - if ( sheet ) - { - m_view->doc()->emitBeginOperation( false ); - sheet->setSelectionStyle( m_view->selectionInfo(), s ); - } - - m_view->slotUpdateView( m_view->activeSheet() ); - } - accept(); -} - -void StyleDlg::slotUser1() -{ - CustomStyle * s = 0; - - TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); - - if ( item ) - { - TQString name( item->text( 0 ) ); - if ( name == i18n( "Default" ) ) - s = m_styleManager->defaultStyle(); - else - s = m_styleManager->style( name ); - } - else - s = m_styleManager->defaultStyle(); - - int i = 1; - TQString newName( i18n( "style%1" ).arg( m_styleManager->count() + i ) ); - while ( m_styleManager->style( newName ) != 0 ) - { - ++i; - newName = i18n( "style%1" ).arg( m_styleManager->count() + i ); - } - - CustomStyle * style = new CustomStyle( newName, s ); - style->setType( Style::TENTATIVE ); - - CellFormatDialog dlg( m_view, style, m_styleManager, m_view->doc() ); - - if ( style->type() == Style::TENTATIVE ) - { - delete style; - return; - } - - m_styleManager->m_styles[ style->name() ] = style; - - slotDisplayMode( m_dlg->m_displayBox->currentItem() ); -} - -void StyleDlg::slotUser2() -{ - TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); - - if ( !item ) - return; - - CustomStyle * s = 0; - - TQString name( item->text( 0 ) ); - if ( name == i18n( "Default" ) ) - s = m_styleManager->defaultStyle(); - else - s = m_styleManager->style( name ); - - if ( !s ) - return; - - CellFormatDialog dlg( m_view, s, m_styleManager, m_view->doc() ); - slotDisplayMode( m_dlg->m_displayBox->currentItem() ); -} - -void StyleDlg::slotUser3() -{ - TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); - - if ( !item ) - return; - - CustomStyle * s = 0; - - TQString name( item->text( 0 ) ); - if ( name == i18n( "Default" ) ) - s = m_styleManager->defaultStyle(); - else - s = m_styleManager->style( name ); - - if ( !s ) - return; - - if ( s->type() != Style::CUSTOM ) - return; - - s->setType( Style::AUTO ); - m_styleManager->takeStyle( s ); - - slotDisplayMode( m_dlg->m_displayBox->currentItem() ); -} - -void StyleDlg::slotSelectionChanged( TQListViewItem * item ) -{ - if ( !item ) - return; - - CustomStyle* style = 0; - TQString name( item->text( 0 ) ); - if ( name == i18n( "Default" ) ) - style = m_styleManager->defaultStyle(); - else - style = m_styleManager->style( name ); - if ( !style ) - { - enableButton( KDialogBase::User3, false ); - return; - } - - if ( style->type() == Style::BUILTIN ) - enableButton( KDialogBase::User3, false ); - else - enableButton( KDialogBase::User3, true ); -} - - -#include "kspread_dlg_styles.moc" - diff --git a/kspread/dialogs/kspread_dlg_styles.cpp b/kspread/dialogs/kspread_dlg_styles.cpp new file mode 100644 index 00000000..bf8f4de2 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_styles.cpp @@ -0,0 +1,332 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Laurent Montel + (C) 2003 Norbert Andres + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_canvas.h" +#include "kspread_cell.h" +#include "kspread_dlg_layout.h" +#include "kspread_sheet.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_view.h" + +#include "kspread_dlg_styles.h" + +using namespace KSpread; + +StyleWidget::StyleWidget( TQWidget * parent, const char * name, WFlags fl ) + : TQWidget( parent, name, fl ) +{ + TQVBoxLayout * layout = new TQVBoxLayout( this, 11, 6, "layout"); + + m_styleList = new TDEListView( this, "m_styleList" ); + m_styleList->addColumn( i18n( "Styles" ) ); + m_styleList->setResizeMode( TDEListView::AllColumns ); + layout->addWidget( m_styleList ); + + m_displayBox = new KComboBox( FALSE, this, "m_displayBox" ); + layout->addWidget( m_displayBox ); + + m_styleList->header()->setLabel( 0, i18n( "Styles" ) ); + m_displayBox->clear(); + m_displayBox->insertItem( i18n( "All Styles" ) ); + m_displayBox->insertItem( i18n( "Applied Styles" ) ); + m_displayBox->insertItem( i18n( "Custom Styles" ) ); + m_displayBox->insertItem( i18n( "Hierarchical" ) ); + connect( m_styleList, TQT_SIGNAL(doubleClicked ( TQListViewItem *)),this, TQT_SIGNAL( modifyStyle())); + resize( TQSize(446, 384).expandedTo(minimumSizeHint()) ); +} + +StyleWidget::~StyleWidget() +{ +} + + + +StyleDlg::StyleDlg( View * parent, StyleManager * manager, + const char * name ) + : KDialogBase( parent, name, true, "", + KDialogBase::Ok | KDialogBase::User1 | KDialogBase::User2 | KDialogBase::User3 | KDialogBase::Close, + KDialogBase::Ok, false, KGuiItem( i18n( "&New..." ) ), KGuiItem( i18n( "&Modify..." ) ), KGuiItem( i18n( "&Delete" ) ) ), + m_view( parent ), + m_styleManager( manager ), + m_dlg( new StyleWidget( this ) ) +{ + setCaption( i18n( "Style Manager" ) ); + setButtonBoxOrientation(Qt::Vertical ); + setMainWidget( m_dlg ); + + slotDisplayMode( 0 ); + enableButton( KDialogBase::User1, true ); + enableButton( KDialogBase::User2, true ); + enableButton( KDialogBase::User3, false ); + + connect( m_dlg->m_styleList, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ), + this, TQT_SLOT( slotSelectionChanged( TQListViewItem * ) ) ); + connect( m_dlg->m_displayBox, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotDisplayMode( int ) ) ); + connect( this, TQT_SIGNAL( user3Clicked() ), this, TQT_SLOT( slotUser3() ) ); + connect( m_dlg, TQT_SIGNAL( modifyStyle() ), this, TQT_SLOT( slotUser2())); +} + +StyleDlg::~StyleDlg() +{ +} + +void StyleDlg::fillComboBox() +{ + class Map : public TQMap {}; + Map entries; + + entries.clear(); + entries[m_styleManager->defaultStyle()] = new TDEListViewItem( m_dlg->m_styleList, i18n( "Default" ) ); + + StyleManager::Styles::const_iterator iter = m_styleManager->m_styles.begin(); + StyleManager::Styles::const_iterator end = m_styleManager->m_styles.end(); + uint count = m_styleManager->m_styles.count() + 1; + + while ( entries.count() != count ) + { + if ( entries.find( iter.data() ) == entries.end() ) + { + if ( iter.data()->parent() == 0 ) + entries[iter.data()] = new TDEListViewItem( m_dlg->m_styleList, iter.data()->name() ); + else + { + Map::const_iterator i = entries.find( iter.data()->parent() ); + if ( i != entries.end() ) + entries[iter.data()] = new TDEListViewItem( i.data(), iter.data()->name() ); + } + } + + ++iter; + if ( iter == end ) + iter = m_styleManager->m_styles.begin(); + } + entries.clear(); +} + +void StyleDlg::slotDisplayMode( int mode ) +{ + m_dlg->m_styleList->clear(); + + if ( mode != 3 ) + m_dlg->m_styleList->setRootIsDecorated( false ); + else + { + m_dlg->m_styleList->setRootIsDecorated( true ); + fillComboBox(); + return; + } + + if ( mode != 2 ) + new TDEListViewItem( m_dlg->m_styleList, i18n( "Default" ) ); + + StyleManager::Styles::iterator iter = m_styleManager->m_styles.begin(); + StyleManager::Styles::iterator end = m_styleManager->m_styles.end(); + + while ( iter != end ) + { + CustomStyle * styleData = iter.data(); + if ( !styleData || styleData->name().isEmpty() ) + { + ++iter; + continue; + } + + if ( mode == 2 ) + { + if ( styleData->type() == Style::CUSTOM ) + new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); + } + else if ( mode == 1 ) + { + if ( styleData->usage() > 0 ) + new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); + } + else + new TDEListViewItem( m_dlg->m_styleList, styleData->name() ); + + ++iter; + } +} + +void StyleDlg::slotOk() +{ + TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); + + if ( !item ) + { + accept(); + return; + } + + CustomStyle * s = 0; + + TQString name( item->text( 0 ) ); + if ( name == i18n( "Default" ) ) + s = m_styleManager->defaultStyle(); + else + s = m_styleManager->style( name ); + + if ( !s ) + { + accept(); + return; + } + + if ( m_view ) + { + Sheet * sheet = m_view->activeSheet(); + + if ( sheet ) + { + m_view->doc()->emitBeginOperation( false ); + sheet->setSelectionStyle( m_view->selectionInfo(), s ); + } + + m_view->slotUpdateView( m_view->activeSheet() ); + } + accept(); +} + +void StyleDlg::slotUser1() +{ + CustomStyle * s = 0; + + TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); + + if ( item ) + { + TQString name( item->text( 0 ) ); + if ( name == i18n( "Default" ) ) + s = m_styleManager->defaultStyle(); + else + s = m_styleManager->style( name ); + } + else + s = m_styleManager->defaultStyle(); + + int i = 1; + TQString newName( i18n( "style%1" ).arg( m_styleManager->count() + i ) ); + while ( m_styleManager->style( newName ) != 0 ) + { + ++i; + newName = i18n( "style%1" ).arg( m_styleManager->count() + i ); + } + + CustomStyle * style = new CustomStyle( newName, s ); + style->setType( Style::TENTATIVE ); + + CellFormatDialog dlg( m_view, style, m_styleManager, m_view->doc() ); + + if ( style->type() == Style::TENTATIVE ) + { + delete style; + return; + } + + m_styleManager->m_styles[ style->name() ] = style; + + slotDisplayMode( m_dlg->m_displayBox->currentItem() ); +} + +void StyleDlg::slotUser2() +{ + TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); + + if ( !item ) + return; + + CustomStyle * s = 0; + + TQString name( item->text( 0 ) ); + if ( name == i18n( "Default" ) ) + s = m_styleManager->defaultStyle(); + else + s = m_styleManager->style( name ); + + if ( !s ) + return; + + CellFormatDialog dlg( m_view, s, m_styleManager, m_view->doc() ); + slotDisplayMode( m_dlg->m_displayBox->currentItem() ); +} + +void StyleDlg::slotUser3() +{ + TDEListViewItem * item = (TDEListViewItem *) m_dlg->m_styleList->currentItem(); + + if ( !item ) + return; + + CustomStyle * s = 0; + + TQString name( item->text( 0 ) ); + if ( name == i18n( "Default" ) ) + s = m_styleManager->defaultStyle(); + else + s = m_styleManager->style( name ); + + if ( !s ) + return; + + if ( s->type() != Style::CUSTOM ) + return; + + s->setType( Style::AUTO ); + m_styleManager->takeStyle( s ); + + slotDisplayMode( m_dlg->m_displayBox->currentItem() ); +} + +void StyleDlg::slotSelectionChanged( TQListViewItem * item ) +{ + if ( !item ) + return; + + CustomStyle* style = 0; + TQString name( item->text( 0 ) ); + if ( name == i18n( "Default" ) ) + style = m_styleManager->defaultStyle(); + else + style = m_styleManager->style( name ); + if ( !style ) + { + enableButton( KDialogBase::User3, false ); + return; + } + + if ( style->type() == Style::BUILTIN ) + enableButton( KDialogBase::User3, false ); + else + enableButton( KDialogBase::User3, true ); +} + + +#include "kspread_dlg_styles.moc" + diff --git a/kspread/dialogs/kspread_dlg_subtotal.cc b/kspread/dialogs/kspread_dlg_subtotal.cc deleted file mode 100644 index 054cc1f7..00000000 --- a/kspread/dialogs/kspread_dlg_subtotal.cc +++ /dev/null @@ -1,321 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 2002 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include "kspreadsubtotal.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "kspread_doc.h" -#include "kspread_util.h" - -#include "kspread_dlg_subtotal.h" - -using namespace KSpread; - -SubtotalDialog::SubtotalDialog( View * parent, TQRect const & selection, const char * name ) - : KDialogBase(parent, name, true, i18n( "Subtotals" ), Ok | Cancel | User1, Ok, true, KGuiItem(i18n( "Remove All" )) ), - m_pView( parent ), - m_pSheet( m_pView->activeSheet() ), - m_selection( selection ), - m_dialog( new Subtotal( this ) ) -{ - setButtonBoxOrientation( Qt::Vertical ); - setMainWidget( m_dialog ); - - fillColumnBoxes(); - fillFunctionBox(); -} - -SubtotalDialog::~SubtotalDialog() -{ -} - -void SubtotalDialog::slotOk() -{ - int numOfCols = m_selection.width(); - TQMemArray columns( numOfCols ); - - int n = 0; - bool empty = true; - int left = m_selection.left(); - for ( TQListViewItem * item = m_dialog->m_columnList->firstChild(); item; item = item->nextSibling() ) - { - if ( ((TQCheckListItem * ) item)->isOn() ) - { - columns[n] = left + n; - empty = false; - } - else - columns[n] = -1; - ++n; - } - - if ( empty ) - { - KMessageBox::sorry( this, i18n("You need to select at least one column for adding subtotals.") ); - return; - } - - if ( m_dialog->m_replaceSubtotals->isChecked() ) - removeSubtotalLines(); - - int mainCol = left + m_dialog->m_columnBox->currentItem(); - int bottom = m_selection.bottom(); - int top = m_selection.top(); - left = m_selection.left(); - TQString oldText = m_pSheet->cellAt( mainCol, top )->strOutText(); - TQString newText; - TQString result( " " + i18n("Result") ); - int lastChangedRow = top; - - m_pView->doc()->emitBeginOperation( false ); - bool ignoreEmptyCells = m_dialog->m_IgnoreBox->isChecked(); - bool addRow; - if ( !m_dialog->m_summaryOnly->isChecked() ) - { - int y = top + 1; - kdDebug() << "Starting in row " << y << endl; - while ( y <= bottom ) - { - addRow = true; - newText = m_pSheet->cellAt( mainCol, y )->strOutText(); - - if ( ignoreEmptyCells && (newText.length() == 0) ) - { - ++y; - kdDebug() << "Still the same -> " << y << endl; - continue; - } - - if (newText != oldText) - { - int saveY = y; - for (int x = 0; x < numOfCols; ++x) - { - kdDebug() << "Column: " << x << ", " << columns[x] << endl; - if (columns[x] != -1) - { - if (!addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result)) - reject(); - - if ( addRow ) - { - ++saveY; - ++bottom; - } - - addRow = false; - } - } - y = saveY; - lastChangedRow = y; - } - oldText = newText; - ++y; - } - - addRow = true; - for ( int x = 0; x < numOfCols; ++x ) - { - if ( columns[x] != -1 ) - { - if ( !addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result ) ) - reject(); - addRow = false; - } - } - ++y; - } - - if ( m_dialog->m_summaryBelow->isChecked() ) - { - addRow = true; - int bottom = m_selection.bottom(); - for (int x = 0; x < numOfCols; ++x) - { - if (columns[x] != -1) - { - addSubtotal( mainCol, columns[x], bottom, top, addRow, i18n("Grand Total") ); - addRow = false; - } - } - } - - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void SubtotalDialog::slotCancel() -{ - reject(); -} - -void SubtotalDialog::slotUser1() -{ - m_pView->doc()->emitBeginOperation( false ); - removeSubtotalLines(); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -void SubtotalDialog::removeSubtotalLines() -{ - kdDebug() << "Removing subtotal lines" << endl; - - int r = m_selection.right(); - int l = m_selection.left(); - int t = m_selection.top(); - - Cell * cell; - TQString text; - - for ( int y = m_selection.bottom(); y >= t; --y ) - { - kdDebug() << "Checking row: " << y << endl; - bool containsSubtotal = false; - for (int x = l; x <= r; ++x ) - { - cell = m_pSheet->cellAt( x, y ); - if ( cell->isDefault() || !cell->isFormula() ) - continue; - - text = cell->text(); - if ( text.find( "SUBTOTAL" ) != -1 ) - { - containsSubtotal = true; - break; - } - } - - if ( containsSubtotal ) - { - kdDebug() << "Line " << y << " contains a subtotal " << endl; - TQRect rect( l, y, m_selection.width(), 1 ); - - m_pSheet->unshiftColumn( rect ); - m_selection.setHeight( m_selection.height() - 1 ); - } - } - kdDebug() << "Done removing subtotals" << endl; -} - -void SubtotalDialog::fillColumnBoxes() -{ - int r = m_selection.right(); - int row = m_selection.top(); - - Cell * cell; - TQCheckListItem * item; - - TQString text; - TQString col( i18n( "Column '%1' ") ); - - for ( int i = m_selection.left(); i <= r; ++i ) - { - cell = m_pSheet->cellAt( i, row ); - text = cell->strOutText(); - - if ( text.length() > 0 ) - { - text = col.arg( Cell::columnName( i ) ); - } - - m_dialog->m_columnBox->insertItem( text ); - - item = new TQCheckListItem( m_dialog->m_columnList, - text, - TQCheckListItem::CheckBox ); - item->setOn(false); - m_dialog->m_columnList->insertItem( item ); - } -} - -void SubtotalDialog::fillFunctionBox() -{ - TQStringList lst; - lst << i18n( "Average" ); - lst << i18n( "Count" ); - lst << i18n( "CountA" ); - lst << i18n( "Max" ); - lst << i18n( "Min" ); - lst << i18n( "Product" ); - lst << i18n( "StDev" ); - lst << i18n( "StDevP" ); - lst << i18n( "Sum" ); - lst << i18n( "Var" ); - lst << i18n( "VarP" ); - m_dialog->m_functionBox->insertStringList(lst); -} - -bool SubtotalDialog::addSubtotal( int mainCol, int column, int row, int topRow, - bool addRow, TQString const & text ) -{ - kdDebug() << "Adding subtotal: " << mainCol << ", " << column << ", Rows: " << row << ", " << topRow - << ": addRow: " << addRow << ", Text: " << text << endl; - if ( addRow ) - { - TQRect rect(m_selection.left(), row + 1, m_selection.width(), 1); - if ( !m_pSheet->shiftColumn( rect ) ) - return false; - - m_selection.setHeight( m_selection.height() + 1 ); - - Cell * cell = m_pSheet->nonDefaultCell( mainCol, row + 1 ); - cell->setCellText( text ); - cell->format()->setTextFontBold( true ); - cell->format()->setTextFontItalic( true ); - cell->format()->setTextFontUnderline( true ); - } - - TQString colName = Cell::columnName( column ); - - TQString formula("=SUBTOTAL("); - formula += TQString::number( m_dialog->m_functionBox->currentItem() + 1 ); - formula += "; "; - formula += colName; - formula += TQString::number( topRow ); - // if ( topRow != row ) - { - formula += ":"; - formula += colName; - formula += TQString::number( row ); - } - formula += ")"; - - Cell * cell = m_pSheet->nonDefaultCell( column, row + 1 ); - cell->setCellText( formula ); - cell->format()->setTextFontBold( true ); - cell->format()->setTextFontItalic( true ); - cell->format()->setTextFontUnderline( true ); - - return true; -} - -#include "kspread_dlg_subtotal.moc" - diff --git a/kspread/dialogs/kspread_dlg_subtotal.cpp b/kspread/dialogs/kspread_dlg_subtotal.cpp new file mode 100644 index 00000000..054cc1f7 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_subtotal.cpp @@ -0,0 +1,321 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 2002 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "kspreadsubtotal.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "kspread_doc.h" +#include "kspread_util.h" + +#include "kspread_dlg_subtotal.h" + +using namespace KSpread; + +SubtotalDialog::SubtotalDialog( View * parent, TQRect const & selection, const char * name ) + : KDialogBase(parent, name, true, i18n( "Subtotals" ), Ok | Cancel | User1, Ok, true, KGuiItem(i18n( "Remove All" )) ), + m_pView( parent ), + m_pSheet( m_pView->activeSheet() ), + m_selection( selection ), + m_dialog( new Subtotal( this ) ) +{ + setButtonBoxOrientation( Qt::Vertical ); + setMainWidget( m_dialog ); + + fillColumnBoxes(); + fillFunctionBox(); +} + +SubtotalDialog::~SubtotalDialog() +{ +} + +void SubtotalDialog::slotOk() +{ + int numOfCols = m_selection.width(); + TQMemArray columns( numOfCols ); + + int n = 0; + bool empty = true; + int left = m_selection.left(); + for ( TQListViewItem * item = m_dialog->m_columnList->firstChild(); item; item = item->nextSibling() ) + { + if ( ((TQCheckListItem * ) item)->isOn() ) + { + columns[n] = left + n; + empty = false; + } + else + columns[n] = -1; + ++n; + } + + if ( empty ) + { + KMessageBox::sorry( this, i18n("You need to select at least one column for adding subtotals.") ); + return; + } + + if ( m_dialog->m_replaceSubtotals->isChecked() ) + removeSubtotalLines(); + + int mainCol = left + m_dialog->m_columnBox->currentItem(); + int bottom = m_selection.bottom(); + int top = m_selection.top(); + left = m_selection.left(); + TQString oldText = m_pSheet->cellAt( mainCol, top )->strOutText(); + TQString newText; + TQString result( " " + i18n("Result") ); + int lastChangedRow = top; + + m_pView->doc()->emitBeginOperation( false ); + bool ignoreEmptyCells = m_dialog->m_IgnoreBox->isChecked(); + bool addRow; + if ( !m_dialog->m_summaryOnly->isChecked() ) + { + int y = top + 1; + kdDebug() << "Starting in row " << y << endl; + while ( y <= bottom ) + { + addRow = true; + newText = m_pSheet->cellAt( mainCol, y )->strOutText(); + + if ( ignoreEmptyCells && (newText.length() == 0) ) + { + ++y; + kdDebug() << "Still the same -> " << y << endl; + continue; + } + + if (newText != oldText) + { + int saveY = y; + for (int x = 0; x < numOfCols; ++x) + { + kdDebug() << "Column: " << x << ", " << columns[x] << endl; + if (columns[x] != -1) + { + if (!addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result)) + reject(); + + if ( addRow ) + { + ++saveY; + ++bottom; + } + + addRow = false; + } + } + y = saveY; + lastChangedRow = y; + } + oldText = newText; + ++y; + } + + addRow = true; + for ( int x = 0; x < numOfCols; ++x ) + { + if ( columns[x] != -1 ) + { + if ( !addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result ) ) + reject(); + addRow = false; + } + } + ++y; + } + + if ( m_dialog->m_summaryBelow->isChecked() ) + { + addRow = true; + int bottom = m_selection.bottom(); + for (int x = 0; x < numOfCols; ++x) + { + if (columns[x] != -1) + { + addSubtotal( mainCol, columns[x], bottom, top, addRow, i18n("Grand Total") ); + addRow = false; + } + } + } + + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void SubtotalDialog::slotCancel() +{ + reject(); +} + +void SubtotalDialog::slotUser1() +{ + m_pView->doc()->emitBeginOperation( false ); + removeSubtotalLines(); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +void SubtotalDialog::removeSubtotalLines() +{ + kdDebug() << "Removing subtotal lines" << endl; + + int r = m_selection.right(); + int l = m_selection.left(); + int t = m_selection.top(); + + Cell * cell; + TQString text; + + for ( int y = m_selection.bottom(); y >= t; --y ) + { + kdDebug() << "Checking row: " << y << endl; + bool containsSubtotal = false; + for (int x = l; x <= r; ++x ) + { + cell = m_pSheet->cellAt( x, y ); + if ( cell->isDefault() || !cell->isFormula() ) + continue; + + text = cell->text(); + if ( text.find( "SUBTOTAL" ) != -1 ) + { + containsSubtotal = true; + break; + } + } + + if ( containsSubtotal ) + { + kdDebug() << "Line " << y << " contains a subtotal " << endl; + TQRect rect( l, y, m_selection.width(), 1 ); + + m_pSheet->unshiftColumn( rect ); + m_selection.setHeight( m_selection.height() - 1 ); + } + } + kdDebug() << "Done removing subtotals" << endl; +} + +void SubtotalDialog::fillColumnBoxes() +{ + int r = m_selection.right(); + int row = m_selection.top(); + + Cell * cell; + TQCheckListItem * item; + + TQString text; + TQString col( i18n( "Column '%1' ") ); + + for ( int i = m_selection.left(); i <= r; ++i ) + { + cell = m_pSheet->cellAt( i, row ); + text = cell->strOutText(); + + if ( text.length() > 0 ) + { + text = col.arg( Cell::columnName( i ) ); + } + + m_dialog->m_columnBox->insertItem( text ); + + item = new TQCheckListItem( m_dialog->m_columnList, + text, + TQCheckListItem::CheckBox ); + item->setOn(false); + m_dialog->m_columnList->insertItem( item ); + } +} + +void SubtotalDialog::fillFunctionBox() +{ + TQStringList lst; + lst << i18n( "Average" ); + lst << i18n( "Count" ); + lst << i18n( "CountA" ); + lst << i18n( "Max" ); + lst << i18n( "Min" ); + lst << i18n( "Product" ); + lst << i18n( "StDev" ); + lst << i18n( "StDevP" ); + lst << i18n( "Sum" ); + lst << i18n( "Var" ); + lst << i18n( "VarP" ); + m_dialog->m_functionBox->insertStringList(lst); +} + +bool SubtotalDialog::addSubtotal( int mainCol, int column, int row, int topRow, + bool addRow, TQString const & text ) +{ + kdDebug() << "Adding subtotal: " << mainCol << ", " << column << ", Rows: " << row << ", " << topRow + << ": addRow: " << addRow << ", Text: " << text << endl; + if ( addRow ) + { + TQRect rect(m_selection.left(), row + 1, m_selection.width(), 1); + if ( !m_pSheet->shiftColumn( rect ) ) + return false; + + m_selection.setHeight( m_selection.height() + 1 ); + + Cell * cell = m_pSheet->nonDefaultCell( mainCol, row + 1 ); + cell->setCellText( text ); + cell->format()->setTextFontBold( true ); + cell->format()->setTextFontItalic( true ); + cell->format()->setTextFontUnderline( true ); + } + + TQString colName = Cell::columnName( column ); + + TQString formula("=SUBTOTAL("); + formula += TQString::number( m_dialog->m_functionBox->currentItem() + 1 ); + formula += "; "; + formula += colName; + formula += TQString::number( topRow ); + // if ( topRow != row ) + { + formula += ":"; + formula += colName; + formula += TQString::number( row ); + } + formula += ")"; + + Cell * cell = m_pSheet->nonDefaultCell( column, row + 1 ); + cell->setCellText( formula ); + cell->format()->setTextFontBold( true ); + cell->format()->setTextFontItalic( true ); + cell->format()->setTextFontUnderline( true ); + + return true; +} + +#include "kspread_dlg_subtotal.moc" + diff --git a/kspread/dialogs/kspread_dlg_validity.cc b/kspread/dialogs/kspread_dlg_validity.cc deleted file mode 100644 index ea462527..00000000 --- a/kspread/dialogs/kspread_dlg_validity.cc +++ /dev/null @@ -1,814 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2002-2003 Norbert Andres - (C) 2002 John Dailey - (C) 2001-2002 Philipp Mueller - (C) 1999-2005 Laurent Montel - (C) 1998-1999 Torben Weis - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -#include "kspread_dlg_validity.h" -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_view.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - -DlgValidity::DlgValidity(View* parent,const char* name , const TQRect &_marker ) - :KDialogBase(KDialogBase::Tabbed, i18n("Validity"),User2|User1|Cancel, User1, parent, name,true,false,KStdGuiItem::ok(),i18n("Clear &All")) - -{ - m_pView=parent; - marker=_marker; - TQFrame *page1 = addPage(i18n("&Values")); - TQVBoxLayout *lay1 = new TQVBoxLayout( page1, KDialogBase::marginHint(), KDialogBase::spacingHint() ); - - TQGroupBox* tmpTQButtonGroup; - tmpTQButtonGroup = new TQGroupBox( 0, Qt::Vertical, i18n("Validity Criteria"), page1, "ButtonGroup_1" ); - tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); - tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); - TQGridLayout *grid1 = new TQGridLayout(tmpTQButtonGroup->layout(),4,2); - - TQLabel *tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_1" ); - tmpTQLabel->setText(i18n("Allow:" )); - grid1->addWidget(tmpTQLabel,0,0); - - chooseType=new TQComboBox(tmpTQButtonGroup); - grid1->addWidget(chooseType,0,1); - TQStringList listType; - listType+=i18n("All"); - listType+=i18n("Number"); - listType+=i18n("Integer"); - listType+=i18n("Text"); - listType+=i18n("Date"); - listType+=i18n("Time"); - listType+=i18n("Text Length"); - listType+=i18n("List"); - chooseType->insertStringList(listType); - chooseType->setCurrentItem(0); - - allowEmptyCell = new TQCheckBox( i18n( "Allow blanks" ), tmpTQButtonGroup ); - grid1->addWidget(allowEmptyCell,1,0); - - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_2" ); - tmpTQLabel->setText(i18n("Data:" )); - grid1->addWidget(tmpTQLabel,2,0); - - choose=new TQComboBox(tmpTQButtonGroup); - grid1->addWidget(choose,2,1); - TQStringList list; - list+=i18n("equal to"); - list+=i18n("greater than"); - list+=i18n("less than"); - list+=i18n("equal to or greater than"); - list+=i18n("equal to or less than"); - list+=i18n("between"); - list+=i18n("different from"); - list+=i18n("different to"); - choose->insertStringList(list); - choose->setCurrentItem(0); - - edit1 = new TQLabel( tmpTQButtonGroup, "Label_3" ); - edit1->setText(i18n("Minimum:" )); - grid1->addWidget(edit1,3,0); - - val_min=new TQLineEdit(tmpTQButtonGroup); - grid1->addWidget(val_min,3,1); - val_min->setValidator( new KFloatValidator( val_min ) ); - - edit2 = new TQLabel( tmpTQButtonGroup, "Label_4" ); - edit2->setText(i18n("Maximum:" )); - grid1->addWidget(edit2,4,0); - - val_max=new TQLineEdit(tmpTQButtonGroup); - grid1->addWidget(val_max,4,1); - val_max->setValidator( new KFloatValidator( val_max ) ); - lay1->addWidget(tmpTQButtonGroup); - - //Apply minimum width of column1 to avoid horizontal move when changing option - //A bit ugly to apply text always, but I couldn't get a label->TQFontMetrix.boundingRect("text").width() - //to give mew the correct results - Philipp - edit2->setText( i18n( "Date:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Date minimum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Date maximum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Time:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Time minimum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Time maximum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Minimum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Maximum:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - edit2->setText( i18n( "Number:" ) ); - grid1->addColSpacing( 0, edit2->width() ); - - validityList = new TQTextEdit( tmpTQButtonGroup ); - grid1->addMultiCellWidget(validityList,2, 4,1, 1); - - validityLabelList = new TQLabel( tmpTQButtonGroup, "Label_Label_List" ); - validityLabelList->setText(i18n("Entries:" )); - grid1->addWidget(validityLabelList,2,0); - - TQFrame *page2 = addPage(i18n("&Error Alert")); - - lay1 = new TQVBoxLayout( page2, KDialogBase::marginHint(), KDialogBase::spacingHint() ); - - tmpTQButtonGroup = new TQButtonGroup( 0, Qt::Vertical, i18n("Contents"), page2, "ButtonGroup_2" ); - tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); - tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); - TQGridLayout *grid2 = new TQGridLayout(tmpTQButtonGroup->layout(),5,2); - - displayMessage = new TQCheckBox(i18n( "Show error message when invalid values are entered" ),tmpTQButtonGroup ); - displayMessage->setChecked( true ); - grid2->addMultiCellWidget(displayMessage,0, 0,0, 1); - - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_5" ); - tmpTQLabel->setText(i18n("Action:" )); - grid2->addWidget(tmpTQLabel,1,0); - - chooseAction=new TQComboBox(tmpTQButtonGroup); - grid2->addWidget(chooseAction,1,1); - TQStringList list2; - list2+=i18n("Stop"); - list2+=i18n("Warning"); - list2+=i18n("Information"); - chooseAction->insertStringList(list2); - chooseAction->setCurrentItem(0); - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_6" ); - tmpTQLabel->setText(i18n("Title:" )); - grid2->addWidget(tmpTQLabel,2,0); - - title=new TQLineEdit( tmpTQButtonGroup); - grid2->addWidget(title,2,1); - - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_7" ); - tmpTQLabel->setText(i18n("Message:" )); - grid2->addWidget(tmpTQLabel,3,0); - - message =new TQTextEdit( tmpTQButtonGroup); - grid2->addMultiCellWidget(message,3, 4,1, 1); - lay1->addWidget(tmpTQButtonGroup); - message->setTextFormat( TQt::PlainText ); - - TQFrame *page3 = addPage(i18n("Input Help")); - lay1 = new TQVBoxLayout( page3, KDialogBase::marginHint(), KDialogBase::spacingHint() ); - - tmpTQButtonGroup = new TQButtonGroup( 0, Qt::Vertical, i18n("Contents"), page3, "ButtonGroup_2" ); - tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); - tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); - - TQGridLayout *grid3 = new TQGridLayout(tmpTQButtonGroup->layout(),5,2); - - displayHelp = new TQCheckBox(i18n( "Show input help when cell is selected" ),tmpTQButtonGroup ); - displayMessage->setChecked( false ); - grid3->addMultiCellWidget(displayHelp,0, 0,0, 1); - - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_6" ); - tmpTQLabel->setText(i18n("Title:" )); - grid3->addWidget(tmpTQLabel,2,0); - - titleHelp=new TQLineEdit( tmpTQButtonGroup); - grid3->addWidget(titleHelp,2,1); - - tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_7" ); - tmpTQLabel->setText(i18n("Message:" )); - grid3->addWidget(tmpTQLabel,3,0); - - messageHelp =new TQTextEdit( tmpTQButtonGroup); - grid3->addMultiCellWidget(messageHelp,3, 4,1, 1); - lay1->addWidget(tmpTQButtonGroup); - messageHelp->setTextFormat( TQt::PlainText ); - - - connect(choose,TQT_SIGNAL(activated(int )),this,TQT_SLOT(changeIndexCond(int))); - connect(chooseType,TQT_SIGNAL(activated(int )),this,TQT_SLOT(changeIndexType(int))); - connect( this, TQT_SIGNAL(user1Clicked()), TQT_SLOT(OkPressed()) ); - connect( this, TQT_SIGNAL(user2Clicked()), TQT_SLOT(clearAllPressed()) ); - init(); -} - -void DlgValidity::displayOrNotListOfValidity( bool _displayList) -{ - if ( _displayList ) - { - validityList->show(); - validityLabelList->show(); - edit1->hide(); - val_min->hide(); - edit2->hide(); - val_max->hide(); - } - else - { - validityList->hide(); - validityLabelList->hide(); - edit1->show(); - val_min->show(); - edit2->show(); - val_max->show(); - } -} - -void DlgValidity::changeIndexType(int _index) -{ - bool activate = ( _index!=0 ); - message->setEnabled(activate); - title->setEnabled(activate); - chooseAction->setEnabled( activate ); - displayHelp->setEnabled(activate); - messageHelp->setEnabled(activate); - titleHelp->setEnabled(activate); - if ( _index == 7 ) - displayOrNotListOfValidity( true ); - else - displayOrNotListOfValidity( false ); - - switch(_index) - { - case 0: - edit1->setText(""); - edit2->setText(""); - val_max->setEnabled(false); - val_min->setEnabled(false); - edit1->setEnabled(false); - edit2->setEnabled(false); - choose->setEnabled(false); - break; - case 1: - val_min->setEnabled(true); - edit1->setEnabled(true); - choose->setEnabled(true); - val_min->setValidator( new KFloatValidator( val_min ) ); - val_max->setValidator( new KFloatValidator( val_max ) ); - if( choose->currentItem()<=4) - { - edit1->setText(i18n("Number:")); - edit2->setText(""); - edit2->setEnabled(false); - val_max->setEnabled(false); - } - else - { - edit1->setText(i18n("Minimum:" )); - edit2->setText(i18n("Maximum:" )); - edit2->setEnabled(true); - val_max->setEnabled(true); - } - break; - case 2: - case 6: - val_min->setEnabled(true); - edit1->setEnabled(true); - choose->setEnabled(true); - val_min->setValidator( new KIntValidator( val_min ) ); - val_max->setValidator( new KIntValidator( val_max ) ); - if( choose->currentItem()<=4) - { - edit1->setText(i18n("Number:")); - edit2->setText(""); - edit2->setEnabled(false); - val_max->setEnabled(false); - } - else - { - edit1->setText(i18n("Minimum:" )); - edit2->setText(i18n("Maximum:" )); - edit2->setEnabled(true); - val_max->setEnabled(true); - } - break; - - case 3: - edit1->setText(""); - edit2->setText(""); - val_max->setEnabled(false); - val_min->setEnabled(false); - choose->setEnabled(false); - edit1->setEnabled(false); - edit2->setEnabled(false); - break; - case 4: - edit1->setText(i18n("Date:")); - edit2->setText(""); - val_min->setEnabled(true); - edit1->setEnabled(true); - choose->setEnabled(true); - - val_min->clearValidator(); - val_max->clearValidator(); - if( choose->currentItem()<=4) - { - edit1->setText(i18n("Date:")); - edit2->setText(""); - edit2->setEnabled(false); - val_max->setEnabled(false); - } - else - { - edit1->setText(i18n("Date minimum:")); - edit2->setText(i18n("Date maximum:")); - edit2->setEnabled(true); - val_max->setEnabled(true); - } - break; - case 5: - val_min->setEnabled(true); - edit1->setEnabled(true); - choose->setEnabled(true); - val_min->clearValidator(); - val_max->clearValidator(); - if( choose->currentItem()<=4) - { - edit1->setText(i18n("Time:")); - edit2->setText(""); - edit2->setEnabled(false); - val_max->setEnabled(false); - } - else - { - edit1->setText(i18n("Time minimum:")); - edit2->setText(i18n("Time maximum:")); - edit2->setEnabled(true); - val_max->setEnabled(true); - } - break; - } - if ( width() < sizeHint().width() ) - resize( sizeHint() ); -} - -void DlgValidity::changeIndexCond(int _index) -{ - switch(_index) - { - case 0: - case 1: - case 2: - case 3: - case 4: - val_max->setEnabled(false); - if(chooseType->currentItem()==1 ||chooseType->currentItem()==2 - ||chooseType->currentItem()==6) - edit1->setText(i18n("Number:")); - else if( chooseType->currentItem()==3) - edit1->setText(""); - else if( chooseType->currentItem()==4) - edit1->setText(i18n("Date:")); - else if( chooseType->currentItem()==5) - edit1->setText(i18n("Time:")); - edit2->setText(""); - edit2->setEnabled(false); - break; - case 5: - case 6: - val_max->setEnabled(true); - edit2->setEnabled(true); - edit1->setEnabled(true); - if(chooseType->currentItem()==1 || chooseType->currentItem()==2 - || chooseType->currentItem()==6) - { - edit1->setText(i18n("Minimum:" )); - edit2->setText(i18n("Maximum:" )); - } - else if(chooseType->currentItem()==3) - { - edit1->setText(""); - edit2->setText(""); - } - else if(chooseType->currentItem()==4) - { - edit1->setText(i18n("Date minimum:")); - edit2->setText(i18n("Date maximum:")); - } - else if(chooseType->currentItem()==5) - { - edit1->setText(i18n("Time minimum:")); - edit2->setText(i18n("Time maximum:")); - } - break; - } -} - -void DlgValidity::init() -{ - Cell *c = m_pView->activeSheet()->cellAt( marker.left(), marker.top() ); - Validity * tmpValidity=c->getValidity(0); - if(tmpValidity!=0) - { - message->setText(tmpValidity->message); - title->setText(tmpValidity->title); - TQString tmp; - switch( tmpValidity->m_restriction) - { - case Restriction::None: - chooseType->setCurrentItem(0); - break; - case Restriction::Number: - chooseType->setCurrentItem(1); - if(tmpValidity->m_cond >=5 ) - val_max->setText(tmp.setNum(tmpValidity->valMax)); - val_min->setText(tmp.setNum(tmpValidity->valMin)); - break; - case Restriction::Integer: - chooseType->setCurrentItem(2); - if(tmpValidity->m_cond >=5 ) - val_max->setText(tmp.setNum(tmpValidity->valMax)); - val_min->setText(tmp.setNum(tmpValidity->valMin)); - break; - case Restriction::TextLength: - chooseType->setCurrentItem(6); - if(tmpValidity->m_cond >=5 ) - val_max->setText(tmp.setNum(tmpValidity->valMax)); - val_min->setText(tmp.setNum(tmpValidity->valMin)); - break; - case Restriction::Text: - chooseType->setCurrentItem(3); - break; - case Restriction::Date: - chooseType->setCurrentItem(4); - val_min->setText(m_pView->doc()->locale()->formatDate(tmpValidity->dateMin,true)); - if(tmpValidity->m_cond >=5 ) - val_max->setText(m_pView->doc()->locale()->formatDate(tmpValidity->dateMax,true)); - break; - case Restriction::Time: - chooseType->setCurrentItem(5); - val_min->setText(m_pView->doc()->locale()->formatTime(tmpValidity->timeMin,true)); - if(tmpValidity->m_cond >=5 ) - val_max->setText(m_pView->doc()->locale()->formatTime(tmpValidity->timeMax,true)); - break; - case Restriction::List: - { - chooseType->setCurrentItem(7); - TQStringList lst =tmpValidity->listValidity; - TQString tmp; - for ( TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { - tmp +=( *it )+"\n"; - } - validityList->setText( tmp ); - } - break; - default : - chooseType->setCurrentItem(0); - break; - } - switch (tmpValidity->m_action) - { - case Action::Stop: - chooseAction->setCurrentItem(0); - break; - case Action::Warning: - chooseAction->setCurrentItem(1); - break; - case Action::Information: - chooseAction->setCurrentItem(2); - break; - default : - chooseAction->setCurrentItem(0); - break; - } - switch ( tmpValidity->m_cond ) - { - case Conditional::Equal: - choose->setCurrentItem(0); - break; - case Conditional::Superior: - choose->setCurrentItem(1); - break; - case Conditional::Inferior: - choose->setCurrentItem(2); - break; - case Conditional::SuperiorEqual: - choose->setCurrentItem(3); - break; - case Conditional::InferiorEqual: - choose->setCurrentItem(4); - break; - case Conditional::Between: - choose->setCurrentItem(5); - break; - case Conditional::Different: - choose->setCurrentItem(6); - break; - case Conditional::DifferentTo: - choose->setCurrentItem(7); - break; - default : - choose->setCurrentItem(0); - break; - } - displayMessage->setChecked( tmpValidity->displayMessage ); - allowEmptyCell->setChecked( tmpValidity->allowEmptyCell ); - titleHelp->setText( tmpValidity->titleInfo ); - messageHelp->setText( tmpValidity->messageInfo ); - displayHelp->setChecked( tmpValidity->displayValidationInformation ); - } - changeIndexType(chooseType->currentItem()) ; - changeIndexCond(choose->currentItem()) ; -} - -void DlgValidity::clearAllPressed() -{ - val_min->setText(""); - val_max->setText(""); - message->setText(""); - title->setText(""); - displayMessage->setChecked( true ); - allowEmptyCell->setChecked( false ); - choose->setCurrentItem(0); - chooseType->setCurrentItem(0); - chooseAction->setCurrentItem(0); - changeIndexType(0); - changeIndexCond(0); - messageHelp->setText("" ); - titleHelp->setText( "" ); - validityList->setText( "" ); - displayHelp->setChecked( false ); -} - -void DlgValidity::OkPressed() -{ - if( chooseType->currentItem()==1) - { - bool ok; - val_min->text().toDouble(&ok); - if(! ok) - { - KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); - val_min->setText(""); - return; - } - val_max->text().toDouble(&ok); - if(! ok && choose->currentItem() >=5 && choose->currentItem()< 7) - { - KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); - val_max->setText(""); - return; - } - } - else if( chooseType->currentItem()==2 || chooseType->currentItem()==6) - { - bool ok; - val_min->text().toInt(&ok); - if(! ok) - { - KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); - val_min->setText(""); - return; - } - val_max->text().toInt(&ok); - if(! ok && choose->currentItem() >=5 && choose->currentItem()< 7) - { - KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); - val_max->setText(""); - return; - } - } - else if( chooseType->currentItem()==5) - { - if(! m_pView->doc()->locale()->readTime(val_min->text()).isValid()) - { - KMessageBox::error( this , i18n("This is not a valid time."),i18n("Error")); - val_min->setText(""); - return; - } - if(! m_pView->doc()->locale()->readTime(val_max->text()).isValid() && choose->currentItem() >=5) - { - KMessageBox::error( this , i18n("This is not a valid time."),i18n("Error")); - val_max->setText(""); - return; - } - } - else if( chooseType->currentItem()==4) - { - if(! m_pView->doc()->locale()->readDate(val_min->text()).isValid()) - { - KMessageBox::error( this , i18n("This is not a valid date."),i18n("Error")); - val_min->setText(""); - return; - } - if(! m_pView->doc()->locale()->readDate(val_max->text()).isValid() && choose->currentItem() >=5 ) - { - KMessageBox::error( this , i18n("This is not a valid date."),i18n("Error")); - val_max->setText(""); - return; - } - } - else if ( chooseType->currentItem()==7 ) - { - //Nothing - } - - if( chooseType->currentItem()==0) - {//no validity - result.m_restriction=Restriction::None; - result.m_action=Action::Stop; - result.m_cond=Conditional::Equal; - result.message=message->text(); - result.title=title->text(); - result.valMin=0; - result.valMax=0; - result.timeMin=TQTime(0,0,0); - result.timeMax=TQTime(0,0,0); - result.dateMin=TQDate(0,0,0); - result.dateMax=TQDate(0,0,0); - } - else - { - switch( chooseType->currentItem()) - { - case 0: - result.m_restriction=Restriction::None; - break; - case 1: - result.m_restriction=Restriction::Number; - break; - case 2: - result.m_restriction=Restriction::Integer; - break; - case 3: - result.m_restriction=Restriction::Text; - break; - case 4: - result.m_restriction=Restriction::Date; - break; - case 5: - result.m_restriction=Restriction::Time; - break; - case 6: - result.m_restriction=Restriction::TextLength; - break; - case 7: - result.m_restriction=Restriction::List; - break; - - default : - break; - } - switch (chooseAction->currentItem()) - { - case 0: - result.m_action=Action::Stop; - break; - case 1: - result.m_action=Action::Warning; - break; - case 2: - result.m_action=Action::Information; - break; - default : - break; - } - switch ( choose->currentItem()) - { - case 0: - result.m_cond=Conditional::Equal; - break; - case 1: - result.m_cond=Conditional::Superior; - break; - case 2: - result.m_cond=Conditional::Inferior; - break; - case 3: - result.m_cond=Conditional::SuperiorEqual; - break; - case 4: - result.m_cond=Conditional::InferiorEqual; - break; - case 5: - result.m_cond=Conditional::Between; - break; - case 6: - result.m_cond=Conditional::Different; - break; - case 7: - result.m_cond=Conditional::DifferentTo; - break; - default : - break; - } - result.message=message->text(); - result.title=title->text(); - result.valMin=0; - result.valMax=0; - result.timeMin=TQTime(0,0,0); - result.timeMax=TQTime(0,0,0); - result.dateMin=TQDate(0,0,0); - result.dateMax=TQDate(0,0,0); - - if( chooseType->currentItem()==1) - { - if(choose->currentItem() <5) - { - result.valMin=val_min->text().toDouble(); - } - else - { - result.valMin=TQMIN(val_min->text().toDouble(),val_max->text().toDouble()); - result.valMax=TQMAX(val_max->text().toDouble(),val_min->text().toDouble()); - } - } - else if( chooseType->currentItem()==2 || chooseType->currentItem()==6) - { - if(choose->currentItem() <5) - { - result.valMin=val_min->text().toInt(); - } - else - { - result.valMin=TQMIN(val_min->text().toInt(),val_max->text().toInt()); - result.valMax=TQMAX(val_max->text().toInt(),val_min->text().toInt()); - } - } - else if( chooseType->currentItem()==4) - { - if(choose->currentItem() <5) - { - result.dateMin=m_pView->doc()->locale()->readDate(val_min->text()); - } - else - { - if(m_pView->doc()->locale()->readDate(val_min->text())doc()->locale()->readDate(val_max->text())) - { - result.dateMin=m_pView->doc()->locale()->readDate(val_min->text()); - result.dateMax=m_pView->doc()->locale()->readDate(val_max->text()); - } - else - { - result.dateMin=m_pView->doc()->locale()->readDate(val_max->text()); - result.dateMax=m_pView->doc()->locale()->readDate(val_min->text()); - } - } - } - else if( chooseType->currentItem()==5) - { - if(choose->currentItem() <5) - { - result.timeMin=m_pView->doc()->locale()->readTime(val_min->text()); - } - else - { - if(m_pView->doc()->locale()->readTime(val_min->text())doc()->locale()->readTime(val_max->text())) - { - result.timeMax=m_pView->doc()->locale()->readTime(val_max->text()); - result.timeMin=m_pView->doc()->locale()->readTime(val_min->text()); - } - else - { - result.timeMax=m_pView->doc()->locale()->readTime(val_min->text()); - result.timeMin=m_pView->doc()->locale()->readTime(val_max->text()); - } - } - } - else if ( chooseType->currentItem()==7 ) - { - result.listValidity=TQStringList::split( "\n", validityList->text() ); - } - } - result.displayMessage = displayMessage->isChecked(); - result.allowEmptyCell = allowEmptyCell->isChecked(); - result.displayValidationInformation = displayHelp->isChecked(); - result.messageInfo= messageHelp->text(); - result.titleInfo = titleHelp->text(); - - m_pView->doc()->emitBeginOperation( false ); - m_pView->activeSheet()->setValidity( m_pView->selectionInfo(), result); - m_pView->slotUpdateView( m_pView->activeSheet() ); - accept(); -} - -#include "kspread_dlg_validity.moc" diff --git a/kspread/dialogs/kspread_dlg_validity.cpp b/kspread/dialogs/kspread_dlg_validity.cpp new file mode 100644 index 00000000..ea462527 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_validity.cpp @@ -0,0 +1,814 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres + (C) 2002 John Dailey + (C) 2001-2002 Philipp Mueller + (C) 1999-2005 Laurent Montel + (C) 1998-1999 Torben Weis + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include "kspread_dlg_validity.h" +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_view.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + +DlgValidity::DlgValidity(View* parent,const char* name , const TQRect &_marker ) + :KDialogBase(KDialogBase::Tabbed, i18n("Validity"),User2|User1|Cancel, User1, parent, name,true,false,KStdGuiItem::ok(),i18n("Clear &All")) + +{ + m_pView=parent; + marker=_marker; + TQFrame *page1 = addPage(i18n("&Values")); + TQVBoxLayout *lay1 = new TQVBoxLayout( page1, KDialogBase::marginHint(), KDialogBase::spacingHint() ); + + TQGroupBox* tmpTQButtonGroup; + tmpTQButtonGroup = new TQGroupBox( 0, Qt::Vertical, i18n("Validity Criteria"), page1, "ButtonGroup_1" ); + tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); + tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); + TQGridLayout *grid1 = new TQGridLayout(tmpTQButtonGroup->layout(),4,2); + + TQLabel *tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_1" ); + tmpTQLabel->setText(i18n("Allow:" )); + grid1->addWidget(tmpTQLabel,0,0); + + chooseType=new TQComboBox(tmpTQButtonGroup); + grid1->addWidget(chooseType,0,1); + TQStringList listType; + listType+=i18n("All"); + listType+=i18n("Number"); + listType+=i18n("Integer"); + listType+=i18n("Text"); + listType+=i18n("Date"); + listType+=i18n("Time"); + listType+=i18n("Text Length"); + listType+=i18n("List"); + chooseType->insertStringList(listType); + chooseType->setCurrentItem(0); + + allowEmptyCell = new TQCheckBox( i18n( "Allow blanks" ), tmpTQButtonGroup ); + grid1->addWidget(allowEmptyCell,1,0); + + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_2" ); + tmpTQLabel->setText(i18n("Data:" )); + grid1->addWidget(tmpTQLabel,2,0); + + choose=new TQComboBox(tmpTQButtonGroup); + grid1->addWidget(choose,2,1); + TQStringList list; + list+=i18n("equal to"); + list+=i18n("greater than"); + list+=i18n("less than"); + list+=i18n("equal to or greater than"); + list+=i18n("equal to or less than"); + list+=i18n("between"); + list+=i18n("different from"); + list+=i18n("different to"); + choose->insertStringList(list); + choose->setCurrentItem(0); + + edit1 = new TQLabel( tmpTQButtonGroup, "Label_3" ); + edit1->setText(i18n("Minimum:" )); + grid1->addWidget(edit1,3,0); + + val_min=new TQLineEdit(tmpTQButtonGroup); + grid1->addWidget(val_min,3,1); + val_min->setValidator( new KFloatValidator( val_min ) ); + + edit2 = new TQLabel( tmpTQButtonGroup, "Label_4" ); + edit2->setText(i18n("Maximum:" )); + grid1->addWidget(edit2,4,0); + + val_max=new TQLineEdit(tmpTQButtonGroup); + grid1->addWidget(val_max,4,1); + val_max->setValidator( new KFloatValidator( val_max ) ); + lay1->addWidget(tmpTQButtonGroup); + + //Apply minimum width of column1 to avoid horizontal move when changing option + //A bit ugly to apply text always, but I couldn't get a label->TQFontMetrix.boundingRect("text").width() + //to give mew the correct results - Philipp + edit2->setText( i18n( "Date:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Date minimum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Date maximum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Time:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Time minimum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Time maximum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Minimum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Maximum:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + edit2->setText( i18n( "Number:" ) ); + grid1->addColSpacing( 0, edit2->width() ); + + validityList = new TQTextEdit( tmpTQButtonGroup ); + grid1->addMultiCellWidget(validityList,2, 4,1, 1); + + validityLabelList = new TQLabel( tmpTQButtonGroup, "Label_Label_List" ); + validityLabelList->setText(i18n("Entries:" )); + grid1->addWidget(validityLabelList,2,0); + + TQFrame *page2 = addPage(i18n("&Error Alert")); + + lay1 = new TQVBoxLayout( page2, KDialogBase::marginHint(), KDialogBase::spacingHint() ); + + tmpTQButtonGroup = new TQButtonGroup( 0, Qt::Vertical, i18n("Contents"), page2, "ButtonGroup_2" ); + tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); + tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); + TQGridLayout *grid2 = new TQGridLayout(tmpTQButtonGroup->layout(),5,2); + + displayMessage = new TQCheckBox(i18n( "Show error message when invalid values are entered" ),tmpTQButtonGroup ); + displayMessage->setChecked( true ); + grid2->addMultiCellWidget(displayMessage,0, 0,0, 1); + + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_5" ); + tmpTQLabel->setText(i18n("Action:" )); + grid2->addWidget(tmpTQLabel,1,0); + + chooseAction=new TQComboBox(tmpTQButtonGroup); + grid2->addWidget(chooseAction,1,1); + TQStringList list2; + list2+=i18n("Stop"); + list2+=i18n("Warning"); + list2+=i18n("Information"); + chooseAction->insertStringList(list2); + chooseAction->setCurrentItem(0); + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_6" ); + tmpTQLabel->setText(i18n("Title:" )); + grid2->addWidget(tmpTQLabel,2,0); + + title=new TQLineEdit( tmpTQButtonGroup); + grid2->addWidget(title,2,1); + + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_7" ); + tmpTQLabel->setText(i18n("Message:" )); + grid2->addWidget(tmpTQLabel,3,0); + + message =new TQTextEdit( tmpTQButtonGroup); + grid2->addMultiCellWidget(message,3, 4,1, 1); + lay1->addWidget(tmpTQButtonGroup); + message->setTextFormat( TQt::PlainText ); + + TQFrame *page3 = addPage(i18n("Input Help")); + lay1 = new TQVBoxLayout( page3, KDialogBase::marginHint(), KDialogBase::spacingHint() ); + + tmpTQButtonGroup = new TQButtonGroup( 0, Qt::Vertical, i18n("Contents"), page3, "ButtonGroup_2" ); + tmpTQButtonGroup->layout()->setSpacing(KDialog::spacingHint()); + tmpTQButtonGroup->layout()->setMargin(KDialog::marginHint()); + + TQGridLayout *grid3 = new TQGridLayout(tmpTQButtonGroup->layout(),5,2); + + displayHelp = new TQCheckBox(i18n( "Show input help when cell is selected" ),tmpTQButtonGroup ); + displayMessage->setChecked( false ); + grid3->addMultiCellWidget(displayHelp,0, 0,0, 1); + + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_6" ); + tmpTQLabel->setText(i18n("Title:" )); + grid3->addWidget(tmpTQLabel,2,0); + + titleHelp=new TQLineEdit( tmpTQButtonGroup); + grid3->addWidget(titleHelp,2,1); + + tmpTQLabel = new TQLabel( tmpTQButtonGroup, "Label_7" ); + tmpTQLabel->setText(i18n("Message:" )); + grid3->addWidget(tmpTQLabel,3,0); + + messageHelp =new TQTextEdit( tmpTQButtonGroup); + grid3->addMultiCellWidget(messageHelp,3, 4,1, 1); + lay1->addWidget(tmpTQButtonGroup); + messageHelp->setTextFormat( TQt::PlainText ); + + + connect(choose,TQT_SIGNAL(activated(int )),this,TQT_SLOT(changeIndexCond(int))); + connect(chooseType,TQT_SIGNAL(activated(int )),this,TQT_SLOT(changeIndexType(int))); + connect( this, TQT_SIGNAL(user1Clicked()), TQT_SLOT(OkPressed()) ); + connect( this, TQT_SIGNAL(user2Clicked()), TQT_SLOT(clearAllPressed()) ); + init(); +} + +void DlgValidity::displayOrNotListOfValidity( bool _displayList) +{ + if ( _displayList ) + { + validityList->show(); + validityLabelList->show(); + edit1->hide(); + val_min->hide(); + edit2->hide(); + val_max->hide(); + } + else + { + validityList->hide(); + validityLabelList->hide(); + edit1->show(); + val_min->show(); + edit2->show(); + val_max->show(); + } +} + +void DlgValidity::changeIndexType(int _index) +{ + bool activate = ( _index!=0 ); + message->setEnabled(activate); + title->setEnabled(activate); + chooseAction->setEnabled( activate ); + displayHelp->setEnabled(activate); + messageHelp->setEnabled(activate); + titleHelp->setEnabled(activate); + if ( _index == 7 ) + displayOrNotListOfValidity( true ); + else + displayOrNotListOfValidity( false ); + + switch(_index) + { + case 0: + edit1->setText(""); + edit2->setText(""); + val_max->setEnabled(false); + val_min->setEnabled(false); + edit1->setEnabled(false); + edit2->setEnabled(false); + choose->setEnabled(false); + break; + case 1: + val_min->setEnabled(true); + edit1->setEnabled(true); + choose->setEnabled(true); + val_min->setValidator( new KFloatValidator( val_min ) ); + val_max->setValidator( new KFloatValidator( val_max ) ); + if( choose->currentItem()<=4) + { + edit1->setText(i18n("Number:")); + edit2->setText(""); + edit2->setEnabled(false); + val_max->setEnabled(false); + } + else + { + edit1->setText(i18n("Minimum:" )); + edit2->setText(i18n("Maximum:" )); + edit2->setEnabled(true); + val_max->setEnabled(true); + } + break; + case 2: + case 6: + val_min->setEnabled(true); + edit1->setEnabled(true); + choose->setEnabled(true); + val_min->setValidator( new KIntValidator( val_min ) ); + val_max->setValidator( new KIntValidator( val_max ) ); + if( choose->currentItem()<=4) + { + edit1->setText(i18n("Number:")); + edit2->setText(""); + edit2->setEnabled(false); + val_max->setEnabled(false); + } + else + { + edit1->setText(i18n("Minimum:" )); + edit2->setText(i18n("Maximum:" )); + edit2->setEnabled(true); + val_max->setEnabled(true); + } + break; + + case 3: + edit1->setText(""); + edit2->setText(""); + val_max->setEnabled(false); + val_min->setEnabled(false); + choose->setEnabled(false); + edit1->setEnabled(false); + edit2->setEnabled(false); + break; + case 4: + edit1->setText(i18n("Date:")); + edit2->setText(""); + val_min->setEnabled(true); + edit1->setEnabled(true); + choose->setEnabled(true); + + val_min->clearValidator(); + val_max->clearValidator(); + if( choose->currentItem()<=4) + { + edit1->setText(i18n("Date:")); + edit2->setText(""); + edit2->setEnabled(false); + val_max->setEnabled(false); + } + else + { + edit1->setText(i18n("Date minimum:")); + edit2->setText(i18n("Date maximum:")); + edit2->setEnabled(true); + val_max->setEnabled(true); + } + break; + case 5: + val_min->setEnabled(true); + edit1->setEnabled(true); + choose->setEnabled(true); + val_min->clearValidator(); + val_max->clearValidator(); + if( choose->currentItem()<=4) + { + edit1->setText(i18n("Time:")); + edit2->setText(""); + edit2->setEnabled(false); + val_max->setEnabled(false); + } + else + { + edit1->setText(i18n("Time minimum:")); + edit2->setText(i18n("Time maximum:")); + edit2->setEnabled(true); + val_max->setEnabled(true); + } + break; + } + if ( width() < sizeHint().width() ) + resize( sizeHint() ); +} + +void DlgValidity::changeIndexCond(int _index) +{ + switch(_index) + { + case 0: + case 1: + case 2: + case 3: + case 4: + val_max->setEnabled(false); + if(chooseType->currentItem()==1 ||chooseType->currentItem()==2 + ||chooseType->currentItem()==6) + edit1->setText(i18n("Number:")); + else if( chooseType->currentItem()==3) + edit1->setText(""); + else if( chooseType->currentItem()==4) + edit1->setText(i18n("Date:")); + else if( chooseType->currentItem()==5) + edit1->setText(i18n("Time:")); + edit2->setText(""); + edit2->setEnabled(false); + break; + case 5: + case 6: + val_max->setEnabled(true); + edit2->setEnabled(true); + edit1->setEnabled(true); + if(chooseType->currentItem()==1 || chooseType->currentItem()==2 + || chooseType->currentItem()==6) + { + edit1->setText(i18n("Minimum:" )); + edit2->setText(i18n("Maximum:" )); + } + else if(chooseType->currentItem()==3) + { + edit1->setText(""); + edit2->setText(""); + } + else if(chooseType->currentItem()==4) + { + edit1->setText(i18n("Date minimum:")); + edit2->setText(i18n("Date maximum:")); + } + else if(chooseType->currentItem()==5) + { + edit1->setText(i18n("Time minimum:")); + edit2->setText(i18n("Time maximum:")); + } + break; + } +} + +void DlgValidity::init() +{ + Cell *c = m_pView->activeSheet()->cellAt( marker.left(), marker.top() ); + Validity * tmpValidity=c->getValidity(0); + if(tmpValidity!=0) + { + message->setText(tmpValidity->message); + title->setText(tmpValidity->title); + TQString tmp; + switch( tmpValidity->m_restriction) + { + case Restriction::None: + chooseType->setCurrentItem(0); + break; + case Restriction::Number: + chooseType->setCurrentItem(1); + if(tmpValidity->m_cond >=5 ) + val_max->setText(tmp.setNum(tmpValidity->valMax)); + val_min->setText(tmp.setNum(tmpValidity->valMin)); + break; + case Restriction::Integer: + chooseType->setCurrentItem(2); + if(tmpValidity->m_cond >=5 ) + val_max->setText(tmp.setNum(tmpValidity->valMax)); + val_min->setText(tmp.setNum(tmpValidity->valMin)); + break; + case Restriction::TextLength: + chooseType->setCurrentItem(6); + if(tmpValidity->m_cond >=5 ) + val_max->setText(tmp.setNum(tmpValidity->valMax)); + val_min->setText(tmp.setNum(tmpValidity->valMin)); + break; + case Restriction::Text: + chooseType->setCurrentItem(3); + break; + case Restriction::Date: + chooseType->setCurrentItem(4); + val_min->setText(m_pView->doc()->locale()->formatDate(tmpValidity->dateMin,true)); + if(tmpValidity->m_cond >=5 ) + val_max->setText(m_pView->doc()->locale()->formatDate(tmpValidity->dateMax,true)); + break; + case Restriction::Time: + chooseType->setCurrentItem(5); + val_min->setText(m_pView->doc()->locale()->formatTime(tmpValidity->timeMin,true)); + if(tmpValidity->m_cond >=5 ) + val_max->setText(m_pView->doc()->locale()->formatTime(tmpValidity->timeMax,true)); + break; + case Restriction::List: + { + chooseType->setCurrentItem(7); + TQStringList lst =tmpValidity->listValidity; + TQString tmp; + for ( TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { + tmp +=( *it )+"\n"; + } + validityList->setText( tmp ); + } + break; + default : + chooseType->setCurrentItem(0); + break; + } + switch (tmpValidity->m_action) + { + case Action::Stop: + chooseAction->setCurrentItem(0); + break; + case Action::Warning: + chooseAction->setCurrentItem(1); + break; + case Action::Information: + chooseAction->setCurrentItem(2); + break; + default : + chooseAction->setCurrentItem(0); + break; + } + switch ( tmpValidity->m_cond ) + { + case Conditional::Equal: + choose->setCurrentItem(0); + break; + case Conditional::Superior: + choose->setCurrentItem(1); + break; + case Conditional::Inferior: + choose->setCurrentItem(2); + break; + case Conditional::SuperiorEqual: + choose->setCurrentItem(3); + break; + case Conditional::InferiorEqual: + choose->setCurrentItem(4); + break; + case Conditional::Between: + choose->setCurrentItem(5); + break; + case Conditional::Different: + choose->setCurrentItem(6); + break; + case Conditional::DifferentTo: + choose->setCurrentItem(7); + break; + default : + choose->setCurrentItem(0); + break; + } + displayMessage->setChecked( tmpValidity->displayMessage ); + allowEmptyCell->setChecked( tmpValidity->allowEmptyCell ); + titleHelp->setText( tmpValidity->titleInfo ); + messageHelp->setText( tmpValidity->messageInfo ); + displayHelp->setChecked( tmpValidity->displayValidationInformation ); + } + changeIndexType(chooseType->currentItem()) ; + changeIndexCond(choose->currentItem()) ; +} + +void DlgValidity::clearAllPressed() +{ + val_min->setText(""); + val_max->setText(""); + message->setText(""); + title->setText(""); + displayMessage->setChecked( true ); + allowEmptyCell->setChecked( false ); + choose->setCurrentItem(0); + chooseType->setCurrentItem(0); + chooseAction->setCurrentItem(0); + changeIndexType(0); + changeIndexCond(0); + messageHelp->setText("" ); + titleHelp->setText( "" ); + validityList->setText( "" ); + displayHelp->setChecked( false ); +} + +void DlgValidity::OkPressed() +{ + if( chooseType->currentItem()==1) + { + bool ok; + val_min->text().toDouble(&ok); + if(! ok) + { + KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); + val_min->setText(""); + return; + } + val_max->text().toDouble(&ok); + if(! ok && choose->currentItem() >=5 && choose->currentItem()< 7) + { + KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); + val_max->setText(""); + return; + } + } + else if( chooseType->currentItem()==2 || chooseType->currentItem()==6) + { + bool ok; + val_min->text().toInt(&ok); + if(! ok) + { + KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); + val_min->setText(""); + return; + } + val_max->text().toInt(&ok); + if(! ok && choose->currentItem() >=5 && choose->currentItem()< 7) + { + KMessageBox::error( this , i18n("This is not a valid value."),i18n("Error")); + val_max->setText(""); + return; + } + } + else if( chooseType->currentItem()==5) + { + if(! m_pView->doc()->locale()->readTime(val_min->text()).isValid()) + { + KMessageBox::error( this , i18n("This is not a valid time."),i18n("Error")); + val_min->setText(""); + return; + } + if(! m_pView->doc()->locale()->readTime(val_max->text()).isValid() && choose->currentItem() >=5) + { + KMessageBox::error( this , i18n("This is not a valid time."),i18n("Error")); + val_max->setText(""); + return; + } + } + else if( chooseType->currentItem()==4) + { + if(! m_pView->doc()->locale()->readDate(val_min->text()).isValid()) + { + KMessageBox::error( this , i18n("This is not a valid date."),i18n("Error")); + val_min->setText(""); + return; + } + if(! m_pView->doc()->locale()->readDate(val_max->text()).isValid() && choose->currentItem() >=5 ) + { + KMessageBox::error( this , i18n("This is not a valid date."),i18n("Error")); + val_max->setText(""); + return; + } + } + else if ( chooseType->currentItem()==7 ) + { + //Nothing + } + + if( chooseType->currentItem()==0) + {//no validity + result.m_restriction=Restriction::None; + result.m_action=Action::Stop; + result.m_cond=Conditional::Equal; + result.message=message->text(); + result.title=title->text(); + result.valMin=0; + result.valMax=0; + result.timeMin=TQTime(0,0,0); + result.timeMax=TQTime(0,0,0); + result.dateMin=TQDate(0,0,0); + result.dateMax=TQDate(0,0,0); + } + else + { + switch( chooseType->currentItem()) + { + case 0: + result.m_restriction=Restriction::None; + break; + case 1: + result.m_restriction=Restriction::Number; + break; + case 2: + result.m_restriction=Restriction::Integer; + break; + case 3: + result.m_restriction=Restriction::Text; + break; + case 4: + result.m_restriction=Restriction::Date; + break; + case 5: + result.m_restriction=Restriction::Time; + break; + case 6: + result.m_restriction=Restriction::TextLength; + break; + case 7: + result.m_restriction=Restriction::List; + break; + + default : + break; + } + switch (chooseAction->currentItem()) + { + case 0: + result.m_action=Action::Stop; + break; + case 1: + result.m_action=Action::Warning; + break; + case 2: + result.m_action=Action::Information; + break; + default : + break; + } + switch ( choose->currentItem()) + { + case 0: + result.m_cond=Conditional::Equal; + break; + case 1: + result.m_cond=Conditional::Superior; + break; + case 2: + result.m_cond=Conditional::Inferior; + break; + case 3: + result.m_cond=Conditional::SuperiorEqual; + break; + case 4: + result.m_cond=Conditional::InferiorEqual; + break; + case 5: + result.m_cond=Conditional::Between; + break; + case 6: + result.m_cond=Conditional::Different; + break; + case 7: + result.m_cond=Conditional::DifferentTo; + break; + default : + break; + } + result.message=message->text(); + result.title=title->text(); + result.valMin=0; + result.valMax=0; + result.timeMin=TQTime(0,0,0); + result.timeMax=TQTime(0,0,0); + result.dateMin=TQDate(0,0,0); + result.dateMax=TQDate(0,0,0); + + if( chooseType->currentItem()==1) + { + if(choose->currentItem() <5) + { + result.valMin=val_min->text().toDouble(); + } + else + { + result.valMin=TQMIN(val_min->text().toDouble(),val_max->text().toDouble()); + result.valMax=TQMAX(val_max->text().toDouble(),val_min->text().toDouble()); + } + } + else if( chooseType->currentItem()==2 || chooseType->currentItem()==6) + { + if(choose->currentItem() <5) + { + result.valMin=val_min->text().toInt(); + } + else + { + result.valMin=TQMIN(val_min->text().toInt(),val_max->text().toInt()); + result.valMax=TQMAX(val_max->text().toInt(),val_min->text().toInt()); + } + } + else if( chooseType->currentItem()==4) + { + if(choose->currentItem() <5) + { + result.dateMin=m_pView->doc()->locale()->readDate(val_min->text()); + } + else + { + if(m_pView->doc()->locale()->readDate(val_min->text())doc()->locale()->readDate(val_max->text())) + { + result.dateMin=m_pView->doc()->locale()->readDate(val_min->text()); + result.dateMax=m_pView->doc()->locale()->readDate(val_max->text()); + } + else + { + result.dateMin=m_pView->doc()->locale()->readDate(val_max->text()); + result.dateMax=m_pView->doc()->locale()->readDate(val_min->text()); + } + } + } + else if( chooseType->currentItem()==5) + { + if(choose->currentItem() <5) + { + result.timeMin=m_pView->doc()->locale()->readTime(val_min->text()); + } + else + { + if(m_pView->doc()->locale()->readTime(val_min->text())doc()->locale()->readTime(val_max->text())) + { + result.timeMax=m_pView->doc()->locale()->readTime(val_max->text()); + result.timeMin=m_pView->doc()->locale()->readTime(val_min->text()); + } + else + { + result.timeMax=m_pView->doc()->locale()->readTime(val_min->text()); + result.timeMin=m_pView->doc()->locale()->readTime(val_max->text()); + } + } + } + else if ( chooseType->currentItem()==7 ) + { + result.listValidity=TQStringList::split( "\n", validityList->text() ); + } + } + result.displayMessage = displayMessage->isChecked(); + result.allowEmptyCell = allowEmptyCell->isChecked(); + result.displayValidationInformation = displayHelp->isChecked(); + result.messageInfo= messageHelp->text(); + result.titleInfo = titleHelp->text(); + + m_pView->doc()->emitBeginOperation( false ); + m_pView->activeSheet()->setValidity( m_pView->selectionInfo(), result); + m_pView->slotUpdateView( m_pView->activeSheet() ); + accept(); +} + +#include "kspread_dlg_validity.moc" diff --git a/kspread/dialogs/link.cc b/kspread/dialogs/link.cc deleted file mode 100644 index e0c1be21..00000000 --- a/kspread/dialogs/link.cc +++ /dev/null @@ -1,288 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005 Ariya Hidayat - (C) 2003 Norbert Andres - (C) 2002 Philipp Mueller - (C) 1999-2002 Laurent Montel - (C) 1999 Stephan Kulow - (C) 1998-1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "link.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - -class LinkDialog::Private -{ -public: - TQString text; - TQFrame* internetPage; - KLineEdit* internetText; - KLineEdit* internetLink; - TQFrame* mailPage; - KLineEdit* mailText; - KLineEdit* mailLink; - TQFrame* filePage; - KLineEdit* fileText; - KURLRequester* fileLink; - TQFrame* cellPage; - KLineEdit* cellText; - KLineEdit* cellLink; -}; - -LinkDialog::LinkDialog( TQWidget*, const char* ) - : KDialogBase( KDialogBase::IconList,i18n( "Insert Link") , - KDialogBase::Ok | KDialogBase::Cancel, - KDialogBase::Ok ) -{ - d = new Private; - - // link for web or ftp - d->internetPage = addPage( i18n( "Internet" ), TQString(), - BarIcon( "text-html",TDEIcon::SizeMedium ) ); - TQVBoxLayout* iLayout = new TQVBoxLayout( d->internetPage, marginHint(), spacingHint() ); - iLayout->add( new TQLabel( i18n("Text to display:" ), d->internetPage ) ); - d->internetText = new KLineEdit( d->internetPage ); - iLayout->add( d->internetText ); - iLayout->add( new TQLabel( i18n("Internet address:" ), d->internetPage ) ); - d->internetLink = new KLineEdit( d->internetPage ); - iLayout->add( d->internetLink ); - iLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); - connect( d->internetText, TQT_SIGNAL( textChanged( const TQString& ) ), this, - TQT_SLOT( setText( const TQString& ) ) ); - - // link for e-mail - d->mailPage = addPage( i18n( "Mail" ), TQString(), - BarIcon( "mail_generic",TDEIcon::SizeMedium ) ); - TQVBoxLayout* mLayout = new TQVBoxLayout( d->mailPage, marginHint(), spacingHint() ); - mLayout->add( new TQLabel( i18n("Text to display:" ), d->mailPage ) ); - d->mailText = new KLineEdit( d->mailPage ); - mLayout->add( d->mailText ); - mLayout->add( new TQLabel( i18n("Email:" ), d->mailPage ) ); - d->mailLink = new KLineEdit( d->mailPage ); - mLayout->add( d->mailLink ); - mLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); - connect( d->mailText, TQT_SIGNAL( textChanged( const TQString& ) ), this, - TQT_SLOT( setText( const TQString& ) ) ); - - // link for external file - d->filePage = addPage( i18n( "File" ), TQString(), - BarIcon( "document-new",TDEIcon::SizeMedium ) ); - TQVBoxLayout* fLayout = new TQVBoxLayout( d->filePage, marginHint(), spacingHint() ); - fLayout->add( new TQLabel( i18n("Text to display:" ), d->filePage ) ); - d->fileText = new KLineEdit( d->filePage ); - fLayout->add( d->fileText ); - fLayout->add( new TQLabel( i18n("File location:" ), d->filePage ) ); - d->fileLink = new KURLRequester( d->filePage ); - fLayout->add( d->fileLink ); - fLayout->add( new TQLabel( i18n("Recent file:" ), d->filePage ) ); - TQComboBox* recentFile = new TQComboBox( d->filePage ); - recentFile->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed ); - fLayout->add( recentFile ); - fLayout->addItem( new TQSpacerItem( 0, 40, TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding ) ); - connect( d->fileText, TQT_SIGNAL( textChanged( const TQString& ) ), this, - TQT_SLOT( setText( const TQString& ) ) ); - TQObject::connect( recentFile, TQT_SIGNAL( highlighted ( const TQString &) ), - d->fileLink->lineEdit(), TQT_SLOT( setText( const TQString & ) ) ); - - - // populate recent files - TQStringList fileList = TDERecentDocument::recentDocuments(); - for( TQStringList::ConstIterator it = fileList.begin();it != fileList.end(); ++it ) - { - KDesktopFile f(*it, true /* read only */); - if ( !f.readURL().isEmpty() ) - recentFile->insertItem( f.readURL() ); - } - if( recentFile->count()==0 ) - { - recentFile->insertItem( i18n("No Entries") ); - recentFile->setEnabled( false ); - } - - // link to another cell - d->cellPage = addPage( i18n( "Cell" ), TQString(), - BarIcon( "misc",TDEIcon::SizeMedium ) ); - TQVBoxLayout* cLayout = new TQVBoxLayout( d->cellPage, marginHint(), spacingHint() ); - cLayout->add( new TQLabel( i18n("Text to display:" ), d->cellPage ) ); - d->cellText = new KLineEdit( d->cellPage ); - cLayout->add( d->cellText ); - cLayout->add( new TQLabel( i18n("Cell:" ), d->cellPage ) ); - d->cellLink = new KLineEdit( d->cellPage ); - cLayout->add( d->cellLink ); - cLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); - connect( d->cellText, TQT_SIGNAL( textChanged( const TQString& ) ), this, - TQT_SLOT( setText( const TQString& ) ) ); - - enableButtonSeparator( true ); - d->internetText->setFocus(); - resize( 400,300 ); -} - -LinkDialog::~LinkDialog() -{ - delete d; -} - -TQString LinkDialog::text() const -{ - return d->text; -} - -TQString LinkDialog::link() const -{ - TQString str; - switch( activePageIndex() ) - { - case 0: - str = d->internetLink->text(); - if( !str.isEmpty() ) - if( str.find( "http://" )==-1 ) - if( str.find( "https://" )==-1 ) - if( str.find( "ftp://" )==-1 ) - str.prepend( "http://" ); - break; - - case 1: - str = d->mailLink->text(); - if( !str.isEmpty() ) - if( str.find( "mailto:" )==-1 ) - str.prepend( "mailto:" ); - break; - - case 2: - str = d->fileLink->lineEdit()->text(); - if( !str.isEmpty() ) - if( str.find( "file:/" )==-1 ) - str.prepend( "file://" ); - break; - - case 3: - str = d->cellLink->text(); - break; - - break; - } - return str; -} - -void LinkDialog::setText( const TQString& text ) -{ - d->text = text; - - d->internetText->blockSignals( true ); - d->internetText->setText( text ); - d->internetText->blockSignals( false ); - - d->mailText->blockSignals( true ); - d->mailText->setText( text ); - d->mailText->blockSignals( false ); - - d->fileText->blockSignals( true ); - d->fileText->setText( text ); - d->fileText->blockSignals( false ); - - d->cellText->blockSignals( true ); - d->cellText->setText( text ); - d->cellText->blockSignals( false ); -} - -// link must be complete, e.g. "http://www.koffice.org" instead of -// "www.koffice.org" only, since protocol is used to decide which page to show -void LinkDialog::setLink( const TQString& link ) -{ - if( link.startsWith( "https://" ) ) - { - d->internetLink->setText( link.mid( TQString("https://").length() ) ); - showPage( 0 ); - return; - } - - if( link.startsWith( "http://" ) ) - { - d->internetLink->setText( link.mid( TQString("http://").length() ) ); - showPage( 0 ); - return; - } - - if( link.startsWith( "ftp://" ) ) - { - d->internetLink->setText( link.mid( TQString("ftp://").length() ) ); - showPage( 0 ); - return; - } - - if( link.startsWith( "mailto:" ) ) - { - d->mailLink->setText( link.mid( TQString("mailto:").length() ) ); - showPage( 1 ); - return; - } - - if( link.startsWith( "file:/" ) ) - { - TQString s = link.mid( TQString("file:/").length() ); - while(s.startsWith("//")) s.remove(0,1); - d->fileLink->lineEdit()->setText(s); - showPage( 2 ); - return; - } - - // assume cell reference - d->cellLink->setText( link ); - showPage( 3 ); -} - -void LinkDialog::slotOk() -{ - TQString str; - switch( activePageIndex() ) - { - case 0: str = i18n( "Internet address is empty" ); break; - case 1: str = i18n( "Mail address is empty" ); break; - case 2: str = i18n( "File name is empty" ); break; - case 3: str = i18n( "Destination cell is empty" ); break; - break; - } - - if( link().isEmpty() ) - { - KMessageBox::error( this, str ); - return; - } - - if( d->text.isEmpty() ) - d->text = link(); - - accept(); -} - -#include "link.moc" diff --git a/kspread/dialogs/link.cpp b/kspread/dialogs/link.cpp new file mode 100644 index 00000000..e0c1be21 --- /dev/null +++ b/kspread/dialogs/link.cpp @@ -0,0 +1,288 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Ariya Hidayat + (C) 2003 Norbert Andres + (C) 2002 Philipp Mueller + (C) 1999-2002 Laurent Montel + (C) 1999 Stephan Kulow + (C) 1998-1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "link.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + +class LinkDialog::Private +{ +public: + TQString text; + TQFrame* internetPage; + KLineEdit* internetText; + KLineEdit* internetLink; + TQFrame* mailPage; + KLineEdit* mailText; + KLineEdit* mailLink; + TQFrame* filePage; + KLineEdit* fileText; + KURLRequester* fileLink; + TQFrame* cellPage; + KLineEdit* cellText; + KLineEdit* cellLink; +}; + +LinkDialog::LinkDialog( TQWidget*, const char* ) + : KDialogBase( KDialogBase::IconList,i18n( "Insert Link") , + KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok ) +{ + d = new Private; + + // link for web or ftp + d->internetPage = addPage( i18n( "Internet" ), TQString(), + BarIcon( "text-html",TDEIcon::SizeMedium ) ); + TQVBoxLayout* iLayout = new TQVBoxLayout( d->internetPage, marginHint(), spacingHint() ); + iLayout->add( new TQLabel( i18n("Text to display:" ), d->internetPage ) ); + d->internetText = new KLineEdit( d->internetPage ); + iLayout->add( d->internetText ); + iLayout->add( new TQLabel( i18n("Internet address:" ), d->internetPage ) ); + d->internetLink = new KLineEdit( d->internetPage ); + iLayout->add( d->internetLink ); + iLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); + connect( d->internetText, TQT_SIGNAL( textChanged( const TQString& ) ), this, + TQT_SLOT( setText( const TQString& ) ) ); + + // link for e-mail + d->mailPage = addPage( i18n( "Mail" ), TQString(), + BarIcon( "mail_generic",TDEIcon::SizeMedium ) ); + TQVBoxLayout* mLayout = new TQVBoxLayout( d->mailPage, marginHint(), spacingHint() ); + mLayout->add( new TQLabel( i18n("Text to display:" ), d->mailPage ) ); + d->mailText = new KLineEdit( d->mailPage ); + mLayout->add( d->mailText ); + mLayout->add( new TQLabel( i18n("Email:" ), d->mailPage ) ); + d->mailLink = new KLineEdit( d->mailPage ); + mLayout->add( d->mailLink ); + mLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); + connect( d->mailText, TQT_SIGNAL( textChanged( const TQString& ) ), this, + TQT_SLOT( setText( const TQString& ) ) ); + + // link for external file + d->filePage = addPage( i18n( "File" ), TQString(), + BarIcon( "document-new",TDEIcon::SizeMedium ) ); + TQVBoxLayout* fLayout = new TQVBoxLayout( d->filePage, marginHint(), spacingHint() ); + fLayout->add( new TQLabel( i18n("Text to display:" ), d->filePage ) ); + d->fileText = new KLineEdit( d->filePage ); + fLayout->add( d->fileText ); + fLayout->add( new TQLabel( i18n("File location:" ), d->filePage ) ); + d->fileLink = new KURLRequester( d->filePage ); + fLayout->add( d->fileLink ); + fLayout->add( new TQLabel( i18n("Recent file:" ), d->filePage ) ); + TQComboBox* recentFile = new TQComboBox( d->filePage ); + recentFile->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed ); + fLayout->add( recentFile ); + fLayout->addItem( new TQSpacerItem( 0, 40, TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding ) ); + connect( d->fileText, TQT_SIGNAL( textChanged( const TQString& ) ), this, + TQT_SLOT( setText( const TQString& ) ) ); + TQObject::connect( recentFile, TQT_SIGNAL( highlighted ( const TQString &) ), + d->fileLink->lineEdit(), TQT_SLOT( setText( const TQString & ) ) ); + + + // populate recent files + TQStringList fileList = TDERecentDocument::recentDocuments(); + for( TQStringList::ConstIterator it = fileList.begin();it != fileList.end(); ++it ) + { + KDesktopFile f(*it, true /* read only */); + if ( !f.readURL().isEmpty() ) + recentFile->insertItem( f.readURL() ); + } + if( recentFile->count()==0 ) + { + recentFile->insertItem( i18n("No Entries") ); + recentFile->setEnabled( false ); + } + + // link to another cell + d->cellPage = addPage( i18n( "Cell" ), TQString(), + BarIcon( "misc",TDEIcon::SizeMedium ) ); + TQVBoxLayout* cLayout = new TQVBoxLayout( d->cellPage, marginHint(), spacingHint() ); + cLayout->add( new TQLabel( i18n("Text to display:" ), d->cellPage ) ); + d->cellText = new KLineEdit( d->cellPage ); + cLayout->add( d->cellText ); + cLayout->add( new TQLabel( i18n("Cell:" ), d->cellPage ) ); + d->cellLink = new KLineEdit( d->cellPage ); + cLayout->add( d->cellLink ); + cLayout->addItem( new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) ); + connect( d->cellText, TQT_SIGNAL( textChanged( const TQString& ) ), this, + TQT_SLOT( setText( const TQString& ) ) ); + + enableButtonSeparator( true ); + d->internetText->setFocus(); + resize( 400,300 ); +} + +LinkDialog::~LinkDialog() +{ + delete d; +} + +TQString LinkDialog::text() const +{ + return d->text; +} + +TQString LinkDialog::link() const +{ + TQString str; + switch( activePageIndex() ) + { + case 0: + str = d->internetLink->text(); + if( !str.isEmpty() ) + if( str.find( "http://" )==-1 ) + if( str.find( "https://" )==-1 ) + if( str.find( "ftp://" )==-1 ) + str.prepend( "http://" ); + break; + + case 1: + str = d->mailLink->text(); + if( !str.isEmpty() ) + if( str.find( "mailto:" )==-1 ) + str.prepend( "mailto:" ); + break; + + case 2: + str = d->fileLink->lineEdit()->text(); + if( !str.isEmpty() ) + if( str.find( "file:/" )==-1 ) + str.prepend( "file://" ); + break; + + case 3: + str = d->cellLink->text(); + break; + + break; + } + return str; +} + +void LinkDialog::setText( const TQString& text ) +{ + d->text = text; + + d->internetText->blockSignals( true ); + d->internetText->setText( text ); + d->internetText->blockSignals( false ); + + d->mailText->blockSignals( true ); + d->mailText->setText( text ); + d->mailText->blockSignals( false ); + + d->fileText->blockSignals( true ); + d->fileText->setText( text ); + d->fileText->blockSignals( false ); + + d->cellText->blockSignals( true ); + d->cellText->setText( text ); + d->cellText->blockSignals( false ); +} + +// link must be complete, e.g. "http://www.koffice.org" instead of +// "www.koffice.org" only, since protocol is used to decide which page to show +void LinkDialog::setLink( const TQString& link ) +{ + if( link.startsWith( "https://" ) ) + { + d->internetLink->setText( link.mid( TQString("https://").length() ) ); + showPage( 0 ); + return; + } + + if( link.startsWith( "http://" ) ) + { + d->internetLink->setText( link.mid( TQString("http://").length() ) ); + showPage( 0 ); + return; + } + + if( link.startsWith( "ftp://" ) ) + { + d->internetLink->setText( link.mid( TQString("ftp://").length() ) ); + showPage( 0 ); + return; + } + + if( link.startsWith( "mailto:" ) ) + { + d->mailLink->setText( link.mid( TQString("mailto:").length() ) ); + showPage( 1 ); + return; + } + + if( link.startsWith( "file:/" ) ) + { + TQString s = link.mid( TQString("file:/").length() ); + while(s.startsWith("//")) s.remove(0,1); + d->fileLink->lineEdit()->setText(s); + showPage( 2 ); + return; + } + + // assume cell reference + d->cellLink->setText( link ); + showPage( 3 ); +} + +void LinkDialog::slotOk() +{ + TQString str; + switch( activePageIndex() ) + { + case 0: str = i18n( "Internet address is empty" ); break; + case 1: str = i18n( "Mail address is empty" ); break; + case 2: str = i18n( "File name is empty" ); break; + case 3: str = i18n( "Destination cell is empty" ); break; + break; + } + + if( link().isEmpty() ) + { + KMessageBox::error( this, str ); + return; + } + + if( d->text.isEmpty() ) + d->text = link(); + + accept(); +} + +#include "link.moc" diff --git a/kspread/dialogs/sheet_properties.cc b/kspread/dialogs/sheet_properties.cc deleted file mode 100644 index c4b79a9d..00000000 --- a/kspread/dialogs/sheet_properties.cc +++ /dev/null @@ -1,192 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 Ariya Hidayat - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include -#include -#include - -#include "kspread_sheet.h" -#include "sheet_properties_base.h" - -#include "sheet_properties.h" - -using namespace KSpread; - -SheetPropertiesDialog::SheetPropertiesDialog( TQWidget* parent ): - KDialogBase( parent, "sheetPropertiesDialog", true, - i18n("Sheet Properties"), - KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Default ) -{ - TQVBox* mainWidget = makeVBoxMainWidget(); - d = new SheetPropertiesBase( mainWidget ); - TQWidget* spacer = new TQWidget( mainWidget ); - spacer->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Expanding ); - enableButtonSeparator( true ); -} - -SheetPropertiesDialog::~SheetPropertiesDialog() -{ - delete d; -} - -void SheetPropertiesDialog::slotDefault() -{ - setLayoutDirection( Sheet::LeftToRight ); - setAutoCalc( true ); - setShowGrid( true ); - setShowFormula( false ); - setHideZero( false ); - setShowFormulaIndicator( true ); - setShowCommentIndicator( true ); - setShowPageBorders( false ); - setColumnAsNumber( false ); - setLcMode( false ); - setCapitalizeFirstLetter( false ); -} - -Sheet::LayoutDirection SheetPropertiesDialog::layoutDirection() const -{ - if( d->directionComboBox->currentText() == i18n( "Left to Right" ) ) - return Sheet::LeftToRight; - - if( d->directionComboBox->currentText() == i18n( "Right to Left" ) ) - return Sheet::RightToLeft; - - // fallback - return Sheet::LeftToRight; -} - -void SheetPropertiesDialog::setLayoutDirection( Sheet::LayoutDirection dir ) -{ - switch( dir ) - { - case Sheet::LeftToRight: - d->directionComboBox->setCurrentText( i18n( "Left to Right" ) ); - break; - case Sheet::RightToLeft: - d->directionComboBox->setCurrentText( i18n( "Right to Left" ) ); - break; - default: break; - }; -} - -bool SheetPropertiesDialog::autoCalc() const -{ - return d->autoCalcCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setAutoCalc( bool b ) -{ - d->autoCalcCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::showGrid() const -{ - return d->showGridCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setShowGrid( bool b ) -{ - d->showGridCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::showPageBorders() const -{ - return d->showPageBordersCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setShowPageBorders( bool b ) -{ - d->showPageBordersCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::showFormula() const -{ - return d->showFormulaCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setShowFormula( bool b ) -{ - d->showFormulaCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::hideZero() const -{ - return d->hideZeroCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setHideZero( bool b ) -{ - d->hideZeroCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::showFormulaIndicator() const -{ - return d->showFormulaIndicatorCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setShowFormulaIndicator( bool b ) -{ - d->showFormulaIndicatorCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::showCommentIndicator() const -{ - return d->showCommentIndicatorCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setShowCommentIndicator( bool b ) -{ - d->showCommentIndicatorCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::columnAsNumber() const -{ - return d->showColumnAsNumbersCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setColumnAsNumber( bool b ) -{ - d->showColumnAsNumbersCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::lcMode() const -{ - return d->useLCModeCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setLcMode( bool b ) -{ - d->useLCModeCheckBox->setChecked( b ); -} - -bool SheetPropertiesDialog::capitalizeFirstLetter() const -{ - return d->capitalizeFirstLetterCheckBox->isChecked(); -} - -void SheetPropertiesDialog::setCapitalizeFirstLetter( bool b ) -{ - d->capitalizeFirstLetterCheckBox->setChecked( b ); -} - -#include "sheet_properties.moc" diff --git a/kspread/dialogs/sheet_properties.cpp b/kspread/dialogs/sheet_properties.cpp new file mode 100644 index 00000000..c4b79a9d --- /dev/null +++ b/kspread/dialogs/sheet_properties.cpp @@ -0,0 +1,192 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Ariya Hidayat + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include + +#include "kspread_sheet.h" +#include "sheet_properties_base.h" + +#include "sheet_properties.h" + +using namespace KSpread; + +SheetPropertiesDialog::SheetPropertiesDialog( TQWidget* parent ): + KDialogBase( parent, "sheetPropertiesDialog", true, + i18n("Sheet Properties"), + KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Default ) +{ + TQVBox* mainWidget = makeVBoxMainWidget(); + d = new SheetPropertiesBase( mainWidget ); + TQWidget* spacer = new TQWidget( mainWidget ); + spacer->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Expanding ); + enableButtonSeparator( true ); +} + +SheetPropertiesDialog::~SheetPropertiesDialog() +{ + delete d; +} + +void SheetPropertiesDialog::slotDefault() +{ + setLayoutDirection( Sheet::LeftToRight ); + setAutoCalc( true ); + setShowGrid( true ); + setShowFormula( false ); + setHideZero( false ); + setShowFormulaIndicator( true ); + setShowCommentIndicator( true ); + setShowPageBorders( false ); + setColumnAsNumber( false ); + setLcMode( false ); + setCapitalizeFirstLetter( false ); +} + +Sheet::LayoutDirection SheetPropertiesDialog::layoutDirection() const +{ + if( d->directionComboBox->currentText() == i18n( "Left to Right" ) ) + return Sheet::LeftToRight; + + if( d->directionComboBox->currentText() == i18n( "Right to Left" ) ) + return Sheet::RightToLeft; + + // fallback + return Sheet::LeftToRight; +} + +void SheetPropertiesDialog::setLayoutDirection( Sheet::LayoutDirection dir ) +{ + switch( dir ) + { + case Sheet::LeftToRight: + d->directionComboBox->setCurrentText( i18n( "Left to Right" ) ); + break; + case Sheet::RightToLeft: + d->directionComboBox->setCurrentText( i18n( "Right to Left" ) ); + break; + default: break; + }; +} + +bool SheetPropertiesDialog::autoCalc() const +{ + return d->autoCalcCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setAutoCalc( bool b ) +{ + d->autoCalcCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::showGrid() const +{ + return d->showGridCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setShowGrid( bool b ) +{ + d->showGridCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::showPageBorders() const +{ + return d->showPageBordersCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setShowPageBorders( bool b ) +{ + d->showPageBordersCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::showFormula() const +{ + return d->showFormulaCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setShowFormula( bool b ) +{ + d->showFormulaCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::hideZero() const +{ + return d->hideZeroCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setHideZero( bool b ) +{ + d->hideZeroCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::showFormulaIndicator() const +{ + return d->showFormulaIndicatorCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setShowFormulaIndicator( bool b ) +{ + d->showFormulaIndicatorCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::showCommentIndicator() const +{ + return d->showCommentIndicatorCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setShowCommentIndicator( bool b ) +{ + d->showCommentIndicatorCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::columnAsNumber() const +{ + return d->showColumnAsNumbersCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setColumnAsNumber( bool b ) +{ + d->showColumnAsNumbersCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::lcMode() const +{ + return d->useLCModeCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setLcMode( bool b ) +{ + d->useLCModeCheckBox->setChecked( b ); +} + +bool SheetPropertiesDialog::capitalizeFirstLetter() const +{ + return d->capitalizeFirstLetterCheckBox->isChecked(); +} + +void SheetPropertiesDialog::setCapitalizeFirstLetter( bool b ) +{ + d->capitalizeFirstLetterCheckBox->setChecked( b ); +} + +#include "sheet_properties.moc" diff --git a/kspread/digest.cc b/kspread/digest.cc deleted file mode 100644 index c4aa90c6..00000000 --- a/kspread/digest.cc +++ /dev/null @@ -1,853 +0,0 @@ -/************************************************************************* - * This implementation has been taken from the OpenOffice 1.0 and modified - * to use KSpread data types. - * - * The Initial Developer of the Original Code is: Sun Microsystems, Inc. - * - * Sun has made the contents of this file available subject to the - * terms of GNU Lesser General Public License Version 2.1 as - * specified in sal/rtl/source/digest.c in the OpenOffice package. - * - * - * Sun Microsystems Inc., October, 2000 - * - * GNU Lesser General Public License Version 2.1 - * ============================================= - * Copyright 2000 by Sun Microsystems, Inc. - * 901 San Antonio Road, Palo Alto, CA 94303, USA - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - * - * All Rights Reserved. - * - * Contributor(s): Matthias Huetsch - * - * - ************************************************************************/ - -#include -#include - -#include "../config.h" -#include "digest.h" -#include -#include - -typedef unsigned char sal_uInt8; -typedef unsigned short sal_uInt16; - -#if SIZEOF_INT == 4 -typedef unsigned int sal_uInt32; -#else -typedef unsigned long sal_uInt32; -#endif - -void rtl_freeZeroMemory(void * p, sal_uInt32 n); -void rtl_freeMemory(void * p); -void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes); -void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes); - -#ifndef OSL_LOBYTE -# define OSL_LOBYTE(w) ((sal_uInt8)((sal_uInt16)(w) & 0xFF)) -#endif -#ifndef OSL_HIBYTE -# define OSL_HIBYTE(w) ((sal_uInt8)(((sal_uInt16)(w) >> 8) & 0xFF)) -#endif -#ifndef OSL_MAKEWORD -# define OSL_MAKEWORD(bl, bh) ((sal_uInt16)((bl) & 0xFF) | (((sal_uInt16)(bh) & 0xFF) << 8)) -#endif -#ifndef OSL_MAKEDWORD -# define OSL_MAKEDWORD(wl, wh) ((sal_uInt32)((wl) & 0xFFFF) | (((sal_uInt32)(wh) & 0xFFFF) << 16)) -#endif -#ifndef OSL_LOWORD -# define OSL_LOWORD(d) ((sal_uInt16)((sal_uInt32)(d) & 0xFFFF)) -#endif -#ifndef OSL_HIWORD -# define OSL_HIWORD(d) ((sal_uInt16)(((sal_uInt32)(d) >> 16) & 0xFFFF)) -#endif - -/** Define macros for swapping between byte orders. - */ -#ifndef OSL_SWAPWORD -# define OSL_SWAPWORD(w) OSL_MAKEWORD(OSL_HIBYTE(w),OSL_LOBYTE(w)) -#endif -#ifndef OSL_SWAPDWORD -# define OSL_SWAPDWORD(d) OSL_MAKEDWORD(OSL_SWAPWORD(OSL_HIWORD(d)),OSL_SWAPWORD(OSL_LOWORD(d))) -#endif - - -/*======================================================================== - * - * rtlDigest. - * - *======================================================================*/ -/** Digest Handle opaque type. - */ -typedef void* rtlDigest; - -/** Digest Algorithm enumeration. - @see rtl_digest_create() - */ -enum __rtl_DigestAlgorithm -{ - rtl_Digest_AlgorithmMD2, - rtl_Digest_AlgorithmMD5, - rtl_Digest_AlgorithmSHA, - rtl_Digest_AlgorithmSHA1, - - rtl_Digest_AlgorithmHMAC_MD5, - rtl_Digest_AlgorithmHMAC_SHA1, - - rtl_Digest_AlgorithmInvalid, - rtl_Digest_Algorithm_FORCE_EQUAL_SIZE -}; - -/** Digest Algorithm type. - */ -typedef enum __rtl_DigestAlgorithm rtlDigestAlgorithm; - - -/** Error Code enumeration. - */ -enum __rtl_DigestError -{ - rtl_Digest_E_None, - rtl_Digest_E_Argument, - rtl_Digest_E_Algorithm, - rtl_Digest_E_BufferSize, - rtl_Digest_E_Memory, - rtl_Digest_E_Unknown, - rtl_Digest_E_FORCE_EQUAL_SIZE -}; - -/** Error Code type. - */ -typedef enum __rtl_DigestError rtlDigestError; - -typedef rtlDigestError Digest_init_t( void * ctx, const sal_uInt8 * Data, sal_uInt32 DatLen ); - -typedef void Digest_delete_t( void *ctx ); - -typedef rtlDigestError Digest_update_t( void * ctx, const void * Data, sal_uInt32 DatLen ); - -typedef rtlDigestError Digest_get_t( void * ctx, sal_uInt8 * Buffer, sal_uInt32 BufLen ); - -/*======================================================================== - * - * rtl_digest_SHA1 interface. - * - *======================================================================*/ -#define RTL_DIGEST_LENGTH_SHA1 20 - -/** Create a SHA1 digest handle. - @descr The SHA1 digest algorithm is specified in - - FIPS PUB 180-1 (Supersedes FIPS PUB 180) - Secure Hash Standard - - @see rtl_digest_create() - */ -rtlDigest rtl_digest_createSHA1 (void); - - -/** Destroy a SHA1 digest handle. - @see rtl_digest_destroy() - */ -void rtl_digest_destroySHA1( rtlDigest Digest ); - - -/** Update a SHA1 digest with given data. - @see rtl_digest_update() - */ -rtlDigestError rtl_digest_updateSHA1( rtlDigest Digest, const void * pData, uint nDatLen ); - - -/** Finalize a SHA1 digest and retrieve the digest value. - @see rtl_digest_get() - */ -rtlDigestError rtl_digest_getSHA1( rtlDigest Digest, sal_uInt8 * pBuffer, uint nBufLen ); - - -/** Evaluate a SHA1 digest value from given data. - @descr This function performs an optimized call sequence on a - single data buffer, avoiding digest creation and destruction. - - @see rtl_digest_updateSHA1() - @see rtl_digest_getSHA1() - - @param pData [in] data buffer. - @param nDatLen [in] data length. - @param pBuffer [in] digest value buffer. - @param nBufLen [in] digest value length. - - @return rtl_Digest_E_None upon success. - */ -rtlDigestError rtl_digest_SHA1( const void * pData, uint nDatLen, - unsigned char * pBuffer, uint nBufLen ); - - -/*======================================================================== - * - * rtlDigest internals. - * - *======================================================================*/ - -void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes) -{ - memset(Ptr, 0, Bytes); -} - -void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes) -{ - memcpy(Dst, Src, Bytes); -} - -void rtl_freeMemory (void * p) -{ - free(p); -} - -void rtl_freeZeroMemory (void * p, sal_uInt32 n) -{ - if (p) - { - memset(p, 0, n); - free(p); - } -} - -#define RTL_DIGEST_CREATE(T) ((T*)(malloc(sizeof(T)))) - -#define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n)))) - -#define RTL_DIGEST_HTONL(l,c) \ - (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) ) & 0xff)) - -#define RTL_DIGEST_LTOC(l,c) \ - (*((c)++) = (sal_uInt8)(((l) ) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \ - *((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff)) - -typedef struct digest_impl_st -{ - rtlDigestAlgorithm m_algorithm; - sal_uInt32 m_length; - Digest_init_t *m_init; - Digest_delete_t *m_delete; - Digest_update_t *m_update; - Digest_get_t *m_get; -} Digest_Impl; - -/* - * __rtl_digest_swapLong. - */ -static void __rtl_digest_swapLong (sal_uInt32 *pData, sal_uInt32 nDatLen) -{ - sal_uInt32 *X; - int i, n; - - X = pData; - n = nDatLen; - - for (i = 0; i < n; i++) - X[i] = OSL_SWAPDWORD(X[i]); -} - -/*======================================================================== - * - * rtlDigest implementation. - * - *======================================================================*/ -/* - * rtl_digest_create. - -rtlDigest rtl_digest_create (rtlDigestAlgorithm Algorithm) -{ - rtlDigest Digest = (rtlDigest)NULL; - switch (Algorithm) - { - case rtl_Digest_AlgorithmMD2: - Digest = rtl_digest_createMD2(); - break; - - case rtl_Digest_AlgorithmMD5: - Digest = rtl_digest_createMD5(); - break; - - case rtl_Digest_AlgorithmSHA: - Digest = rtl_digest_createSHA(); - break; - - case rtl_Digest_AlgorithmSHA1: - Digest = rtl_digest_createSHA1(); - break; - - case rtl_Digest_AlgorithmHMAC_MD5: - Digest = rtl_digest_createHMAC_MD5(); - break; - - case rtl_Digest_AlgorithmHMAC_SHA1: - Digest = rtl_digest_createHMAC_SHA1(); - break; - - default: // rtl_Digest_AlgorithmInvalid - break; - } - return Digest; -} - - -// rtl_digest_queryAlgorithm. - -rtlDigestAlgorithm rtl_digest_queryAlgorithm (rtlDigest Digest) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl) - return pImpl->m_algorithm; - else - return rtl_Digest_AlgorithmInvalid; -} - - // rtl_digest_queryLength. -sal_uInt32 rtl_digest_queryLength (rtlDigest Digest) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl) - return pImpl->m_length; - else - return 0; -} - -// * rtl_digest_init. -rtlDigestError rtl_digest_init ( - rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl) - { - if (pImpl->m_init) - return pImpl->m_init (Digest, pData, nDatLen); - else - return rtl_Digest_E_None; - } - return rtl_Digest_E_Argument; -} - -// * rtl_digest_update. -rtlDigestError rtl_digest_update ( - rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl && pImpl->m_update) - return pImpl->m_update (Digest, pData, nDatLen); - else - return rtl_Digest_E_Argument; -} - -// * rtl_digest_get. -rtlDigestError rtl_digest_get ( - rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl && pImpl->m_get) - return pImpl->m_get (Digest, pBuffer, nBufLen); - else - return rtl_Digest_E_Argument; -} - -// * rtl_digest_destroy. -void rtl_digest_destroy (rtlDigest Digest) -{ - Digest_Impl *pImpl = (Digest_Impl *)Digest; - if (pImpl && pImpl->m_delete) - pImpl->m_delete (Digest); -} -*/ - -/*======================================================================== - * - * rtl_digest_(SHA|SHA1) common internals. - * - *======================================================================*/ -#define DIGEST_CBLOCK_SHA 64 -#define DIGEST_LBLOCK_SHA 16 - -typedef sal_uInt32 DigestSHA_update_t (sal_uInt32 x); - -static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x); - -typedef struct digestSHA_context_st -{ - DigestSHA_update_t *m_update; - sal_uInt32 m_nDatLen; - sal_uInt32 m_pData[DIGEST_LBLOCK_SHA]; - sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE; - sal_uInt32 m_nL, m_nH; -} DigestContextSHA; - -typedef struct digestSHA_impl_st -{ - Digest_Impl m_digest; - DigestContextSHA m_context; -} DigestSHA_Impl; - -static void __rtl_digest_initSHA ( - DigestContextSHA *ctx, DigestSHA_update_t *fct); - -static void __rtl_digest_updateSHA (DigestContextSHA *ctx); -static void __rtl_digest_endSHA (DigestContextSHA *ctx); - -#define K_00_19 (sal_uInt32)0x5a827999L -#define K_20_39 (sal_uInt32)0x6ed9eba1L -#define K_40_59 (sal_uInt32)0x8f1bbcdcL -#define K_60_79 (sal_uInt32)0xca62c1d6L - -#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) -#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) -#define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) -#define F_60_79(b,c,d) F_20_39(b,c,d) - -#define BODY_X(i) \ - (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f]) - -#define BODY_00_15(u,i,a,b,c,d,e,f) \ - (f) = X[i]; \ - (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ - (b) = RTL_DIGEST_ROTL((b), 30); - -#define BODY_16_19(u,i,a,b,c,d,e,f) \ - (f) = BODY_X((i)); \ - (f) = X[(i)&0x0f] = (u)((f)); \ - (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ - (b) = RTL_DIGEST_ROTL((b), 30); - -#define BODY_20_39(u,i,a,b,c,d,e,f) \ - (f) = BODY_X((i)); \ - (f) = X[(i)&0x0f] = (u)((f)); \ - (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \ - (b) = RTL_DIGEST_ROTL((b), 30); - -#define BODY_40_59(u,i,a,b,c,d,e,f) \ - (f) = BODY_X((i)); \ - (f) = X[(i)&0x0f] = (u)((f)); \ - (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \ - (b) = RTL_DIGEST_ROTL((b), 30); - -#define BODY_60_79(u,i,a,b,c,d,e,f) \ - (f) = BODY_X((i)); \ - (f) = X[(i)&0x0f] = (u)((f)); \ - (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \ - (b) = RTL_DIGEST_ROTL((b), 30); - -/* - * __rtl_digest_initSHA. - */ -static void __rtl_digest_initSHA ( - DigestContextSHA *ctx, DigestSHA_update_t *fct) -{ - rtl_zeroMemory (ctx, sizeof (DigestContextSHA)); - ctx->m_update = fct; - - ctx->m_nA = (sal_uInt32)0x67452301L; - ctx->m_nB = (sal_uInt32)0xefcdab89L; - ctx->m_nC = (sal_uInt32)0x98badcfeL; - ctx->m_nD = (sal_uInt32)0x10325476L; - ctx->m_nE = (sal_uInt32)0xc3d2e1f0L; -} - -/* - * __rtl_digest_updateSHA. - */ -static void __rtl_digest_updateSHA (DigestContextSHA *ctx) -{ - sal_uInt32 A, B, C, D, E, T; - sal_uInt32 *X; - - DigestSHA_update_t *U; - U = ctx->m_update; - - A = ctx->m_nA; - B = ctx->m_nB; - C = ctx->m_nC; - D = ctx->m_nD; - E = ctx->m_nE; - X = ctx->m_pData; - - BODY_00_15 (U, 0, A, B, C, D, E, T); - BODY_00_15 (U, 1, T, A, B, C, D, E); - BODY_00_15 (U, 2, E, T, A, B, C, D); - BODY_00_15 (U, 3, D, E, T, A, B, C); - BODY_00_15 (U, 4, C, D, E, T, A, B); - BODY_00_15 (U, 5, B, C, D, E, T, A); - BODY_00_15 (U, 6, A, B, C, D, E, T); - BODY_00_15 (U, 7, T, A, B, C, D, E); - BODY_00_15 (U, 8, E, T, A, B, C, D); - BODY_00_15 (U, 9, D, E, T, A, B, C); - BODY_00_15 (U, 10, C, D, E, T, A, B); - BODY_00_15 (U, 11, B, C, D, E, T, A); - BODY_00_15 (U, 12, A, B, C, D, E, T); - BODY_00_15 (U, 13, T, A, B, C, D, E); - BODY_00_15 (U, 14, E, T, A, B, C, D); - BODY_00_15 (U, 15, D, E, T, A, B, C); - BODY_16_19 (U, 16, C, D, E, T, A, B); - BODY_16_19 (U, 17, B, C, D, E, T, A); - BODY_16_19 (U, 18, A, B, C, D, E, T); - BODY_16_19 (U, 19, T, A, B, C, D, E); - - BODY_20_39 (U, 20, E, T, A, B, C, D); - BODY_20_39 (U, 21, D, E, T, A, B, C); - BODY_20_39 (U, 22, C, D, E, T, A, B); - BODY_20_39 (U, 23, B, C, D, E, T, A); - BODY_20_39 (U, 24, A, B, C, D, E, T); - BODY_20_39 (U, 25, T, A, B, C, D, E); - BODY_20_39 (U, 26, E, T, A, B, C, D); - BODY_20_39 (U, 27, D, E, T, A, B, C); - BODY_20_39 (U, 28, C, D, E, T, A, B); - BODY_20_39 (U, 29, B, C, D, E, T, A); - BODY_20_39 (U, 30, A, B, C, D, E, T); - BODY_20_39 (U, 31, T, A, B, C, D, E); - BODY_20_39 (U, 32, E, T, A, B, C, D); - BODY_20_39 (U, 33, D, E, T, A, B, C); - BODY_20_39 (U, 34, C, D, E, T, A, B); - BODY_20_39 (U, 35, B, C, D, E, T, A); - BODY_20_39 (U, 36, A, B, C, D, E, T); - BODY_20_39 (U, 37, T, A, B, C, D, E); - BODY_20_39 (U, 38, E, T, A, B, C, D); - BODY_20_39 (U, 39, D, E, T, A, B, C); - - BODY_40_59 (U, 40, C, D, E, T, A, B); - BODY_40_59 (U, 41, B, C, D, E, T, A); - BODY_40_59 (U, 42, A, B, C, D, E, T); - BODY_40_59 (U, 43, T, A, B, C, D, E); - BODY_40_59 (U, 44, E, T, A, B, C, D); - BODY_40_59 (U, 45, D, E, T, A, B, C); - BODY_40_59 (U, 46, C, D, E, T, A, B); - BODY_40_59 (U, 47, B, C, D, E, T, A); - BODY_40_59 (U, 48, A, B, C, D, E, T); - BODY_40_59 (U, 49, T, A, B, C, D, E); - BODY_40_59 (U, 50, E, T, A, B, C, D); - BODY_40_59 (U, 51, D, E, T, A, B, C); - BODY_40_59 (U, 52, C, D, E, T, A, B); - BODY_40_59 (U, 53, B, C, D, E, T, A); - BODY_40_59 (U, 54, A, B, C, D, E, T); - BODY_40_59 (U, 55, T, A, B, C, D, E); - BODY_40_59 (U, 56, E, T, A, B, C, D); - BODY_40_59 (U, 57, D, E, T, A, B, C); - BODY_40_59 (U, 58, C, D, E, T, A, B); - BODY_40_59 (U, 59, B, C, D, E, T, A); - - BODY_60_79 (U, 60, A, B, C, D, E, T); - BODY_60_79 (U, 61, T, A, B, C, D, E); - BODY_60_79 (U, 62, E, T, A, B, C, D); - BODY_60_79 (U, 63, D, E, T, A, B, C); - BODY_60_79 (U, 64, C, D, E, T, A, B); - BODY_60_79 (U, 65, B, C, D, E, T, A); - BODY_60_79 (U, 66, A, B, C, D, E, T); - BODY_60_79 (U, 67, T, A, B, C, D, E); - BODY_60_79 (U, 68, E, T, A, B, C, D); - BODY_60_79 (U, 69, D, E, T, A, B, C); - BODY_60_79 (U, 70, C, D, E, T, A, B); - BODY_60_79 (U, 71, B, C, D, E, T, A); - BODY_60_79 (U, 72, A, B, C, D, E, T); - BODY_60_79 (U, 73, T, A, B, C, D, E); - BODY_60_79 (U, 74, E, T, A, B, C, D); - BODY_60_79 (U, 75, D, E, T, A, B, C); - BODY_60_79 (U, 76, C, D, E, T, A, B); - BODY_60_79 (U, 77, B, C, D, E, T, A); - BODY_60_79 (U, 78, A, B, C, D, E, T); - BODY_60_79 (U, 79, T, A, B, C, D, E); - - ctx->m_nA += E; - ctx->m_nB += T; - ctx->m_nC += A; - ctx->m_nD += B; - ctx->m_nE += C; -} - -/* - * __rtl_digest_endSHA. - */ -static void __rtl_digest_endSHA (DigestContextSHA *ctx) -{ - static const sal_uInt8 end[4] = - { - 0x80, 0x00, 0x00, 0x00 - }; - const sal_uInt8 *p = end; - - sal_uInt32 *X; - int i; - - X = ctx->m_pData; - i = (ctx->m_nDatLen >> 2); - -#ifdef WORDS_BIGENDIAN - __rtl_digest_swapLong (X, i + 1); -#endif - - switch (ctx->m_nDatLen & 0x03) - { - case 1: X[i] &= 0x000000ff; break; - case 2: X[i] &= 0x0000ffff; break; - case 3: X[i] &= 0x00ffffff; break; - } - - switch (ctx->m_nDatLen & 0x03) - { - case 0: X[i] = ((sal_uInt32)(*(p++))) << 0L; - case 1: X[i] |= ((sal_uInt32)(*(p++))) << 8L; - case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L; - case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L; - } - - __rtl_digest_swapLong (X, i + 1); - - i += 1; - - if (i >= (DIGEST_LBLOCK_SHA - 2)) - { - for (; i < DIGEST_LBLOCK_SHA; i++) - X[i] = 0; - __rtl_digest_updateSHA (ctx); - i = 0; - } - - for (; i < (DIGEST_LBLOCK_SHA - 2); i++) - X[i] = 0; - - X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH; - X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL; - - __rtl_digest_updateSHA (ctx); -} - -/*======================================================================== - * - * rtl_digest_SHA1 internals. - * - *======================================================================*/ -/* - * __rtl_digest_SHA_1. - */ -static const Digest_Impl __rtl_digest_SHA_1 = { rtl_Digest_AlgorithmSHA1, - RTL_DIGEST_LENGTH_SHA1, - 0, - rtl_digest_destroySHA1, - rtl_digest_updateSHA1, - rtl_digest_getSHA1 -}; - -/* - * __rtl_digest_updateSHA_1. - */ -static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x) -{ - return RTL_DIGEST_ROTL (x, 1); -} - -/*======================================================================== - * - * rtl_digest_SHA1 implementation. - * - *======================================================================*/ -/* - * rtl_digest_SHA1. - */ -rtlDigestError rtl_digest_SHA1 ( - const void *pData, sal_uInt32 nDatLen, - sal_uInt8 *pBuffer, sal_uInt32 nBufLen) -{ - DigestSHA_Impl digest; - rtlDigestError result; - - digest.m_digest = __rtl_digest_SHA_1; - __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_1); - - result = rtl_digest_updateSHA1 (&digest, pData, nDatLen); - if (result == rtl_Digest_E_None) - result = rtl_digest_getSHA1 (&digest, pBuffer, nBufLen); - - rtl_zeroMemory (&digest, sizeof (digest)); - return (result); -} - -/* - * rtl_digest_createSHA1. - */ -rtlDigest rtl_digest_createSHA1 (void) -{ - DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL; - pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl); - if (pImpl) - { - pImpl->m_digest = __rtl_digest_SHA_1; - __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1); - } - return ((rtlDigest)pImpl); -} - -/* - * rtl_digest_updateSHA1. - */ -rtlDigestError rtl_digest_updateSHA1 ( - rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) -{ - DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; - const sal_uInt8 *d = (const sal_uInt8 *)pData; - - DigestContextSHA *ctx; - sal_uInt32 len; - - if ((pImpl == NULL) || (pData == NULL)) - return rtl_Digest_E_Argument; - - if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)) - return rtl_Digest_E_Algorithm; - - if (nDatLen == 0) - return rtl_Digest_E_None; - - ctx = &(pImpl->m_context); - - len = ctx->m_nL + (nDatLen << 3); - if (len < ctx->m_nL) ctx->m_nH += 1; - ctx->m_nH += (nDatLen >> 29); - ctx->m_nL = len; - - if (ctx->m_nDatLen) - { - sal_uInt8 *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen; - sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen; - - if (nDatLen < n) - { - rtl_copyMemory (p, d, nDatLen); - ctx->m_nDatLen += nDatLen; - - return rtl_Digest_E_None; - } - - rtl_copyMemory (p, d, n); - d += n; - nDatLen -= n; - -#ifndef WORDS_BIGENDIAN - __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA); -#endif - - __rtl_digest_updateSHA (ctx); - ctx->m_nDatLen = 0; - } - - while (nDatLen >= DIGEST_CBLOCK_SHA) - { - rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA); - d += DIGEST_CBLOCK_SHA; - nDatLen -= DIGEST_CBLOCK_SHA; - -#ifndef WORDS_BIGENDIAN - __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA); -#endif - - __rtl_digest_updateSHA (ctx); - } - - rtl_copyMemory (ctx->m_pData, d, nDatLen); - ctx->m_nDatLen = nDatLen; - - return rtl_Digest_E_None; -} - -/* - * rtl_digest_getSHA1. - */ -rtlDigestError rtl_digest_getSHA1 ( - rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) -{ - DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; - sal_uInt8 *p = pBuffer; - - DigestContextSHA *ctx; - - if ((pImpl == NULL) || (pBuffer == NULL)) - return rtl_Digest_E_Argument; - - if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)) - return rtl_Digest_E_Algorithm; - - if (!(pImpl->m_digest.m_length <= nBufLen)) - return rtl_Digest_E_BufferSize; - - ctx = &(pImpl->m_context); - - __rtl_digest_endSHA (ctx); - RTL_DIGEST_HTONL (ctx->m_nA, p); - RTL_DIGEST_HTONL (ctx->m_nB, p); - RTL_DIGEST_HTONL (ctx->m_nC, p); - RTL_DIGEST_HTONL (ctx->m_nD, p); - RTL_DIGEST_HTONL (ctx->m_nE, p); - __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_1); - - return rtl_Digest_E_None; -} - -/* - * rtl_digest_destroySHA1. - */ -void rtl_digest_destroySHA1 (rtlDigest Digest) -{ - DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; - if (pImpl) - { - if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1) - rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl)); - else - rtl_freeMemory (pImpl); - } -} - -/*======================================================================== - * - * The End. - * - *======================================================================*/ - -bool SHA1::getHash( TQString const & text, TQCString & hash ) -{ - rtlDigest aDigest = rtl_digest_createSHA1(); - rtlDigestError aError = rtl_digest_updateSHA1( aDigest, text.unicode(), text.length() * sizeof(TQChar) ); - - if ( aError == rtl_Digest_E_None ) - { - TQCString digest; - digest.resize( RTL_DIGEST_LENGTH_SHA1 + 1 ); - digest.fill( '\0', RTL_DIGEST_LENGTH_SHA1 ); - - aError = rtl_digest_getSHA1( aDigest, (unsigned char *) digest.data(), RTL_DIGEST_LENGTH_SHA1 ); - - if (aError != rtl_Digest_E_None) - return false; - - hash = digest; - - return true; - } - - return false; -} diff --git a/kspread/digest.cpp b/kspread/digest.cpp new file mode 100644 index 00000000..c4aa90c6 --- /dev/null +++ b/kspread/digest.cpp @@ -0,0 +1,853 @@ +/************************************************************************* + * This implementation has been taken from the OpenOffice 1.0 and modified + * to use KSpread data types. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Sun has made the contents of this file available subject to the + * terms of GNU Lesser General Public License Version 2.1 as + * specified in sal/rtl/source/digest.c in the OpenOffice package. + * + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + * + * All Rights Reserved. + * + * Contributor(s): Matthias Huetsch + * + * + ************************************************************************/ + +#include +#include + +#include "../config.h" +#include "digest.h" +#include +#include + +typedef unsigned char sal_uInt8; +typedef unsigned short sal_uInt16; + +#if SIZEOF_INT == 4 +typedef unsigned int sal_uInt32; +#else +typedef unsigned long sal_uInt32; +#endif + +void rtl_freeZeroMemory(void * p, sal_uInt32 n); +void rtl_freeMemory(void * p); +void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes); +void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes); + +#ifndef OSL_LOBYTE +# define OSL_LOBYTE(w) ((sal_uInt8)((sal_uInt16)(w) & 0xFF)) +#endif +#ifndef OSL_HIBYTE +# define OSL_HIBYTE(w) ((sal_uInt8)(((sal_uInt16)(w) >> 8) & 0xFF)) +#endif +#ifndef OSL_MAKEWORD +# define OSL_MAKEWORD(bl, bh) ((sal_uInt16)((bl) & 0xFF) | (((sal_uInt16)(bh) & 0xFF) << 8)) +#endif +#ifndef OSL_MAKEDWORD +# define OSL_MAKEDWORD(wl, wh) ((sal_uInt32)((wl) & 0xFFFF) | (((sal_uInt32)(wh) & 0xFFFF) << 16)) +#endif +#ifndef OSL_LOWORD +# define OSL_LOWORD(d) ((sal_uInt16)((sal_uInt32)(d) & 0xFFFF)) +#endif +#ifndef OSL_HIWORD +# define OSL_HIWORD(d) ((sal_uInt16)(((sal_uInt32)(d) >> 16) & 0xFFFF)) +#endif + +/** Define macros for swapping between byte orders. + */ +#ifndef OSL_SWAPWORD +# define OSL_SWAPWORD(w) OSL_MAKEWORD(OSL_HIBYTE(w),OSL_LOBYTE(w)) +#endif +#ifndef OSL_SWAPDWORD +# define OSL_SWAPDWORD(d) OSL_MAKEDWORD(OSL_SWAPWORD(OSL_HIWORD(d)),OSL_SWAPWORD(OSL_LOWORD(d))) +#endif + + +/*======================================================================== + * + * rtlDigest. + * + *======================================================================*/ +/** Digest Handle opaque type. + */ +typedef void* rtlDigest; + +/** Digest Algorithm enumeration. + @see rtl_digest_create() + */ +enum __rtl_DigestAlgorithm +{ + rtl_Digest_AlgorithmMD2, + rtl_Digest_AlgorithmMD5, + rtl_Digest_AlgorithmSHA, + rtl_Digest_AlgorithmSHA1, + + rtl_Digest_AlgorithmHMAC_MD5, + rtl_Digest_AlgorithmHMAC_SHA1, + + rtl_Digest_AlgorithmInvalid, + rtl_Digest_Algorithm_FORCE_EQUAL_SIZE +}; + +/** Digest Algorithm type. + */ +typedef enum __rtl_DigestAlgorithm rtlDigestAlgorithm; + + +/** Error Code enumeration. + */ +enum __rtl_DigestError +{ + rtl_Digest_E_None, + rtl_Digest_E_Argument, + rtl_Digest_E_Algorithm, + rtl_Digest_E_BufferSize, + rtl_Digest_E_Memory, + rtl_Digest_E_Unknown, + rtl_Digest_E_FORCE_EQUAL_SIZE +}; + +/** Error Code type. + */ +typedef enum __rtl_DigestError rtlDigestError; + +typedef rtlDigestError Digest_init_t( void * ctx, const sal_uInt8 * Data, sal_uInt32 DatLen ); + +typedef void Digest_delete_t( void *ctx ); + +typedef rtlDigestError Digest_update_t( void * ctx, const void * Data, sal_uInt32 DatLen ); + +typedef rtlDigestError Digest_get_t( void * ctx, sal_uInt8 * Buffer, sal_uInt32 BufLen ); + +/*======================================================================== + * + * rtl_digest_SHA1 interface. + * + *======================================================================*/ +#define RTL_DIGEST_LENGTH_SHA1 20 + +/** Create a SHA1 digest handle. + @descr The SHA1 digest algorithm is specified in + + FIPS PUB 180-1 (Supersedes FIPS PUB 180) + Secure Hash Standard + + @see rtl_digest_create() + */ +rtlDigest rtl_digest_createSHA1 (void); + + +/** Destroy a SHA1 digest handle. + @see rtl_digest_destroy() + */ +void rtl_digest_destroySHA1( rtlDigest Digest ); + + +/** Update a SHA1 digest with given data. + @see rtl_digest_update() + */ +rtlDigestError rtl_digest_updateSHA1( rtlDigest Digest, const void * pData, uint nDatLen ); + + +/** Finalize a SHA1 digest and retrieve the digest value. + @see rtl_digest_get() + */ +rtlDigestError rtl_digest_getSHA1( rtlDigest Digest, sal_uInt8 * pBuffer, uint nBufLen ); + + +/** Evaluate a SHA1 digest value from given data. + @descr This function performs an optimized call sequence on a + single data buffer, avoiding digest creation and destruction. + + @see rtl_digest_updateSHA1() + @see rtl_digest_getSHA1() + + @param pData [in] data buffer. + @param nDatLen [in] data length. + @param pBuffer [in] digest value buffer. + @param nBufLen [in] digest value length. + + @return rtl_Digest_E_None upon success. + */ +rtlDigestError rtl_digest_SHA1( const void * pData, uint nDatLen, + unsigned char * pBuffer, uint nBufLen ); + + +/*======================================================================== + * + * rtlDigest internals. + * + *======================================================================*/ + +void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes) +{ + memset(Ptr, 0, Bytes); +} + +void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes) +{ + memcpy(Dst, Src, Bytes); +} + +void rtl_freeMemory (void * p) +{ + free(p); +} + +void rtl_freeZeroMemory (void * p, sal_uInt32 n) +{ + if (p) + { + memset(p, 0, n); + free(p); + } +} + +#define RTL_DIGEST_CREATE(T) ((T*)(malloc(sizeof(T)))) + +#define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n)))) + +#define RTL_DIGEST_HTONL(l,c) \ + (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) ) & 0xff)) + +#define RTL_DIGEST_LTOC(l,c) \ + (*((c)++) = (sal_uInt8)(((l) ) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \ + *((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff)) + +typedef struct digest_impl_st +{ + rtlDigestAlgorithm m_algorithm; + sal_uInt32 m_length; + Digest_init_t *m_init; + Digest_delete_t *m_delete; + Digest_update_t *m_update; + Digest_get_t *m_get; +} Digest_Impl; + +/* + * __rtl_digest_swapLong. + */ +static void __rtl_digest_swapLong (sal_uInt32 *pData, sal_uInt32 nDatLen) +{ + sal_uInt32 *X; + int i, n; + + X = pData; + n = nDatLen; + + for (i = 0; i < n; i++) + X[i] = OSL_SWAPDWORD(X[i]); +} + +/*======================================================================== + * + * rtlDigest implementation. + * + *======================================================================*/ +/* + * rtl_digest_create. + +rtlDigest rtl_digest_create (rtlDigestAlgorithm Algorithm) +{ + rtlDigest Digest = (rtlDigest)NULL; + switch (Algorithm) + { + case rtl_Digest_AlgorithmMD2: + Digest = rtl_digest_createMD2(); + break; + + case rtl_Digest_AlgorithmMD5: + Digest = rtl_digest_createMD5(); + break; + + case rtl_Digest_AlgorithmSHA: + Digest = rtl_digest_createSHA(); + break; + + case rtl_Digest_AlgorithmSHA1: + Digest = rtl_digest_createSHA1(); + break; + + case rtl_Digest_AlgorithmHMAC_MD5: + Digest = rtl_digest_createHMAC_MD5(); + break; + + case rtl_Digest_AlgorithmHMAC_SHA1: + Digest = rtl_digest_createHMAC_SHA1(); + break; + + default: // rtl_Digest_AlgorithmInvalid + break; + } + return Digest; +} + + +// rtl_digest_queryAlgorithm. + +rtlDigestAlgorithm rtl_digest_queryAlgorithm (rtlDigest Digest) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl) + return pImpl->m_algorithm; + else + return rtl_Digest_AlgorithmInvalid; +} + + // rtl_digest_queryLength. +sal_uInt32 rtl_digest_queryLength (rtlDigest Digest) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl) + return pImpl->m_length; + else + return 0; +} + +// * rtl_digest_init. +rtlDigestError rtl_digest_init ( + rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl) + { + if (pImpl->m_init) + return pImpl->m_init (Digest, pData, nDatLen); + else + return rtl_Digest_E_None; + } + return rtl_Digest_E_Argument; +} + +// * rtl_digest_update. +rtlDigestError rtl_digest_update ( + rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl && pImpl->m_update) + return pImpl->m_update (Digest, pData, nDatLen); + else + return rtl_Digest_E_Argument; +} + +// * rtl_digest_get. +rtlDigestError rtl_digest_get ( + rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl && pImpl->m_get) + return pImpl->m_get (Digest, pBuffer, nBufLen); + else + return rtl_Digest_E_Argument; +} + +// * rtl_digest_destroy. +void rtl_digest_destroy (rtlDigest Digest) +{ + Digest_Impl *pImpl = (Digest_Impl *)Digest; + if (pImpl && pImpl->m_delete) + pImpl->m_delete (Digest); +} +*/ + +/*======================================================================== + * + * rtl_digest_(SHA|SHA1) common internals. + * + *======================================================================*/ +#define DIGEST_CBLOCK_SHA 64 +#define DIGEST_LBLOCK_SHA 16 + +typedef sal_uInt32 DigestSHA_update_t (sal_uInt32 x); + +static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x); + +typedef struct digestSHA_context_st +{ + DigestSHA_update_t *m_update; + sal_uInt32 m_nDatLen; + sal_uInt32 m_pData[DIGEST_LBLOCK_SHA]; + sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE; + sal_uInt32 m_nL, m_nH; +} DigestContextSHA; + +typedef struct digestSHA_impl_st +{ + Digest_Impl m_digest; + DigestContextSHA m_context; +} DigestSHA_Impl; + +static void __rtl_digest_initSHA ( + DigestContextSHA *ctx, DigestSHA_update_t *fct); + +static void __rtl_digest_updateSHA (DigestContextSHA *ctx); +static void __rtl_digest_endSHA (DigestContextSHA *ctx); + +#define K_00_19 (sal_uInt32)0x5a827999L +#define K_20_39 (sal_uInt32)0x6ed9eba1L +#define K_40_59 (sal_uInt32)0x8f1bbcdcL +#define K_60_79 (sal_uInt32)0xca62c1d6L + +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#define BODY_X(i) \ + (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f]) + +#define BODY_00_15(u,i,a,b,c,d,e,f) \ + (f) = X[i]; \ + (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ + (b) = RTL_DIGEST_ROTL((b), 30); + +#define BODY_16_19(u,i,a,b,c,d,e,f) \ + (f) = BODY_X((i)); \ + (f) = X[(i)&0x0f] = (u)((f)); \ + (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ + (b) = RTL_DIGEST_ROTL((b), 30); + +#define BODY_20_39(u,i,a,b,c,d,e,f) \ + (f) = BODY_X((i)); \ + (f) = X[(i)&0x0f] = (u)((f)); \ + (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \ + (b) = RTL_DIGEST_ROTL((b), 30); + +#define BODY_40_59(u,i,a,b,c,d,e,f) \ + (f) = BODY_X((i)); \ + (f) = X[(i)&0x0f] = (u)((f)); \ + (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \ + (b) = RTL_DIGEST_ROTL((b), 30); + +#define BODY_60_79(u,i,a,b,c,d,e,f) \ + (f) = BODY_X((i)); \ + (f) = X[(i)&0x0f] = (u)((f)); \ + (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \ + (b) = RTL_DIGEST_ROTL((b), 30); + +/* + * __rtl_digest_initSHA. + */ +static void __rtl_digest_initSHA ( + DigestContextSHA *ctx, DigestSHA_update_t *fct) +{ + rtl_zeroMemory (ctx, sizeof (DigestContextSHA)); + ctx->m_update = fct; + + ctx->m_nA = (sal_uInt32)0x67452301L; + ctx->m_nB = (sal_uInt32)0xefcdab89L; + ctx->m_nC = (sal_uInt32)0x98badcfeL; + ctx->m_nD = (sal_uInt32)0x10325476L; + ctx->m_nE = (sal_uInt32)0xc3d2e1f0L; +} + +/* + * __rtl_digest_updateSHA. + */ +static void __rtl_digest_updateSHA (DigestContextSHA *ctx) +{ + sal_uInt32 A, B, C, D, E, T; + sal_uInt32 *X; + + DigestSHA_update_t *U; + U = ctx->m_update; + + A = ctx->m_nA; + B = ctx->m_nB; + C = ctx->m_nC; + D = ctx->m_nD; + E = ctx->m_nE; + X = ctx->m_pData; + + BODY_00_15 (U, 0, A, B, C, D, E, T); + BODY_00_15 (U, 1, T, A, B, C, D, E); + BODY_00_15 (U, 2, E, T, A, B, C, D); + BODY_00_15 (U, 3, D, E, T, A, B, C); + BODY_00_15 (U, 4, C, D, E, T, A, B); + BODY_00_15 (U, 5, B, C, D, E, T, A); + BODY_00_15 (U, 6, A, B, C, D, E, T); + BODY_00_15 (U, 7, T, A, B, C, D, E); + BODY_00_15 (U, 8, E, T, A, B, C, D); + BODY_00_15 (U, 9, D, E, T, A, B, C); + BODY_00_15 (U, 10, C, D, E, T, A, B); + BODY_00_15 (U, 11, B, C, D, E, T, A); + BODY_00_15 (U, 12, A, B, C, D, E, T); + BODY_00_15 (U, 13, T, A, B, C, D, E); + BODY_00_15 (U, 14, E, T, A, B, C, D); + BODY_00_15 (U, 15, D, E, T, A, B, C); + BODY_16_19 (U, 16, C, D, E, T, A, B); + BODY_16_19 (U, 17, B, C, D, E, T, A); + BODY_16_19 (U, 18, A, B, C, D, E, T); + BODY_16_19 (U, 19, T, A, B, C, D, E); + + BODY_20_39 (U, 20, E, T, A, B, C, D); + BODY_20_39 (U, 21, D, E, T, A, B, C); + BODY_20_39 (U, 22, C, D, E, T, A, B); + BODY_20_39 (U, 23, B, C, D, E, T, A); + BODY_20_39 (U, 24, A, B, C, D, E, T); + BODY_20_39 (U, 25, T, A, B, C, D, E); + BODY_20_39 (U, 26, E, T, A, B, C, D); + BODY_20_39 (U, 27, D, E, T, A, B, C); + BODY_20_39 (U, 28, C, D, E, T, A, B); + BODY_20_39 (U, 29, B, C, D, E, T, A); + BODY_20_39 (U, 30, A, B, C, D, E, T); + BODY_20_39 (U, 31, T, A, B, C, D, E); + BODY_20_39 (U, 32, E, T, A, B, C, D); + BODY_20_39 (U, 33, D, E, T, A, B, C); + BODY_20_39 (U, 34, C, D, E, T, A, B); + BODY_20_39 (U, 35, B, C, D, E, T, A); + BODY_20_39 (U, 36, A, B, C, D, E, T); + BODY_20_39 (U, 37, T, A, B, C, D, E); + BODY_20_39 (U, 38, E, T, A, B, C, D); + BODY_20_39 (U, 39, D, E, T, A, B, C); + + BODY_40_59 (U, 40, C, D, E, T, A, B); + BODY_40_59 (U, 41, B, C, D, E, T, A); + BODY_40_59 (U, 42, A, B, C, D, E, T); + BODY_40_59 (U, 43, T, A, B, C, D, E); + BODY_40_59 (U, 44, E, T, A, B, C, D); + BODY_40_59 (U, 45, D, E, T, A, B, C); + BODY_40_59 (U, 46, C, D, E, T, A, B); + BODY_40_59 (U, 47, B, C, D, E, T, A); + BODY_40_59 (U, 48, A, B, C, D, E, T); + BODY_40_59 (U, 49, T, A, B, C, D, E); + BODY_40_59 (U, 50, E, T, A, B, C, D); + BODY_40_59 (U, 51, D, E, T, A, B, C); + BODY_40_59 (U, 52, C, D, E, T, A, B); + BODY_40_59 (U, 53, B, C, D, E, T, A); + BODY_40_59 (U, 54, A, B, C, D, E, T); + BODY_40_59 (U, 55, T, A, B, C, D, E); + BODY_40_59 (U, 56, E, T, A, B, C, D); + BODY_40_59 (U, 57, D, E, T, A, B, C); + BODY_40_59 (U, 58, C, D, E, T, A, B); + BODY_40_59 (U, 59, B, C, D, E, T, A); + + BODY_60_79 (U, 60, A, B, C, D, E, T); + BODY_60_79 (U, 61, T, A, B, C, D, E); + BODY_60_79 (U, 62, E, T, A, B, C, D); + BODY_60_79 (U, 63, D, E, T, A, B, C); + BODY_60_79 (U, 64, C, D, E, T, A, B); + BODY_60_79 (U, 65, B, C, D, E, T, A); + BODY_60_79 (U, 66, A, B, C, D, E, T); + BODY_60_79 (U, 67, T, A, B, C, D, E); + BODY_60_79 (U, 68, E, T, A, B, C, D); + BODY_60_79 (U, 69, D, E, T, A, B, C); + BODY_60_79 (U, 70, C, D, E, T, A, B); + BODY_60_79 (U, 71, B, C, D, E, T, A); + BODY_60_79 (U, 72, A, B, C, D, E, T); + BODY_60_79 (U, 73, T, A, B, C, D, E); + BODY_60_79 (U, 74, E, T, A, B, C, D); + BODY_60_79 (U, 75, D, E, T, A, B, C); + BODY_60_79 (U, 76, C, D, E, T, A, B); + BODY_60_79 (U, 77, B, C, D, E, T, A); + BODY_60_79 (U, 78, A, B, C, D, E, T); + BODY_60_79 (U, 79, T, A, B, C, D, E); + + ctx->m_nA += E; + ctx->m_nB += T; + ctx->m_nC += A; + ctx->m_nD += B; + ctx->m_nE += C; +} + +/* + * __rtl_digest_endSHA. + */ +static void __rtl_digest_endSHA (DigestContextSHA *ctx) +{ + static const sal_uInt8 end[4] = + { + 0x80, 0x00, 0x00, 0x00 + }; + const sal_uInt8 *p = end; + + sal_uInt32 *X; + int i; + + X = ctx->m_pData; + i = (ctx->m_nDatLen >> 2); + +#ifdef WORDS_BIGENDIAN + __rtl_digest_swapLong (X, i + 1); +#endif + + switch (ctx->m_nDatLen & 0x03) + { + case 1: X[i] &= 0x000000ff; break; + case 2: X[i] &= 0x0000ffff; break; + case 3: X[i] &= 0x00ffffff; break; + } + + switch (ctx->m_nDatLen & 0x03) + { + case 0: X[i] = ((sal_uInt32)(*(p++))) << 0L; + case 1: X[i] |= ((sal_uInt32)(*(p++))) << 8L; + case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L; + case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L; + } + + __rtl_digest_swapLong (X, i + 1); + + i += 1; + + if (i >= (DIGEST_LBLOCK_SHA - 2)) + { + for (; i < DIGEST_LBLOCK_SHA; i++) + X[i] = 0; + __rtl_digest_updateSHA (ctx); + i = 0; + } + + for (; i < (DIGEST_LBLOCK_SHA - 2); i++) + X[i] = 0; + + X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH; + X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL; + + __rtl_digest_updateSHA (ctx); +} + +/*======================================================================== + * + * rtl_digest_SHA1 internals. + * + *======================================================================*/ +/* + * __rtl_digest_SHA_1. + */ +static const Digest_Impl __rtl_digest_SHA_1 = { rtl_Digest_AlgorithmSHA1, + RTL_DIGEST_LENGTH_SHA1, + 0, + rtl_digest_destroySHA1, + rtl_digest_updateSHA1, + rtl_digest_getSHA1 +}; + +/* + * __rtl_digest_updateSHA_1. + */ +static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x) +{ + return RTL_DIGEST_ROTL (x, 1); +} + +/*======================================================================== + * + * rtl_digest_SHA1 implementation. + * + *======================================================================*/ +/* + * rtl_digest_SHA1. + */ +rtlDigestError rtl_digest_SHA1 ( + const void *pData, sal_uInt32 nDatLen, + sal_uInt8 *pBuffer, sal_uInt32 nBufLen) +{ + DigestSHA_Impl digest; + rtlDigestError result; + + digest.m_digest = __rtl_digest_SHA_1; + __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_1); + + result = rtl_digest_updateSHA1 (&digest, pData, nDatLen); + if (result == rtl_Digest_E_None) + result = rtl_digest_getSHA1 (&digest, pBuffer, nBufLen); + + rtl_zeroMemory (&digest, sizeof (digest)); + return (result); +} + +/* + * rtl_digest_createSHA1. + */ +rtlDigest rtl_digest_createSHA1 (void) +{ + DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL; + pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl); + if (pImpl) + { + pImpl->m_digest = __rtl_digest_SHA_1; + __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1); + } + return ((rtlDigest)pImpl); +} + +/* + * rtl_digest_updateSHA1. + */ +rtlDigestError rtl_digest_updateSHA1 ( + rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) +{ + DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; + const sal_uInt8 *d = (const sal_uInt8 *)pData; + + DigestContextSHA *ctx; + sal_uInt32 len; + + if ((pImpl == NULL) || (pData == NULL)) + return rtl_Digest_E_Argument; + + if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)) + return rtl_Digest_E_Algorithm; + + if (nDatLen == 0) + return rtl_Digest_E_None; + + ctx = &(pImpl->m_context); + + len = ctx->m_nL + (nDatLen << 3); + if (len < ctx->m_nL) ctx->m_nH += 1; + ctx->m_nH += (nDatLen >> 29); + ctx->m_nL = len; + + if (ctx->m_nDatLen) + { + sal_uInt8 *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen; + sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen; + + if (nDatLen < n) + { + rtl_copyMemory (p, d, nDatLen); + ctx->m_nDatLen += nDatLen; + + return rtl_Digest_E_None; + } + + rtl_copyMemory (p, d, n); + d += n; + nDatLen -= n; + +#ifndef WORDS_BIGENDIAN + __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA); +#endif + + __rtl_digest_updateSHA (ctx); + ctx->m_nDatLen = 0; + } + + while (nDatLen >= DIGEST_CBLOCK_SHA) + { + rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA); + d += DIGEST_CBLOCK_SHA; + nDatLen -= DIGEST_CBLOCK_SHA; + +#ifndef WORDS_BIGENDIAN + __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA); +#endif + + __rtl_digest_updateSHA (ctx); + } + + rtl_copyMemory (ctx->m_pData, d, nDatLen); + ctx->m_nDatLen = nDatLen; + + return rtl_Digest_E_None; +} + +/* + * rtl_digest_getSHA1. + */ +rtlDigestError rtl_digest_getSHA1 ( + rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) +{ + DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; + sal_uInt8 *p = pBuffer; + + DigestContextSHA *ctx; + + if ((pImpl == NULL) || (pBuffer == NULL)) + return rtl_Digest_E_Argument; + + if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)) + return rtl_Digest_E_Algorithm; + + if (!(pImpl->m_digest.m_length <= nBufLen)) + return rtl_Digest_E_BufferSize; + + ctx = &(pImpl->m_context); + + __rtl_digest_endSHA (ctx); + RTL_DIGEST_HTONL (ctx->m_nA, p); + RTL_DIGEST_HTONL (ctx->m_nB, p); + RTL_DIGEST_HTONL (ctx->m_nC, p); + RTL_DIGEST_HTONL (ctx->m_nD, p); + RTL_DIGEST_HTONL (ctx->m_nE, p); + __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_1); + + return rtl_Digest_E_None; +} + +/* + * rtl_digest_destroySHA1. + */ +void rtl_digest_destroySHA1 (rtlDigest Digest) +{ + DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest; + if (pImpl) + { + if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1) + rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl)); + else + rtl_freeMemory (pImpl); + } +} + +/*======================================================================== + * + * The End. + * + *======================================================================*/ + +bool SHA1::getHash( TQString const & text, TQCString & hash ) +{ + rtlDigest aDigest = rtl_digest_createSHA1(); + rtlDigestError aError = rtl_digest_updateSHA1( aDigest, text.unicode(), text.length() * sizeof(TQChar) ); + + if ( aError == rtl_Digest_E_None ) + { + TQCString digest; + digest.resize( RTL_DIGEST_LENGTH_SHA1 + 1 ); + digest.fill( '\0', RTL_DIGEST_LENGTH_SHA1 ); + + aError = rtl_digest_getSHA1( aDigest, (unsigned char *) digest.data(), RTL_DIGEST_LENGTH_SHA1 ); + + if (aError != rtl_Digest_E_None) + return false; + + hash = digest; + + return true; + } + + return false; +} diff --git a/kspread/formula.cc b/kspread/formula.cc deleted file mode 100644 index 3522f06b..00000000 --- a/kspread/formula.cc +++ /dev/null @@ -1,1535 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003,2004 Ariya Hidayat - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "formula.h" - -#include "kspread_cell.h" -#include "kspread_sheet.h" -#include "kspread_doc.h" -#include "kspread_util.h" -#include "kspread_value.h" - -#include "valuecalc.h" -#include "valueconverter.h" -#include "valueparser.h" - -#include "functions.h" - -#include - -#include -#include -#include -#include - -#include - -/* - To understand how this formula engine works, please refer to the documentation - in file DESIGN.html. - - Useful references: - - "Principles of Compiler Design", A.V.Aho, J.D.Ullman, Addison Wesley, 1978 - - "Writing Interactive Compilers and Interpreters", P.J. Brown, - John Wiley and Sons, 1979. - - "The Theory and Practice of Compiler Writing", J.Tremblay, P.G.Sorenson, - McGraw-Hill, 1985. - - "The Java(TM) Virtual Machine Specification", T.Lindholm, F.Yellin, - Addison-Wesley, 1997. - - "Java Virtual Machine", J.Meyer, T.Downing, O'Reilly, 1997. - - */ - - - /* -TODO - features: - - handle Intersection - - cell reference is made relative (absolute now) - - shared formula (different owner, same data) - - relative internal representation (independent of owner) - - OASIS support -TODO - optimizations: - - handle initial formula marker = (and +) - - reuse constant already in the pool - - reuse references already in the pool - - expression optimization (e.g. 1+2+A1 becomes 3+A1) - */ - -namespace KSpread -{ - -class Opcode -{ -public: - - enum { Nop = 0, Load, Ref, Cell, Range, Function, Add, Sub, Neg, Mul, Div, - Pow, Concat, Not, Equal, Less, Greater }; - - unsigned type; - unsigned index; - - Opcode(): type(Nop), index(0) {}; - Opcode( unsigned t ): type(t), index(0) {}; - Opcode( unsigned t, unsigned i ): type(t), index(i) {}; -}; - -class Formula::Private -{ -public: - Formula *formula; - Cell *cell; - Sheet *sheet; - bool dirty; - bool valid; - TQString expression; - TQValueVector codes; - TQValueVector constants; -}; - -class TokenStack : public TQValueVector -{ -public: - TokenStack(); - bool isEmpty() const; - unsigned itemCount() const; - void push( const Token& token ); - Token pop(); - const Token& top(); - const Token& top( unsigned index ); -private: - void ensureSpace(); - unsigned topIndex; -}; - -} - -using namespace KSpread; - -// for null token -const Token Token::null; - -// helper function: return operator of given token text -// e.g. "*" yields Operator::Asterisk, and so on -Token::Op KSpread::matchOperator( const TQString& text ) -{ - Token::Op result = Token::InvalidOp; - - if( text.length() == 1 ) - { - TQChar p = text[0]; - switch( p.unicode() ) - { - case '+': result = Token::Plus; break; - case '-': result = Token::Minus; break; - case '*': result = Token::Asterisk; break; - case '/': result = Token::Slash; break; - case '^': result = Token::Caret; break; - case ',': result = Token::Comma; break; - case ';': result = Token::Semicolon; break; - case '(': result = Token::LeftPar; break; - case ')': result = Token::RightPar; break; - case '&': result = Token::Ampersand; break; - case '=': result = Token::Equal; break; - case '<': result = Token::Less; break; - case '>': result = Token::Greater; break; - case '%': result = Token::Percent; break; - default : result = Token::InvalidOp; break; - } - } - - if( text.length() == 2 ) - { - if( text == "<>" ) result = Token::NotEqual; - if( text == "<=" ) result = Token::LessEqual; - if( text == ">=" ) result = Token::GreaterEqual; - if( text == "==" ) result = Token::Equal; - } - - return result; -} - -// helper function: give operator precedence -// e.g. "+" is 1 while "*" is 3 -static int opPrecedence( Token::Op op ) -{ - int prec = -1; - switch( op ) - { - case Token::Percent : prec = 8; break; - case Token::Caret : prec = 7; break; - case Token::Asterisk : prec = 5; break; - case Token::Slash : prec = 6; break; - case Token::Plus : prec = 3; break; - case Token::Minus : prec = 3; break; - case Token::Ampersand : prec = 2; break; - case Token::Equal : prec = 1; break; - case Token::NotEqual : prec = 1; break; - case Token::Less : prec = 1; break; - case Token::Greater : prec = 1; break; - case Token::LessEqual : prec = 1; break; - case Token::GreaterEqual : prec = 1; break; - case Token::Semicolon : prec = 0; break; - case Token::RightPar : prec = 0; break; - case Token::LeftPar : prec = -1; break; - default: prec = -1; break; - } - return prec; -} - -// helper function -static Value tokenAsValue( const Token& token ) -{ - Value value; - if( token.isBoolean() ) value = Value( token.asBoolean() ); - else if( token.isInteger() ) value = Value( token.asInteger() ); - else if( token.isFloat() ) value = Value( token.asFloat() ); - else if( token.isString() ) value = Value( token.asString() ); - return value; -} - -/********************** - Token - **********************/ - -// creates a token -Token::Token( Type type, const TQString& text, int pos ) -{ - m_type = type; - m_text = text; - m_pos = pos; -} - -// copy constructor -Token::Token( const Token& token ) -{ - m_type = token.m_type; - m_text = token.m_text; - m_pos = token.m_pos; -} - -// assignment operator -Token& Token::operator=( const Token& token ) -{ - m_type = token.m_type; - m_text = token.m_text; - m_pos = token.m_pos; - return *this; -} - -bool Token::asBoolean() const -{ - if( !isBoolean() ) return false; - return m_text.lower() == "true"; - // FIXME check also for i18n version -} - -long Token::asInteger() const -{ - if( isInteger() ) return m_text.toLong(); - else return 0; -} - -double Token::asFloat() const -{ - if( isFloat() ) return m_text.toDouble(); - else return 0.0; -} - -TQString Token::asString() const -{ - if( isString() ) return m_text.mid( 1, m_text.length()-2 ); - else return TQString(); -} - -Token::Op Token::asOperator() const -{ - if( isOperator() ) return matchOperator( m_text ); - else return InvalidOp; -} - -TQString Token::sheetName() const -{ - if( !isCell() && !isRange() ) return TQString(); - int i = m_text.find( '!' ); - if( i < 0 ) return TQString(); - TQString sheet = m_text.left( i ); - return sheet; -} - -TQString Token::description() const -{ - TQString desc; - - switch (m_type ) - { - case Boolean: desc = "Boolean"; break; - case Integer: desc = "Integer"; break; - case Float: desc = "Float"; break; - case String: desc = "String"; break; - case Identifier: desc = "Identifier"; break; - case Cell: desc = "Cell"; break; - case Range: desc = "Range"; break; - case Operator: desc = "Operator"; break; - default: desc = "Unknown"; break; - } - - while( desc.length() < 10 ) desc.prepend( ' ' ); - desc.prepend( " " ); - desc.prepend( TQString::number( m_pos ) ); - desc.append( " : " ).append( m_text ); - - return desc; -} - - -/********************** - TokenStack - **********************/ - -TokenStack::TokenStack(): TQValueVector() -{ - topIndex = 0; - ensureSpace(); -} - -bool TokenStack::isEmpty() const -{ - return topIndex == 0; -} - -unsigned TokenStack::itemCount() const -{ - return topIndex; -} - -void TokenStack::push( const Token& token ) -{ - ensureSpace(); - at( topIndex++ ) = token; -} - -Token TokenStack::pop() -{ - return (topIndex > 0 ) ? Token( at( --topIndex ) ) : Token(); -} - -const Token& TokenStack::top() -{ - return top( 0 ); -} - -const Token& TokenStack::top( unsigned index ) -{ - if( topIndex > index ) - return at( topIndex-index-1 ); - return Token::null; -} - -void TokenStack::ensureSpace() -{ - while( topIndex >= size() ) - resize( size() + 10 ); -} - -/********************** - FormulaPrivate - **********************/ - -// helper function: return true for valid identifier character -bool KSpread::isIdentifier( TQChar ch ) -{ - return ( ch.unicode() == '_' ) || (ch.unicode() == '$' ) || ( ch.isLetter() ); -} - - - - -/********************** - Formula - **********************/ - -// Constructor - -Formula::Formula (Sheet *sheet, Cell *cell) -{ - d = new Private; - d->cell = cell; - d->sheet = sheet; - clear(); -} - -Formula::Formula() -{ - d = new Private; - d->cell = 0; - d->sheet = 0; - clear(); -} - -// Destructor - -Formula::~Formula() -{ - delete d; -} - -Cell* Formula::cell() const -{ - return d->cell; -} - -Sheet* Formula::sheet() const -{ - return d->sheet; -} - -// Sets a new expression for this formula. -// note that both the real lex and parse processes will happen later on -// when needed (i.e. "lazy parse"), for example during formula evaluation. - -void Formula::setExpression( const TQString& expr ) -{ - d->expression = expr; - d->dirty = true; - d->valid = false; -} - -// Returns the expression associated with this formula. - -TQString Formula::expression() const -{ - return d->expression; -} - -// Returns the validity of the formula. -// note: empty formula is always invalid. - -bool Formula::isValid() const -{ - if( d->dirty ) - { - TDELocale* locale = d->cell ? d->cell->locale() : 0; - if ((!locale) && d->sheet) - locale = d->sheet->doc()->locale(); - Tokens tokens = scan( d->expression, locale ); - if( tokens.valid() ) - compile( tokens ); - else - d->valid = false; - } - return d->valid; -} - -// Clears everything, also mark the formula as invalid. - -void Formula::clear() -{ - d->expression = TQString(); - d->dirty = true; - d->valid = false; - d->constants.clear(); - d->codes.clear(); -} - -// Returns list of token for the expression. -// this triggers again the lexical analysis step. it is however preferable -// (even when there's small performance penalty) because otherwise we need to -// store parsed tokens all the time which serves no good purpose. - -Tokens Formula::tokens() const -{ - TDELocale* locale = d->cell ? d->cell->locale() : 0; - if ((!locale) && d->sheet) - locale = d->sheet->doc()->locale(); - return scan( d->expression, locale ); -} - -Tokens Formula::scan( const TQString& expr, TDELocale* locale ) const -{ - // to hold the result - Tokens tokens; - - // parsing state - enum { Start, Finish, Bad, InNumber, InDecimal, InExpIndicator, InExponent, - InString, InIdentifier, InCell, InRange, InSheetOrAreaName } state; - - // use locale settings if specified - TQString thousand = locale ? locale->thousandsSeparator() : ""; - TQString decimal = locale ? locale->decimalSymbol() : "."; - - // initialize variables - state = Start; - unsigned int i = 0; - TQString ex = expr; - TQString tokenText; - int tokenStart = 0; - - // first character must be equal sign (=) - if( ex[0] != '=' ) - return tokens; - - // but the scanner should not see this equal sign - ex.remove( 0, 1 ); - - // force a terminator - ex.append( TQChar() ); - - // main loop - while( (state != Bad) && (state != Finish) && (i < ex.length()) ) - { - TQChar ch = ex[i]; - - switch( state ) - { - - case Start: - - tokenStart = i; - - // skip any whitespaces - if( ch.isSpace() ) i++; - - // check for number - else if( ch.isDigit() ) - { - state = InNumber; - } - - // a string ? - else if ( ch == '"' ) - { - tokenText.append( ex[i++] ); - state = InString; - } - - // beginning with alphanumeric ? - // could be identifier, cell, range, or function... - else if( isIdentifier( ch ) ) - { - state = InIdentifier; - } - - // aposthrophe (') marks sheet name for 3-d cell, e.g 'Sales Q3'!A4, or a named range - else if ( ch.unicode() == '\'' ) - { - i++; - state = InSheetOrAreaName; - } - - // decimal dot ? - else if ( ch == decimal ) - { - tokenText.append( ex[i++] ); - state = InDecimal; - } - - // terminator character - else if ( ch == TQChar::null ) - state = Finish; - - // look for operator match - else - { - int op; - TQString s; - - // check for two-chars operator, such as '<=', '>=', etc - s.append( ch ).append( ex[i+1] ); - op = matchOperator( s ); - - // check for one-char operator, such as '+', ';', etc - if( op == Token::InvalidOp ) - { - s = TQString( ch ); - op = matchOperator( s ); - } - - // any matched operator ? - if( op != Token::InvalidOp ) - { - int len = s.length(); - i += len; - tokens.append( Token( Token::Operator, s.left( len ), tokenStart ) ); - } - else state = Bad; - } - break; - - case InIdentifier: - - // consume as long as alpha, dollar sign, underscore, or digit - if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); - - // a '!' ? then this must be sheet name, e.g "Sheet4!" - else if( ch == '!' ) - { - tokenText.append( ex[i++] ); - state = InCell; - } - - // a '(' ? then this must be a function identifier - else if( ch == '(' ) - { - tokens.append (Token (Token::Identifier, tokenText, tokenStart)); - tokenStart = i; - tokenText = ""; - state = Start; - } - - // we're done with identifier - else - { - // check for cell reference, e.g A1, VV123, ... - TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); - int n = exp.search( tokenText ); - if( n >= 0 ) - state = InCell; - else - { - if ( isNamedArea( tokenText ) ) - tokens.append (Token (Token::Range, tokenText, tokenStart)); - else - tokens.append (Token (Token::Identifier, tokenText, tokenStart)); - tokenStart = i; - tokenText = ""; - state = Start; - } - } - break; - - case InCell: - - // consume as long as alpha, dollar sign, underscore, or digit - if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); - - // we're done with cell ref, possibly with sheet name (like "Sheet2!B2") - // note that "Sheet2!TotalSales" is also possible, in which "TotalSales" is a named area - else - { - - // check if it's a cell ref like A32, not named area - TQString cell; - for( int j = tokenText.length()-1; j>=0; j-- ) - if( tokenText[j] == '!' ) - break; - else - cell.prepend( tokenText[j] ); - TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); - if( exp.search( cell ) != 0 ) - { - - // we're done with named area - // (Tomas) huh? this doesn't seem to check for named areas ... - tokens.append( Token( Token::Range, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - } - - else - { - - // so up to now we've got something like A2 or Sheet2!F4 - // check for range reference - if( ch == ':' ) - { - tokenText.append( ex[i++] ); - state = InRange; - } - else - { - // we're done with cell reference - tokens.append( Token( Token::Cell, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - } - } - } - break; - - case InRange: - - // consume as long as alpha, dollar sign, underscore, or digit - if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); - - // we're done with range reference - else - { - tokens.append( Token( Token::Range, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - } - break; - - case InSheetOrAreaName: - - // consume until ' - if ( ch.unicode() != '\'' ) - tokenText.append( ex[i++] ); - - else - { - // eat the aposthrophe itself - ++i; - // must be followed by '!' to be sheet name - if( ex[i] == '!' ) - { - tokenText.append( ex[i++] ); - state = InCell; - } - else - { - if ( isNamedArea( tokenText ) ) - tokens.append (Token (Token::Range, tokenText, tokenStart)); - else - tokens.append (Token (Token::Identifier, tokenText, tokenStart)); - tokenStart = i; - tokenText = ""; - state = Start; - } - } - break; - - case InNumber: - - // consume as long as it's digit - if( ch.isDigit() ) tokenText.append( ex[i++] ); - - // skip thousand separator - else if( !thousand.isEmpty() && ( ch ==thousand[0] ) ) i++; - - // convert decimal separator to '.', also support '.' directly - // we always support '.' because of bug #98455 - else if(( !decimal.isEmpty() && ( ch == decimal[0] ) ) || (ch == '.')) - { - tokenText.append( '.' ); - i++; - state = InDecimal; - } - - // exponent ? - else if( ch.upper() == 'E' ) - { - tokenText.append( 'E' ); - i++; - state = InExpIndicator; - } - - // reference sheet delimiter? - else if( ch == '!' ) - { - tokenText.append( ex[i++] ); - state = InCell; - } - - // identifier? - else if( isIdentifier( ch ) ) - { - // has to be a sheet or area name then - state = InIdentifier; - } - - // we're done with integer number - else - { - tokens.append( Token( Token::Integer, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - }; - break; - - case InDecimal: - - // consume as long as it's digit - if( ch.isDigit() ) tokenText.append( ex[i++] ); - - // exponent ? - else if( ch.upper() == 'E' ) - { - tokenText.append( 'E' ); - i++; - state = InExpIndicator; - } - - // we're done with floating-point number - else - { - tokens.append( Token( Token::Float, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - }; - break; - - case InExpIndicator: - - // possible + or - right after E, e.g 1.23E+12 or 4.67E-8 - if( ( ch == '+' ) || ( ch == '-' ) ) tokenText.append( ex[i++] ); - - // consume as long as it's digit - else if( ch.isDigit() ) state = InExponent; - - // invalid thing here - else state = Bad; - - break; - - case InExponent: - - // consume as long as it's digit - if( ch.isDigit() ) tokenText.append( ex[i++] ); - - // we're done with floating-point number - else - { - tokens.append( Token( Token::Float, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - }; - break; - - case InString: - - // consume until " - if( ch != '"' ) tokenText.append( ex[i++] ); - - else - { - tokenText.append( ch ); i++; - tokens.append( Token( Token::String, tokenText, tokenStart ) ); - tokenText = ""; - state = Start; - } - break; - - case Bad: - default: - break; - }; - }; - - if( state == Bad ) - tokens.setValid( false ); - - return tokens; -} - -// will affect: dirty, valid, codes, constants -void Formula::compile( const Tokens& tokens ) const -{ - // initialize variables - d->dirty = false; - d->valid = false; - d->codes.clear(); - d->constants.clear(); - - // sanity check - if( tokens.count() == 0 ) return; - - TokenStack syntaxStack; - TQValueStack argStack; - unsigned argCount = 1; - - for( unsigned i = 0; i <= tokens.count(); i++ ) - { - // helper token: InvalidOp is end-of-formula - Token token = ( i < tokens.count() ) ? tokens[i] : Token( Token::Operator ); - Token::Type tokenType = token.type(); - - // unknown token is invalid - if( tokenType == Token::Unknown ) break; - - // for constants, push immediately to stack - // generate code to load from a constant - if ( ( tokenType == Token::Integer ) || ( tokenType == Token::Float ) || - ( tokenType == Token::String ) || ( tokenType == Token::Boolean ) ) - { - syntaxStack.push( token ); - d->constants.append( tokenAsValue( token ) ); - d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); - } - - // for cell, range, or identifier, push immediately to stack - // generate code to load from reference - if( ( tokenType == Token::Cell ) || ( tokenType == Token::Range ) || - ( tokenType == Token::Identifier ) ) - { - syntaxStack.push( token ); - d->constants.append( Value( token.text() ) ); - if (tokenType == Token::Cell) - d->codes.append( Opcode( Opcode::Cell, d->constants.count()-1 ) ); - else if (tokenType == Token::Range) - d->codes.append( Opcode( Opcode::Range, d->constants.count()-1 ) ); - else - d->codes.append( Opcode( Opcode::Ref, d->constants.count()-1 ) ); - } - - // are we entering a function ? - // if token is operator, and stack already has: id ( arg - if( tokenType == Token::Operator ) - if( syntaxStack.itemCount() >= 3 ) - { - Token arg = syntaxStack.top(); - Token par = syntaxStack.top( 1 ); - Token id = syntaxStack.top( 2 ); - if( !arg.isOperator() ) - if( par.asOperator() == Token::LeftPar ) - if( id.isIdentifier() ) - { - argStack.push( argCount ); - argCount = 1; - } - } - - // special case for percentage - if( tokenType == Token::Operator ) - if( token.asOperator() == Token::Percent ) - if( syntaxStack.itemCount() >= 1 ) - if( !syntaxStack.top().isOperator() ) - { - d->constants.append( Value( 0.01 ) ); - d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); - d->codes.append( Opcode( Opcode::Mul ) ); - } - - // for any other operator, try to apply all parsing rules - if( tokenType == Token::Operator ) - if( token.asOperator() != Token::Percent ) - { - // repeat until no more rule applies - for( ; ; ) - { - bool ruleFound = false; - - // rule for function arguments, if token is ; or ) - // id ( arg1 ; arg2 -> id ( arg - if( !ruleFound ) - if( syntaxStack.itemCount() >= 5 ) - if( ( token.asOperator() == Token::RightPar ) || - ( token.asOperator() == Token::Semicolon ) ) - { - Token arg2 = syntaxStack.top(); - Token sep = syntaxStack.top( 1 ); - Token arg1 = syntaxStack.top( 2 ); - Token par = syntaxStack.top( 3 ); - Token id = syntaxStack.top( 4 ); - if( !arg2.isOperator() ) - if( sep.asOperator() == Token::Semicolon ) - if( !arg1.isOperator() ) - if( par.asOperator() == Token::LeftPar ) - if( id.isIdentifier() ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - argCount++; - } - } - - // rule for function last argument: - // id ( arg ) -> arg - if( !ruleFound ) - if( syntaxStack.itemCount() >= 4 ) - { - Token par2 = syntaxStack.top(); - Token arg = syntaxStack.top( 1 ); - Token par1 = syntaxStack.top( 2 ); - Token id = syntaxStack.top( 3 ); - if( par2.asOperator() == Token::RightPar ) - if( !arg.isOperator() ) - if( par1.asOperator() == Token::LeftPar ) - if( id.isIdentifier() ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( arg ); - d->codes.append( Opcode( Opcode::Function, argCount ) ); - argCount = argStack.empty() ? 0 : argStack.pop(); - } - } - - // rule for function call with parentheses, but without argument - // e.g. "2*PI()" - if( !ruleFound ) - if( syntaxStack.itemCount() >= 3 ) - { - Token par2 = syntaxStack.top(); - Token par1 = syntaxStack.top( 1 ); - Token id = syntaxStack.top( 2 ); - if( par2.asOperator() == Token::RightPar ) - if( par1.asOperator() == Token::LeftPar ) - if( id.isIdentifier() ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( Token( Token::Integer ) ); - d->codes.append( Opcode( Opcode::Function, 0 ) ); - } - } - - // rule for parenthesis: ( Y ) -> Y - if( !ruleFound ) - if( syntaxStack.itemCount() >= 3 ) - { - Token right = syntaxStack.top(); - Token y = syntaxStack.top( 1 ); - Token left = syntaxStack.top( 2 ); - if( right.isOperator() ) - if( !y.isOperator() ) - if( left.isOperator() ) - if( right.asOperator() == Token::RightPar ) - if( left.asOperator() == Token::LeftPar ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( y ); - } - } - - // rule for binary operator: A (op) B -> A - // conditions: precedence of op >= precedence of token - // action: push (op) to result - // e.g. "A * B" becomes "A" if token is operator "+" - // exception: for caret (power operator), if op is another caret - // then the rule doesn't apply, e.g. "2^3^2" is evaluated as "2^(3^2)" - if( !ruleFound ) - if( syntaxStack.itemCount() >= 3 ) - { - Token b = syntaxStack.top(); - Token op = syntaxStack.top( 1 ); - Token a = syntaxStack.top( 2 ); - if( !a.isOperator() ) - if( !b.isOperator() ) - if( op.isOperator() ) - if( token.asOperator() != Token::LeftPar ) - if( token.asOperator() != Token::Caret ) - if( opPrecedence( op.asOperator() ) >= opPrecedence( token.asOperator() ) ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( b ); - switch( op.asOperator() ) - { - // simple binary operations - case Token::Plus: d->codes.append( Opcode::Add ); break; - case Token::Minus: d->codes.append( Opcode::Sub ); break; - case Token::Asterisk: d->codes.append( Opcode::Mul ); break; - case Token::Slash: d->codes.append( Opcode::Div ); break; - case Token::Caret: d->codes.append( Opcode::Pow ); break; - case Token::Ampersand: d->codes.append( Opcode::Concat ); break; - - // simple value comparisons - case Token::Equal: d->codes.append( Opcode::Equal ); break; - case Token::Less: d->codes.append( Opcode::Less ); break; - case Token::Greater: d->codes.append( Opcode::Greater ); break; - - // NotEqual is Equal, followed by Not - case Token::NotEqual: - d->codes.append( Opcode::Equal ); - d->codes.append( Opcode::Not ); - break; - - // LessOrEqual is Greater, followed by Not - case Token::LessEqual: - d->codes.append( Opcode::Greater ); - d->codes.append( Opcode::Not ); - break; - - // GreaterOrEqual is Less, followed by Not - case Token::GreaterEqual: - d->codes.append( Opcode::Less ); - d->codes.append( Opcode::Not ); - break; - default: break; - }; - } - } - - // rule for unary operator: (op1) (op2) X -> (op1) X - // conditions: op2 is unary, token is not '(' - // action: push (op2) to result - // e.g. "* - 2" becomes "*" - if( !ruleFound ) - if( token.asOperator() != Token::LeftPar ) - if( syntaxStack.itemCount() >= 3 ) - { - Token x = syntaxStack.top(); - Token op2 = syntaxStack.top( 1 ); - Token op1 = syntaxStack.top( 2 ); - if( !x.isOperator() ) - if( op1.isOperator() ) - if( op2.isOperator() ) - if( ( op2.asOperator() == Token::Plus ) || - ( op2.asOperator() == Token::Minus ) ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( x ); - if( op2.asOperator() == Token::Minus ) - d->codes.append( Opcode( Opcode::Neg ) ); - } - } - - // auxilary rule for unary operator: (op) X -> X - // conditions: op is unary, op is first in syntax stack, token is not '(' - // action: push (op) to result - if( !ruleFound ) - if( token.asOperator() != Token::LeftPar ) - if( syntaxStack.itemCount() == 2 ) - { - Token x = syntaxStack.top(); - Token op = syntaxStack.top( 1 ); - if( !x.isOperator() ) - if( op.isOperator() ) - if( ( op.asOperator() == Token::Plus ) || - ( op.asOperator() == Token::Minus ) ) - { - ruleFound = true; - syntaxStack.pop(); - syntaxStack.pop(); - syntaxStack.push( x ); - if( op.asOperator() == Token::Minus ) - d->codes.append( Opcode( Opcode::Neg ) ); - } - } - - if( !ruleFound ) break; - } - - // can't apply rules anymore, push the token - if( token.asOperator() != Token::Percent ) - syntaxStack.push( token ); - } - } - - // syntaxStack must left only one operand and end-of-formula (i.e. InvalidOp) - d->valid = false; - if( syntaxStack.itemCount() == 2 ) - if( syntaxStack.top().isOperator() ) - if( syntaxStack.top().asOperator() == Token::InvalidOp ) - if( !syntaxStack.top(1).isOperator() ) - d->valid = true; - - // bad parsing ? clean-up everything - if( !d->valid ) - { - d->constants.clear(); - d->codes.clear(); - } -} - -bool Formula::isNamedArea( const TQString& expr ) const -{ - TQString tokenText( expr ); - // check for named areas ... - if (d->sheet) { - const TQValueList areas = d->sheet->doc()->listArea(); - TQValueList::const_iterator it; - for (it = areas.begin(); it != areas.end(); ++it) { - if ((*it).ref_name.lower() == tokenText.lower()) { - // we got a named area - return true; - } - } - } - return false; -} - - -// Evaluates the formula, returns the result. - -struct stackEntry { - void reset () { row1 = col1 = row2 = col2 = -1; }; - Value val; - int row1, col1, row2, col2; -}; - -Value Formula::eval() const -{ - TQValueStack stack; - stackEntry entry; - unsigned index; - Value val1, val2; - TQString c; - TQValueVector args; - - Sheet *sheet = 0; - ValueParser* parser = 0; - ValueConverter* converter = 0; - ValueCalc* calc = 0; - - if (d->sheet) - { - sheet = d->sheet; - converter = sheet->doc()->converter(); - calc = sheet->doc()->calc(); - } - else - { - parser = new ValueParser( TDEGlobal::locale() ); - converter = new ValueConverter( parser ); - calc = new ValueCalc( converter ); - } - - Function* function; - FuncExtra fe; - fe.mycol = fe.myrow = 0; - if (d->cell) { - fe.mycol = d->cell->column(); - fe.myrow = d->cell->row(); - } - - if( d->dirty ) - { - Tokens tokens = scan( d->expression ); - d->valid = tokens.valid(); - if( tokens.valid() ) - compile( tokens ); - } - - if( !d->valid ) - return Value::errorVALUE(); - - for( unsigned pc = 0; pc < d->codes.count(); pc++ ) - { - Value ret; // for the function caller - Opcode& opcode = d->codes[pc]; - index = opcode.index; - switch( opcode.type ) - { - // no operation - case Opcode::Nop: - break; - - // load a constant, push to stack - case Opcode::Load: - entry.reset(); - entry.val = d->constants[index]; - stack.push (entry); - break; - - // unary operation - case Opcode::Neg: - entry.reset(); - entry.val = stack.pop().val; - if (!entry.val.isError()) // do nothing if we got an error - entry.val = calc->mul (entry.val, -1); - stack.push (entry); - break; - - // binary operation: take two values from stack, do the operation, - // push the result to stack - case Opcode::Add: - entry.reset(); - val2 = stack.pop().val; - val1 = stack.pop().val; - val2 = calc->add( val1, val2 ); - entry.reset(); - entry.val = val2; - stack.push (entry); - break; - - case Opcode::Sub: - val2 = stack.pop().val; - val1 = stack.pop().val; - val2 = calc->sub( val1, val2 ); - entry.reset(); - entry.val = val2; - stack.push (entry); - break; - - case Opcode::Mul: - val2 = stack.pop().val; - val1 = stack.pop().val; - val2 = calc->mul( val1, val2 ); - entry.reset(); - entry.val = val2; - stack.push (entry); - break; - - case Opcode::Div: - val2 = stack.pop().val; - val1 = stack.pop().val; - val2 = calc->div( val1, val2 ); - entry.reset(); - entry.val = val2; - stack.push (entry); - break; - - case Opcode::Pow: - val2 = stack.pop().val; - val1 = stack.pop().val; - val2 = calc->pow( val1, val2 ); - entry.reset(); - entry.val = val2; - stack.push (entry); - break; - - // string concatenation - case Opcode::Concat: - val1 = converter->asString (stack.pop().val); - val2 = converter->asString (stack.pop().val); - if (val1.isError() || val2.isError()) - val1 = Value::errorVALUE(); - else - val1.setValue( val2.asString().append( val1.asString() ) ); - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - // logical not - case Opcode::Not: - val1 = converter->asBoolean (stack.pop().val); - if( val1.isError() ) - val1 = Value::errorVALUE(); - else - val1.setValue( !val1.asBoolean() ); - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - // comparison - case Opcode::Equal: - val1 = stack.pop().val; - val2 = stack.pop().val; - if( !val1.allowComparison( val2 ) ) - val1 = Value::errorNA(); - else if( val2.compare( val1 ) == 0 ) - val1 = Value (true); - else - val1 = Value (false); - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - // less than - case Opcode::Less: - val1 = stack.pop().val; - val2 = stack.pop().val; - if( !val1.allowComparison( val2 ) ) - val1 = Value::errorNA(); - else if( val2.compare( val1 ) < 0 ) - val1 = Value (true); - else - val1 = Value (false); - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - // greater than - case Opcode::Greater: - val1 = stack.pop().val; - val2 = stack.pop().val; - if( !val1.allowComparison( val2 ) ) - val1 = Value::errorNA(); - else if( val2.compare( val1 ) > 0 ) - val1 = Value (true); - else - val1 = Value (false); - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - - case Opcode::Cell: - c = d->constants[index].asString(); - val1 = Value::empty(); - entry.reset(); - if (sheet) - { - Point cell (c, sheet->workbook(), sheet); - if (cell.isValid()) - { - val1 = cell.sheet()->value (cell.column(), cell.row()); - // store the reference, so we can use it within functions - entry.col1 = entry.col2 = cell.column(); - entry.row1 = entry.row2 = cell.row(); - } - } - entry.val = val1; - stack.push (entry); - break; - - case Opcode::Range: - c = d->constants[index].asString(); - val1 = Value::empty(); - entry.reset(); - if (sheet) - { - Range range (c, sheet->workbook(), sheet); - if (range.isValid()) - { - val1 = range.sheet()->valueRange (range.startCol(), range.startRow(), - range.endCol(), range.endRow()); - // store the reference, so we can use it within functions - entry.col1 = range.startCol(); - entry.row1 = range.startRow(); - entry.col2 = range.endCol(); - entry.row2 = range.endRow(); - } - } - entry.val = val1; - stack.push (entry); - break; - - case Opcode::Ref: - val1 = d->constants[index]; - entry.reset(); - entry.val = val1; - stack.push (entry); - break; - - // calling function - case Opcode::Function: - if( stack.count() < index ) - // (Tomas) umm, how could that be ? I mean, the index value - // is computed from the stack *confused* - return Value::errorVALUE(); // not enough arguments - - args.clear(); - fe.ranges.clear (); - fe.ranges.reserve (index); - fe.sheet = sheet; - for( ; index; index-- ) - { - stackEntry e = stack.pop(); - args.insert (args.begin(), e.val); - // TODO: create and fill a FunctionExtra object, if needed - // problem: we don't know if we need it, as we don't have the - // fuction name yet ... - fe.ranges[index - 1].col1 = e.col1; - fe.ranges[index - 1].row1 = e.row1; - fe.ranges[index - 1].col2 = e.col2; - fe.ranges[index - 1].row2 = e.row2; - } - - // function name as string value - val1 = converter->asString (stack.pop().val); - if( val1.isError() ) - return Value::errorVALUE(); - function = FunctionRepository::self()->function ( val1.asString() ); - if( !function ) - return Value::errorVALUE(); // no such function - - ret = function->exec (args, calc, &fe); - entry.reset(); - entry.val = ret; - stack.push (entry); - - break; - - default: - break; - } - } - - if (!d->sheet) { - delete parser; - delete converter; - delete calc; - } - - // more than one value in stack ? unsuccesful execution... - if( stack.count() != 1 ) - return Value::errorVALUE(); - - return stack.pop().val; - -} - -// Debugging aid - -TQString Formula::dump() const -{ - TQString result; - - if( d->dirty ) - { - Tokens tokens = scan( d->expression ); - compile( tokens ); - } - - result = TQString("Expression: [%1]\n").arg( d->expression ); -#if 0 - Value value = eval(); - result.append( TQString("Result: %1\n").arg( - converter->asString(value).asString() ) ); -#endif - - result.append(" Constants:\n"); - for( unsigned c = 0; c < d->constants.count(); c++ ) - { - TQString vtext; - Value val = d->constants[c]; - if( val.isString() ) vtext = TQString("[%1]").arg( val.asString() ); - else if( val.isNumber() ) vtext = TQString("%1").arg( val.asFloat() ); - else if( val.isBoolean() ) vtext = TQString("%1").arg( val.asBoolean() ? "True":"False"); - else if( val.isError() ) vtext = "error"; - else vtext = "???"; - result += TQString(" #%1 = %2\n").arg(c).arg( vtext ); - } - - result.append("\n"); - result.append(" Code:\n"); - for( unsigned i = 0; i < d->codes.count(); i++ ) - { - TQString ctext; - switch( d->codes[i].type ) - { - case Opcode::Load: ctext = TQString("Load #%1").arg( d->codes[i].index ); break; - case Opcode::Ref: ctext = TQString("Ref #%1").arg( d->codes[i].index ); break; - case Opcode::Function: ctext = TQString("Function (%1)").arg( d->codes[i].index ); break; - case Opcode::Add: ctext = "Add"; break; - case Opcode::Sub: ctext = "Sub"; break; - case Opcode::Mul: ctext = "Mul"; break; - case Opcode::Div: ctext = "Div"; break; - case Opcode::Neg: ctext = "Neg"; break; - case Opcode::Concat: ctext = "Concat"; break; - case Opcode::Pow: ctext = "Pow"; break; - case Opcode::Equal: ctext = "Equal"; break; - case Opcode::Not: ctext = "Not"; break; - case Opcode::Less: ctext = "Less"; break; - case Opcode::Greater: ctext = "Greater"; break; - default: ctext = "Unknown"; break; - } - result.append( " " ).append( ctext ).append("\n"); - } - - return result; -} - -TQTextStream& operator<<( TQTextStream& ts, Formula formula ) -{ - ts << formula.dump(); - return ts; -} diff --git a/kspread/formula.cpp b/kspread/formula.cpp new file mode 100644 index 00000000..3522f06b --- /dev/null +++ b/kspread/formula.cpp @@ -0,0 +1,1535 @@ +/* This file is part of the KDE project + Copyright (C) 2003,2004 Ariya Hidayat + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "formula.h" + +#include "kspread_cell.h" +#include "kspread_sheet.h" +#include "kspread_doc.h" +#include "kspread_util.h" +#include "kspread_value.h" + +#include "valuecalc.h" +#include "valueconverter.h" +#include "valueparser.h" + +#include "functions.h" + +#include + +#include +#include +#include +#include + +#include + +/* + To understand how this formula engine works, please refer to the documentation + in file DESIGN.html. + + Useful references: + - "Principles of Compiler Design", A.V.Aho, J.D.Ullman, Addison Wesley, 1978 + - "Writing Interactive Compilers and Interpreters", P.J. Brown, + John Wiley and Sons, 1979. + - "The Theory and Practice of Compiler Writing", J.Tremblay, P.G.Sorenson, + McGraw-Hill, 1985. + - "The Java(TM) Virtual Machine Specification", T.Lindholm, F.Yellin, + Addison-Wesley, 1997. + - "Java Virtual Machine", J.Meyer, T.Downing, O'Reilly, 1997. + + */ + + + /* +TODO - features: + - handle Intersection + - cell reference is made relative (absolute now) + - shared formula (different owner, same data) + - relative internal representation (independent of owner) + - OASIS support +TODO - optimizations: + - handle initial formula marker = (and +) + - reuse constant already in the pool + - reuse references already in the pool + - expression optimization (e.g. 1+2+A1 becomes 3+A1) + */ + +namespace KSpread +{ + +class Opcode +{ +public: + + enum { Nop = 0, Load, Ref, Cell, Range, Function, Add, Sub, Neg, Mul, Div, + Pow, Concat, Not, Equal, Less, Greater }; + + unsigned type; + unsigned index; + + Opcode(): type(Nop), index(0) {}; + Opcode( unsigned t ): type(t), index(0) {}; + Opcode( unsigned t, unsigned i ): type(t), index(i) {}; +}; + +class Formula::Private +{ +public: + Formula *formula; + Cell *cell; + Sheet *sheet; + bool dirty; + bool valid; + TQString expression; + TQValueVector codes; + TQValueVector constants; +}; + +class TokenStack : public TQValueVector +{ +public: + TokenStack(); + bool isEmpty() const; + unsigned itemCount() const; + void push( const Token& token ); + Token pop(); + const Token& top(); + const Token& top( unsigned index ); +private: + void ensureSpace(); + unsigned topIndex; +}; + +} + +using namespace KSpread; + +// for null token +const Token Token::null; + +// helper function: return operator of given token text +// e.g. "*" yields Operator::Asterisk, and so on +Token::Op KSpread::matchOperator( const TQString& text ) +{ + Token::Op result = Token::InvalidOp; + + if( text.length() == 1 ) + { + TQChar p = text[0]; + switch( p.unicode() ) + { + case '+': result = Token::Plus; break; + case '-': result = Token::Minus; break; + case '*': result = Token::Asterisk; break; + case '/': result = Token::Slash; break; + case '^': result = Token::Caret; break; + case ',': result = Token::Comma; break; + case ';': result = Token::Semicolon; break; + case '(': result = Token::LeftPar; break; + case ')': result = Token::RightPar; break; + case '&': result = Token::Ampersand; break; + case '=': result = Token::Equal; break; + case '<': result = Token::Less; break; + case '>': result = Token::Greater; break; + case '%': result = Token::Percent; break; + default : result = Token::InvalidOp; break; + } + } + + if( text.length() == 2 ) + { + if( text == "<>" ) result = Token::NotEqual; + if( text == "<=" ) result = Token::LessEqual; + if( text == ">=" ) result = Token::GreaterEqual; + if( text == "==" ) result = Token::Equal; + } + + return result; +} + +// helper function: give operator precedence +// e.g. "+" is 1 while "*" is 3 +static int opPrecedence( Token::Op op ) +{ + int prec = -1; + switch( op ) + { + case Token::Percent : prec = 8; break; + case Token::Caret : prec = 7; break; + case Token::Asterisk : prec = 5; break; + case Token::Slash : prec = 6; break; + case Token::Plus : prec = 3; break; + case Token::Minus : prec = 3; break; + case Token::Ampersand : prec = 2; break; + case Token::Equal : prec = 1; break; + case Token::NotEqual : prec = 1; break; + case Token::Less : prec = 1; break; + case Token::Greater : prec = 1; break; + case Token::LessEqual : prec = 1; break; + case Token::GreaterEqual : prec = 1; break; + case Token::Semicolon : prec = 0; break; + case Token::RightPar : prec = 0; break; + case Token::LeftPar : prec = -1; break; + default: prec = -1; break; + } + return prec; +} + +// helper function +static Value tokenAsValue( const Token& token ) +{ + Value value; + if( token.isBoolean() ) value = Value( token.asBoolean() ); + else if( token.isInteger() ) value = Value( token.asInteger() ); + else if( token.isFloat() ) value = Value( token.asFloat() ); + else if( token.isString() ) value = Value( token.asString() ); + return value; +} + +/********************** + Token + **********************/ + +// creates a token +Token::Token( Type type, const TQString& text, int pos ) +{ + m_type = type; + m_text = text; + m_pos = pos; +} + +// copy constructor +Token::Token( const Token& token ) +{ + m_type = token.m_type; + m_text = token.m_text; + m_pos = token.m_pos; +} + +// assignment operator +Token& Token::operator=( const Token& token ) +{ + m_type = token.m_type; + m_text = token.m_text; + m_pos = token.m_pos; + return *this; +} + +bool Token::asBoolean() const +{ + if( !isBoolean() ) return false; + return m_text.lower() == "true"; + // FIXME check also for i18n version +} + +long Token::asInteger() const +{ + if( isInteger() ) return m_text.toLong(); + else return 0; +} + +double Token::asFloat() const +{ + if( isFloat() ) return m_text.toDouble(); + else return 0.0; +} + +TQString Token::asString() const +{ + if( isString() ) return m_text.mid( 1, m_text.length()-2 ); + else return TQString(); +} + +Token::Op Token::asOperator() const +{ + if( isOperator() ) return matchOperator( m_text ); + else return InvalidOp; +} + +TQString Token::sheetName() const +{ + if( !isCell() && !isRange() ) return TQString(); + int i = m_text.find( '!' ); + if( i < 0 ) return TQString(); + TQString sheet = m_text.left( i ); + return sheet; +} + +TQString Token::description() const +{ + TQString desc; + + switch (m_type ) + { + case Boolean: desc = "Boolean"; break; + case Integer: desc = "Integer"; break; + case Float: desc = "Float"; break; + case String: desc = "String"; break; + case Identifier: desc = "Identifier"; break; + case Cell: desc = "Cell"; break; + case Range: desc = "Range"; break; + case Operator: desc = "Operator"; break; + default: desc = "Unknown"; break; + } + + while( desc.length() < 10 ) desc.prepend( ' ' ); + desc.prepend( " " ); + desc.prepend( TQString::number( m_pos ) ); + desc.append( " : " ).append( m_text ); + + return desc; +} + + +/********************** + TokenStack + **********************/ + +TokenStack::TokenStack(): TQValueVector() +{ + topIndex = 0; + ensureSpace(); +} + +bool TokenStack::isEmpty() const +{ + return topIndex == 0; +} + +unsigned TokenStack::itemCount() const +{ + return topIndex; +} + +void TokenStack::push( const Token& token ) +{ + ensureSpace(); + at( topIndex++ ) = token; +} + +Token TokenStack::pop() +{ + return (topIndex > 0 ) ? Token( at( --topIndex ) ) : Token(); +} + +const Token& TokenStack::top() +{ + return top( 0 ); +} + +const Token& TokenStack::top( unsigned index ) +{ + if( topIndex > index ) + return at( topIndex-index-1 ); + return Token::null; +} + +void TokenStack::ensureSpace() +{ + while( topIndex >= size() ) + resize( size() + 10 ); +} + +/********************** + FormulaPrivate + **********************/ + +// helper function: return true for valid identifier character +bool KSpread::isIdentifier( TQChar ch ) +{ + return ( ch.unicode() == '_' ) || (ch.unicode() == '$' ) || ( ch.isLetter() ); +} + + + + +/********************** + Formula + **********************/ + +// Constructor + +Formula::Formula (Sheet *sheet, Cell *cell) +{ + d = new Private; + d->cell = cell; + d->sheet = sheet; + clear(); +} + +Formula::Formula() +{ + d = new Private; + d->cell = 0; + d->sheet = 0; + clear(); +} + +// Destructor + +Formula::~Formula() +{ + delete d; +} + +Cell* Formula::cell() const +{ + return d->cell; +} + +Sheet* Formula::sheet() const +{ + return d->sheet; +} + +// Sets a new expression for this formula. +// note that both the real lex and parse processes will happen later on +// when needed (i.e. "lazy parse"), for example during formula evaluation. + +void Formula::setExpression( const TQString& expr ) +{ + d->expression = expr; + d->dirty = true; + d->valid = false; +} + +// Returns the expression associated with this formula. + +TQString Formula::expression() const +{ + return d->expression; +} + +// Returns the validity of the formula. +// note: empty formula is always invalid. + +bool Formula::isValid() const +{ + if( d->dirty ) + { + TDELocale* locale = d->cell ? d->cell->locale() : 0; + if ((!locale) && d->sheet) + locale = d->sheet->doc()->locale(); + Tokens tokens = scan( d->expression, locale ); + if( tokens.valid() ) + compile( tokens ); + else + d->valid = false; + } + return d->valid; +} + +// Clears everything, also mark the formula as invalid. + +void Formula::clear() +{ + d->expression = TQString(); + d->dirty = true; + d->valid = false; + d->constants.clear(); + d->codes.clear(); +} + +// Returns list of token for the expression. +// this triggers again the lexical analysis step. it is however preferable +// (even when there's small performance penalty) because otherwise we need to +// store parsed tokens all the time which serves no good purpose. + +Tokens Formula::tokens() const +{ + TDELocale* locale = d->cell ? d->cell->locale() : 0; + if ((!locale) && d->sheet) + locale = d->sheet->doc()->locale(); + return scan( d->expression, locale ); +} + +Tokens Formula::scan( const TQString& expr, TDELocale* locale ) const +{ + // to hold the result + Tokens tokens; + + // parsing state + enum { Start, Finish, Bad, InNumber, InDecimal, InExpIndicator, InExponent, + InString, InIdentifier, InCell, InRange, InSheetOrAreaName } state; + + // use locale settings if specified + TQString thousand = locale ? locale->thousandsSeparator() : ""; + TQString decimal = locale ? locale->decimalSymbol() : "."; + + // initialize variables + state = Start; + unsigned int i = 0; + TQString ex = expr; + TQString tokenText; + int tokenStart = 0; + + // first character must be equal sign (=) + if( ex[0] != '=' ) + return tokens; + + // but the scanner should not see this equal sign + ex.remove( 0, 1 ); + + // force a terminator + ex.append( TQChar() ); + + // main loop + while( (state != Bad) && (state != Finish) && (i < ex.length()) ) + { + TQChar ch = ex[i]; + + switch( state ) + { + + case Start: + + tokenStart = i; + + // skip any whitespaces + if( ch.isSpace() ) i++; + + // check for number + else if( ch.isDigit() ) + { + state = InNumber; + } + + // a string ? + else if ( ch == '"' ) + { + tokenText.append( ex[i++] ); + state = InString; + } + + // beginning with alphanumeric ? + // could be identifier, cell, range, or function... + else if( isIdentifier( ch ) ) + { + state = InIdentifier; + } + + // aposthrophe (') marks sheet name for 3-d cell, e.g 'Sales Q3'!A4, or a named range + else if ( ch.unicode() == '\'' ) + { + i++; + state = InSheetOrAreaName; + } + + // decimal dot ? + else if ( ch == decimal ) + { + tokenText.append( ex[i++] ); + state = InDecimal; + } + + // terminator character + else if ( ch == TQChar::null ) + state = Finish; + + // look for operator match + else + { + int op; + TQString s; + + // check for two-chars operator, such as '<=', '>=', etc + s.append( ch ).append( ex[i+1] ); + op = matchOperator( s ); + + // check for one-char operator, such as '+', ';', etc + if( op == Token::InvalidOp ) + { + s = TQString( ch ); + op = matchOperator( s ); + } + + // any matched operator ? + if( op != Token::InvalidOp ) + { + int len = s.length(); + i += len; + tokens.append( Token( Token::Operator, s.left( len ), tokenStart ) ); + } + else state = Bad; + } + break; + + case InIdentifier: + + // consume as long as alpha, dollar sign, underscore, or digit + if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); + + // a '!' ? then this must be sheet name, e.g "Sheet4!" + else if( ch == '!' ) + { + tokenText.append( ex[i++] ); + state = InCell; + } + + // a '(' ? then this must be a function identifier + else if( ch == '(' ) + { + tokens.append (Token (Token::Identifier, tokenText, tokenStart)); + tokenStart = i; + tokenText = ""; + state = Start; + } + + // we're done with identifier + else + { + // check for cell reference, e.g A1, VV123, ... + TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); + int n = exp.search( tokenText ); + if( n >= 0 ) + state = InCell; + else + { + if ( isNamedArea( tokenText ) ) + tokens.append (Token (Token::Range, tokenText, tokenStart)); + else + tokens.append (Token (Token::Identifier, tokenText, tokenStart)); + tokenStart = i; + tokenText = ""; + state = Start; + } + } + break; + + case InCell: + + // consume as long as alpha, dollar sign, underscore, or digit + if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); + + // we're done with cell ref, possibly with sheet name (like "Sheet2!B2") + // note that "Sheet2!TotalSales" is also possible, in which "TotalSales" is a named area + else + { + + // check if it's a cell ref like A32, not named area + TQString cell; + for( int j = tokenText.length()-1; j>=0; j-- ) + if( tokenText[j] == '!' ) + break; + else + cell.prepend( tokenText[j] ); + TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); + if( exp.search( cell ) != 0 ) + { + + // we're done with named area + // (Tomas) huh? this doesn't seem to check for named areas ... + tokens.append( Token( Token::Range, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + } + + else + { + + // so up to now we've got something like A2 or Sheet2!F4 + // check for range reference + if( ch == ':' ) + { + tokenText.append( ex[i++] ); + state = InRange; + } + else + { + // we're done with cell reference + tokens.append( Token( Token::Cell, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + } + } + } + break; + + case InRange: + + // consume as long as alpha, dollar sign, underscore, or digit + if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex[i++] ); + + // we're done with range reference + else + { + tokens.append( Token( Token::Range, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + } + break; + + case InSheetOrAreaName: + + // consume until ' + if ( ch.unicode() != '\'' ) + tokenText.append( ex[i++] ); + + else + { + // eat the aposthrophe itself + ++i; + // must be followed by '!' to be sheet name + if( ex[i] == '!' ) + { + tokenText.append( ex[i++] ); + state = InCell; + } + else + { + if ( isNamedArea( tokenText ) ) + tokens.append (Token (Token::Range, tokenText, tokenStart)); + else + tokens.append (Token (Token::Identifier, tokenText, tokenStart)); + tokenStart = i; + tokenText = ""; + state = Start; + } + } + break; + + case InNumber: + + // consume as long as it's digit + if( ch.isDigit() ) tokenText.append( ex[i++] ); + + // skip thousand separator + else if( !thousand.isEmpty() && ( ch ==thousand[0] ) ) i++; + + // convert decimal separator to '.', also support '.' directly + // we always support '.' because of bug #98455 + else if(( !decimal.isEmpty() && ( ch == decimal[0] ) ) || (ch == '.')) + { + tokenText.append( '.' ); + i++; + state = InDecimal; + } + + // exponent ? + else if( ch.upper() == 'E' ) + { + tokenText.append( 'E' ); + i++; + state = InExpIndicator; + } + + // reference sheet delimiter? + else if( ch == '!' ) + { + tokenText.append( ex[i++] ); + state = InCell; + } + + // identifier? + else if( isIdentifier( ch ) ) + { + // has to be a sheet or area name then + state = InIdentifier; + } + + // we're done with integer number + else + { + tokens.append( Token( Token::Integer, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + }; + break; + + case InDecimal: + + // consume as long as it's digit + if( ch.isDigit() ) tokenText.append( ex[i++] ); + + // exponent ? + else if( ch.upper() == 'E' ) + { + tokenText.append( 'E' ); + i++; + state = InExpIndicator; + } + + // we're done with floating-point number + else + { + tokens.append( Token( Token::Float, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + }; + break; + + case InExpIndicator: + + // possible + or - right after E, e.g 1.23E+12 or 4.67E-8 + if( ( ch == '+' ) || ( ch == '-' ) ) tokenText.append( ex[i++] ); + + // consume as long as it's digit + else if( ch.isDigit() ) state = InExponent; + + // invalid thing here + else state = Bad; + + break; + + case InExponent: + + // consume as long as it's digit + if( ch.isDigit() ) tokenText.append( ex[i++] ); + + // we're done with floating-point number + else + { + tokens.append( Token( Token::Float, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + }; + break; + + case InString: + + // consume until " + if( ch != '"' ) tokenText.append( ex[i++] ); + + else + { + tokenText.append( ch ); i++; + tokens.append( Token( Token::String, tokenText, tokenStart ) ); + tokenText = ""; + state = Start; + } + break; + + case Bad: + default: + break; + }; + }; + + if( state == Bad ) + tokens.setValid( false ); + + return tokens; +} + +// will affect: dirty, valid, codes, constants +void Formula::compile( const Tokens& tokens ) const +{ + // initialize variables + d->dirty = false; + d->valid = false; + d->codes.clear(); + d->constants.clear(); + + // sanity check + if( tokens.count() == 0 ) return; + + TokenStack syntaxStack; + TQValueStack argStack; + unsigned argCount = 1; + + for( unsigned i = 0; i <= tokens.count(); i++ ) + { + // helper token: InvalidOp is end-of-formula + Token token = ( i < tokens.count() ) ? tokens[i] : Token( Token::Operator ); + Token::Type tokenType = token.type(); + + // unknown token is invalid + if( tokenType == Token::Unknown ) break; + + // for constants, push immediately to stack + // generate code to load from a constant + if ( ( tokenType == Token::Integer ) || ( tokenType == Token::Float ) || + ( tokenType == Token::String ) || ( tokenType == Token::Boolean ) ) + { + syntaxStack.push( token ); + d->constants.append( tokenAsValue( token ) ); + d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); + } + + // for cell, range, or identifier, push immediately to stack + // generate code to load from reference + if( ( tokenType == Token::Cell ) || ( tokenType == Token::Range ) || + ( tokenType == Token::Identifier ) ) + { + syntaxStack.push( token ); + d->constants.append( Value( token.text() ) ); + if (tokenType == Token::Cell) + d->codes.append( Opcode( Opcode::Cell, d->constants.count()-1 ) ); + else if (tokenType == Token::Range) + d->codes.append( Opcode( Opcode::Range, d->constants.count()-1 ) ); + else + d->codes.append( Opcode( Opcode::Ref, d->constants.count()-1 ) ); + } + + // are we entering a function ? + // if token is operator, and stack already has: id ( arg + if( tokenType == Token::Operator ) + if( syntaxStack.itemCount() >= 3 ) + { + Token arg = syntaxStack.top(); + Token par = syntaxStack.top( 1 ); + Token id = syntaxStack.top( 2 ); + if( !arg.isOperator() ) + if( par.asOperator() == Token::LeftPar ) + if( id.isIdentifier() ) + { + argStack.push( argCount ); + argCount = 1; + } + } + + // special case for percentage + if( tokenType == Token::Operator ) + if( token.asOperator() == Token::Percent ) + if( syntaxStack.itemCount() >= 1 ) + if( !syntaxStack.top().isOperator() ) + { + d->constants.append( Value( 0.01 ) ); + d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); + d->codes.append( Opcode( Opcode::Mul ) ); + } + + // for any other operator, try to apply all parsing rules + if( tokenType == Token::Operator ) + if( token.asOperator() != Token::Percent ) + { + // repeat until no more rule applies + for( ; ; ) + { + bool ruleFound = false; + + // rule for function arguments, if token is ; or ) + // id ( arg1 ; arg2 -> id ( arg + if( !ruleFound ) + if( syntaxStack.itemCount() >= 5 ) + if( ( token.asOperator() == Token::RightPar ) || + ( token.asOperator() == Token::Semicolon ) ) + { + Token arg2 = syntaxStack.top(); + Token sep = syntaxStack.top( 1 ); + Token arg1 = syntaxStack.top( 2 ); + Token par = syntaxStack.top( 3 ); + Token id = syntaxStack.top( 4 ); + if( !arg2.isOperator() ) + if( sep.asOperator() == Token::Semicolon ) + if( !arg1.isOperator() ) + if( par.asOperator() == Token::LeftPar ) + if( id.isIdentifier() ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + argCount++; + } + } + + // rule for function last argument: + // id ( arg ) -> arg + if( !ruleFound ) + if( syntaxStack.itemCount() >= 4 ) + { + Token par2 = syntaxStack.top(); + Token arg = syntaxStack.top( 1 ); + Token par1 = syntaxStack.top( 2 ); + Token id = syntaxStack.top( 3 ); + if( par2.asOperator() == Token::RightPar ) + if( !arg.isOperator() ) + if( par1.asOperator() == Token::LeftPar ) + if( id.isIdentifier() ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( arg ); + d->codes.append( Opcode( Opcode::Function, argCount ) ); + argCount = argStack.empty() ? 0 : argStack.pop(); + } + } + + // rule for function call with parentheses, but without argument + // e.g. "2*PI()" + if( !ruleFound ) + if( syntaxStack.itemCount() >= 3 ) + { + Token par2 = syntaxStack.top(); + Token par1 = syntaxStack.top( 1 ); + Token id = syntaxStack.top( 2 ); + if( par2.asOperator() == Token::RightPar ) + if( par1.asOperator() == Token::LeftPar ) + if( id.isIdentifier() ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( Token( Token::Integer ) ); + d->codes.append( Opcode( Opcode::Function, 0 ) ); + } + } + + // rule for parenthesis: ( Y ) -> Y + if( !ruleFound ) + if( syntaxStack.itemCount() >= 3 ) + { + Token right = syntaxStack.top(); + Token y = syntaxStack.top( 1 ); + Token left = syntaxStack.top( 2 ); + if( right.isOperator() ) + if( !y.isOperator() ) + if( left.isOperator() ) + if( right.asOperator() == Token::RightPar ) + if( left.asOperator() == Token::LeftPar ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( y ); + } + } + + // rule for binary operator: A (op) B -> A + // conditions: precedence of op >= precedence of token + // action: push (op) to result + // e.g. "A * B" becomes "A" if token is operator "+" + // exception: for caret (power operator), if op is another caret + // then the rule doesn't apply, e.g. "2^3^2" is evaluated as "2^(3^2)" + if( !ruleFound ) + if( syntaxStack.itemCount() >= 3 ) + { + Token b = syntaxStack.top(); + Token op = syntaxStack.top( 1 ); + Token a = syntaxStack.top( 2 ); + if( !a.isOperator() ) + if( !b.isOperator() ) + if( op.isOperator() ) + if( token.asOperator() != Token::LeftPar ) + if( token.asOperator() != Token::Caret ) + if( opPrecedence( op.asOperator() ) >= opPrecedence( token.asOperator() ) ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( b ); + switch( op.asOperator() ) + { + // simple binary operations + case Token::Plus: d->codes.append( Opcode::Add ); break; + case Token::Minus: d->codes.append( Opcode::Sub ); break; + case Token::Asterisk: d->codes.append( Opcode::Mul ); break; + case Token::Slash: d->codes.append( Opcode::Div ); break; + case Token::Caret: d->codes.append( Opcode::Pow ); break; + case Token::Ampersand: d->codes.append( Opcode::Concat ); break; + + // simple value comparisons + case Token::Equal: d->codes.append( Opcode::Equal ); break; + case Token::Less: d->codes.append( Opcode::Less ); break; + case Token::Greater: d->codes.append( Opcode::Greater ); break; + + // NotEqual is Equal, followed by Not + case Token::NotEqual: + d->codes.append( Opcode::Equal ); + d->codes.append( Opcode::Not ); + break; + + // LessOrEqual is Greater, followed by Not + case Token::LessEqual: + d->codes.append( Opcode::Greater ); + d->codes.append( Opcode::Not ); + break; + + // GreaterOrEqual is Less, followed by Not + case Token::GreaterEqual: + d->codes.append( Opcode::Less ); + d->codes.append( Opcode::Not ); + break; + default: break; + }; + } + } + + // rule for unary operator: (op1) (op2) X -> (op1) X + // conditions: op2 is unary, token is not '(' + // action: push (op2) to result + // e.g. "* - 2" becomes "*" + if( !ruleFound ) + if( token.asOperator() != Token::LeftPar ) + if( syntaxStack.itemCount() >= 3 ) + { + Token x = syntaxStack.top(); + Token op2 = syntaxStack.top( 1 ); + Token op1 = syntaxStack.top( 2 ); + if( !x.isOperator() ) + if( op1.isOperator() ) + if( op2.isOperator() ) + if( ( op2.asOperator() == Token::Plus ) || + ( op2.asOperator() == Token::Minus ) ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( x ); + if( op2.asOperator() == Token::Minus ) + d->codes.append( Opcode( Opcode::Neg ) ); + } + } + + // auxilary rule for unary operator: (op) X -> X + // conditions: op is unary, op is first in syntax stack, token is not '(' + // action: push (op) to result + if( !ruleFound ) + if( token.asOperator() != Token::LeftPar ) + if( syntaxStack.itemCount() == 2 ) + { + Token x = syntaxStack.top(); + Token op = syntaxStack.top( 1 ); + if( !x.isOperator() ) + if( op.isOperator() ) + if( ( op.asOperator() == Token::Plus ) || + ( op.asOperator() == Token::Minus ) ) + { + ruleFound = true; + syntaxStack.pop(); + syntaxStack.pop(); + syntaxStack.push( x ); + if( op.asOperator() == Token::Minus ) + d->codes.append( Opcode( Opcode::Neg ) ); + } + } + + if( !ruleFound ) break; + } + + // can't apply rules anymore, push the token + if( token.asOperator() != Token::Percent ) + syntaxStack.push( token ); + } + } + + // syntaxStack must left only one operand and end-of-formula (i.e. InvalidOp) + d->valid = false; + if( syntaxStack.itemCount() == 2 ) + if( syntaxStack.top().isOperator() ) + if( syntaxStack.top().asOperator() == Token::InvalidOp ) + if( !syntaxStack.top(1).isOperator() ) + d->valid = true; + + // bad parsing ? clean-up everything + if( !d->valid ) + { + d->constants.clear(); + d->codes.clear(); + } +} + +bool Formula::isNamedArea( const TQString& expr ) const +{ + TQString tokenText( expr ); + // check for named areas ... + if (d->sheet) { + const TQValueList areas = d->sheet->doc()->listArea(); + TQValueList::const_iterator it; + for (it = areas.begin(); it != areas.end(); ++it) { + if ((*it).ref_name.lower() == tokenText.lower()) { + // we got a named area + return true; + } + } + } + return false; +} + + +// Evaluates the formula, returns the result. + +struct stackEntry { + void reset () { row1 = col1 = row2 = col2 = -1; }; + Value val; + int row1, col1, row2, col2; +}; + +Value Formula::eval() const +{ + TQValueStack stack; + stackEntry entry; + unsigned index; + Value val1, val2; + TQString c; + TQValueVector args; + + Sheet *sheet = 0; + ValueParser* parser = 0; + ValueConverter* converter = 0; + ValueCalc* calc = 0; + + if (d->sheet) + { + sheet = d->sheet; + converter = sheet->doc()->converter(); + calc = sheet->doc()->calc(); + } + else + { + parser = new ValueParser( TDEGlobal::locale() ); + converter = new ValueConverter( parser ); + calc = new ValueCalc( converter ); + } + + Function* function; + FuncExtra fe; + fe.mycol = fe.myrow = 0; + if (d->cell) { + fe.mycol = d->cell->column(); + fe.myrow = d->cell->row(); + } + + if( d->dirty ) + { + Tokens tokens = scan( d->expression ); + d->valid = tokens.valid(); + if( tokens.valid() ) + compile( tokens ); + } + + if( !d->valid ) + return Value::errorVALUE(); + + for( unsigned pc = 0; pc < d->codes.count(); pc++ ) + { + Value ret; // for the function caller + Opcode& opcode = d->codes[pc]; + index = opcode.index; + switch( opcode.type ) + { + // no operation + case Opcode::Nop: + break; + + // load a constant, push to stack + case Opcode::Load: + entry.reset(); + entry.val = d->constants[index]; + stack.push (entry); + break; + + // unary operation + case Opcode::Neg: + entry.reset(); + entry.val = stack.pop().val; + if (!entry.val.isError()) // do nothing if we got an error + entry.val = calc->mul (entry.val, -1); + stack.push (entry); + break; + + // binary operation: take two values from stack, do the operation, + // push the result to stack + case Opcode::Add: + entry.reset(); + val2 = stack.pop().val; + val1 = stack.pop().val; + val2 = calc->add( val1, val2 ); + entry.reset(); + entry.val = val2; + stack.push (entry); + break; + + case Opcode::Sub: + val2 = stack.pop().val; + val1 = stack.pop().val; + val2 = calc->sub( val1, val2 ); + entry.reset(); + entry.val = val2; + stack.push (entry); + break; + + case Opcode::Mul: + val2 = stack.pop().val; + val1 = stack.pop().val; + val2 = calc->mul( val1, val2 ); + entry.reset(); + entry.val = val2; + stack.push (entry); + break; + + case Opcode::Div: + val2 = stack.pop().val; + val1 = stack.pop().val; + val2 = calc->div( val1, val2 ); + entry.reset(); + entry.val = val2; + stack.push (entry); + break; + + case Opcode::Pow: + val2 = stack.pop().val; + val1 = stack.pop().val; + val2 = calc->pow( val1, val2 ); + entry.reset(); + entry.val = val2; + stack.push (entry); + break; + + // string concatenation + case Opcode::Concat: + val1 = converter->asString (stack.pop().val); + val2 = converter->asString (stack.pop().val); + if (val1.isError() || val2.isError()) + val1 = Value::errorVALUE(); + else + val1.setValue( val2.asString().append( val1.asString() ) ); + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + // logical not + case Opcode::Not: + val1 = converter->asBoolean (stack.pop().val); + if( val1.isError() ) + val1 = Value::errorVALUE(); + else + val1.setValue( !val1.asBoolean() ); + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + // comparison + case Opcode::Equal: + val1 = stack.pop().val; + val2 = stack.pop().val; + if( !val1.allowComparison( val2 ) ) + val1 = Value::errorNA(); + else if( val2.compare( val1 ) == 0 ) + val1 = Value (true); + else + val1 = Value (false); + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + // less than + case Opcode::Less: + val1 = stack.pop().val; + val2 = stack.pop().val; + if( !val1.allowComparison( val2 ) ) + val1 = Value::errorNA(); + else if( val2.compare( val1 ) < 0 ) + val1 = Value (true); + else + val1 = Value (false); + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + // greater than + case Opcode::Greater: + val1 = stack.pop().val; + val2 = stack.pop().val; + if( !val1.allowComparison( val2 ) ) + val1 = Value::errorNA(); + else if( val2.compare( val1 ) > 0 ) + val1 = Value (true); + else + val1 = Value (false); + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + + case Opcode::Cell: + c = d->constants[index].asString(); + val1 = Value::empty(); + entry.reset(); + if (sheet) + { + Point cell (c, sheet->workbook(), sheet); + if (cell.isValid()) + { + val1 = cell.sheet()->value (cell.column(), cell.row()); + // store the reference, so we can use it within functions + entry.col1 = entry.col2 = cell.column(); + entry.row1 = entry.row2 = cell.row(); + } + } + entry.val = val1; + stack.push (entry); + break; + + case Opcode::Range: + c = d->constants[index].asString(); + val1 = Value::empty(); + entry.reset(); + if (sheet) + { + Range range (c, sheet->workbook(), sheet); + if (range.isValid()) + { + val1 = range.sheet()->valueRange (range.startCol(), range.startRow(), + range.endCol(), range.endRow()); + // store the reference, so we can use it within functions + entry.col1 = range.startCol(); + entry.row1 = range.startRow(); + entry.col2 = range.endCol(); + entry.row2 = range.endRow(); + } + } + entry.val = val1; + stack.push (entry); + break; + + case Opcode::Ref: + val1 = d->constants[index]; + entry.reset(); + entry.val = val1; + stack.push (entry); + break; + + // calling function + case Opcode::Function: + if( stack.count() < index ) + // (Tomas) umm, how could that be ? I mean, the index value + // is computed from the stack *confused* + return Value::errorVALUE(); // not enough arguments + + args.clear(); + fe.ranges.clear (); + fe.ranges.reserve (index); + fe.sheet = sheet; + for( ; index; index-- ) + { + stackEntry e = stack.pop(); + args.insert (args.begin(), e.val); + // TODO: create and fill a FunctionExtra object, if needed + // problem: we don't know if we need it, as we don't have the + // fuction name yet ... + fe.ranges[index - 1].col1 = e.col1; + fe.ranges[index - 1].row1 = e.row1; + fe.ranges[index - 1].col2 = e.col2; + fe.ranges[index - 1].row2 = e.row2; + } + + // function name as string value + val1 = converter->asString (stack.pop().val); + if( val1.isError() ) + return Value::errorVALUE(); + function = FunctionRepository::self()->function ( val1.asString() ); + if( !function ) + return Value::errorVALUE(); // no such function + + ret = function->exec (args, calc, &fe); + entry.reset(); + entry.val = ret; + stack.push (entry); + + break; + + default: + break; + } + } + + if (!d->sheet) { + delete parser; + delete converter; + delete calc; + } + + // more than one value in stack ? unsuccesful execution... + if( stack.count() != 1 ) + return Value::errorVALUE(); + + return stack.pop().val; + +} + +// Debugging aid + +TQString Formula::dump() const +{ + TQString result; + + if( d->dirty ) + { + Tokens tokens = scan( d->expression ); + compile( tokens ); + } + + result = TQString("Expression: [%1]\n").arg( d->expression ); +#if 0 + Value value = eval(); + result.append( TQString("Result: %1\n").arg( + converter->asString(value).asString() ) ); +#endif + + result.append(" Constants:\n"); + for( unsigned c = 0; c < d->constants.count(); c++ ) + { + TQString vtext; + Value val = d->constants[c]; + if( val.isString() ) vtext = TQString("[%1]").arg( val.asString() ); + else if( val.isNumber() ) vtext = TQString("%1").arg( val.asFloat() ); + else if( val.isBoolean() ) vtext = TQString("%1").arg( val.asBoolean() ? "True":"False"); + else if( val.isError() ) vtext = "error"; + else vtext = "???"; + result += TQString(" #%1 = %2\n").arg(c).arg( vtext ); + } + + result.append("\n"); + result.append(" Code:\n"); + for( unsigned i = 0; i < d->codes.count(); i++ ) + { + TQString ctext; + switch( d->codes[i].type ) + { + case Opcode::Load: ctext = TQString("Load #%1").arg( d->codes[i].index ); break; + case Opcode::Ref: ctext = TQString("Ref #%1").arg( d->codes[i].index ); break; + case Opcode::Function: ctext = TQString("Function (%1)").arg( d->codes[i].index ); break; + case Opcode::Add: ctext = "Add"; break; + case Opcode::Sub: ctext = "Sub"; break; + case Opcode::Mul: ctext = "Mul"; break; + case Opcode::Div: ctext = "Div"; break; + case Opcode::Neg: ctext = "Neg"; break; + case Opcode::Concat: ctext = "Concat"; break; + case Opcode::Pow: ctext = "Pow"; break; + case Opcode::Equal: ctext = "Equal"; break; + case Opcode::Not: ctext = "Not"; break; + case Opcode::Less: ctext = "Less"; break; + case Opcode::Greater: ctext = "Greater"; break; + default: ctext = "Unknown"; break; + } + result.append( " " ).append( ctext ).append("\n"); + } + + return result; +} + +TQTextStream& operator<<( TQTextStream& ts, Formula formula ) +{ + ts << formula.dump(); + return ts; +} diff --git a/kspread/functions.cc b/kspread/functions.cc deleted file mode 100644 index f6bc16e2..00000000 --- a/kspread/functions.cc +++ /dev/null @@ -1,526 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2003,2004 Ariya Hidayat - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "formula.h" -#include "functions.h" -#include "valuecalc.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kspread_factory.h" - -namespace KSpread -{ - -class Function::Private -{ -public: - TQString name; - FunctionPtr ptr; - int paramMin, paramMax; - bool acceptArray; - bool ne; // need FunctionExtra* when called ? -}; - -class FunctionRepository::Private -{ -public: - TQDict functions; - TQDict funcs; -}; - -} // namespace KSpread - - -using namespace KSpread; - -Function::Function( const TQString& name, FunctionPtr ptr ) -{ - d = new Private; - d->name = name; - d->ptr = ptr; - d->acceptArray = false; - d->paramMin = 1; - d->paramMax = 1; - d->ne = false; -} - -Function::~Function() -{ - delete d; -} - -TQString Function::name() const -{ - return d->name; -} - -void Function::setParamCount (int min, int max) -{ - d->paramMin = min; - d->paramMax = (max == 0) ? min : max; -} - -bool Function::paramCountOkay (int count) -{ - // less than needed - if (count < d->paramMin) return false; - // no upper limit - if (d->paramMax == -1) return true; - // more than needed - if (count > d->paramMax) return false; - // okay otherwise - return true; -} - -void Function::setAcceptArray (bool accept) { - d->acceptArray = accept; -} - -bool Function::needsExtra () { - return d->ne; -} -void Function::setNeedsExtra (bool extra) { - d->ne = extra; -} - -Value Function::exec (valVector args, ValueCalc *calc, FuncExtra *extra) -{ - // check number of parameters - if (!paramCountOkay (args.count())) - return Value::errorVALUE(); - - // do we need to perform array expansion ? - bool mustExpandArray = false; - if (!d->acceptArray) - for (unsigned int i = 0; i < args.count(); ++i) { - if (args[i].isArray()) - mustExpandArray = true; - } - - if( !d->ptr ) return Value::errorVALUE(); - - // perform the actual array expansion if need be - - if (mustExpandArray) { - // compute number of rows/cols of the result - int rows = 0; - int cols = 0; - for (unsigned int i = 0; i < args.count(); ++i) { - int x = (args[i].type() == Value::Array) ? args[i].rows() : 1; - if (x > rows) rows = x; - x = (args[i].type() == Value::Array) ? args[i].columns() : 1; - if (x > cols) cols = x; - } - // allocate the resulting array - Value res (cols, rows); - // perform the actual computation for each element of the array - for (int row = 0; row < rows; ++row) - for (int col = 0; col < cols; ++col) { - // fill in the parameter vector - valVector vals (args.count()); - for (unsigned int i = 0; i < args.count(); ++i) { - int r = args[i].rows(); - int c = args[i].columns(); - vals[i] = args[i].isArray() ? - args[i].element (col % c, row % r): args[i]; - } - - // execute the function on each element - res.setElement (col, row, exec (vals, calc, extra)); - } - return res; - } - else - // call the function - return (*d->ptr) (args, calc, extra); -} - - -// these are defined in kspread_function_*.cc -void RegisterConversionFunctions(); -void RegisterDatabaseFunctions(); -void RegisterDateTimeFunctions(); -void RegisterEngineeringFunctions(); -void RegisterFinancialFunctions(); -void RegisterInformationFunctions(); -void RegisterLogicFunctions(); -void RegisterMathFunctions(); -void RegisterReferenceFunctions(); -void RegisterStatisticalFunctions(); -void RegisterTextFunctions(); -void RegisterTrigFunctions(); - - -static KStaticDeleter fr_sd; -FunctionRepository* FunctionRepository::s_self = 0; - -FunctionRepository* FunctionRepository::self() -{ - if( !s_self ) - { - kdDebug() << "Creating function repository" << endl; - - fr_sd.setObject( s_self, new FunctionRepository() ); - - kdDebug() << "Registering functions" << endl; - - // register all existing functions - RegisterConversionFunctions(); - RegisterDatabaseFunctions(); - RegisterDateTimeFunctions(); - RegisterEngineeringFunctions(); - RegisterFinancialFunctions(); - RegisterInformationFunctions(); - RegisterLogicFunctions(); - RegisterMathFunctions(); - RegisterReferenceFunctions(); - RegisterStatisticalFunctions(); - RegisterTextFunctions(); - RegisterTrigFunctions(); - - kdDebug() << "Functions registered, loading descriptions" << endl; - - // find all XML description files - TQStringList files = Factory::global()->dirs()->findAllResources - ("extensions", "*.xml", TRUE); - - // load desc/help from XML file - for( TQStringList::Iterator it = files.begin(); it != files.end(); ++it ) - s_self->loadFile (*it); - - kdDebug() << "All ok, repository ready" << endl; - - } - return s_self; -} - -FunctionRepository::FunctionRepository() -{ - d = new Private; - - d->functions.setAutoDelete( true ); - d->funcs.setAutoDelete( true ); -} - -FunctionRepository::~FunctionRepository() -{ - delete d; - s_self = 0; -} - -void FunctionRepository::add( Function* function ) -{ - if( !function ) return; - d->functions.insert( function->name().upper(), function ); -} - -Function *FunctionRepository::function (const TQString& name) -{ - return d->functions.find (name.upper()); -} - -FunctionDescription *FunctionRepository::functionInfo (const TQString& name) -{ - return d->funcs.find (name.upper()); -} - -// returns names of function in certain group -TQStringList FunctionRepository::functionNames( const TQString& group ) -{ - TQStringList lst; - - TQDictIterator it (d->funcs); - for(; it.current(); ++it) { - if (group.isNull() || (it.current()->group() == group)) - lst.append (it.current()->name()); - } - - lst.sort(); - return lst; -} - -void FunctionRepository::loadFile (const TQString& filename) -{ - TQFile file (filename); - if (!file.open (IO_ReadOnly)) - return; - - TQDomDocument doc; - doc.setContent( &file ); - file.close(); - - TQString group = ""; - - TQDomNode n = doc.documentElement().firstChild(); - for (; !n.isNull(); n = n.nextSibling()) - { - if (!n.isElement()) - continue; - TQDomElement e = n.toElement(); - if (e.tagName() == "Group") - { - group = i18n (e.namedItem ("GroupName").toElement().text().utf8()); - m_groups.append( group ); - m_groups.sort(); - - TQDomNode n2 = e.firstChild(); - for (; !n2.isNull(); n2 = n2.nextSibling()) - { - if (!n2.isElement()) - continue; - TQDomElement e2 = n2.toElement(); - if (e2.tagName() == "Function") - { - FunctionDescription* desc = new FunctionDescription( e2 ); - desc->setGroup (group); - if (d->functions.find (desc->name())) - d->funcs.insert (desc->name(), desc); - } - } - group = ""; - } - } -} - -// ------------------------------------------------------------ - -static ParameterType toType( const TQString& type ) -{ - if ( type == "Boolean" ) - return KSpread_Boolean; - if ( type == "Int" ) - return KSpread_Int; - if ( type == "String" ) - return KSpread_String; - if ( type == "Any" ) - return KSpread_Any; - - return KSpread_Float; -} - -static TQString toString (ParameterType type, bool range = FALSE) -{ - if ( !range ) - { - switch(type) { - case KSpread_String: - return i18n("Text"); - case KSpread_Int: - return i18n("Whole number (like 1, 132, 2344)"); - case KSpread_Boolean: - return i18n("A truth value (TRUE or FALSE)" ); - case KSpread_Float: - return i18n("A floating point value (like 1.3, 0.343, 253 )" ); - case KSpread_Any: - return i18n("Any kind of value"); - } - } - else - { - switch(type) { - case KSpread_String: - return i18n("A range of strings"); - case KSpread_Int: - return i18n("A range of whole numbers (like 1, 132, 2344)"); - case KSpread_Boolean: - return i18n("A range of truth values (TRUE or FALSE)" ); - case KSpread_Float: - return i18n("A range of floating point values (like 1.3, 0.343, 253 )" ); - case KSpread_Any: - return i18n("A range of any kind of values"); - } - } - - return TQString(); -} - -FunctionParameter::FunctionParameter() -{ - m_type = KSpread_Float; - m_range = FALSE; -} - -FunctionParameter::FunctionParameter (const FunctionParameter& param) -{ - m_help = param.m_help; - m_type = param.m_type; - m_range = param.m_range; -} - -FunctionParameter::FunctionParameter (const TQDomElement& element) -{ - m_type = KSpread_Float; - m_range = FALSE; - - TQDomNode n = element.firstChild(); - for( ; !n.isNull(); n = n.nextSibling() ) - if ( n.isElement() ) - { - TQDomElement e = n.toElement(); - if ( e.tagName() == "Comment" ) - m_help = i18n( e.text().utf8() ); - else if ( e.tagName() == "Type" ) - { - m_type = toType( e.text() ); - if ( e.hasAttribute( "range" )) - { - if (e.attribute("range").lower() == "true") - m_range = TRUE; - } - } - } -} - -FunctionDescription::FunctionDescription() -{ - m_type = KSpread_Float; -} - -FunctionDescription::FunctionDescription (const TQDomElement& element) -{ - TQDomNode n = element.firstChild(); - for( ; !n.isNull(); n = n.nextSibling() ) - { - if (!n.isElement()) - continue; - TQDomElement e = n.toElement(); - if ( e.tagName() == "Name" ) - m_name = e.text(); - else if ( e.tagName() == "Type" ) - m_type = toType( e.text() ); - else if ( e.tagName() == "Parameter" ) - m_params.append (FunctionParameter (e)); - else if ( e.tagName() == "Help" ) - { - TQDomNode n2 = e.firstChild(); - for( ; !n2.isNull(); n2 = n2.nextSibling() ) - { - if (!n2.isElement()) - continue; - TQDomElement e2 = n2.toElement(); - if ( e2.tagName() == "Text" ) - m_help.append ( i18n( e2.text().utf8() ) ); - else if ( e2.tagName() == "Syntax" ) - m_syntax.append( i18n( e2.text().utf8() ) ); - else if ( e2.tagName() == "Example" ) - m_examples.append( i18n( e2.text().utf8() ) ); - else if ( e2.tagName() == "Related" ) - m_related.append( i18n( e2.text().utf8() ) ); - } - } - } -} - -FunctionDescription::FunctionDescription( const FunctionDescription& desc ) -{ - m_examples = desc.m_examples; - m_related = desc.m_related; - m_syntax = desc.m_syntax; - m_help = desc.m_help; - m_name = desc.m_name; - m_type = desc.m_type; -} - -TQString FunctionDescription::toTQML() const -{ - TQString text( "

" ); - text += name(); - text += "

"; - - if( !m_help.isEmpty() ) - { - text += i18n("

"); - TQStringList::ConstIterator it = m_help.begin(); - for( ; it != m_help.end(); ++it ) - { - text += *it; - text += "

"; - } - text += "

"; - } - - text += i18n("

Return type: "); - text += toString( type() ); - text += "

"; - - if ( !m_syntax.isEmpty() ) - { - text += i18n("

Syntax

    "); - TQStringList::ConstIterator it = m_syntax.begin(); - for( ; it != m_syntax.end(); ++it ) - { - text += "
  • "; - text += *it; - } - text += "
"; - } - - if ( !m_params.isEmpty() ) - { - text += i18n("

Parameters

    "); - TQValueList::ConstIterator it = m_params.begin(); - for( ; it != m_params.end(); ++it ) - { - text += i18n("
  • Comment: "); - text += (*it).helpText(); - text += i18n("
    Type: "); - text += toString( (*it).type(), (*it).hasRange() ); - } - text += "
"; - } - - if ( !m_examples.isEmpty() ) - { - text += i18n("

Examples

    "); - TQStringList::ConstIterator it = m_examples.begin(); - for( ; it != m_examples.end(); ++it ) - { - text += "
  • "; - text += *it; - } - text += "
"; - } - - if ( !m_related.isEmpty() ) - { - text += i18n("

Related Functions

"; - } - - text += ""; - return text; -} diff --git a/kspread/functions.cpp b/kspread/functions.cpp new file mode 100644 index 00000000..fa485171 --- /dev/null +++ b/kspread/functions.cpp @@ -0,0 +1,526 @@ +/* This file is part of the KDE project + Copyright (C) 2003,2004 Ariya Hidayat + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "formula.h" +#include "functions.h" +#include "valuecalc.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kspread_factory.h" + +namespace KSpread +{ + +class Function::Private +{ +public: + TQString name; + FunctionPtr ptr; + int paramMin, paramMax; + bool acceptArray; + bool ne; // need FunctionExtra* when called ? +}; + +class FunctionRepository::Private +{ +public: + TQDict functions; + TQDict funcs; +}; + +} // namespace KSpread + + +using namespace KSpread; + +Function::Function( const TQString& name, FunctionPtr ptr ) +{ + d = new Private; + d->name = name; + d->ptr = ptr; + d->acceptArray = false; + d->paramMin = 1; + d->paramMax = 1; + d->ne = false; +} + +Function::~Function() +{ + delete d; +} + +TQString Function::name() const +{ + return d->name; +} + +void Function::setParamCount (int min, int max) +{ + d->paramMin = min; + d->paramMax = (max == 0) ? min : max; +} + +bool Function::paramCountOkay (int count) +{ + // less than needed + if (count < d->paramMin) return false; + // no upper limit + if (d->paramMax == -1) return true; + // more than needed + if (count > d->paramMax) return false; + // okay otherwise + return true; +} + +void Function::setAcceptArray (bool accept) { + d->acceptArray = accept; +} + +bool Function::needsExtra () { + return d->ne; +} +void Function::setNeedsExtra (bool extra) { + d->ne = extra; +} + +Value Function::exec (valVector args, ValueCalc *calc, FuncExtra *extra) +{ + // check number of parameters + if (!paramCountOkay (args.count())) + return Value::errorVALUE(); + + // do we need to perform array expansion ? + bool mustExpandArray = false; + if (!d->acceptArray) + for (unsigned int i = 0; i < args.count(); ++i) { + if (args[i].isArray()) + mustExpandArray = true; + } + + if( !d->ptr ) return Value::errorVALUE(); + + // perform the actual array expansion if need be + + if (mustExpandArray) { + // compute number of rows/cols of the result + int rows = 0; + int cols = 0; + for (unsigned int i = 0; i < args.count(); ++i) { + int x = (args[i].type() == Value::Array) ? args[i].rows() : 1; + if (x > rows) rows = x; + x = (args[i].type() == Value::Array) ? args[i].columns() : 1; + if (x > cols) cols = x; + } + // allocate the resulting array + Value res (cols, rows); + // perform the actual computation for each element of the array + for (int row = 0; row < rows; ++row) + for (int col = 0; col < cols; ++col) { + // fill in the parameter vector + valVector vals (args.count()); + for (unsigned int i = 0; i < args.count(); ++i) { + int r = args[i].rows(); + int c = args[i].columns(); + vals[i] = args[i].isArray() ? + args[i].element (col % c, row % r): args[i]; + } + + // execute the function on each element + res.setElement (col, row, exec (vals, calc, extra)); + } + return res; + } + else + // call the function + return (*d->ptr) (args, calc, extra); +} + + +// these are defined in kspread_function_*.cpp +void RegisterConversionFunctions(); +void RegisterDatabaseFunctions(); +void RegisterDateTimeFunctions(); +void RegisterEngineeringFunctions(); +void RegisterFinancialFunctions(); +void RegisterInformationFunctions(); +void RegisterLogicFunctions(); +void RegisterMathFunctions(); +void RegisterReferenceFunctions(); +void RegisterStatisticalFunctions(); +void RegisterTextFunctions(); +void RegisterTrigFunctions(); + + +static KStaticDeleter fr_sd; +FunctionRepository* FunctionRepository::s_self = 0; + +FunctionRepository* FunctionRepository::self() +{ + if( !s_self ) + { + kdDebug() << "Creating function repository" << endl; + + fr_sd.setObject( s_self, new FunctionRepository() ); + + kdDebug() << "Registering functions" << endl; + + // register all existing functions + RegisterConversionFunctions(); + RegisterDatabaseFunctions(); + RegisterDateTimeFunctions(); + RegisterEngineeringFunctions(); + RegisterFinancialFunctions(); + RegisterInformationFunctions(); + RegisterLogicFunctions(); + RegisterMathFunctions(); + RegisterReferenceFunctions(); + RegisterStatisticalFunctions(); + RegisterTextFunctions(); + RegisterTrigFunctions(); + + kdDebug() << "Functions registered, loading descriptions" << endl; + + // find all XML description files + TQStringList files = Factory::global()->dirs()->findAllResources + ("extensions", "*.xml", TRUE); + + // load desc/help from XML file + for( TQStringList::Iterator it = files.begin(); it != files.end(); ++it ) + s_self->loadFile (*it); + + kdDebug() << "All ok, repository ready" << endl; + + } + return s_self; +} + +FunctionRepository::FunctionRepository() +{ + d = new Private; + + d->functions.setAutoDelete( true ); + d->funcs.setAutoDelete( true ); +} + +FunctionRepository::~FunctionRepository() +{ + delete d; + s_self = 0; +} + +void FunctionRepository::add( Function* function ) +{ + if( !function ) return; + d->functions.insert( function->name().upper(), function ); +} + +Function *FunctionRepository::function (const TQString& name) +{ + return d->functions.find (name.upper()); +} + +FunctionDescription *FunctionRepository::functionInfo (const TQString& name) +{ + return d->funcs.find (name.upper()); +} + +// returns names of function in certain group +TQStringList FunctionRepository::functionNames( const TQString& group ) +{ + TQStringList lst; + + TQDictIterator it (d->funcs); + for(; it.current(); ++it) { + if (group.isNull() || (it.current()->group() == group)) + lst.append (it.current()->name()); + } + + lst.sort(); + return lst; +} + +void FunctionRepository::loadFile (const TQString& filename) +{ + TQFile file (filename); + if (!file.open (IO_ReadOnly)) + return; + + TQDomDocument doc; + doc.setContent( &file ); + file.close(); + + TQString group = ""; + + TQDomNode n = doc.documentElement().firstChild(); + for (; !n.isNull(); n = n.nextSibling()) + { + if (!n.isElement()) + continue; + TQDomElement e = n.toElement(); + if (e.tagName() == "Group") + { + group = i18n (e.namedItem ("GroupName").toElement().text().utf8()); + m_groups.append( group ); + m_groups.sort(); + + TQDomNode n2 = e.firstChild(); + for (; !n2.isNull(); n2 = n2.nextSibling()) + { + if (!n2.isElement()) + continue; + TQDomElement e2 = n2.toElement(); + if (e2.tagName() == "Function") + { + FunctionDescription* desc = new FunctionDescription( e2 ); + desc->setGroup (group); + if (d->functions.find (desc->name())) + d->funcs.insert (desc->name(), desc); + } + } + group = ""; + } + } +} + +// ------------------------------------------------------------ + +static ParameterType toType( const TQString& type ) +{ + if ( type == "Boolean" ) + return KSpread_Boolean; + if ( type == "Int" ) + return KSpread_Int; + if ( type == "String" ) + return KSpread_String; + if ( type == "Any" ) + return KSpread_Any; + + return KSpread_Float; +} + +static TQString toString (ParameterType type, bool range = FALSE) +{ + if ( !range ) + { + switch(type) { + case KSpread_String: + return i18n("Text"); + case KSpread_Int: + return i18n("Whole number (like 1, 132, 2344)"); + case KSpread_Boolean: + return i18n("A truth value (TRUE or FALSE)" ); + case KSpread_Float: + return i18n("A floating point value (like 1.3, 0.343, 253 )" ); + case KSpread_Any: + return i18n("Any kind of value"); + } + } + else + { + switch(type) { + case KSpread_String: + return i18n("A range of strings"); + case KSpread_Int: + return i18n("A range of whole numbers (like 1, 132, 2344)"); + case KSpread_Boolean: + return i18n("A range of truth values (TRUE or FALSE)" ); + case KSpread_Float: + return i18n("A range of floating point values (like 1.3, 0.343, 253 )" ); + case KSpread_Any: + return i18n("A range of any kind of values"); + } + } + + return TQString(); +} + +FunctionParameter::FunctionParameter() +{ + m_type = KSpread_Float; + m_range = FALSE; +} + +FunctionParameter::FunctionParameter (const FunctionParameter& param) +{ + m_help = param.m_help; + m_type = param.m_type; + m_range = param.m_range; +} + +FunctionParameter::FunctionParameter (const TQDomElement& element) +{ + m_type = KSpread_Float; + m_range = FALSE; + + TQDomNode n = element.firstChild(); + for( ; !n.isNull(); n = n.nextSibling() ) + if ( n.isElement() ) + { + TQDomElement e = n.toElement(); + if ( e.tagName() == "Comment" ) + m_help = i18n( e.text().utf8() ); + else if ( e.tagName() == "Type" ) + { + m_type = toType( e.text() ); + if ( e.hasAttribute( "range" )) + { + if (e.attribute("range").lower() == "true") + m_range = TRUE; + } + } + } +} + +FunctionDescription::FunctionDescription() +{ + m_type = KSpread_Float; +} + +FunctionDescription::FunctionDescription (const TQDomElement& element) +{ + TQDomNode n = element.firstChild(); + for( ; !n.isNull(); n = n.nextSibling() ) + { + if (!n.isElement()) + continue; + TQDomElement e = n.toElement(); + if ( e.tagName() == "Name" ) + m_name = e.text(); + else if ( e.tagName() == "Type" ) + m_type = toType( e.text() ); + else if ( e.tagName() == "Parameter" ) + m_params.append (FunctionParameter (e)); + else if ( e.tagName() == "Help" ) + { + TQDomNode n2 = e.firstChild(); + for( ; !n2.isNull(); n2 = n2.nextSibling() ) + { + if (!n2.isElement()) + continue; + TQDomElement e2 = n2.toElement(); + if ( e2.tagName() == "Text" ) + m_help.append ( i18n( e2.text().utf8() ) ); + else if ( e2.tagName() == "Syntax" ) + m_syntax.append( i18n( e2.text().utf8() ) ); + else if ( e2.tagName() == "Example" ) + m_examples.append( i18n( e2.text().utf8() ) ); + else if ( e2.tagName() == "Related" ) + m_related.append( i18n( e2.text().utf8() ) ); + } + } + } +} + +FunctionDescription::FunctionDescription( const FunctionDescription& desc ) +{ + m_examples = desc.m_examples; + m_related = desc.m_related; + m_syntax = desc.m_syntax; + m_help = desc.m_help; + m_name = desc.m_name; + m_type = desc.m_type; +} + +TQString FunctionDescription::toTQML() const +{ + TQString text( "

" ); + text += name(); + text += "

"; + + if( !m_help.isEmpty() ) + { + text += i18n("

"); + TQStringList::ConstIterator it = m_help.begin(); + for( ; it != m_help.end(); ++it ) + { + text += *it; + text += "

"; + } + text += "

"; + } + + text += i18n("

Return type: "); + text += toString( type() ); + text += "

"; + + if ( !m_syntax.isEmpty() ) + { + text += i18n("

Syntax

    "); + TQStringList::ConstIterator it = m_syntax.begin(); + for( ; it != m_syntax.end(); ++it ) + { + text += "
  • "; + text += *it; + } + text += "
"; + } + + if ( !m_params.isEmpty() ) + { + text += i18n("

Parameters

    "); + TQValueList::ConstIterator it = m_params.begin(); + for( ; it != m_params.end(); ++it ) + { + text += i18n("
  • Comment: "); + text += (*it).helpText(); + text += i18n("
    Type: "); + text += toString( (*it).type(), (*it).hasRange() ); + } + text += "
"; + } + + if ( !m_examples.isEmpty() ) + { + text += i18n("

Examples

    "); + TQStringList::ConstIterator it = m_examples.begin(); + for( ; it != m_examples.end(); ++it ) + { + text += "
  • "; + text += *it; + } + text += "
"; + } + + if ( !m_related.isEmpty() ) + { + text += i18n("

Related Functions

    "); + TQStringList::ConstIterator it = m_related.begin(); + for( ; it != m_related.end(); ++it ) + { + text += "
  • "; + text += ""; + text += *it; + text += ""; + } + text += "
"; + } + + text += "
"; + return text; +} diff --git a/kspread/kspread_autofill.cc b/kspread/kspread_autofill.cc deleted file mode 100644 index e110e1ad..00000000 --- a/kspread/kspread_autofill.cc +++ /dev/null @@ -1,1217 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2005 Raphael Langerhorst - Copyright 2002-2004 Ariya Hidayat - Copyright 2002-2003 Norbert Andres - Copyright 2002 John Dailey - Copyright 2001-2002 Philipp Mueller - Copyright 2000-2002 Laurent Montel - Copyright 2000-2001 Werner Trobin - Copyright 1999-2001 David Faure - Copyright 1998-2000 Torben Weis - Copyright 1998-1999 Stephan Kulow - Copyright 1998 Reginald Stadlbauer - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include - -#include -#include - -#include "kspread_doc.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_undo.h" -#include "kspread_value.h" -#include "valueconverter.h" -#include "kspread_autofill.h" - -using namespace KSpread; - -TQStringList *AutoFillSequenceItem::month = 0L; -TQStringList *AutoFillSequenceItem::shortMonth = 0L; -TQStringList *AutoFillSequenceItem::day = 0L; -TQStringList *AutoFillSequenceItem::shortDay = 0L; -TQStringList *AutoFillSequenceItem::other = 0L; -/********************************************************************************** - * - * AutoFillDeltaSequence - * - **********************************************************************************/ - -AutoFillDeltaSequence::AutoFillDeltaSequence( AutoFillSequence *_first, AutoFillSequence *_next ) - : m_ok(true), - m_sequence(0L) -{ - if ( _first->count() != _next->count() ) - { - m_ok = false; - return; - } - - m_sequence = new TQMemArray ( _first->count() ); - - AutoFillSequenceItem *item = _first->getFirst(); - AutoFillSequenceItem *item2 = _next->getFirst(); - int i = 0; - // for( item = _first->getFirst(); item != 0L && item2 != 0L; item = _first->getNext() ); - for ( i = 0; i < _first->count(); i++ ) - { - double d; - if ( !item->getDelta( item2, d ) ) - { - m_ok = false; - return; - } - m_sequence->at( i++ ) = d; - item2 = _next->getNext(); - item = _first->getNext(); - } -} - -AutoFillDeltaSequence::~AutoFillDeltaSequence() -{ - delete m_sequence; -} - -bool AutoFillDeltaSequence::equals( AutoFillDeltaSequence *_delta ) -{ - if ( m_sequence == 0L ) - return false; - if ( _delta->getSequence() == 0L ) - return false; - if ( m_sequence->size() != _delta->getSequence()->size() ) - return false; - - for ( unsigned int i = 0; i < m_sequence->size(); i++ ) - { - if ( m_sequence->at( i ) != _delta->getSequence()->at( i ) ) - return false; - } - - return true; -} - -double AutoFillDeltaSequence::getItemDelta( int _pos ) -{ - if ( m_sequence == 0L ) - return 0.0; - - return m_sequence->at( _pos ); -} - -/********************************************************************************** - * - * AutoFillSequenceItem - * - **********************************************************************************/ - -AutoFillSequenceItem::AutoFillSequenceItem( int _i ) -{ - m_IValue = _i; - m_Type = INTEGER; -} - -AutoFillSequenceItem::AutoFillSequenceItem( double _d ) -{ - m_DValue = _d; - m_Type = FLOAT; -} - -AutoFillSequenceItem::AutoFillSequenceItem( const TQString &_str ) -{ - m_String = _str; - m_Type = STRING; - - if ( month == 0L ) - { - month = new TQStringList(); - month->append( i18n("January") ); - month->append( i18n("February") ); - month->append( i18n("March") ); - month->append( i18n("April") ); - month->append( i18n("May") ); - month->append( i18n("June") ); - month->append( i18n("July") ); - month->append( i18n("August") ); - month->append( i18n("September") ); - month->append( i18n("October") ); - month->append( i18n("November") ); - month->append( i18n("December") ); - } - - if ( shortMonth == 0L ) - { - shortMonth = new TQStringList(); - shortMonth->append( i18n("Jan") ); - shortMonth->append( i18n("Feb") ); - shortMonth->append( i18n("Mar") ); - shortMonth->append( i18n("Apr") ); - shortMonth->append( i18n("May short", "May") ); - shortMonth->append( i18n("Jun") ); - shortMonth->append( i18n("Jul") ); - shortMonth->append( i18n("Aug") ); - shortMonth->append( i18n("Sep") ); - shortMonth->append( i18n("Oct") ); - shortMonth->append( i18n("Nov") ); - shortMonth->append( i18n("Dec") ); - } - - if ( day == 0L ) - { - day = new TQStringList(); - day->append( i18n("Monday") ); - day->append( i18n("Tuesday") ); - day->append( i18n("Wednesday") ); - day->append( i18n("Thursday") ); - day->append( i18n("Friday") ); - day->append( i18n("Saturday") ); - day->append( i18n("Sunday") ); - } - - if ( shortDay == 0L ) - { - shortDay = new TQStringList(); - shortDay->append( i18n("Mon") ); - shortDay->append( i18n("Tue") ); - shortDay->append( i18n("Wed") ); - shortDay->append( i18n("Thu") ); - shortDay->append( i18n("Fri") ); - shortDay->append( i18n("Sat") ); - shortDay->append( i18n("Sun") ); - } - - if( other==0L) - { - // other=new TQStringList(); - TDEConfig *config = Factory::global()->config(); - config->setGroup( "Parameters" ); - other=new TQStringList(config->readListEntry("Other list")); - } - - if ( month->find( _str ) != month->end() ) - { - m_Type = MONTH; - return; - } - - if ( shortMonth->find( _str ) != shortMonth->end() ) - { - m_Type = SHORTMONTH; - return; - } - - if ( day->find( _str ) != day->end() ) - { - m_Type = DAY; - return; - } - - if ( shortDay->find( _str ) != shortDay->end() ) - { - m_Type = SHORTDAY; - return; - } - - if( other->find(_str)!=other->end()) - { - m_Type = OTHER; - m_OtherBegin=0; - m_OtherEnd=other->count(); - int index= other->findIndex(_str); - //find end and begin of qstringlist of other. - for ( TQStringList::Iterator it = other->find(_str); it != other->end();++it ) - { - if((*it)=="\\") - { - m_OtherEnd=index; - break; - } - index++; - } - index= other->findIndex(_str); - for ( TQStringList::Iterator it = other->find(_str); it != other->begin();--it ) - { - if((*it)=="\\") - { - m_OtherBegin=index; - break; - } - index--; - } - return; - } - - if ( m_String[0] == '=' ) - m_Type = FORMULA; -} - -bool AutoFillSequenceItem::getDelta( AutoFillSequenceItem *seq, double &_delta ) -{ - if ( seq->getType() != m_Type ) - return false; - - switch( m_Type ) - { - case INTEGER: - _delta = (double)( seq->getIValue() - m_IValue ); - return true; - case FLOAT: - _delta = seq->getDValue() - m_DValue; - return true; - case FORMULA: - case STRING: - if ( m_String == seq->getString() ) - { - _delta = 0.0; - return true; - } - return false; - case MONTH: - { - int i = month->findIndex( m_String ); - int j = month->findIndex( seq->getString() ); - int k = j; - - if ( j + 1 == i ) - _delta = -1.0; - else - _delta = ( double )( k - i ); - return true; - } - - case SHORTMONTH: - { - int i = shortMonth->findIndex( m_String ); - int j = shortMonth->findIndex( seq->getString() ); - int k = j; - - if ( j + 1 == i ) - _delta = -1.0; - else - _delta = ( double )( k - i ); - return true; - } - - case DAY: - { - int i = day->findIndex( m_String ); - int j = day->findIndex( seq->getString() ); - int k = j; - - if ( j + 1 == i ) - _delta = -1.0; - else - _delta = ( double )( k - i ); - kdDebug() << m_String << " i: " << i << " j: " << j << " k: " << k << " delta: " << _delta << endl; - return true; - } - - case SHORTDAY: - { - int i = shortDay->findIndex( m_String ); - int j = shortDay->findIndex( seq->getString() ); - int k = j; - - if ( j + 1 == i ) - _delta = -1.0; - else - _delta = ( double )( k - i ); - return true; - } - case OTHER: - { - if( m_OtherEnd!= seq->getIOtherEnd() || m_OtherBegin!= seq->getIOtherBegin()) - return false; - int i = other->findIndex( m_String ); - int j = other->findIndex( seq->getString() ); - int k = j; - if ( j < i ) - k += (m_OtherEnd - m_OtherBegin - 1); - /*if ( j + 1 == i ) - _delta = -1.0; - else*/ - _delta = ( double )( k - i ); - return true; - } - default: - return false; - } -} - -TQString AutoFillSequenceItem::getSuccessor( int _no, double _delta ) -{ - TQString erg; - switch( m_Type ) - { - case INTEGER: - erg.sprintf("%i", m_IValue + _no * (int)_delta ); - break; - case FLOAT: - erg.sprintf("%f", m_DValue + (double)_no * _delta ); - break; - case FORMULA: - case STRING: - erg = m_String; - break; - case MONTH: - { - int i = month->findIndex( m_String ); - int j = i + _no * (int) _delta; - while (j < 0) - j += month->count(); - int k = j % month->count(); - erg = (*month->at( k )); - } - break; - case SHORTMONTH: - { - int i = shortMonth->findIndex( m_String ); - int j = i + _no * (int) _delta; - while (j < 0) - j += shortMonth->count(); - int k = j % shortMonth->count(); - erg = (*shortMonth->at( k )); - } - break; - case DAY: - { - int i = day->findIndex( m_String ); - int j = i + _no * (int) _delta; - while (j < 0) - j += day->count(); - int k = j % day->count(); - erg = (*day->at( k )); - } - break; - case SHORTDAY: - { - int i = shortDay->findIndex( m_String ); - int j = i + _no * (int) _delta; - while (j < 0) - j += shortDay->count(); - int k = j % shortDay->count(); - erg = (*shortDay->at( k )); - } - break; - case OTHER: - { - int i = other->findIndex( m_String )-(m_OtherBegin+1); - int j = i + _no * (int) _delta; - int k = j % (m_OtherEnd - m_OtherBegin-1); - erg = (*other->at( (k+m_OtherBegin+1) )); - } - case TIME: - case DATE: - // gets never called but fixes a warning while compiling - break; - } - - return TQString( erg ); -} - -TQString AutoFillSequenceItem::getPredecessor( int _no, double _delta ) -{ - TQString erg; - switch( m_Type ) - { - case INTEGER: - erg.sprintf("%i", m_IValue - _no * (int)_delta ); - break; - case FLOAT: - erg.sprintf("%f", m_DValue - (double)_no * _delta ); - break; - case FORMULA: - case STRING: - erg = m_String; - break; - case MONTH: - { - int i = month->findIndex( m_String ); - int j = i - _no * (int) _delta; - while ( j < 0 ) - j += month->count(); - int k = j % month->count(); - erg = (*month->at( k )); - } - break; - case SHORTMONTH: - { - int i = shortMonth->findIndex( m_String ); - int j = i - _no * (int) _delta; - while ( j < 0 ) - j += shortMonth->count(); - int k = j % shortMonth->count(); - erg = (*shortMonth->at( k )); - } - break; - case DAY: - { - int i = day->findIndex( m_String ); - int j = i - _no * (int) _delta; - while ( j < 0 ) - j += day->count(); - int k = j % day->count(); - erg = (*day->at( k )); - } - break; - case SHORTDAY: - { - int i = shortDay->findIndex( m_String ); - int j = i - _no * (int) _delta; - while ( j < 0 ) - j += shortDay->count(); - int k = j % shortDay->count(); - erg = (*shortDay->at( k )); - } - break; - case OTHER: - { - int i = other->findIndex( m_String ) - (m_OtherBegin + 1); - int j = i - _no * (int) _delta; - while ( j < 0 ) - j += (m_OtherEnd - m_OtherBegin - 1); - int k = j % (m_OtherEnd - m_OtherBegin - 1); - erg = (*other->at( (k + m_OtherBegin + 1) )); - } - case TIME: - case DATE: - // gets never called but fixes a warning while compiling - break; - } - - return TQString( erg ); -} - -/********************************************************************************** - * - * AutoFillSequence - * - **********************************************************************************/ - -AutoFillSequence::AutoFillSequence( Cell *_cell ) -{ - sequence.setAutoDelete( true ); - - if ( _cell->isFormula() ) - { - TQString d = _cell->encodeFormula(); - sequence.append( new AutoFillSequenceItem( d ) ); - } - else if ( _cell->value().isNumber() ) - { - if ( floor( _cell->value().asFloat() ) == _cell->value().asFloat() ) - { - sequence.append( new AutoFillSequenceItem( (int)_cell->value().asFloat()) ); - } - else - sequence.append( new AutoFillSequenceItem(_cell->value().asFloat() ) ); - } - else if ( !_cell->text().isEmpty() ) - sequence.append( new AutoFillSequenceItem( _cell->text() ) ); -} - -bool AutoFillSequence::matches( AutoFillSequence* _seq, AutoFillDeltaSequence *_delta ) -{ - AutoFillDeltaSequence delta( this, _seq ); - if ( !delta.isOk() ) - return false; - - if ( delta.equals( _delta ) ) - return true; - - return false; -} - -void AutoFillSequence::fillCell( Cell *src, Cell *dest, AutoFillDeltaSequence *delta, int _block, bool down ) -{ - TQString erg = ""; - - // Special handling for formulas - if ( sequence.first() != 0L && sequence.first()->getType() == AutoFillSequenceItem::FORMULA ) - { - TQString f = dest->decodeFormula( sequence.first()->getString() ); - dest->setCellText( f ); - dest->copyFormat( src ); - return; - } - - AutoFillSequenceItem *item; - int i = 0; - if (down) - { - for ( item = sequence.first(); item != 0L; item = sequence.next() ) - erg += item->getSuccessor( _block, delta->getItemDelta( i++ ) ); - } - else - { - for ( item = sequence.first(); item != 0L; item = sequence.next() ) - erg += item->getPredecessor( _block, delta->getItemDelta( i++ ) ); - } - - dest->setCellText( erg ); - dest->copyFormat( src ); -} - -/********************************************************************************** - * - * Sheet - * - **********************************************************************************/ - -void Sheet::autofill( TQRect &src, TQRect &dest ) -{ - if (src == dest) - { - return; - } - - setRegionPaintDirty( dest ); - - doc()->emitBeginOperation(); - - if ( !doc()->undoLocked() ) - { - UndoAutofill *undo = new UndoAutofill( doc(), this, dest ); - doc()->addCommand( undo ); - } - - // disable the update of the max sroll range on each cell insertion - // Bug 124806: creating series takes extremely long time - enableScrollBarUpdates(false); - - // Fill from left to right - if ( src.left() == dest.left() && src.right() < dest.right() ) - { - for ( int y = src.top(); y <= src.bottom(); y++ ) - { - int x; - TQPtrList destList; - for ( x = src.right() + 1; x <= dest.right(); x++ ) - destList.append( nonDefaultCell( x, y ) ); - TQPtrList srcList; - for ( x = src.left(); x <= src.right(); x++ ) - srcList.append( cellAt( x, y ) ); - TQPtrList seqList; - seqList.setAutoDelete( true ); - for ( x = src.left(); x <= src.right(); x++ ) - seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); - fillSequence( srcList, destList, seqList ); - } - } - - // Fill from top to bottom - if ( src.top() == dest.top() && src.bottom() < dest.bottom() ) - { - for ( int x = src.left(); x <= dest.right(); x++ ) - { - int y; - TQPtrList destList; - for ( y = src.bottom() + 1; y <= dest.bottom(); y++ ) - destList.append( nonDefaultCell( x, y ) ); - TQPtrList srcList; - for ( y = src.top(); y <= src.bottom(); y++ ) - { - srcList.append( cellAt( x, y ) ); - } - TQPtrList seqList; - seqList.setAutoDelete( true ); - for ( y = src.top(); y <= src.bottom(); y++ ) - seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); - fillSequence( srcList, destList, seqList ); - } - } - - // Fill from right to left - if ( ( src.left() == dest.right() || src.left() == dest.right() - 1) && src.right() >= dest.right() ) - { - if ( src.left() != dest.right() ) - dest.setRight( dest.right() - 1 ); - - for ( int y = dest.top(); y <= dest.bottom(); y++ ) - { - int x; - TQPtrList destList; - - for ( x = dest.left(); x < src.left(); x++ ) - { - destList.append( nonDefaultCell( x, y ) ); - } - TQPtrList srcList; - for ( x = src.left(); x <= src.right(); x++ ) - { - srcList.append( cellAt( x, y ) ); - } - TQPtrList seqList; - seqList.setAutoDelete( true ); - for ( x = src.left(); x <= src.right(); x++ ) - seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); - fillSequence( srcList, destList, seqList, false ); - } - } - - // Fill from bottom to top - if ( (src.top() == dest.bottom() || src.top() == (dest.bottom() - 1) ) && src.bottom() >= dest.bottom() ) - { - if (src.top() != dest.bottom() ) - dest.setBottom(dest.bottom() - 1); - int startVal = TQMIN( dest.left(), src.left()); - int endVal = TQMAX(src.right(), dest.right()); - for ( int x = startVal; x <= endVal; x++ ) - { - int y; - TQPtrList destList; - for ( y = dest.top(); y < src.top(); y++ ) - destList.append( nonDefaultCell( x, y ) ); - TQPtrList srcList; - for ( y = src.top(); y <= src.bottom(); ++y ) - { - srcList.append( cellAt( x, y ) ); - } - TQPtrList seqList; - seqList.setAutoDelete( true ); - for ( y = src.top(); y <= src.bottom(); y++ ) - seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); - fillSequence( srcList, destList, seqList, false ); - } - } - - // update the max sroll range ONCE here - enableScrollBarUpdates(true); - checkRangeHBorder(dest.right()); - checkRangeVBorder(dest.bottom()); - - emit sig_updateView( this ); - // doc()->emitEndOperation(); -} - - -void Sheet::fillSequence( TQPtrList& _srcList, - TQPtrList& _destList, - TQPtrList& _seqList, - bool down) -{ - doc()->emitBeginOperation(true); - - /* try finding an interval to use to fill the sequence */ - if (!FillSequenceWithInterval(_srcList, _destList, _seqList, down)) - { - /* if no interval was found, just copy down through */ - FillSequenceWithCopy(_srcList, _destList, down); - } - - doc()->emitEndOperation(); - -} - -TQVariant getDiff( const Value& value1, const Value& value2 , AutoFillSequenceItem::Type type ) -{ - if ( type == AutoFillSequenceItem::FLOAT ) - return TQVariant( value2.asFloat() - value1.asFloat() ); - if ( type == AutoFillSequenceItem::TIME || type == AutoFillSequenceItem::DATE ) - return TQVariant( (int)( value2.asInteger() - value1.asInteger() ) ); - - return TQVariant( (int)0 ); - // note: date and time difference can be calculated as - // the difference of the serial number - /* if( (type == AutoFillSequenceItem::FLOAT) || - (type == AutoFillSequenceItem::DATE) || - (type == AutoFillSequenceItem::TIME) ) - return ( value2.asFloat() - value1.asFloat() ); - else - return 0.0;*/ -} - -bool Sheet::FillSequenceWithInterval(TQPtrList& _srcList, - TQPtrList& _destList, - TQPtrList& _seqList, - bool down) -{ - if (_srcList.first()->isFormula()) - return false; - - TQPtrList deltaList; - deltaList.setAutoDelete( true ); - bool ok = false; - - if ( _srcList.first()->value().isNumber() || _srcList.first()->isDate() || _srcList.first()->isTime() ) - { - AutoFillSequenceItem::Type type; - - TQValueVector< TQVariant > tmp( _seqList.count() ); /*= new TQValueList< TQVariant > ( _seqList.count() )*/; - TQValueVector< TQVariant > diff( _seqList.count() ); /*= new TQValueList< TQVariant > ( _seqList.count() )*/; - int p = -1; - int count = 0; - int tmpcount = 0; - - Cell * cell = _srcList.first(); - Cell * cell2 = _srcList.next(); - - bool singleCellOnly = (cell2 == 0); - - if ( cell->isDate() ) - type = AutoFillSequenceItem::DATE; - else if ( cell->isTime() ) - type = AutoFillSequenceItem::TIME; - else if ( cell->value().isNumber() ) - type = AutoFillSequenceItem::FLOAT; - else - return false; // Cannot happen due to if condition - - while ( cell && (cell2 || singleCellOnly) ) - { - - Value cellValue = cell->value(); - Value cell2Value; - - //If we only have a single cell, the interval will depend upon the data type. - //- For numeric values, set the interval to 0 as we don't know what might be useful as a sequence - //- For time values, set the interval to one hour, as this will probably be the most useful setting - //- For date values, set the interval to one day, as this will probably be the most useful setting - // - //Note that the above options were chosen for consistency with Excel. Gnumeric (1.59) sets - //the interval to 0 for all types, OpenOffice.org (2.00) uses increments of 1.00, 1 hour and 1 day - //respectively - if (singleCellOnly) - { - if (type == AutoFillSequenceItem::FLOAT) - cell2Value = cellValue; - else if ( type == AutoFillSequenceItem::TIME) - cell2Value = Value( cellValue.asTime().addSecs( 60*60 ) ); - else if ( type == AutoFillSequenceItem::DATE) - cell2Value = Value ( cellValue.asDate().addDays( 1 ) ); - } - else - { - cell2Value = cell2->value(); - - // check if both cells contain the same type - if ( ( !cellValue.isNumber() ) - || ( cell2->isDate() && type != AutoFillSequenceItem::DATE ) - || ( cell2->isTime() && type != AutoFillSequenceItem::TIME ) ) - { - count = 0; - ok = false; - break; - } - } - - TQVariant delta = getDiff(cellValue , cell2Value , type ); - - if (count < 1) - { - p = count; - diff[ count++ ] = delta; - } - else - { - // same value again? - if (diff[ p ] == delta) - { - // store it somewhere else for the case we need it later - ++p; - tmp[ tmpcount++ ] = delta; - } - else - { - // if we have saved values in another buffer we have to insert them first - if ( tmpcount > 0 ) - { - for ( int i = 0; i < tmpcount; ++i ) - { - diff[ count++ ] = tmp.at( i ); - } - - tmpcount = 0; - } - - // insert the value - p = 0; - diff[ count++ ] = delta; - } - } - - // check next cell pair - cell = cell2; - cell2 = _srcList.next(); - } - - // we have found something: - if (count > 0 && (tmpcount > 0 || count == 1)) - { - TQVariant cellValue( (int) 0 ); - - Cell * dest; - Cell * src; - - int i = tmpcount; - if (down) - { - dest = _destList.first(); - src = _srcList.last(); - } - else - { - dest = _destList.last(); - src = _srcList.first(); - - i *= -1; - } - - if ( type == AutoFillSequenceItem::FLOAT ) - cellValue = src->value().asFloat(); - else - cellValue = (int)src->value().asInteger(); - - TQString res; - // copy all the data - while (dest) - { - if (down) - { - while ( i >= count ) - i -= count; - } - else - { - while ( i < 0) - i += count; - } - - TQVariant currentDiff = diff.at( i ); - - if (cellValue.type() == TQVariant::Double) - if (down) - cellValue = cellValue.asDouble() + currentDiff.asDouble(); - else - cellValue = cellValue.asDouble() - currentDiff.asDouble(); - else - if (down) - cellValue = cellValue.asInt() + currentDiff.asInt(); - else - cellValue = cellValue.asInt() - currentDiff.asInt(); - - if ( type == AutoFillSequenceItem::TIME) - { - Value timeValue = doc()->converter()->asTime( Value(cellValue.asInt()) ); - Value stringValue = doc()->converter()->asString( timeValue ); - dest->setCellText( stringValue.asString() ); - } - else if ( type == AutoFillSequenceItem::DATE) - { - Value dateValue = doc()->converter()->asDate( Value(cellValue.asInt()) ); - Value stringValue = doc()->converter()->asString( dateValue ); - dest->setCellText( stringValue.asString() ); - } - else - dest->setCellText( cellValue.asString() ); - - dest->copyFormat( src ); - - if (down) - { - ++i; - dest = _destList.next(); - src = _srcList.next(); - } - else - { - --i; - dest = _destList.prev(); - src = _srcList.prev(); - } - - if (!src) - src = _srcList.last(); - } - - ok = true; - } - else - { - ok = false; - } - - // delete tmp; - // delete diff; - - return ok; - } - - // What is the interval (block)? If your sheet looks like this: - // 1 3 5 7 9 - // then the interval has the length 1 and the delta list is [2]. - // 2 200 3 300 4 400 - // Here the interval has length 2 and the delta list is [1,100] - - - // How big is the interval. It is in the range from [2...n/2]. - // The case of an interval of length n is handled below. - // - // We try to find the shortest interval. - for ( unsigned int step = 1; step <= _seqList.count() / 2; step++ ) - { - kdDebug() << "Looking for interval: " << step << " seqList count: " << _seqList.count() << endl; - // If the interval is of length 'step' then the _seqList size must - // be a multiple of 'step' - if ( _seqList.count() % step == 0 ) - { - // Be optimistic - ok = true; - - deltaList.clear(); - - // Guess the delta by looking at cells 0...2*step-1 - // - // Since the interval may be of length 'step' we calculate the delta - // between cells 0 and step, 1 and step+1, ...., step-1 and 2*step-1 - for ( unsigned int t = 0; t < step; t++ ) - { - deltaList.append( new AutoFillDeltaSequence( _seqList.at(t), - _seqList.at(t+step) ) ); - ok = deltaList.getLast()->isOk(); - } - - /* Verify the delta by looking at cells step..._seqList.count() - We only looked at the cells 0 ... '2*step-1'. - Now test wether the cells from "(tst-1) * step + s" share the same delta - with the cell "tst * step + s" for all test=1..._seqList.count()/step - and for all s=0...step-1. - */ - for ( unsigned int tst = 1; ok && ( tst * step < _seqList.count() ); - tst++ ) - { - for ( unsigned int s = 0; ok && ( s < step ); s++ ) - { - if ( !_seqList.at( (tst-1) * step + s )-> - matches( _seqList.at( tst * step + s ), deltaList.at( s ) ) ) - ok = false; - } - } - // Did we find a valid interval ? - if ( ok ) - { - unsigned int s = 0; - // Amount of intervals (blocks) - int block = _seqList.count() / step; - - // Start iterating with the first cell - Cell * cell; - if (down) - cell = _destList.first(); - else - { - cell = _destList.last(); - block -= (_seqList.count() - 1); - } - - - // Loop over all destination cells - while ( cell ) - { - kdDebug() << "Valid interval, cell: " << cell->row() << " block: " << block << endl; - - // End of block? -> start again from beginning - if (down) - { - if ( s == step ) - { - ++block; - s = 0; - } - } - else - { - if ( s >= step ) - { - s = step - 1; - ++block; - } - } - - kdDebug() << "Step: " << step << " S: " << s << " Block " << block - << " SeqList: " << _seqList.count() - << " SrcList: " << _srcList.count() << " DeltaList: " << deltaList.count() - << endl; - - // Set the value of 'cell' by adding 'block' times the delta tp the - // value of cell 's'. - _seqList.at( s )->fillCell( _srcList.at( s ), cell, - deltaList.at( s ), block, down ); - - if (down) - { - // Next cell - cell = _destList.next(); - ++s; - } - else - { - // Previous cell - cell = _destList.prev(); - --s; - } - } - } - } - } - return ok; -} - -void Sheet::FillSequenceWithCopy(TQPtrList& _srcList, - TQPtrList& _destList, - bool down) -{ - // We did not find any valid interval. So just copy over the marked - // area. - Cell * cell; - - if (down) - cell = _destList.first(); - else - cell = _destList.last(); - int incr = 1; - unsigned int s = 0; - double factor = 1; - - if (!down) - s = _srcList.count() - 1; - - if ( _srcList.at( s )->value().isNumber() && - !(_srcList.at( s )->isDate() || _srcList.at( s )->isTime() ) ) - factor = _srcList.at( s )->value().asFloat(); - - while ( cell ) - { - if (down) - { - if ( s == _srcList.count() ) - s = 0; - } - else - { - if ( s >= _srcList.count() ) - s = _srcList.count() - 1; - } - - if ( !_srcList.at( s )->text().isEmpty() ) - { - if ( _srcList.at( s )->isFormula() ) - { - TQString d = _srcList.at( s )->encodeFormula(); - cell->setCellText( cell->decodeFormula( d ) ); - } - else if(_srcList.at( s )->value().isNumber() && _srcList.count()==1) - { - double val; - int format_type = _srcList.at( s )->formatType(); - if ( format_type == Percentage_format ) - { - factor = 0.01; // one percent - } - else if ( _srcList.at( s )->isTime() ) - { - // FIXME this is a workaround to avoid those nasty one minute off - // "dragging down" time is inaccurate overa large lists! - // This is the best approximation I could find (raphael) - if (down) - { -// factor = 1.000002/24. + 0.000000001; - factor = 0.041666751; - } - else - { //when dragging "up" the error must of course be the other way round - factor = 0.0416665; - } - } - - if (!down) - val = (_srcList.at( s )->value().asFloat() - (incr * factor)); - else - val = (_srcList.at( s )->value().asFloat() + (incr * factor)); - - TQString tmp; - tmp = tmp.setNum(val); - cell->setCellText( tmp ); - ++incr; - } - else if((AutoFillSequenceItem::month != 0L) - && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != 0L - && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != AutoFillSequenceItem::month->end() - && _srcList.count() == 1) - { - TQString strMonth=_srcList.at( s )->text(); - int i = AutoFillSequenceItem::month->findIndex( strMonth )+incr; - int k = (i) % AutoFillSequenceItem::month->count(); - cell->setCellText((*AutoFillSequenceItem::month->at( k ))); - incr++; - } - else if(AutoFillSequenceItem::day != 0L - && AutoFillSequenceItem::day->find( _srcList.at( s )->text()) != 0L - && AutoFillSequenceItem::day->find( _srcList.at( s )->text()) - != AutoFillSequenceItem::day->end() - && _srcList.count()==1) - { - TQString strDay=_srcList.at( s )->text(); - int i = AutoFillSequenceItem::day->findIndex( strDay )+incr; - int k = (i) % AutoFillSequenceItem::day->count(); - cell->setCellText((*AutoFillSequenceItem::day->at( k ))); - incr++; - } - else - { - TQRegExp number("(\\d+)"); - int pos =number.search(_srcList.at( s )->text()); - if( pos!=-1 ) - { - TQString tmp=number.cap(1); - int num=tmp.toInt()+incr; - cell->setCellText(_srcList.at( s )->text().replace(number,TQString::number(num))); - ++incr; - } - else if ( !_srcList.at( s )->link().isEmpty() ) - { - cell->setCellText( _srcList.at( s )->text() ); - cell->setLink( _srcList.at( s )->link() ); - } - else - { - cell->setCellText( _srcList.at( s )->text() ); - } - } - } - else - cell->setCellText( "" ); - - cell->copyFormat( _srcList.at( s ) ); - - if (down) - { - cell = _destList.next(); - ++s; - } - else - { - cell = _destList.prev(); - --s; - } - } - return; -} diff --git a/kspread/kspread_autofill.cpp b/kspread/kspread_autofill.cpp new file mode 100644 index 00000000..e110e1ad --- /dev/null +++ b/kspread/kspread_autofill.cpp @@ -0,0 +1,1217 @@ +/* This file is part of the KDE project + + Copyright 2005 Raphael Langerhorst + Copyright 2002-2004 Ariya Hidayat + Copyright 2002-2003 Norbert Andres + Copyright 2002 John Dailey + Copyright 2001-2002 Philipp Mueller + Copyright 2000-2002 Laurent Montel + Copyright 2000-2001 Werner Trobin + Copyright 1999-2001 David Faure + Copyright 1998-2000 Torben Weis + Copyright 1998-1999 Stephan Kulow + Copyright 1998 Reginald Stadlbauer + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include + +#include +#include + +#include "kspread_doc.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_undo.h" +#include "kspread_value.h" +#include "valueconverter.h" +#include "kspread_autofill.h" + +using namespace KSpread; + +TQStringList *AutoFillSequenceItem::month = 0L; +TQStringList *AutoFillSequenceItem::shortMonth = 0L; +TQStringList *AutoFillSequenceItem::day = 0L; +TQStringList *AutoFillSequenceItem::shortDay = 0L; +TQStringList *AutoFillSequenceItem::other = 0L; +/********************************************************************************** + * + * AutoFillDeltaSequence + * + **********************************************************************************/ + +AutoFillDeltaSequence::AutoFillDeltaSequence( AutoFillSequence *_first, AutoFillSequence *_next ) + : m_ok(true), + m_sequence(0L) +{ + if ( _first->count() != _next->count() ) + { + m_ok = false; + return; + } + + m_sequence = new TQMemArray ( _first->count() ); + + AutoFillSequenceItem *item = _first->getFirst(); + AutoFillSequenceItem *item2 = _next->getFirst(); + int i = 0; + // for( item = _first->getFirst(); item != 0L && item2 != 0L; item = _first->getNext() ); + for ( i = 0; i < _first->count(); i++ ) + { + double d; + if ( !item->getDelta( item2, d ) ) + { + m_ok = false; + return; + } + m_sequence->at( i++ ) = d; + item2 = _next->getNext(); + item = _first->getNext(); + } +} + +AutoFillDeltaSequence::~AutoFillDeltaSequence() +{ + delete m_sequence; +} + +bool AutoFillDeltaSequence::equals( AutoFillDeltaSequence *_delta ) +{ + if ( m_sequence == 0L ) + return false; + if ( _delta->getSequence() == 0L ) + return false; + if ( m_sequence->size() != _delta->getSequence()->size() ) + return false; + + for ( unsigned int i = 0; i < m_sequence->size(); i++ ) + { + if ( m_sequence->at( i ) != _delta->getSequence()->at( i ) ) + return false; + } + + return true; +} + +double AutoFillDeltaSequence::getItemDelta( int _pos ) +{ + if ( m_sequence == 0L ) + return 0.0; + + return m_sequence->at( _pos ); +} + +/********************************************************************************** + * + * AutoFillSequenceItem + * + **********************************************************************************/ + +AutoFillSequenceItem::AutoFillSequenceItem( int _i ) +{ + m_IValue = _i; + m_Type = INTEGER; +} + +AutoFillSequenceItem::AutoFillSequenceItem( double _d ) +{ + m_DValue = _d; + m_Type = FLOAT; +} + +AutoFillSequenceItem::AutoFillSequenceItem( const TQString &_str ) +{ + m_String = _str; + m_Type = STRING; + + if ( month == 0L ) + { + month = new TQStringList(); + month->append( i18n("January") ); + month->append( i18n("February") ); + month->append( i18n("March") ); + month->append( i18n("April") ); + month->append( i18n("May") ); + month->append( i18n("June") ); + month->append( i18n("July") ); + month->append( i18n("August") ); + month->append( i18n("September") ); + month->append( i18n("October") ); + month->append( i18n("November") ); + month->append( i18n("December") ); + } + + if ( shortMonth == 0L ) + { + shortMonth = new TQStringList(); + shortMonth->append( i18n("Jan") ); + shortMonth->append( i18n("Feb") ); + shortMonth->append( i18n("Mar") ); + shortMonth->append( i18n("Apr") ); + shortMonth->append( i18n("May short", "May") ); + shortMonth->append( i18n("Jun") ); + shortMonth->append( i18n("Jul") ); + shortMonth->append( i18n("Aug") ); + shortMonth->append( i18n("Sep") ); + shortMonth->append( i18n("Oct") ); + shortMonth->append( i18n("Nov") ); + shortMonth->append( i18n("Dec") ); + } + + if ( day == 0L ) + { + day = new TQStringList(); + day->append( i18n("Monday") ); + day->append( i18n("Tuesday") ); + day->append( i18n("Wednesday") ); + day->append( i18n("Thursday") ); + day->append( i18n("Friday") ); + day->append( i18n("Saturday") ); + day->append( i18n("Sunday") ); + } + + if ( shortDay == 0L ) + { + shortDay = new TQStringList(); + shortDay->append( i18n("Mon") ); + shortDay->append( i18n("Tue") ); + shortDay->append( i18n("Wed") ); + shortDay->append( i18n("Thu") ); + shortDay->append( i18n("Fri") ); + shortDay->append( i18n("Sat") ); + shortDay->append( i18n("Sun") ); + } + + if( other==0L) + { + // other=new TQStringList(); + TDEConfig *config = Factory::global()->config(); + config->setGroup( "Parameters" ); + other=new TQStringList(config->readListEntry("Other list")); + } + + if ( month->find( _str ) != month->end() ) + { + m_Type = MONTH; + return; + } + + if ( shortMonth->find( _str ) != shortMonth->end() ) + { + m_Type = SHORTMONTH; + return; + } + + if ( day->find( _str ) != day->end() ) + { + m_Type = DAY; + return; + } + + if ( shortDay->find( _str ) != shortDay->end() ) + { + m_Type = SHORTDAY; + return; + } + + if( other->find(_str)!=other->end()) + { + m_Type = OTHER; + m_OtherBegin=0; + m_OtherEnd=other->count(); + int index= other->findIndex(_str); + //find end and begin of qstringlist of other. + for ( TQStringList::Iterator it = other->find(_str); it != other->end();++it ) + { + if((*it)=="\\") + { + m_OtherEnd=index; + break; + } + index++; + } + index= other->findIndex(_str); + for ( TQStringList::Iterator it = other->find(_str); it != other->begin();--it ) + { + if((*it)=="\\") + { + m_OtherBegin=index; + break; + } + index--; + } + return; + } + + if ( m_String[0] == '=' ) + m_Type = FORMULA; +} + +bool AutoFillSequenceItem::getDelta( AutoFillSequenceItem *seq, double &_delta ) +{ + if ( seq->getType() != m_Type ) + return false; + + switch( m_Type ) + { + case INTEGER: + _delta = (double)( seq->getIValue() - m_IValue ); + return true; + case FLOAT: + _delta = seq->getDValue() - m_DValue; + return true; + case FORMULA: + case STRING: + if ( m_String == seq->getString() ) + { + _delta = 0.0; + return true; + } + return false; + case MONTH: + { + int i = month->findIndex( m_String ); + int j = month->findIndex( seq->getString() ); + int k = j; + + if ( j + 1 == i ) + _delta = -1.0; + else + _delta = ( double )( k - i ); + return true; + } + + case SHORTMONTH: + { + int i = shortMonth->findIndex( m_String ); + int j = shortMonth->findIndex( seq->getString() ); + int k = j; + + if ( j + 1 == i ) + _delta = -1.0; + else + _delta = ( double )( k - i ); + return true; + } + + case DAY: + { + int i = day->findIndex( m_String ); + int j = day->findIndex( seq->getString() ); + int k = j; + + if ( j + 1 == i ) + _delta = -1.0; + else + _delta = ( double )( k - i ); + kdDebug() << m_String << " i: " << i << " j: " << j << " k: " << k << " delta: " << _delta << endl; + return true; + } + + case SHORTDAY: + { + int i = shortDay->findIndex( m_String ); + int j = shortDay->findIndex( seq->getString() ); + int k = j; + + if ( j + 1 == i ) + _delta = -1.0; + else + _delta = ( double )( k - i ); + return true; + } + case OTHER: + { + if( m_OtherEnd!= seq->getIOtherEnd() || m_OtherBegin!= seq->getIOtherBegin()) + return false; + int i = other->findIndex( m_String ); + int j = other->findIndex( seq->getString() ); + int k = j; + if ( j < i ) + k += (m_OtherEnd - m_OtherBegin - 1); + /*if ( j + 1 == i ) + _delta = -1.0; + else*/ + _delta = ( double )( k - i ); + return true; + } + default: + return false; + } +} + +TQString AutoFillSequenceItem::getSuccessor( int _no, double _delta ) +{ + TQString erg; + switch( m_Type ) + { + case INTEGER: + erg.sprintf("%i", m_IValue + _no * (int)_delta ); + break; + case FLOAT: + erg.sprintf("%f", m_DValue + (double)_no * _delta ); + break; + case FORMULA: + case STRING: + erg = m_String; + break; + case MONTH: + { + int i = month->findIndex( m_String ); + int j = i + _no * (int) _delta; + while (j < 0) + j += month->count(); + int k = j % month->count(); + erg = (*month->at( k )); + } + break; + case SHORTMONTH: + { + int i = shortMonth->findIndex( m_String ); + int j = i + _no * (int) _delta; + while (j < 0) + j += shortMonth->count(); + int k = j % shortMonth->count(); + erg = (*shortMonth->at( k )); + } + break; + case DAY: + { + int i = day->findIndex( m_String ); + int j = i + _no * (int) _delta; + while (j < 0) + j += day->count(); + int k = j % day->count(); + erg = (*day->at( k )); + } + break; + case SHORTDAY: + { + int i = shortDay->findIndex( m_String ); + int j = i + _no * (int) _delta; + while (j < 0) + j += shortDay->count(); + int k = j % shortDay->count(); + erg = (*shortDay->at( k )); + } + break; + case OTHER: + { + int i = other->findIndex( m_String )-(m_OtherBegin+1); + int j = i + _no * (int) _delta; + int k = j % (m_OtherEnd - m_OtherBegin-1); + erg = (*other->at( (k+m_OtherBegin+1) )); + } + case TIME: + case DATE: + // gets never called but fixes a warning while compiling + break; + } + + return TQString( erg ); +} + +TQString AutoFillSequenceItem::getPredecessor( int _no, double _delta ) +{ + TQString erg; + switch( m_Type ) + { + case INTEGER: + erg.sprintf("%i", m_IValue - _no * (int)_delta ); + break; + case FLOAT: + erg.sprintf("%f", m_DValue - (double)_no * _delta ); + break; + case FORMULA: + case STRING: + erg = m_String; + break; + case MONTH: + { + int i = month->findIndex( m_String ); + int j = i - _no * (int) _delta; + while ( j < 0 ) + j += month->count(); + int k = j % month->count(); + erg = (*month->at( k )); + } + break; + case SHORTMONTH: + { + int i = shortMonth->findIndex( m_String ); + int j = i - _no * (int) _delta; + while ( j < 0 ) + j += shortMonth->count(); + int k = j % shortMonth->count(); + erg = (*shortMonth->at( k )); + } + break; + case DAY: + { + int i = day->findIndex( m_String ); + int j = i - _no * (int) _delta; + while ( j < 0 ) + j += day->count(); + int k = j % day->count(); + erg = (*day->at( k )); + } + break; + case SHORTDAY: + { + int i = shortDay->findIndex( m_String ); + int j = i - _no * (int) _delta; + while ( j < 0 ) + j += shortDay->count(); + int k = j % shortDay->count(); + erg = (*shortDay->at( k )); + } + break; + case OTHER: + { + int i = other->findIndex( m_String ) - (m_OtherBegin + 1); + int j = i - _no * (int) _delta; + while ( j < 0 ) + j += (m_OtherEnd - m_OtherBegin - 1); + int k = j % (m_OtherEnd - m_OtherBegin - 1); + erg = (*other->at( (k + m_OtherBegin + 1) )); + } + case TIME: + case DATE: + // gets never called but fixes a warning while compiling + break; + } + + return TQString( erg ); +} + +/********************************************************************************** + * + * AutoFillSequence + * + **********************************************************************************/ + +AutoFillSequence::AutoFillSequence( Cell *_cell ) +{ + sequence.setAutoDelete( true ); + + if ( _cell->isFormula() ) + { + TQString d = _cell->encodeFormula(); + sequence.append( new AutoFillSequenceItem( d ) ); + } + else if ( _cell->value().isNumber() ) + { + if ( floor( _cell->value().asFloat() ) == _cell->value().asFloat() ) + { + sequence.append( new AutoFillSequenceItem( (int)_cell->value().asFloat()) ); + } + else + sequence.append( new AutoFillSequenceItem(_cell->value().asFloat() ) ); + } + else if ( !_cell->text().isEmpty() ) + sequence.append( new AutoFillSequenceItem( _cell->text() ) ); +} + +bool AutoFillSequence::matches( AutoFillSequence* _seq, AutoFillDeltaSequence *_delta ) +{ + AutoFillDeltaSequence delta( this, _seq ); + if ( !delta.isOk() ) + return false; + + if ( delta.equals( _delta ) ) + return true; + + return false; +} + +void AutoFillSequence::fillCell( Cell *src, Cell *dest, AutoFillDeltaSequence *delta, int _block, bool down ) +{ + TQString erg = ""; + + // Special handling for formulas + if ( sequence.first() != 0L && sequence.first()->getType() == AutoFillSequenceItem::FORMULA ) + { + TQString f = dest->decodeFormula( sequence.first()->getString() ); + dest->setCellText( f ); + dest->copyFormat( src ); + return; + } + + AutoFillSequenceItem *item; + int i = 0; + if (down) + { + for ( item = sequence.first(); item != 0L; item = sequence.next() ) + erg += item->getSuccessor( _block, delta->getItemDelta( i++ ) ); + } + else + { + for ( item = sequence.first(); item != 0L; item = sequence.next() ) + erg += item->getPredecessor( _block, delta->getItemDelta( i++ ) ); + } + + dest->setCellText( erg ); + dest->copyFormat( src ); +} + +/********************************************************************************** + * + * Sheet + * + **********************************************************************************/ + +void Sheet::autofill( TQRect &src, TQRect &dest ) +{ + if (src == dest) + { + return; + } + + setRegionPaintDirty( dest ); + + doc()->emitBeginOperation(); + + if ( !doc()->undoLocked() ) + { + UndoAutofill *undo = new UndoAutofill( doc(), this, dest ); + doc()->addCommand( undo ); + } + + // disable the update of the max sroll range on each cell insertion + // Bug 124806: creating series takes extremely long time + enableScrollBarUpdates(false); + + // Fill from left to right + if ( src.left() == dest.left() && src.right() < dest.right() ) + { + for ( int y = src.top(); y <= src.bottom(); y++ ) + { + int x; + TQPtrList destList; + for ( x = src.right() + 1; x <= dest.right(); x++ ) + destList.append( nonDefaultCell( x, y ) ); + TQPtrList srcList; + for ( x = src.left(); x <= src.right(); x++ ) + srcList.append( cellAt( x, y ) ); + TQPtrList seqList; + seqList.setAutoDelete( true ); + for ( x = src.left(); x <= src.right(); x++ ) + seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); + fillSequence( srcList, destList, seqList ); + } + } + + // Fill from top to bottom + if ( src.top() == dest.top() && src.bottom() < dest.bottom() ) + { + for ( int x = src.left(); x <= dest.right(); x++ ) + { + int y; + TQPtrList destList; + for ( y = src.bottom() + 1; y <= dest.bottom(); y++ ) + destList.append( nonDefaultCell( x, y ) ); + TQPtrList srcList; + for ( y = src.top(); y <= src.bottom(); y++ ) + { + srcList.append( cellAt( x, y ) ); + } + TQPtrList seqList; + seqList.setAutoDelete( true ); + for ( y = src.top(); y <= src.bottom(); y++ ) + seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); + fillSequence( srcList, destList, seqList ); + } + } + + // Fill from right to left + if ( ( src.left() == dest.right() || src.left() == dest.right() - 1) && src.right() >= dest.right() ) + { + if ( src.left() != dest.right() ) + dest.setRight( dest.right() - 1 ); + + for ( int y = dest.top(); y <= dest.bottom(); y++ ) + { + int x; + TQPtrList destList; + + for ( x = dest.left(); x < src.left(); x++ ) + { + destList.append( nonDefaultCell( x, y ) ); + } + TQPtrList srcList; + for ( x = src.left(); x <= src.right(); x++ ) + { + srcList.append( cellAt( x, y ) ); + } + TQPtrList seqList; + seqList.setAutoDelete( true ); + for ( x = src.left(); x <= src.right(); x++ ) + seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); + fillSequence( srcList, destList, seqList, false ); + } + } + + // Fill from bottom to top + if ( (src.top() == dest.bottom() || src.top() == (dest.bottom() - 1) ) && src.bottom() >= dest.bottom() ) + { + if (src.top() != dest.bottom() ) + dest.setBottom(dest.bottom() - 1); + int startVal = TQMIN( dest.left(), src.left()); + int endVal = TQMAX(src.right(), dest.right()); + for ( int x = startVal; x <= endVal; x++ ) + { + int y; + TQPtrList destList; + for ( y = dest.top(); y < src.top(); y++ ) + destList.append( nonDefaultCell( x, y ) ); + TQPtrList srcList; + for ( y = src.top(); y <= src.bottom(); ++y ) + { + srcList.append( cellAt( x, y ) ); + } + TQPtrList seqList; + seqList.setAutoDelete( true ); + for ( y = src.top(); y <= src.bottom(); y++ ) + seqList.append( new AutoFillSequence( cellAt( x, y ) ) ); + fillSequence( srcList, destList, seqList, false ); + } + } + + // update the max sroll range ONCE here + enableScrollBarUpdates(true); + checkRangeHBorder(dest.right()); + checkRangeVBorder(dest.bottom()); + + emit sig_updateView( this ); + // doc()->emitEndOperation(); +} + + +void Sheet::fillSequence( TQPtrList& _srcList, + TQPtrList& _destList, + TQPtrList& _seqList, + bool down) +{ + doc()->emitBeginOperation(true); + + /* try finding an interval to use to fill the sequence */ + if (!FillSequenceWithInterval(_srcList, _destList, _seqList, down)) + { + /* if no interval was found, just copy down through */ + FillSequenceWithCopy(_srcList, _destList, down); + } + + doc()->emitEndOperation(); + +} + +TQVariant getDiff( const Value& value1, const Value& value2 , AutoFillSequenceItem::Type type ) +{ + if ( type == AutoFillSequenceItem::FLOAT ) + return TQVariant( value2.asFloat() - value1.asFloat() ); + if ( type == AutoFillSequenceItem::TIME || type == AutoFillSequenceItem::DATE ) + return TQVariant( (int)( value2.asInteger() - value1.asInteger() ) ); + + return TQVariant( (int)0 ); + // note: date and time difference can be calculated as + // the difference of the serial number + /* if( (type == AutoFillSequenceItem::FLOAT) || + (type == AutoFillSequenceItem::DATE) || + (type == AutoFillSequenceItem::TIME) ) + return ( value2.asFloat() - value1.asFloat() ); + else + return 0.0;*/ +} + +bool Sheet::FillSequenceWithInterval(TQPtrList& _srcList, + TQPtrList& _destList, + TQPtrList& _seqList, + bool down) +{ + if (_srcList.first()->isFormula()) + return false; + + TQPtrList deltaList; + deltaList.setAutoDelete( true ); + bool ok = false; + + if ( _srcList.first()->value().isNumber() || _srcList.first()->isDate() || _srcList.first()->isTime() ) + { + AutoFillSequenceItem::Type type; + + TQValueVector< TQVariant > tmp( _seqList.count() ); /*= new TQValueList< TQVariant > ( _seqList.count() )*/; + TQValueVector< TQVariant > diff( _seqList.count() ); /*= new TQValueList< TQVariant > ( _seqList.count() )*/; + int p = -1; + int count = 0; + int tmpcount = 0; + + Cell * cell = _srcList.first(); + Cell * cell2 = _srcList.next(); + + bool singleCellOnly = (cell2 == 0); + + if ( cell->isDate() ) + type = AutoFillSequenceItem::DATE; + else if ( cell->isTime() ) + type = AutoFillSequenceItem::TIME; + else if ( cell->value().isNumber() ) + type = AutoFillSequenceItem::FLOAT; + else + return false; // Cannot happen due to if condition + + while ( cell && (cell2 || singleCellOnly) ) + { + + Value cellValue = cell->value(); + Value cell2Value; + + //If we only have a single cell, the interval will depend upon the data type. + //- For numeric values, set the interval to 0 as we don't know what might be useful as a sequence + //- For time values, set the interval to one hour, as this will probably be the most useful setting + //- For date values, set the interval to one day, as this will probably be the most useful setting + // + //Note that the above options were chosen for consistency with Excel. Gnumeric (1.59) sets + //the interval to 0 for all types, OpenOffice.org (2.00) uses increments of 1.00, 1 hour and 1 day + //respectively + if (singleCellOnly) + { + if (type == AutoFillSequenceItem::FLOAT) + cell2Value = cellValue; + else if ( type == AutoFillSequenceItem::TIME) + cell2Value = Value( cellValue.asTime().addSecs( 60*60 ) ); + else if ( type == AutoFillSequenceItem::DATE) + cell2Value = Value ( cellValue.asDate().addDays( 1 ) ); + } + else + { + cell2Value = cell2->value(); + + // check if both cells contain the same type + if ( ( !cellValue.isNumber() ) + || ( cell2->isDate() && type != AutoFillSequenceItem::DATE ) + || ( cell2->isTime() && type != AutoFillSequenceItem::TIME ) ) + { + count = 0; + ok = false; + break; + } + } + + TQVariant delta = getDiff(cellValue , cell2Value , type ); + + if (count < 1) + { + p = count; + diff[ count++ ] = delta; + } + else + { + // same value again? + if (diff[ p ] == delta) + { + // store it somewhere else for the case we need it later + ++p; + tmp[ tmpcount++ ] = delta; + } + else + { + // if we have saved values in another buffer we have to insert them first + if ( tmpcount > 0 ) + { + for ( int i = 0; i < tmpcount; ++i ) + { + diff[ count++ ] = tmp.at( i ); + } + + tmpcount = 0; + } + + // insert the value + p = 0; + diff[ count++ ] = delta; + } + } + + // check next cell pair + cell = cell2; + cell2 = _srcList.next(); + } + + // we have found something: + if (count > 0 && (tmpcount > 0 || count == 1)) + { + TQVariant cellValue( (int) 0 ); + + Cell * dest; + Cell * src; + + int i = tmpcount; + if (down) + { + dest = _destList.first(); + src = _srcList.last(); + } + else + { + dest = _destList.last(); + src = _srcList.first(); + + i *= -1; + } + + if ( type == AutoFillSequenceItem::FLOAT ) + cellValue = src->value().asFloat(); + else + cellValue = (int)src->value().asInteger(); + + TQString res; + // copy all the data + while (dest) + { + if (down) + { + while ( i >= count ) + i -= count; + } + else + { + while ( i < 0) + i += count; + } + + TQVariant currentDiff = diff.at( i ); + + if (cellValue.type() == TQVariant::Double) + if (down) + cellValue = cellValue.asDouble() + currentDiff.asDouble(); + else + cellValue = cellValue.asDouble() - currentDiff.asDouble(); + else + if (down) + cellValue = cellValue.asInt() + currentDiff.asInt(); + else + cellValue = cellValue.asInt() - currentDiff.asInt(); + + if ( type == AutoFillSequenceItem::TIME) + { + Value timeValue = doc()->converter()->asTime( Value(cellValue.asInt()) ); + Value stringValue = doc()->converter()->asString( timeValue ); + dest->setCellText( stringValue.asString() ); + } + else if ( type == AutoFillSequenceItem::DATE) + { + Value dateValue = doc()->converter()->asDate( Value(cellValue.asInt()) ); + Value stringValue = doc()->converter()->asString( dateValue ); + dest->setCellText( stringValue.asString() ); + } + else + dest->setCellText( cellValue.asString() ); + + dest->copyFormat( src ); + + if (down) + { + ++i; + dest = _destList.next(); + src = _srcList.next(); + } + else + { + --i; + dest = _destList.prev(); + src = _srcList.prev(); + } + + if (!src) + src = _srcList.last(); + } + + ok = true; + } + else + { + ok = false; + } + + // delete tmp; + // delete diff; + + return ok; + } + + // What is the interval (block)? If your sheet looks like this: + // 1 3 5 7 9 + // then the interval has the length 1 and the delta list is [2]. + // 2 200 3 300 4 400 + // Here the interval has length 2 and the delta list is [1,100] + + + // How big is the interval. It is in the range from [2...n/2]. + // The case of an interval of length n is handled below. + // + // We try to find the shortest interval. + for ( unsigned int step = 1; step <= _seqList.count() / 2; step++ ) + { + kdDebug() << "Looking for interval: " << step << " seqList count: " << _seqList.count() << endl; + // If the interval is of length 'step' then the _seqList size must + // be a multiple of 'step' + if ( _seqList.count() % step == 0 ) + { + // Be optimistic + ok = true; + + deltaList.clear(); + + // Guess the delta by looking at cells 0...2*step-1 + // + // Since the interval may be of length 'step' we calculate the delta + // between cells 0 and step, 1 and step+1, ...., step-1 and 2*step-1 + for ( unsigned int t = 0; t < step; t++ ) + { + deltaList.append( new AutoFillDeltaSequence( _seqList.at(t), + _seqList.at(t+step) ) ); + ok = deltaList.getLast()->isOk(); + } + + /* Verify the delta by looking at cells step..._seqList.count() + We only looked at the cells 0 ... '2*step-1'. + Now test wether the cells from "(tst-1) * step + s" share the same delta + with the cell "tst * step + s" for all test=1..._seqList.count()/step + and for all s=0...step-1. + */ + for ( unsigned int tst = 1; ok && ( tst * step < _seqList.count() ); + tst++ ) + { + for ( unsigned int s = 0; ok && ( s < step ); s++ ) + { + if ( !_seqList.at( (tst-1) * step + s )-> + matches( _seqList.at( tst * step + s ), deltaList.at( s ) ) ) + ok = false; + } + } + // Did we find a valid interval ? + if ( ok ) + { + unsigned int s = 0; + // Amount of intervals (blocks) + int block = _seqList.count() / step; + + // Start iterating with the first cell + Cell * cell; + if (down) + cell = _destList.first(); + else + { + cell = _destList.last(); + block -= (_seqList.count() - 1); + } + + + // Loop over all destination cells + while ( cell ) + { + kdDebug() << "Valid interval, cell: " << cell->row() << " block: " << block << endl; + + // End of block? -> start again from beginning + if (down) + { + if ( s == step ) + { + ++block; + s = 0; + } + } + else + { + if ( s >= step ) + { + s = step - 1; + ++block; + } + } + + kdDebug() << "Step: " << step << " S: " << s << " Block " << block + << " SeqList: " << _seqList.count() + << " SrcList: " << _srcList.count() << " DeltaList: " << deltaList.count() + << endl; + + // Set the value of 'cell' by adding 'block' times the delta tp the + // value of cell 's'. + _seqList.at( s )->fillCell( _srcList.at( s ), cell, + deltaList.at( s ), block, down ); + + if (down) + { + // Next cell + cell = _destList.next(); + ++s; + } + else + { + // Previous cell + cell = _destList.prev(); + --s; + } + } + } + } + } + return ok; +} + +void Sheet::FillSequenceWithCopy(TQPtrList& _srcList, + TQPtrList& _destList, + bool down) +{ + // We did not find any valid interval. So just copy over the marked + // area. + Cell * cell; + + if (down) + cell = _destList.first(); + else + cell = _destList.last(); + int incr = 1; + unsigned int s = 0; + double factor = 1; + + if (!down) + s = _srcList.count() - 1; + + if ( _srcList.at( s )->value().isNumber() && + !(_srcList.at( s )->isDate() || _srcList.at( s )->isTime() ) ) + factor = _srcList.at( s )->value().asFloat(); + + while ( cell ) + { + if (down) + { + if ( s == _srcList.count() ) + s = 0; + } + else + { + if ( s >= _srcList.count() ) + s = _srcList.count() - 1; + } + + if ( !_srcList.at( s )->text().isEmpty() ) + { + if ( _srcList.at( s )->isFormula() ) + { + TQString d = _srcList.at( s )->encodeFormula(); + cell->setCellText( cell->decodeFormula( d ) ); + } + else if(_srcList.at( s )->value().isNumber() && _srcList.count()==1) + { + double val; + int format_type = _srcList.at( s )->formatType(); + if ( format_type == Percentage_format ) + { + factor = 0.01; // one percent + } + else if ( _srcList.at( s )->isTime() ) + { + // FIXME this is a workaround to avoid those nasty one minute off + // "dragging down" time is inaccurate overa large lists! + // This is the best approximation I could find (raphael) + if (down) + { +// factor = 1.000002/24. + 0.000000001; + factor = 0.041666751; + } + else + { //when dragging "up" the error must of course be the other way round + factor = 0.0416665; + } + } + + if (!down) + val = (_srcList.at( s )->value().asFloat() - (incr * factor)); + else + val = (_srcList.at( s )->value().asFloat() + (incr * factor)); + + TQString tmp; + tmp = tmp.setNum(val); + cell->setCellText( tmp ); + ++incr; + } + else if((AutoFillSequenceItem::month != 0L) + && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != 0L + && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != AutoFillSequenceItem::month->end() + && _srcList.count() == 1) + { + TQString strMonth=_srcList.at( s )->text(); + int i = AutoFillSequenceItem::month->findIndex( strMonth )+incr; + int k = (i) % AutoFillSequenceItem::month->count(); + cell->setCellText((*AutoFillSequenceItem::month->at( k ))); + incr++; + } + else if(AutoFillSequenceItem::day != 0L + && AutoFillSequenceItem::day->find( _srcList.at( s )->text()) != 0L + && AutoFillSequenceItem::day->find( _srcList.at( s )->text()) + != AutoFillSequenceItem::day->end() + && _srcList.count()==1) + { + TQString strDay=_srcList.at( s )->text(); + int i = AutoFillSequenceItem::day->findIndex( strDay )+incr; + int k = (i) % AutoFillSequenceItem::day->count(); + cell->setCellText((*AutoFillSequenceItem::day->at( k ))); + incr++; + } + else + { + TQRegExp number("(\\d+)"); + int pos =number.search(_srcList.at( s )->text()); + if( pos!=-1 ) + { + TQString tmp=number.cap(1); + int num=tmp.toInt()+incr; + cell->setCellText(_srcList.at( s )->text().replace(number,TQString::number(num))); + ++incr; + } + else if ( !_srcList.at( s )->link().isEmpty() ) + { + cell->setCellText( _srcList.at( s )->text() ); + cell->setLink( _srcList.at( s )->link() ); + } + else + { + cell->setCellText( _srcList.at( s )->text() ); + } + } + } + else + cell->setCellText( "" ); + + cell->copyFormat( _srcList.at( s ) ); + + if (down) + { + cell = _destList.next(); + ++s; + } + else + { + cell = _destList.prev(); + --s; + } + } + return; +} diff --git a/kspread/kspread_brush.cc b/kspread/kspread_brush.cc deleted file mode 100644 index d585950b..00000000 --- a/kspread/kspread_brush.cc +++ /dev/null @@ -1,270 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005-2006 Thorsten Zachmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_brush.h" - -#include -#include -#include -#include - -KSpreadBrush::KSpreadBrush() -: m_gColor1( TQt::red ) -, m_gColor2( TQt::green ) -, m_gType( BCT_GHORZ ) -, m_fillType( FT_BRUSH ) -, m_unbalanced( false ) -, m_xfactor( 100 ) -, m_yfactor( 100 ) -{ -} - - -KSpreadBrush::KSpreadBrush( const TQBrush &brush, const TQColor &gColor1, const TQColor &gColor2, - BCType gType, FillType fillType, bool unbalanced, - int xfactor, int yfactor ) -: m_brush( brush ) -, m_gColor1( gColor1 ) -, m_gColor2( gColor2 ) -, m_gType( gType ) -, m_fillType( fillType ) -, m_unbalanced( unbalanced ) -, m_xfactor( xfactor ) -, m_yfactor( yfactor ) -{ -} - - -KSpreadBrush & KSpreadBrush::operator=( const KSpreadBrush &brush ) -{ - m_brush = brush.m_brush; - m_gColor1 = brush.m_gColor1; - m_gColor2 = brush.m_gColor2; - m_gType = brush.m_gType; - m_fillType = brush.m_fillType; - m_unbalanced = brush.m_unbalanced; - m_xfactor = brush.m_xfactor; - m_yfactor = brush.m_yfactor; - return *this; -} - - -void KSpreadBrush::saveOasisFillStyle( KoGenStyle &styleObjectAuto, KoGenStyles& mainStyles ) const -{ - switch ( m_fillType ) - { - case FT_BRUSH: - { - if( m_brush.style() != TQt::NoBrush ) - { - KoOasisStyles::saveOasisFillStyle( styleObjectAuto, mainStyles, m_brush ); - } - else - { - styleObjectAuto.addProperty( "draw:fill","none" ); - } - break; - } - case FT_GRADIENT: - styleObjectAuto.addProperty( "draw:fill","gradient" ); -#if 0 - styleObjectAuto.addProperty( "draw:fill-gradient-name", saveOasisGradientStyle( mainStyles ) ); -#endif - break; - } -} - - -/*TQString KSpreadBrush::saveOasisGradientStyle( KoGenStyles& mainStyles ) const -{ - KoGenStyle gradientStyle( KPrDocument::STYLE_GRADIENT no family name); - gradientStyle.addAttribute( "draw:start-color", m_gColor1.name() ); - gradientStyle.addAttribute( "draw:end-color", m_gColor2.name() ); - - TQString unbalancedx( "50%" ); - TQString unbalancedy( "50%" ); - - if ( m_unbalanced ) - { - unbalancedx = TQString( "%1%" ).arg( m_xfactor / 4 + 50 ); - unbalancedy = TQString( "%1%" ).arg( m_yfactor / 4 + 50 ); - } - gradientStyle.addAttribute( "draw:cx", unbalancedx ); - gradientStyle.addAttribute( "draw:cy", unbalancedy ); - - switch( m_gType ) - { - case BCT_PLAIN: - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", "linear" ); - break; - case BCT_GHORZ: - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", "linear" ); - break; - case BCT_GVERT: - gradientStyle.addAttribute( "draw:angle", 900 ); - gradientStyle.addAttribute( "draw:style", "linear" ); - break; - case BCT_GDIAGONAL1: - gradientStyle.addAttribute( "draw:angle", 450 ); - gradientStyle.addAttribute( "draw:style", "linear" ); - break; - case BCT_GDIAGONAL2: - gradientStyle.addAttribute( "draw:angle", 135 ); - gradientStyle.addAttribute( "draw:style", "linear" ); - break; - case BCT_GCIRCLE: - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", "radial" ); - break; - case BCT_GRECT: - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", "square" ); - break; - case BCT_GPIPECROSS: - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", "axial" ); - break; - case BCT_GPYRAMID: //todo fixme ! it doesn't work ! - gradientStyle.addAttribute( "draw:angle", 0 ); - gradientStyle.addAttribute( "draw:style", 0 ); - break; - } - - return mainStyles.lookup( gradientStyle, "gradient" ); -}*/ - - -void KSpreadBrush::loadOasisFillStyle( KoOasisContext &context, const char * propertyType ) -{ - KoStyleStack &styleStack = context.styleStack(); - styleStack.setTypeProperties( propertyType ); - - if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill" ) ) - { - const TQString fill = styleStack.attributeNS( KoXmlNS::draw, "fill" ); - kdDebug(33001) << " load object gradient fill type :" << fill << endl; - - if ( fill == "solid" || fill == "hatch" ) - { - setBrush( KoOasisStyles::loadOasisFillStyle( styleStack, fill, context.oasisStyles() ) ); - } - else if ( fill == "gradient" ) - { - TQString style = styleStack.attributeNS( KoXmlNS::draw, "fill-gradient-name" ); - TQDomElement* draw = context.oasisStyles().drawStyles()[style]; - - if ( draw ) - { - setGColor1( draw->attributeNS( KoXmlNS::draw, "start-color", TQString() ) ); - setGColor2( draw->attributeNS( KoXmlNS::draw, "end-color", TQString() ) ); - - TQString type = draw->attributeNS( KoXmlNS::draw, "style", TQString() ); - kdDebug()<<" type :"<attributeNS( KoXmlNS::draw, "angle", TQString() ).toInt() / 10; - - // make sure the angle is between 0 and 359 - angle = abs( angle ); - angle -= ( (int) ( angle / 360 ) ) * 360; - - // What we are trying to do here is to find out if the given - // angle belongs to a horizontal, vertical or diagonal gradient. - int lower, upper, nearAngle = 0; - for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 ) - { - if ( upper >= angle ) - { - int distanceToUpper = abs( angle - upper ); - int distanceToLower = abs( angle - lower ); - nearAngle = distanceToUpper > distanceToLower ? lower : upper; - break; - } - } - // nearAngle should now be one of: 0, 45, 90, 135, 180... - if ( nearAngle == 0 || nearAngle == 180 ) - setGType( BCT_GHORZ ); // horizontal - else if ( nearAngle == 90 || nearAngle == 270 ) - setGType( BCT_GVERT ); // vertical - else if ( nearAngle == 45 || nearAngle == 225 ) - setGType( BCT_GDIAGONAL1 ); // diagonal 1 - else if ( nearAngle == 135 || nearAngle == 315 ) - setGType( BCT_GDIAGONAL2 ); // diagonal 2 - } - else if ( type == "radial" || type == "ellipsoid" ) - setGType( BCT_GCIRCLE ); // circle - else if ( type == "square" || type == "rectangular" ) - setGType( BCT_GRECT ); // rectangle - else if ( type == "axial" ) - setGType( BCT_GPIPECROSS ); // pipecross - else //safe - setGType( BCT_PLAIN ); // plain - - // Hard to map between x- and y-center settings of ooimpress - // and (un-)balanced settings of kpresenter. Let's try it. - int x, y; - if ( draw->hasAttributeNS( KoXmlNS::draw, "cx" ) ) - x = draw->attributeNS( KoXmlNS::draw, "cx", TQString() ).remove( '%' ).toInt(); - else - x = 50; - - if ( draw->hasAttributeNS( KoXmlNS::draw, "cy" ) ) - y = draw->attributeNS( KoXmlNS::draw, "cy", TQString() ).remove( '%' ).toInt(); - else - y = 50; - - if ( x == 50 && y == 50 ) - { - setGUnbalanced( false ); - setGXFactor( 100 ); - setGYFactor( 100 ); - } - else - { - setGUnbalanced( true ); - // map 0 - 100% to -200 - 200 - setGXFactor( 4 * x - 200 ); - setGYFactor( 4 * y - 200 ); - } - } - - // We have to set a brush with brushstyle != no background fill - // otherwise the properties dialog for the object won't - // display the preview for the gradient. - TQBrush tmpBrush; - tmpBrush.setStyle( static_cast( 1 ) ); - setBrush( tmpBrush ); - setFillType( FT_GRADIENT ); - } - else if ( fill == "none" ) - { - //nothing - } - else if ( fill == "bitmap" ) - { - //todo - //not implementer in kpresenter... - //the drawing object is filled with the bitmap specified by the draw:fill-image-name attribute. - //TQBrush implement setPixmap - //easy just add pixmap and store it. - } - } -} diff --git a/kspread/kspread_brush.cpp b/kspread/kspread_brush.cpp new file mode 100644 index 00000000..d585950b --- /dev/null +++ b/kspread/kspread_brush.cpp @@ -0,0 +1,270 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Thorsten Zachmann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_brush.h" + +#include +#include +#include +#include + +KSpreadBrush::KSpreadBrush() +: m_gColor1( TQt::red ) +, m_gColor2( TQt::green ) +, m_gType( BCT_GHORZ ) +, m_fillType( FT_BRUSH ) +, m_unbalanced( false ) +, m_xfactor( 100 ) +, m_yfactor( 100 ) +{ +} + + +KSpreadBrush::KSpreadBrush( const TQBrush &brush, const TQColor &gColor1, const TQColor &gColor2, + BCType gType, FillType fillType, bool unbalanced, + int xfactor, int yfactor ) +: m_brush( brush ) +, m_gColor1( gColor1 ) +, m_gColor2( gColor2 ) +, m_gType( gType ) +, m_fillType( fillType ) +, m_unbalanced( unbalanced ) +, m_xfactor( xfactor ) +, m_yfactor( yfactor ) +{ +} + + +KSpreadBrush & KSpreadBrush::operator=( const KSpreadBrush &brush ) +{ + m_brush = brush.m_brush; + m_gColor1 = brush.m_gColor1; + m_gColor2 = brush.m_gColor2; + m_gType = brush.m_gType; + m_fillType = brush.m_fillType; + m_unbalanced = brush.m_unbalanced; + m_xfactor = brush.m_xfactor; + m_yfactor = brush.m_yfactor; + return *this; +} + + +void KSpreadBrush::saveOasisFillStyle( KoGenStyle &styleObjectAuto, KoGenStyles& mainStyles ) const +{ + switch ( m_fillType ) + { + case FT_BRUSH: + { + if( m_brush.style() != TQt::NoBrush ) + { + KoOasisStyles::saveOasisFillStyle( styleObjectAuto, mainStyles, m_brush ); + } + else + { + styleObjectAuto.addProperty( "draw:fill","none" ); + } + break; + } + case FT_GRADIENT: + styleObjectAuto.addProperty( "draw:fill","gradient" ); +#if 0 + styleObjectAuto.addProperty( "draw:fill-gradient-name", saveOasisGradientStyle( mainStyles ) ); +#endif + break; + } +} + + +/*TQString KSpreadBrush::saveOasisGradientStyle( KoGenStyles& mainStyles ) const +{ + KoGenStyle gradientStyle( KPrDocument::STYLE_GRADIENT no family name); + gradientStyle.addAttribute( "draw:start-color", m_gColor1.name() ); + gradientStyle.addAttribute( "draw:end-color", m_gColor2.name() ); + + TQString unbalancedx( "50%" ); + TQString unbalancedy( "50%" ); + + if ( m_unbalanced ) + { + unbalancedx = TQString( "%1%" ).arg( m_xfactor / 4 + 50 ); + unbalancedy = TQString( "%1%" ).arg( m_yfactor / 4 + 50 ); + } + gradientStyle.addAttribute( "draw:cx", unbalancedx ); + gradientStyle.addAttribute( "draw:cy", unbalancedy ); + + switch( m_gType ) + { + case BCT_PLAIN: + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", "linear" ); + break; + case BCT_GHORZ: + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", "linear" ); + break; + case BCT_GVERT: + gradientStyle.addAttribute( "draw:angle", 900 ); + gradientStyle.addAttribute( "draw:style", "linear" ); + break; + case BCT_GDIAGONAL1: + gradientStyle.addAttribute( "draw:angle", 450 ); + gradientStyle.addAttribute( "draw:style", "linear" ); + break; + case BCT_GDIAGONAL2: + gradientStyle.addAttribute( "draw:angle", 135 ); + gradientStyle.addAttribute( "draw:style", "linear" ); + break; + case BCT_GCIRCLE: + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", "radial" ); + break; + case BCT_GRECT: + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", "square" ); + break; + case BCT_GPIPECROSS: + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", "axial" ); + break; + case BCT_GPYRAMID: //todo fixme ! it doesn't work ! + gradientStyle.addAttribute( "draw:angle", 0 ); + gradientStyle.addAttribute( "draw:style", 0 ); + break; + } + + return mainStyles.lookup( gradientStyle, "gradient" ); +}*/ + + +void KSpreadBrush::loadOasisFillStyle( KoOasisContext &context, const char * propertyType ) +{ + KoStyleStack &styleStack = context.styleStack(); + styleStack.setTypeProperties( propertyType ); + + if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill" ) ) + { + const TQString fill = styleStack.attributeNS( KoXmlNS::draw, "fill" ); + kdDebug(33001) << " load object gradient fill type :" << fill << endl; + + if ( fill == "solid" || fill == "hatch" ) + { + setBrush( KoOasisStyles::loadOasisFillStyle( styleStack, fill, context.oasisStyles() ) ); + } + else if ( fill == "gradient" ) + { + TQString style = styleStack.attributeNS( KoXmlNS::draw, "fill-gradient-name" ); + TQDomElement* draw = context.oasisStyles().drawStyles()[style]; + + if ( draw ) + { + setGColor1( draw->attributeNS( KoXmlNS::draw, "start-color", TQString() ) ); + setGColor2( draw->attributeNS( KoXmlNS::draw, "end-color", TQString() ) ); + + TQString type = draw->attributeNS( KoXmlNS::draw, "style", TQString() ); + kdDebug()<<" type :"<attributeNS( KoXmlNS::draw, "angle", TQString() ).toInt() / 10; + + // make sure the angle is between 0 and 359 + angle = abs( angle ); + angle -= ( (int) ( angle / 360 ) ) * 360; + + // What we are trying to do here is to find out if the given + // angle belongs to a horizontal, vertical or diagonal gradient. + int lower, upper, nearAngle = 0; + for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 ) + { + if ( upper >= angle ) + { + int distanceToUpper = abs( angle - upper ); + int distanceToLower = abs( angle - lower ); + nearAngle = distanceToUpper > distanceToLower ? lower : upper; + break; + } + } + // nearAngle should now be one of: 0, 45, 90, 135, 180... + if ( nearAngle == 0 || nearAngle == 180 ) + setGType( BCT_GHORZ ); // horizontal + else if ( nearAngle == 90 || nearAngle == 270 ) + setGType( BCT_GVERT ); // vertical + else if ( nearAngle == 45 || nearAngle == 225 ) + setGType( BCT_GDIAGONAL1 ); // diagonal 1 + else if ( nearAngle == 135 || nearAngle == 315 ) + setGType( BCT_GDIAGONAL2 ); // diagonal 2 + } + else if ( type == "radial" || type == "ellipsoid" ) + setGType( BCT_GCIRCLE ); // circle + else if ( type == "square" || type == "rectangular" ) + setGType( BCT_GRECT ); // rectangle + else if ( type == "axial" ) + setGType( BCT_GPIPECROSS ); // pipecross + else //safe + setGType( BCT_PLAIN ); // plain + + // Hard to map between x- and y-center settings of ooimpress + // and (un-)balanced settings of kpresenter. Let's try it. + int x, y; + if ( draw->hasAttributeNS( KoXmlNS::draw, "cx" ) ) + x = draw->attributeNS( KoXmlNS::draw, "cx", TQString() ).remove( '%' ).toInt(); + else + x = 50; + + if ( draw->hasAttributeNS( KoXmlNS::draw, "cy" ) ) + y = draw->attributeNS( KoXmlNS::draw, "cy", TQString() ).remove( '%' ).toInt(); + else + y = 50; + + if ( x == 50 && y == 50 ) + { + setGUnbalanced( false ); + setGXFactor( 100 ); + setGYFactor( 100 ); + } + else + { + setGUnbalanced( true ); + // map 0 - 100% to -200 - 200 + setGXFactor( 4 * x - 200 ); + setGYFactor( 4 * y - 200 ); + } + } + + // We have to set a brush with brushstyle != no background fill + // otherwise the properties dialog for the object won't + // display the preview for the gradient. + TQBrush tmpBrush; + tmpBrush.setStyle( static_cast( 1 ) ); + setBrush( tmpBrush ); + setFillType( FT_GRADIENT ); + } + else if ( fill == "none" ) + { + //nothing + } + else if ( fill == "bitmap" ) + { + //todo + //not implementer in kpresenter... + //the drawing object is filled with the bitmap specified by the draw:fill-image-name attribute. + //TQBrush implement setPixmap + //easy just add pixmap and store it. + } + } +} diff --git a/kspread/kspread_canvas.cc b/kspread/kspread_canvas.cc deleted file mode 100644 index 0518e274..00000000 --- a/kspread/kspread_canvas.cc +++ /dev/null @@ -1,6167 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2006 Robert Knight - Copyright 2006 Inge Wallin - Copyright 2006 Stefan Nikolaus - Copyright 1999-2002,2004 Laurent Montel - Copyright 2002-2005 Ariya Hidayat - Copyright 1999-2004 David Faure - Copyright 2004-2005 Meni Livne - Copyright 2001-2003 Philipp Mueller - Copyright 2002-2003 Norbert Andres - Copyright 2003 Hamish Rodda - Copyright 2003 Joseph Wenninger - Copyright 2003 Lukas Tinkl - Copyright 2000-2002 Werner Trobin - Copyright 2002 Harri Porten - Copyright 2002 John Dailey - Copyright 2002 Daniel Naber - Copyright 1999-2000 Torben Weis - Copyright 1999-2000 Stephan Kulow - Copyright 2000 Bernd Wuebben - Copyright 2000 Wilco Greven - Copyright 2000 Simon Hausmann - Copyright 1999 Boris Wedl - Copyright 1999 Reginald Stadlbauer - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "commands.h" -#include "kspread_doc.h" -#include "kspread_editors.h" -#include "kspread_global.h" -#include "kspread_locale.h" -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_undo.h" -#include "kspread_util.h" -#include "kspread_view.h" -#include "selection.h" - -#include "kspread_canvas.h" - -// TODO Stefan: undefine/remove, if non-contiguous selections don't work -// properly or if we are sure, that they do. ;-) -#define NONCONTIGUOUSSELECTION - -#define MIN_SIZE 10 - -using namespace KSpread; - -class Canvas::Private -{ - public: - ComboboxLocationEditWidget *posWidget; - KSpread::EditWidget *editWidget; - KSpread::CellEditor *cellEditor; - - View *view; - TQTimer* scrollTimer; - - // Non visible range left from current screen - // Example: If the first visible column is 'E', then xOffset stores - // the width of the invisible columns 'A' to 'D'. - double xOffset; - - // Non visible range on top of the current screen - // Example: If the first visible row is '5', then yOffset stores - // the height of the invisible rows '1' to '4'. - double yOffset; - - // Used to draw the grey grid that is usually only visible on the - // screen, but not by printing on paper. - TQPen defaultGridPen; - - // see setLastEditorWithFocus, lastEditorWithFocus - Canvas::EditorType focusEditorType; - - TQLabel *validationInfo; - - // true if the user is to choose a cell. - bool chooseCell; - - // True when the mouse button is pressed - bool mousePressed; - - // If the user is dragging around with the mouse then this tells us what he is doing. - // The user may want to mark cells or he started in the lower right corner - // of the marker which is something special. The values for the 2 above - // methods are called 'Mark' and 'ResizeCell' or 'AutoFill' depending - // on the mouse button used. By default this variable holds - // the value 'NoAction'. - Canvas::MouseActions mouseAction; - - // If we use the lower right corner of the marker to start autofilling, then this - // rectangle conatins all cells that were already marker when the user started - // to mark the rectangle which he wants to become autofilled. - TQRect autoFillSource; - - // Start coordinates for drag and drop - TQPoint dragStart; - bool dragging; - - // Used to indicate whether the user started drawing a rubber band rectangle - bool rubberBandStarted; - TQPoint rubberBandStart; - TQPoint rubberBandEnd; - - // If the mouse is over some anchor ( in the sense of HTML anchors ) - TQString anchor; - - bool mouseSelectedObject; - bool drawContour; - ModifyType modType; - /** - * Saves the last mouse position during mouse move events. - */ - TQPoint m_savedMousePos; - - //---- stuff needed for resizing ---- - /// object which gets resized - EmbeddedObject *m_resizeObject; - /// ratio of the object ( width / height ) - double m_ratio; - bool m_isResizing; - /// The last position of the mouse during moving - KoPoint m_origMousePos; - - //---- stuff needed for moving ---- - bool m_isMoving; - KoPoint m_moveStartPoint; - - /// size of the object at when resizing is started - KoRect m_rectBeforeResize; - /// Start position for move with mouse - KoPoint m_moveStartPosMouse; - - /// object which is selected and should be shown above all the other objects - EmbeddedObject * m_objectDisplayAbove; - - // bool mouseOverHighlightRangeSizeGrip; - - // The row and column of 1) the last cell under mouse pointer, 2) the last focused cell, and - // the last spoken cell. - int prevSpokenPointerRow; - int prevSpokenPointerCol; - int prevSpokenFocusRow; - int prevSpokenFocusCol; - int prevSpokenRow; - int prevSpokenCol; -}; - - - -/**************************************************************** - * - * Canvas - * - ****************************************************************/ - -Canvas::Canvas (View *_view) - : TQWidget( _view, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ) -{ - d = new Private; - - d->cellEditor = 0; - d->chooseCell = false; - d->validationInfo = 0L; - - TQWidget::setFocusPolicy( TQ_StrongFocus ); - - d->dragStart = TQPoint( -1, -1 ); - d->dragging = false; - - - d->defaultGridPen.setColor( lightGray ); - d->defaultGridPen.setWidth( 1 ); - d->defaultGridPen.setStyle( Qt::SolidLine ); - - d->xOffset = 0.0; - d->yOffset = 0.0; - d->view = _view; - // m_eAction = DefaultAction; - d->mouseAction = NoAction; - d->rubberBandStarted = false; - // m_bEditDirtyFlag = false; - - //Now built afterwards(David) - //d->editWidget = d->view->editWidget(); - d->posWidget = d->view->posWidget(); - - setBackgroundMode( PaletteBase ); - - setMouseTracking( true ); - d->mousePressed = false; - d->mouseSelectedObject = false; - d->drawContour = false; - d->modType = MT_NONE; - - d->m_resizeObject = 0L; - d->m_ratio = 0.0; - d->m_isMoving = false; - d->m_objectDisplayAbove = 0; - d->m_isResizing = false; - - d->prevSpokenPointerRow = -1; - d->prevSpokenPointerCol = -1; - d->prevSpokenFocusRow = -1; - d->prevSpokenFocusCol = -1; - d->prevSpokenRow = -1; - d->prevSpokenCol = -1; - - d->scrollTimer = new TQTimer( this ); - connect (d->scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); - - if( d->view) - { - connect( d->view, TQT_SIGNAL( autoScroll( const TQPoint & )), this, TQT_SLOT( slotAutoScroll( const TQPoint &))); - } - if (kospeaker) - { - connect (kospeaker, TQT_SIGNAL(customSpeakWidget(TQWidget*, const TQPoint&, uint)), - this, TQT_SLOT(speakCell(TQWidget*, const TQPoint&, uint))); - } - - setFocus(); - installEventFilter( this ); - (void)new ToolTip( this ); - setAcceptDrops( true ); - setInputMethodEnabled( true ); // ensure using the InputMethod - - setWFlags(TQt::WNoAutoErase); -} - -Canvas::~Canvas() -{ - delete d->scrollTimer; - delete d->validationInfo; - delete d; -} - -KSpread::View* Canvas::view() const -{ - return d->view; -} - -Doc* Canvas::doc() const -{ - return d->view->doc(); -} - -void Canvas::setEditWidget( KSpread::EditWidget * ew ) -{ - d->editWidget = ew; -} - -KSpread::EditWidget* Canvas::editWidget() const -{ - return d->editWidget; -} - -CellEditor* Canvas::editor() const -{ - return d->cellEditor; -} - -double Canvas::xOffset() const -{ - return d->xOffset; -} - -double Canvas::yOffset() const -{ - return d->yOffset; -} - -void Canvas::setXOffset( double _xOffset ) -{ - d->xOffset = _xOffset; -} - -void Canvas::setYOffset( double _yOffset ) -{ - d->yOffset = _yOffset; -} - -const TQPen& Canvas::defaultGridPen() const -{ - return d->defaultGridPen; -} - -void Canvas::setLastEditorWithFocus( Canvas::EditorType type ) -{ - d->focusEditorType = type; -} - -Canvas::EditorType Canvas::lastEditorWithFocus() const -{ - return d->focusEditorType; -} - - -bool Canvas::eventFilter( TQObject *o, TQEvent *e ) -{ - /* this canvas event filter acts on events sent to the line edit as well - as events to this filter itself. - */ - if ( !o || !e ) - return true; - switch ( e->type() ) - { - case TQEvent::KeyPress: - { - TQKeyEvent * keyev = TQT_TQKEYEVENT(e); - if ((keyev->key()==Key_Tab) || (keyev->key()==Key_Backtab)) - { - keyPressEvent ( keyev ); - return true; - } - break; - } - case TQEvent::IMStart: - case TQEvent::IMCompose: - case TQEvent::IMEnd: - { - TQIMEvent * imev = static_cast(e); - processIMEvent( imev ); - break; - } - default: - break; - } - return false; -} - -bool Canvas::focusNextPrevChild( bool ) -{ - return true; // Don't allow to go out of the canvas widget by pressing "Tab" -} - -Selection* Canvas::selectionInfo() const -{ - return d->view->selectionInfo(); -} - -Selection* Canvas::choice() const -{ - return d->view->choice(); -} - -TQRect Canvas::selection() const -{ - return d->view->selectionInfo()->selection(); -} - -TQPoint Canvas::marker() const -{ - return d->view->selectionInfo()->marker(); -} - -int Canvas::markerColumn() const -{ - return d->view->selectionInfo()->marker().x(); -} - -int Canvas::markerRow() const -{ - return d->view->selectionInfo()->marker().y(); -} - -double Canvas::zoom() const -{ - return d->view->zoom(); -} - -void Canvas::setChooseMode(bool state) -{ - d->chooseCell = state; -} - -bool Canvas::chooseMode() const -{ - return d->chooseCell; -} - -void Canvas::startChoose() -{ - if ( d->chooseCell ) - return; - - choice()->clear(); - choice()->setSheet(activeSheet()); - - // It is important to enable this AFTER we set the rect! - d->chooseCell = true; -} - -void Canvas::startChoose( const TQRect& rect ) -{ - if (d->chooseCell) - return; - - choice()->setSheet(activeSheet()); - choice()->initialize(rect); - - // It is important to enable this AFTER we set the rect! - d->chooseCell = true; -} - -void Canvas::endChoose() -{ - // While entering a formula the choose mode is turned on and off. - // Clear the choice even if we are not in choose mode. Otherwise, - // cell references will stay highlighted. - if (!choice()->isEmpty()) - { - choice()->clear(); - update(); - } - - if ( !d->chooseCell ) - return; - - d->chooseCell = false; - - Sheet *sheet = choice()->sheet(); - if (sheet) - { - d->view->setActiveSheet(sheet); - } -} - -HBorder* Canvas::hBorderWidget() const -{ - return d->view->hBorderWidget(); -} - -VBorder* Canvas::vBorderWidget() const -{ - return d->view->vBorderWidget(); -} - -TQScrollBar* Canvas::horzScrollBar() const -{ - return d->view->horzScrollBar(); -} - -TQScrollBar* Canvas::vertScrollBar() const -{ - return d->view->vertScrollBar(); -} - -Sheet* Canvas::findSheet( const TQString& _name ) const -{ - return d->view->doc()->map()->findSheet( _name ); -} - -Sheet* Canvas::activeSheet() const -{ - return d->view->activeSheet(); -} - -void Canvas::validateSelection() -{ - Sheet* sheet = activeSheet(); - if (!sheet) - { - return; - } - - if ( selectionInfo()->isSingular() ) - { - int col = selectionInfo()->marker().x(); - int row = selectionInfo()->marker().y(); - Cell * cell = sheet->cellAt( col,row ); - if ( cell && cell->getValidity(0) && cell->getValidity()->displayValidationInformation) - { - TQString title = cell->getValidity(0)->titleInfo; - TQString message = cell->getValidity(0)->messageInfo; - if ( title.isEmpty() && message.isEmpty() ) - return; - - if ( !d->validationInfo ) - d->validationInfo = new TQLabel( this ); - kdDebug()<<" display info validation\n"; - double u = cell->dblWidth( col ); - double v = cell->dblHeight( row ); - double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset(); - double ypos = sheet->dblRowPos( markerRow() ) - yOffset(); - // Special treatment for obscured cells. - if ( cell->isObscured() && cell->isPartOfMerged() ) - { - cell = cell->obscuringCells().first(); - int moveX = cell->column(); - int moveY = cell->row(); - - // Use the obscuring cells dimensions - u = cell->dblWidth( moveX ); - v = cell->dblHeight( moveY ); - xpos = sheet->dblColumnPos( moveX ); - ypos = sheet->dblRowPos( moveY ); - } - //d->validationInfo->setGeometry( 3, y + 3, len + 2, hei + 2 ); - d->validationInfo->setAlignment( TQt::AlignVCenter ); - TQPainter painter; - painter.begin( this ); - int len = 0; - int hei = 0; - TQString resultText; - if ( !title.isEmpty() ) - { - len = painter.fontMetrics().width( title ); - hei = painter.fontMetrics().height(); - resultText = title + "\n"; - } - if ( !message.isEmpty() ) - { - int i = 0; - int pos = 0; - TQString t; - do - { - i = message.find( "\n", pos ); - if ( i == -1 ) - t = message.mid( pos, message.length() - pos ); - else - { - t = message.mid( pos, i - pos ); - pos = i + 1; - } - hei += painter.fontMetrics().height(); - len = TQMAX( len, painter.fontMetrics().width( t ) ); - } - while ( i != -1 ); - resultText += message; - } - painter.end(); - d->validationInfo->setText( resultText ); - - KoRect unzoomedMarker( xpos - xOffset()+u, - ypos - yOffset()+v, - len, - hei ); - TQRect marker( d->view->doc()->zoomRect( unzoomedMarker ) ); - - d->validationInfo->setGeometry( marker ); - d->validationInfo->show(); - } - else - { - delete d->validationInfo; - d->validationInfo = 0L; - } - } - else - { - delete d->validationInfo; - d->validationInfo = 0L; - } -} - - -void Canvas::scrollToCell(TQPoint location) const -{ - Sheet* sheet = activeSheet(); - if (sheet == NULL) - return; - - if (d->view->isLoading()) - return; - - // kdDebug(36001) << "------------------------------------------------" << endl; - // kdDebug(36001) << "scrollToCell(): at location [" << location.x() << "," - // << location.y() << "]" << endl; - - /* we don't need this cell ptr, but this call is necessary to update the - scroll bar correctly. I don't like having that as part of the cellAt function - but I suppose that's ok for now. - */ - Cell* cell = sheet->cellAt(location.x(), location.y(), true); - Q_UNUSED(cell); - - double unzoomedWidth = d->view->doc()->unzoomItX( width() ); - double unzoomedHeight = d->view->doc()->unzoomItY( height() ); - - //kdDebug(36001) << "Unzoomed view size: [" << unzoomedWidth << "," - // << unzoomedHeight << "]" << endl; - - // xpos is the position of the cell in the current window in unzoomed - // document coordinates. - double xpos; - if ( sheet->layoutDirection()==Sheet::LeftToRight ) - xpos = sheet->dblColumnPos( location.x() ) - xOffset(); - else - xpos = unzoomedWidth - sheet->dblColumnPos( location.x() ) + xOffset(); - double ypos = sheet->dblRowPos( location.y() ) - yOffset(); - - //kdDebug(36001) << "Position: [" << xpos << "," << ypos << "]" << endl; - - double minY = 40.0; - double maxY = unzoomedHeight - 40.0; - //kdDebug(36001) << "Canvas::scrollToCell : height=" << height() << endl; - //kdDebug(36001) << "Canvas::scrollToCell : width=" << width() << endl; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) { - // Right to left sheet. - - double minX = unzoomedWidth - 100.0; // less than that, we scroll - double maxX = 100.0; // more than that, we scroll - - // kdDebug() << "rtl2: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << ", Offset: " << xOffset() << endl; - - // Do we need to scroll left? - if ( xpos > minX ) - horzScrollBar()->setValue( horzScrollBar()->maxValue() - - d->view->doc()->zoomItX( xOffset() - xpos + minX ) ); - - // Do we need to scroll right? - else if ( xpos < maxX ) - { - double horzScrollBarValue = xOffset() - xpos + maxX; - double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth; - - //We don't want to display any area > KS_colMax widths - if ( horzScrollBarValue > horzScrollBarValueMax ) - horzScrollBarValue = horzScrollBarValueMax; - - horzScrollBar()->setValue( horzScrollBar()->maxValue() - - d->view->doc()->zoomItX( horzScrollBarValue ) ); - } - } - else { - // Left to right sheet. - - double minX = 100.0; // less than that, we scroll - double maxX = unzoomedWidth - 100.0; // more than that, we scroll - - // kdDebug() << "ltr: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << endl; - - // Do we need to scroll left? - if ( xpos < minX ) - horzScrollBar()->setValue( d->view->doc()->zoomItX( xOffset() + xpos - minX ) ); - - // Do we need to scroll right? - else if ( xpos > maxX ) - { - double horzScrollBarValue = xOffset() + xpos - maxX; - double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth; - - //We don't want to display any area > KS_colMax widths - if ( horzScrollBarValue > horzScrollBarValueMax ) - horzScrollBarValue = horzScrollBarValueMax; - - horzScrollBar()->setValue( d->view->doc()->zoomItX( horzScrollBarValue ) ); - } - } -// kdDebug() << "ltr: YPos: " << ypos << ", min: " << minY << ", maxY: " << maxY << endl; - - // do we need to scroll up - if ( ypos < minY ) - vertScrollBar()->setValue( d->view->doc()->zoomItY( yOffset() + ypos - minY ) ); - - // do we need to scroll down - else if ( ypos > maxY ) - { - double vertScrollBarValue = yOffset() + ypos - maxY; - double vertScrollBarValueMax = sheet->sizeMaxY() - unzoomedHeight; - - //We don't want to display any area > KS_rowMax heights - if ( vertScrollBarValue > vertScrollBarValueMax ) - vertScrollBarValue = vertScrollBarValueMax; - - vertScrollBar()->setValue( d->view->doc()->zoomItY( vertScrollBarValue ) ); - } -} - -void Canvas::slotScrollHorz( int _value ) -{ - Sheet * sheet = activeSheet(); - - if ( sheet == 0L ) - return; - - kdDebug(36001) << "slotScrollHorz: value = " << _value << endl; - //kdDebug(36001) << kdBacktrace() << endl; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - _value = horzScrollBar()->maxValue() - _value; - - double unzoomedValue = d->view->doc()->unzoomItX( _value ); - double dwidth = d->view->doc()->unzoomItX( width() ); - - d->view->doc()->emitBeginOperation(false); - - if ( unzoomedValue < 0.0 ) { - kdDebug (36001) - << "Canvas::slotScrollHorz: value out of range (unzoomedValue: " - << unzoomedValue << ")" << endl; - unzoomedValue = 0.0; - } - - double xpos = sheet->dblColumnPos( TQMIN( KS_colMax, d->view->activeSheet()->maxColumn()+10 ) ) - d->xOffset; - if ( unzoomedValue > ( xpos + d->xOffset ) ) - unzoomedValue = xpos + d->xOffset; - - sheet->enableScrollBarUpdates( false ); - - // Relative movement - int dx = d->view->doc()->zoomItX( d->xOffset - unzoomedValue ); - - - /* what cells will need painted now? */ - TQRect area = visibleCells(); - double tmp; - if (dx > 0) - { - area.setRight( area.left() ); - area.setLeft( sheet->leftColumn( unzoomedValue, tmp ) ); - } - else - { - area.setLeft( area.right() ); - area.setRight( sheet->rightColumn( dwidth + unzoomedValue ) ); - } - - sheet->setRegionPaintDirty(area); - - // New absolute position - kdDebug(36001) << "slotScrollHorz(): XOffset before setting: " - << d->xOffset << endl; - d->xOffset = unzoomedValue; - kdDebug(36001) << "slotScrollHorz(): XOffset after setting: " - << d->xOffset << endl; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - dx = -dx; - - scroll( dx, 0 ); - - hBorderWidget()->scroll( dx, 0 ); - - sheet->enableScrollBarUpdates( true ); - - d->view->doc()->emitEndOperation( sheet->visibleRect( this ) ); -} - -void Canvas::slotScrollVert( int _value ) -{ - if ( activeSheet() == 0L ) - return; - - d->view->doc()->emitBeginOperation(false); - double unzoomedValue = d->view->doc()->unzoomItY( _value ); - - if ( unzoomedValue < 0 ) - { - unzoomedValue = 0; - kdDebug (36001) << "Canvas::slotScrollVert: value out of range (unzoomedValue: " << - unzoomedValue << ")" << endl; - } - - double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, d->view->activeSheet()->maxRow()+10 ) ); - if ( unzoomedValue > ypos ) - unzoomedValue = ypos; - - activeSheet()->enableScrollBarUpdates( false ); - - // Relative movement - int dy = d->view->doc()->zoomItY( d->yOffset - unzoomedValue ); - - - /* what cells will need painted now? */ - TQRect area = visibleCells(); - double tmp; - if (dy > 0) - { - area.setBottom(area.top()); - area.setTop(activeSheet()->topRow(unzoomedValue, tmp)); - } - else - { - area.setTop(area.bottom()); - area.setBottom(activeSheet()->bottomRow(d->view->doc()->unzoomItY(height()) + - unzoomedValue)); - } - - activeSheet()->setRegionPaintDirty( area ); - - // New absolute position - d->yOffset = unzoomedValue; - scroll( 0, dy ); - vBorderWidget()->scroll( 0, dy ); - - activeSheet()->enableScrollBarUpdates( true ); - - d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) ); -} - -void Canvas::slotMaxColumn( int _max_column ) -{ - int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); - double xpos = activeSheet()->dblColumnPos( TQMIN( KS_colMax, _max_column + 10 ) ) - xOffset(); - double unzoomWidth = d->view->doc()->unzoomItX( width() ); - - //Don't go beyond the maximum column range (KS_colMax) - double sizeMaxX = activeSheet()->sizeMaxX(); - if ( xpos > sizeMaxX - xOffset() - unzoomWidth ) - xpos = sizeMaxX - xOffset() - unzoomWidth; - - horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( xpos + xOffset() ) ); - - if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) - horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); -} - -void Canvas::slotMaxRow( int _max_row ) -{ - double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, _max_row + 10 ) ) - yOffset(); - double unzoomHeight = d->view->doc()->unzoomItY( height() ); - - //Don't go beyond the maximum row range (KS_rowMax) - double sizeMaxY = activeSheet()->sizeMaxY(); - if ( ypos > sizeMaxY - yOffset() - unzoomHeight ) - ypos = sizeMaxY - yOffset() - unzoomHeight; - - vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( ypos + yOffset() ) ); -} - -void Canvas::mouseMoveEvent( TQMouseEvent * _ev ) -{ - // Dont allow modifications if document is readonly. Selecting is no modification - if ( (!d->view->koDocument()->isReadWrite()) && (d->mouseAction!=Mark)) - return; - - if ( d->mousePressed && d->modType != MT_NONE ) - { - KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) ); - docPoint += KoPoint( xOffset(), yOffset() ); - - if ( d->modType == MT_MOVE ) - { - if ( !d->m_isMoving ) - { - d->m_moveStartPoint = objectRect( false ).topLeft(); - d->m_isMoving = true; - } - moveObjectsByMouse( docPoint, _ev->state() & AltButton || _ev->state() & ControlButton ); - } - else if ( d->m_resizeObject ) - { - if ( !d->m_isResizing ) - d->m_isResizing = true; - - bool keepRatio = d->m_resizeObject->isKeepRatio(); - if ( _ev->state() & AltButton ) - { - keepRatio = true; - } - docPoint = KoPoint( doc()->unzoomPoint( _ev->pos() ) ); - resizeObject( d->modType, docPoint, keepRatio ); - } - return; - } - - - /*if ( d->mousePressed && d->m_resizeObject && d->modType != MT_NONE ) - { - if ( !d->m_isMoving ) - { - d->m_isMoving = true; - update(); - } - else - update( d->m_boundingRealRect ); - - - TQRect drawingRect; - - if ( d->modType == MT_MOVE ) - { - drawingRect = TQRect( _ev->pos() - d->m_origPos, d->m_origSize ); - d->m_boundingRealRect = drawingRect; - } - else - { - drawingRect = doc()->zoomRect( calculateNewGeometry(d->modType, _ev->pos().x(), _ev->pos().y() ) ); - drawingRect.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ) , (int)( -yOffset() * doc()->zoomedResolutionY() ) ); - } - - // Autoscrolling - if ( ( d->modType == MT_MOVE && drawingRect.top() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().y() < 0 ) ) - { - vertScrollBar()->setValue ((int) ( vertScrollBar()->value() - - autoScrollAccelerationY( - drawingRect.top() ) ) ); - } - else if ( ( d->modType == MT_MOVE && drawingRect.bottom() > height() ) || ( d->modType != MT_MOVE && _ev->pos().y() > height() ) ) - { - vertScrollBar()->setValue ((int) ( vertScrollBar()->value() + - autoScrollAccelerationY ( drawingRect.bottom() - height() ) ) ); - } - if ( ( d->modType == MT_MOVE && drawingRect.left() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().x() < 0 ) ) - { - horzScrollBar()->setValue ((int) ( horzScrollBar()->value() - - autoScrollAccelerationX( - drawingRect.left() ) ) ); - } - else if ( ( d->modType == MT_MOVE && drawingRect.right() > width() ) || ( d->modType != MT_MOVE && _ev->pos().x() > width() ) ) - { - horzScrollBar()->setValue ((int) (horzScrollBar()->value() + - autoScrollAccelerationX( drawingRect.right() - width() ) ) ); - } - - if ( drawingRect.left() < 0 ) - { - drawingRect.setRight( drawingRect.right() -drawingRect.left() ); - drawingRect.setLeft( 0 ); - } - if ( drawingRect.top() < 0 ) - { - drawingRect.setBottom( drawingRect.bottom() -drawingRect.top() ); - drawingRect.setTop( 0 ); - } - - d->m_boundingRealRect = drawingRect; //redraw this area next time the mouse has been moved - - //update( d->m_boundingRealRect ); - TQPainter p(this); - p.setRasterOp( NotROP ); - p.setPen( TQPen( black, 0, DotLine ) ); - p.drawRect( drawingRect ); - p.end(); - return; -}*/ - - if ( d->dragging ) - { - return; - } - if ( d->dragStart.x() != -1 ) - { - TQPoint p ( (int) _ev->pos().x() + (int) xOffset(), - (int) _ev->pos().y() + (int) yOffset() ); - - if ( ( d->dragStart - p ).manhattanLength() > 4 ) - { - d->dragging = true; - startTheDrag(); - d->dragStart.setX( -1 ); - } - d->dragging = false; - return; - } - - // Get info about where the event occurred - this is duplicated - // in ::mousePressEvent, needs to be separated into one function - Sheet *sheet = activeSheet(); - if ( !sheet ) - { - return; - } - - if ( d->mouseSelectedObject ) - { - EmbeddedObject *obj = 0; - TQPoint p ( (int) _ev->x(), - (int) _ev->y() ); - if ( ( obj = getObject( p, activeSheet() ) ) && obj->isSelected() ) - { - KoRect const bound = obj->geometry(); - TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(), - bound.width(), - bound.height() ) ); - zoomedBound.moveBy( (int)(-xOffset() * doc()->zoomedResolutionX() ), (int)(-yOffset() * doc()->zoomedResolutionY() )); - setCursor( obj->getCursor( p, d->modType, zoomedBound ) ); - return; - } - } - - double dwidth = d->view->doc()->unzoomItX( width() ); - double ev_PosX; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - } - else - { - ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - } - double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); - - // In which cell did the user click ? - double xpos; - double ypos; - int col = sheet->leftColumn( ev_PosX, xpos ); - int row = sheet->topRow( ev_PosY, ypos ); - - // you cannot move marker when col > KS_colMax or row > KS_rowMax - if ( col > KS_colMax || row > KS_rowMax ) - { - kdDebug(36001) << "Canvas::mouseMoveEvent: col or row is out of range: " - << "col: " << col << " row: " << row << endl; - return; - } - - - //*** Highlighted Range Resize Handling *** - if (d->mouseAction == ResizeSelection) - { - choice()->update(TQPoint(col,row)); - return; - } - - //Check to see if the mouse is over a highlight range size grip and if it is, change the cursor - //shape to a resize arrow - if (highlightRangeSizeGripAt(ev_PosX,ev_PosY)) - { - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - setCursor( sizeBDiagCursor ); - else - setCursor( sizeFDiagCursor ); - return; - } - - TQRect rct( (d->chooseCell ? choice() : selectionInfo())->lastRange() ); - - TQRect r1; - TQRect r2; - - double lx = sheet->dblColumnPos( rct.left() ); - double rx = sheet->dblColumnPos( rct.right() + 1 ); - double ty = sheet->dblRowPos( rct.top() ); - double by = sheet->dblRowPos( rct.bottom() + 1 ); - - r1.setLeft( (int) (lx - 1) ); - r1.setTop( (int) (ty - 1) ); - r1.setRight( (int) (rx + 1) ); - r1.setBottom( (int) (by + 1) ); - - r2.setLeft( (int) (lx + 1) ); - r2.setTop( (int) (ty + 1) ); - r2.setRight( (int) (rx - 1) ); - r2.setBottom( (int) (by - 1) ); - - // Test whether the mouse is over some anchor - { - Cell *cell = sheet->visibleCellAt( col, row ); - TQString anchor; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - anchor = cell->testAnchor( d->view->doc()->zoomItX( cell->dblWidth() - ev_PosX + xpos ), - d->view->doc()->zoomItY( ev_PosY - ypos ) ); - } - else - { - anchor = cell->testAnchor( d->view->doc()->zoomItX( ev_PosX - xpos ), - d->view->doc()->zoomItY( ev_PosY - ypos ) ); - } - if ( !anchor.isEmpty() && anchor != d->anchor ) - { - setCursor( KCursor::handCursor() ); - } - - d->anchor = anchor; - } - - // Test wether mouse is over the selection handle - TQRect selectionHandle = d->view->selectionInfo()->selectionHandleArea(); - if ( selectionHandle.contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ), - d->view->doc()->zoomItY( ev_PosY ) ) ) ) - { - //If the cursor is over the handle, than it might be already on the next cell. - //Recalculate the cell! - col = sheet->leftColumn( ev_PosX - d->view->doc()->unzoomItX( 2 ), xpos ); - row = sheet->topRow( ev_PosY - d->view->doc()->unzoomItY( 2 ), ypos ); - - if ( !sheet->isProtected() ) - { - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - setCursor( sizeBDiagCursor ); - else - setCursor( sizeFDiagCursor ); - } - } - else if ( !d->anchor.isEmpty() ) - { - if ( !sheet->isProtected() ) - setCursor( KCursor::handCursor() ); - } - else if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) - && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) ) - { - setCursor( KCursor::handCursor() ); - } - else if ( d->chooseCell ) - { - //Visual cue to indicate that the user can drag-select the choice selection - setCursor( KCursor::crossCursor() ); - } - else - { - //Nothing special is happening, use a normal arrow cursor - setCursor( arrowCursor ); - } - - // No marking, selecting etc. in progess? Then quit here. - if ( d->mouseAction == NoAction ) - return; - - // Set the new extent of the selection - (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row)); -} - -void Canvas::mouseReleaseEvent( TQMouseEvent* /*_ev*/) -{ - if ( d->scrollTimer->isActive() ) - d->scrollTimer->stop(); - - d->mousePressed = false; - d->view->disableAutoScroll(); - - if ( d->modType != MT_NONE /*&& d->m_resizeObject && d->m_resizeObject->isSelected() */) - { - switch ( d->modType ) - { - case MT_MOVE: - { - KoPoint move( objectRect( false ).topLeft() - d->m_moveStartPosMouse ); - if ( move != KoPoint( 0, 0 ) ) - { - KCommand *cmd= activeSheet()->moveObject( view(), move.x(), move.y() ); - if(cmd) - doc()->addCommand( cmd ); - } else - { - repaint(); - } - d->m_isMoving = false; - break; - } - case MT_RESIZE_UP: case MT_RESIZE_LF: case MT_RESIZE_RT: case MT_RESIZE_LU: case MT_RESIZE_LD: case MT_RESIZE_RU: case MT_RESIZE_RD: - finishResizeObject( i18n("Resize Object") ); - break; - case MT_RESIZE_DN: - finishResizeObject( i18n("Resize Object"), false ); - break; - default: - break; - } - return; - } - - Sheet *sheet = activeSheet(); - if ( !sheet ) - return; - - Selection* selectionInfo = d->view->selectionInfo(); - TQRect s( selectionInfo->lastRange() ); - - // The user started the drag in the lower right corner of the marker ? - if ( d->mouseAction == ResizeCell && !sheet->isProtected() ) - { - sheet->mergeCells(selectionInfo->lastRange()); - d->view->updateEditWidget(); - } - else if ( d->mouseAction == AutoFill && !sheet->isProtected() ) - { - TQRect dest = s; - sheet->autofill( d->autoFillSource, dest ); - - d->view->updateEditWidget(); - } - // The user started the drag in the middle of a cell ? - else if ( d->mouseAction == Mark && !d->chooseCell ) - { - d->view->updateEditWidget(); - } - - d->mouseAction = NoAction; - d->dragging = false; - d->dragStart.setX( -1 ); -} - -void Canvas::processClickSelectionHandle( TQMouseEvent *event ) -{ - // Auto fill ? That is done using the left mouse button. - if ( event->button() == Qt::LeftButton ) - { - d->mouseAction = AutoFill; - d->autoFillSource = selectionInfo()->lastRange(); - } - // Resize a cell (done with the right mouse button) ? - // But for that to work there must not be a selection. - else if ( event->button() == Qt::MidButton && selectionInfo()->isSingular()) - { - d->mouseAction = ResizeCell; - } - - return; -} - -void Canvas::processLeftClickAnchor() -{ - bool isRefLink = localReferenceAnchor( d->anchor ); - bool isLocalLink = (d->anchor.find("file:") == 0); - if ( !isRefLink ) - { - TQString type=KMimeType::findByURL(d->anchor, 0, isLocalLink)->name(); - - if ( KRun::isExecutableFile( d->anchor , type ) ) - { - //TQString question = i18n("Do you want to open this link to '%1'?\n").arg(d->anchor); - - //question += i18n("Note that opening a link to a local file may " - // "compromise your system's security."); - - TQString question = i18n("This link points to the program or script '%1'.\n" - "Malicious programs can harm your computer. Are you sure that you want to run this program?").arg(d->anchor); - // this will also start local programs, so adding a "don't warn again" - // checkbox will probably be too dangerous - int choice = KMessageBox::warningYesNo(this, question, i18n("Open Link?")); - if ( choice != KMessageBox::Yes ) - { - return; - //(void) new KRun( d->anchor ); - } - } - - new KRun(d->anchor); - } - else - { - selectionInfo()->initialize(Region(d->view, d->anchor)); - } -} - -bool Canvas::highlightRangeSizeGripAt(double x, double y) -{ - if (!d->chooseCell) - return 0; - - Region::ConstIterator end = choice()->constEnd(); - for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it) - { - // TODO Stefan: adapt to Selection::selectionHandleArea - KoRect visibleRect; - sheetAreaToRect((*it)->rect().normalize(), visibleRect); - - TQPoint bottomRight((int) visibleRect.right(), (int) visibleRect.bottom()); - TQRect handle( ( (int) bottomRight.x() - 6 ), - ( (int) bottomRight.y() - 6 ), - ( 6 ), - ( 6 ) ); - - if (handle.contains(TQPoint((int) x,(int) y))) - { - return true; - } - } - - return false; -} - -void Canvas::mousePressEvent( TQMouseEvent * _ev ) -{ - if ( _ev->button() == Qt::LeftButton ) - { - d->mousePressed = true; - d->view->enableAutoScroll(); - } - - if ( activeSheet() && _ev->button() == Qt::LeftButton) - { - d->m_moveStartPosMouse = objectRect( false ).topLeft(); - EmbeddedObject *obj = getObject( _ev->pos(), activeSheet() ); - - if ( obj ) - { - // use ctrl + Button to select / deselect object - if ( _ev->state() & ControlButton && obj->isSelected() ) - deselectObject( obj ); - else if ( _ev->state() & ControlButton ) - { - if ( d->modType == MT_NONE) - return; - - selectObject( obj ); - raiseObject( obj ); - d->m_moveStartPosMouse = objectRect( false ).topLeft(); - } - else - { - if ( d->modType != MT_MOVE || !obj->isSelected() ) - deselectAllObjects(); - - selectObject( obj ); - - raiseObject( obj ); - d->m_moveStartPosMouse = objectRect( false ).topLeft(); - } - - // start resizing - if ( d->modType != MT_MOVE && d->modType != MT_NONE && !obj->isProtect() ) - { - deselectAllObjects(); - selectObject( obj ); - raiseObject( obj ); - - d->m_resizeObject = obj; - - d->m_ratio = static_cast( obj->geometry().width() ) / - static_cast( obj->geometry().height() ); - d->m_rectBeforeResize = obj->geometry(); - } - - KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) ); - docPoint += KoPoint( xOffset(), yOffset() ); - d->m_origMousePos = docPoint; - d->m_moveStartPosMouse = objectRect( false ).topLeft(); - return; - } - else - { - d->modType = MT_NONE; - if ( !( _ev->state() & ShiftButton ) && !( _ev->state() & ControlButton ) ) - deselectAllObjects(); - } - } - - // Get info about where the event occurred - this is duplicated - // in ::mouseMoveEvent, needs to be separated into one function - Sheet *sheet = activeSheet(); - if ( !sheet ) - { - return; - } - - double dwidth = d->view->doc()->unzoomItX( width() ); - double ev_PosX; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - } - else - { - ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - } - double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); - - // In which cell did the user click ? - double xpos; - double ypos; - int col = sheet->leftColumn( ev_PosX, xpos ); - int row = sheet->topRow( ev_PosY, ypos ); - // you cannot move marker when col > KS_colMax or row > KS_rowMax - if ( col > KS_colMax || row > KS_rowMax ) - { - kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: " - << "col: " << col << " row: " << row << endl; - return; - } - - // you cannot move marker when col > KS_colMax or row > KS_rowMax - if ( col > KS_colMax || row > KS_rowMax ) - { - kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: " - << "col: " << col << " row: " << row << endl; - return; - } - - if (d->chooseCell && highlightRangeSizeGripAt(ev_PosX,ev_PosY)) - { - choice()->setActiveElement(TQPoint(col,row)); - d->mouseAction = ResizeSelection; - return; - } - - // We were editing a cell -> save value and get out of editing mode - if ( d->cellEditor && !d->chooseCell ) - { - deleteEditor( true ); // save changes - } - - d->scrollTimer->start( 50 ); - - // Did we click in the lower right corner of the marker/marked-area ? - if ( selectionInfo()->selectionHandleArea().contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ), - d->view->doc()->zoomItY( ev_PosY ) ) ) ) - { - processClickSelectionHandle( _ev ); - return; - } - - - // TODO Stefan: adapt to non-cont. selection - { - // start drag ? - TQRect rct( selectionInfo()->lastRange() ); - - TQRect r1; - TQRect r2; - { - double lx = sheet->dblColumnPos( rct.left() ); - double rx = sheet->dblColumnPos( rct.right() + 1 ); - double ty = sheet->dblRowPos( rct.top() ); - double by = sheet->dblRowPos( rct.bottom() + 1 ); - - r1.setLeft( (int) (lx - 1) ); - r1.setTop( (int) (ty - 1) ); - r1.setRight( (int) (rx + 1) ); - r1.setBottom( (int) (by + 1) ); - - r2.setLeft( (int) (lx + 1) ); - r2.setTop( (int) (ty + 1) ); - r2.setRight( (int) (rx - 1) ); - r2.setBottom( (int) (by - 1) ); - } - - d->dragStart.setX( -1 ); - - if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) - && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) ) - { - d->dragStart.setX( (int) ev_PosX ); - d->dragStart.setY( (int) ev_PosY ); - - return; - } - } - - // kdDebug() << "Clicked in cell " << col << ", " << row << endl; - - // Extending an existing selection with the shift button ? - if ((_ev->state() & ShiftButton) && - d->view->koDocument()->isReadWrite() && - !selectionInfo()->isColumnOrRowSelected()) - { - (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row)); - return; - } - - - // Go to the upper left corner of the obscuring object if cells are merged - Cell *cell = sheet->cellAt( col, row ); - if (cell->isPartOfMerged()) - { - cell = cell->obscuringCells().first(); - col = cell->column(); - row = cell->row(); - } - - switch (_ev->button()) - { - case Qt::LeftButton: - if (!d->anchor.isEmpty()) - { - // Hyperlink pressed - processLeftClickAnchor(); - } -#ifdef NONCONTIGUOUSSELECTION - else if ( _ev->state() & ControlButton ) - { - if (d->chooseCell) - { -#if 0 // TODO Stefan: remove for NCS of choices - // Start a marking action - d->mouseAction = Mark; - // extend the existing selection - choice()->extend(TQPoint(col,row), activeSheet()); -#endif - } - else - { - // Start a marking action - d->mouseAction = Mark; - // extend the existing selection - selectionInfo()->extend(TQPoint(col,row), activeSheet()); - } -// TODO Stefan: simplification, if NCS of choices is working -/* (d->chooseCell ? choice() : selectionInfo())->extend(TQPoint(col,row), activeSheet());*/ - } -#endif - else - { - // Start a marking action - d->mouseAction = Mark; - // reinitialize the selection - (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet()); - } - break; - case Qt::MidButton: - // Paste operation with the middle button? - if ( d->view->koDocument()->isReadWrite() && !sheet->isProtected() ) - { - (d->chooseCell ? choice() : selectionInfo())->initialize( TQPoint( col, row ), activeSheet() ); - sheet->paste(selectionInfo()->lastRange(), true, Paste::Normal, - Paste::OverWrite, false, 0, false, TQClipboard::Selection); - sheet->setRegionPaintDirty(*selectionInfo()); - } - break; - case Qt::RightButton: - if (!selectionInfo()->contains( TQPoint( col, row ) )) - { - // No selection or the mouse press was outside of an existing selection? - (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet()); - } - break; - default: - break; - } - - scrollToCell(selectionInfo()->marker()); - if ( !d->chooseCell ) - { - d->view->updateEditWidgetOnPress(); - } - updatePosWidget(); - - // Context menu? - if ( _ev->button() == Qt::RightButton ) - { - // TODO: Handle anchor // TODO Stefan: ??? - TQPoint p = mapToGlobal( _ev->pos() ); - d->view->openPopupMenu( p ); - } -} - -void Canvas::startTheDrag() -{ - Sheet * sheet = activeSheet(); - if ( !sheet ) - return; - - // right area for start dragging - TextDrag * d = new TextDrag( this ); - setCursor( KCursor::handCursor() ); - - TQDomDocument doc = sheet->saveCellRegion(*selectionInfo()); - - // Save to buffer - TQBuffer buffer; - buffer.open( IO_WriteOnly ); - TQTextStream str( &buffer ); - str.setEncoding( TQTextStream::UnicodeUTF8 ); - str << doc; - buffer.close(); - - d->setPlain( sheet->copyAsText( selectionInfo() ) ); - d->setKSpread( buffer.buffer() ); - - d->dragCopy(); - setCursor( KCursor::arrowCursor() ); -} - -void Canvas::mouseDoubleClickEvent( TQMouseEvent* _ev) -{ - - EmbeddedObject *obj; - if ( ( obj = getObject( _ev->pos(), activeSheet() ) ) ) - { - switch ( obj->getType() ) - { - case OBJECT_KOFFICE_PART: case OBJECT_CHART: - { - dynamic_cast(obj)->activate( view(), this ); - return; - break; - } - default: - { - view()->extraProperties(); - return; - break; - } - } - } - - if ( d->view->koDocument()->isReadWrite() && activeSheet() ) - createEditor(true); -} - -void Canvas::wheelEvent( TQWheelEvent* _ev ) -{ - if ( _ev->orientation() == Qt::Vertical ) - { - if ( vertScrollBar() ) - TQApplication::sendEvent( vertScrollBar(), _ev ); - } - else if ( horzScrollBar() ) - { - TQApplication::sendEvent( horzScrollBar(), _ev ); - } -} - -void Canvas::paintEvent( TQPaintEvent* _ev ) -{ - if ( d->view->doc()->isLoading() ) - return; - - Sheet* sheet = activeSheet(); - if ( !sheet ) - return; - - // ElapsedTime et( "Canvas::paintEvent" ); - - double dwidth = d->view->doc()->unzoomItX( width() ); - KoRect rect = d->view->doc()->unzoomRect( _ev->rect() & TQWidget::rect() ); - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - rect.moveBy( -xOffset(), yOffset() ); - else - rect.moveBy( xOffset(), yOffset() ); - - KoPoint tl = rect.topLeft(); - KoPoint br = rect.bottomRight(); - - double tmp; - int left_col; - int right_col; - //Philipp: I don't know why we need the +1, but otherwise we don't get it correctly - //Testcase: Move a dialog slowly up left. Sometimes the top/left most points are not painted - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - right_col = sheet->leftColumn( dwidth - tl.x(), tmp ); - left_col = sheet->rightColumn( dwidth - br.x() + 1.0 ); - } - else - { - left_col = sheet->leftColumn( tl.x(), tmp ); - right_col = sheet->rightColumn( br.x() + 1.0 ); - } - int top_row = sheet->topRow( tl.y(), tmp ); - int bottom_row = sheet->bottomRow( br.y() + 1.0 ); - - TQRect vr( TQPoint(left_col, top_row), - TQPoint(right_col, bottom_row) ); - d->view->doc()->emitBeginOperation( false ); - sheet->setRegionPaintDirty( vr ); - d->view->doc()->emitEndOperation( vr ); -} - -void Canvas::focusInEvent( TQFocusEvent* ) -{ - if ( !d->cellEditor ) - return; - - //kdDebug(36001) << "d->chooseCell : " << ( d->chooseCell ? "true" : "false" ) << endl; - // If we are in editing mode, we redirect the - // focus to the CellEditor or EditWidget - // And we know which, using lastEditorWithFocus. - // This screws up though (David) - if ( lastEditorWithFocus() == EditWidget ) - { - d->editWidget->setFocus(); - //kdDebug(36001) << "Focus to EditWidget" << endl; - return; - } - - //kdDebug(36001) << "Redirecting focus to editor" << endl; - d->cellEditor->setFocus(); -} - -void Canvas::focusOutEvent( TQFocusEvent* ) -{ - if ( d->scrollTimer->isActive() ) - d->scrollTimer->stop(); - d->mousePressed = false; - d->view->disableAutoScroll(); -} - -void Canvas::dragMoveEvent( TQDragMoveEvent * _ev ) -{ - Sheet * sheet = activeSheet(); - if ( !sheet ) - { - _ev->ignore(); - return; - } - - _ev->accept( TextDrag::canDecode( _ev ) ); - - double dwidth = d->view->doc()->unzoomItX( width() ); - double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() ); - double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() ); - double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this ); - double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this ); - - TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3); - - double ev_PosX; - if (sheet->layoutDirection()==Sheet::RightToLeft) - ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - else - ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - - double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); - - if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) ) - _ev->ignore( r1 ); -} - -void Canvas::dragLeaveEvent( TQDragLeaveEvent * ) -{ - if ( d->scrollTimer->isActive() ) - d->scrollTimer->stop(); -} - -void Canvas::dropEvent( TQDropEvent * _ev ) -{ - d->dragging = false; - if ( d->scrollTimer->isActive() ) - d->scrollTimer->stop(); - Sheet * sheet = activeSheet(); - if ( !sheet || sheet->isProtected() ) - { - _ev->ignore(); - return; - } - - double dwidth = d->view->doc()->unzoomItX( width() ); - double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() ); - double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() ); - double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this ); - double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this ); - - TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3); - - double ev_PosX; - if (sheet->layoutDirection()==Sheet::RightToLeft) - ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - else - ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); - - double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); - - if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) ) - { - _ev->ignore( ); - return; - } - else - _ev->accept( ); - - double tmp; - int col = sheet->leftColumn( ev_PosX, tmp ); - int row = sheet->topRow( ev_PosY, tmp ); - - if ( !TextDrag::canDecode( _ev ) ) - { - _ev->ignore(); - return; - } - - TQByteArray b; - - bool makeUndo = true; - - if ( _ev->provides( TextDrag::selectionMimeType() ) ) - { - if ( TextDrag::target() == _ev->source() ) - { - if ( !d->view->doc()->undoLocked() ) - { - UndoDragDrop * undo - = new UndoDragDrop(d->view->doc(), sheet, *selectionInfo(), - TQRect(col, row, - selectionInfo()->boundingRect().width(), - selectionInfo()->boundingRect().height())); - d->view->doc()->addCommand( undo ); - makeUndo = false; - } - sheet->deleteSelection( selectionInfo(), false ); - } - - - b = _ev->encodedData( TextDrag::selectionMimeType() ); - sheet->paste( b, TQRect( col, row, 1, 1 ), makeUndo ); - - if ( _ev->source() == this ) - _ev->acceptAction(); - _ev->accept(); - } - else - { - TQString text; - if ( !TQTextDrag::decode( _ev, text ) ) - { - _ev->ignore(); - return; - } - // if ( TextDrag::target() == _ev->source() ) - // sheet->deleteSelection( selectionInfo() ); - - sheet->pasteTextPlain( text, TQRect( col, row, 1, 1 ) ); - _ev->accept(); - if ( _ev->source() == this ) - _ev->acceptAction(); - - return; - } -} - -void Canvas::resizeEvent( TQResizeEvent* _ev ) -{ - if (!activeSheet()) - return; - - - double ev_Width = d->view->doc()->unzoomItX( _ev->size().width() ); - double ev_Height = d->view->doc()->unzoomItY( _ev->size().height() ); - - // workaround to allow horizontal resizing and zoom changing when sheet - // direction and interface direction don't match (e.g. an RTL sheet on an - // LTR interface) - if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() ) - { - int dx = _ev->size().width() - _ev->oldSize().width(); - scroll(dx, 0); - } - else if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() ) - { - int dx = _ev->size().width() - _ev->oldSize().width(); - scroll(-dx, 0); - } - - // If we rise horizontally, then check if we are still within the valid area (KS_colMax) - if ( _ev->size().width() > _ev->oldSize().width() ) - { - int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); - - if ( ( xOffset() + ev_Width ) > - d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) ) - { - horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) ); - if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) - horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); - } - } - // If we lower vertically, then check if the range should represent the maximum range - else if ( _ev->size().width() < _ev->oldSize().width() ) - { - int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); - - if ( horzScrollBar()->maxValue() == - int( d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) - ev_Width ) ) - { - horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) ); - if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) - horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); - } - } - - // If we rise vertically, then check if we are still within the valid area (KS_rowMax) - if ( _ev->size().height() > _ev->oldSize().height() ) - { - if ( ( yOffset() + ev_Height ) > - d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) ) - { - vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) ); - } - } - // If we lower vertically, then check if the range should represent the maximum range - else if ( _ev->size().height() < _ev->oldSize().height() ) - { - if ( vertScrollBar()->maxValue() == - int( d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) - ev_Height ) ) - { - vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) ); - } - } -} - -TQPoint Canvas::cursorPos() -{ - TQPoint cursor; - if (d->chooseCell && !choice()->isEmpty()) - cursor = choice()->cursor(); - else - cursor = selectionInfo()->cursor(); - - return cursor; -} - -TQRect Canvas::moveDirection( KSpread::MoveTo direction, bool extendSelection ) -{ - kdDebug(36001) << "Canvas::moveDirection" << endl; - - TQPoint destination; - TQPoint cursor = cursorPos(); - - TQPoint cellCorner = cursor; - Cell* cell = activeSheet()->cellAt(cursor.x(), cursor.y()); - - /* cell is either the same as the marker, or the cell that is forced obscuring - the marker cell - */ - if (cell->isPartOfMerged()) - { - cell = cell->obscuringCells().first(); - cellCorner = TQPoint(cell->column(), cell->row()); - } - - /* how many cells must we move to get to the next cell? */ - int offset = 0; - RowFormat *rl = NULL; - ColumnFormat *cl = NULL; - switch (direction) - /* for each case, figure out how far away the next cell is and then keep - going one row/col at a time after that until a visible row/col is found - - NEVER use cell->column() or cell->row() -- it might be a default cell - */ - { - case KSpread::Bottom: - offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide()) - { - offset++; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - } - - destination = TQPoint(cursor.x(), TQMIN(cursor.y() + offset, KS_rowMax)); - break; - case KSpread::Top: - offset = (cellCorner.y() - cursor.y()) - 1; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - while ( ((cursor.y() + offset) >= 1) && rl->isHide()) - { - offset--; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - } - destination = TQPoint(cursor.x(), TQMAX(cursor.y() + offset, 1)); - break; - case KSpread::Left: - offset = (cellCorner.x() - cursor.x()) - 1; - cl = activeSheet()->columnFormat( cursor.x() + offset ); - while ( ((cursor.x() + offset) >= 1) && cl->isHide()) - { - offset--; - cl = activeSheet()->columnFormat( cursor.x() + offset ); - } - destination = TQPoint(TQMAX(cursor.x() + offset, 1), cursor.y()); - break; - case KSpread::Right: - offset = cell->mergedXCells() - (cursor.x() - cellCorner.x()) + 1; - cl = activeSheet()->columnFormat( cursor.x() + offset ); - while ( ((cursor.x() + offset) <= KS_colMax) && cl->isHide()) - { - offset++; - cl = activeSheet()->columnFormat( cursor.x() + offset ); - } - destination = TQPoint(TQMIN(cursor.x() + offset, KS_colMax), cursor.y()); - break; - case KSpread::BottomFirst: - offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide()) - { - ++offset; - rl = activeSheet()->rowFormat( cursor.y() + offset ); - } - - destination = TQPoint( 1, TQMIN( cursor.y() + offset, KS_rowMax ) ); - break; - } - - if (extendSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - d->view->updateEditWidget(); - - return TQRect( cursor, destination ); -} - -void Canvas::processEnterKey(TQKeyEvent* event) -{ - // array is true, if ctrl+alt are pressed - bool array = (event->state() & TQt::AltButton) && - (event->state() & TQt::ControlButton); - - /* save changes to the current editor */ - if (!d->chooseCell) - { - deleteEditor(true, array); - } - - /* use the configuration setting to see which direction we're supposed to move - when enter is pressed. - */ - KSpread::MoveTo direction = d->view->doc()->getMoveToValue(); - - //if shift Button clicked inverse move direction - if (event->state() & TQt::ShiftButton) - { - switch( direction ) - { - case KSpread::Bottom: - direction = KSpread::Top; - break; - case KSpread::Top: - direction = KSpread::Bottom; - break; - case KSpread::Left: - direction = KSpread::Right; - break; - case KSpread::Right: - direction = KSpread::Left; - break; - case KSpread::BottomFirst: - direction = KSpread::BottomFirst; - break; - } - } - - /* never extend a selection with the enter key -- the shift key reverses - direction, not extends the selection - */ - TQRect r( moveDirection( direction, false ) ); - d->view->doc()->emitEndOperation( r ); -} - -void Canvas::processArrowKey( TQKeyEvent *event) -{ - /* NOTE: hitting the tab key also calls this function. Don't forget - to account for it - */ - - /* save changes to the current editor */ - if (!d->chooseCell) - { - deleteEditor( true ); - } - - KSpread::MoveTo direction = KSpread::Bottom; - bool makingSelection = event->state() & ShiftButton; - - switch (event->key()) - { - case Key_Down: - direction = KSpread::Bottom; - break; - case Key_Up: - direction = KSpread::Top; - break; - case Key_Left: - if (activeSheet()->layoutDirection()==Sheet::RightToLeft) - direction = KSpread::Right; - else - direction = KSpread::Left; - break; - case Key_Right: - if (activeSheet()->layoutDirection()==Sheet::RightToLeft) - direction = KSpread::Left; - else - direction = KSpread::Right; - break; - case Key_Tab: - direction = KSpread::Right; - break; - case Key_Backtab: - //Shift+Tab moves to the left - direction = KSpread::Left; - makingSelection = false; - break; - default: - Q_ASSERT(false); - break; - } - - TQRect r( moveDirection( direction, makingSelection ) ); - d->view->doc()->emitEndOperation( r ); -} - -void Canvas::processEscapeKey(TQKeyEvent * event) -{ - if ( d->cellEditor ) - deleteEditor( false ); - - if ( view()->isInsertingObject() ) - { - view()->resetInsertHandle(); - setCursor( arrowCursor ); - return; - } - - event->accept(); // ? - TQPoint cursor = cursorPos(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); - - if ( d->mousePressed /*&& toolEditMode == TEM_MOUSE */) - { - switch (d->modType) - { - case MT_RESIZE_UP: - case MT_RESIZE_DN: - case MT_RESIZE_LF: - case MT_RESIZE_RT: - case MT_RESIZE_LU: - case MT_RESIZE_LD: - case MT_RESIZE_RU: - case MT_RESIZE_RD: - { - TQRect oldBoundingRect = doc()->zoomRect( d->m_resizeObject->geometry()/*getRepaintRect()*/); - d->m_resizeObject->setGeometry( d->m_rectBeforeResize ); - oldBoundingRect.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , - (int)( -yOffset() * doc()->zoomedResolutionY()) ); - - activeSheet()->setRegionPaintDirty( oldBoundingRect ); - repaint( oldBoundingRect ); - repaintObject( d->m_resizeObject ); - d->m_ratio = 0.0; - d->m_resizeObject = 0; - d->m_isResizing = false; - view()->disableAutoScroll(); - d->mousePressed = false; - d->modType = MT_NONE; - break; - } - case MT_MOVE: - { - if ( d->m_isMoving ) - { - KoPoint move( d->m_moveStartPoint - objectRect( false ).topLeft() ); - activeSheet()->moveObject( view(), move, false ); - view()->disableAutoScroll(); - d->mousePressed = false; - d->modType = MT_NONE; - d->m_isMoving = false; - update(); - } - break; - } - default: - break; - } - } -} - -bool Canvas::processHomeKey(TQKeyEvent* event) -{ - bool makingSelection = event->state() & ShiftButton; - Sheet* sheet = activeSheet(); - - if ( d->cellEditor ) - // We are in edit mode -> go beginning of line - { - TQApplication::sendEvent( d->editWidget, event ); - return false; - } - else - { - TQPoint destination; - /* start at the first used cell in the row and cycle through the right until - we find a cell that has some output text. But don't look past the current - marker. - The end result we want is to move to the left to the first cell with text, - or just to the first column if there is no more text to the left. - - But why? In excel, home key sends you to the first column always. - We might want to change to that behavior. - */ - - if (event->state() & ControlButton) - { - /* ctrl + Home will always just send us to location (1,1) */ - destination = TQPoint( 1, 1 ); - } - else - { - TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); - - Cell * cell = sheet->getFirstCellRow(marker.y()); - while (cell != NULL && cell->column() < marker.x() && cell->isEmpty()) - { - cell = sheet->getNextCellRight(cell->column(), cell->row()); - } - - int col = ( cell ? cell->column() : 1 ); - if ( col == marker.x()) - col = 1; - destination = TQPoint(col, marker.y()); - } - - if ( selectionInfo()->marker() == destination ) - { - d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); - return false; - } - - if (makingSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - } - return true; -} - -bool Canvas::processEndKey( TQKeyEvent *event ) -{ - bool makingSelection = event->state() & ShiftButton; - Sheet* sheet = activeSheet(); - Cell* cell = NULL; - TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); - - // move to the last used cell in the row - // We are in edit mode -> go beginning of line - if ( d->cellEditor ) - { - TQApplication::sendEvent( d->editWidget, event ); - d->view->doc()->emitEndOperation( TQRect( marker, marker ) ); - return false; - } - else - { - int col = 1; - - cell = sheet->getLastCellRow(marker.y()); - while (cell != NULL && cell->column() > markerColumn() && cell->isEmpty()) - { - cell = sheet->getNextCellLeft(cell->column(), cell->row()); - } - - col = (cell == NULL) ? KS_colMax : cell->column(); - - TQPoint destination( col, marker.y() ); - if ( destination == marker ) - { - d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); - return false; - } - - if (makingSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - } - return true; -} - -bool Canvas::processPriorKey(TQKeyEvent *event) -{ - bool makingSelection = event->state() & ShiftButton; - if (!d->chooseCell) - { - deleteEditor( true ); - } - - TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); - - TQPoint destination(marker.x(), TQMAX(1, marker.y() - 10)); - if ( destination == marker ) - { - d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); - return false; - } - - if (makingSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - return true; -} - -bool Canvas::processNextKey(TQKeyEvent *event) -{ - bool makingSelection = event->state() & ShiftButton; - - if (!d->chooseCell) - { - deleteEditor( true /*save changes*/ ); - } - - TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); - TQPoint destination(marker.x(), TQMAX(1, marker.y() + 10)); - - if ( marker == destination ) - { - d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); - return false; - } - - if (makingSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - return true; -} - -void Canvas::processDeleteKey(TQKeyEvent* /* event */) -{ - if ( isObjectSelected() ) - { - d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) ); - d->view->deleteSelectedObjects(); - return; - } - - activeSheet()->clearTextSelection( selectionInfo() ); - d->editWidget->setText( "" ); - - TQPoint cursor = cursorPos(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); - return; -} - -void Canvas::processF2Key(TQKeyEvent* /* event */) -{ - d->editWidget->setFocus(); - if ( d->cellEditor ) - d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() - 1 ); - d->editWidget->cursorForward( false ); - - - TQPoint cursor = cursorPos(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); - return; -} - -void Canvas::processF4Key(TQKeyEvent* event) -{ - /* passes F4 to the editor (if any), which will process it - */ - if ( d->cellEditor ) - { - d->cellEditor->handleKeyPressEvent( event ); -// d->editWidget->setFocus(); - d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() ); - } - TQPoint cursor = cursorPos(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); - return; -} - -void Canvas::processOtherKey(TQKeyEvent *event) -{ - // No null character ... - if ( event->text().isEmpty() || !d->view->koDocument()->isReadWrite() - || !activeSheet() || activeSheet()->isProtected() ) - { - event->accept(); - } - else - { - if ( !d->cellEditor && !d->chooseCell ) - { - // Switch to editing mode - createEditor( CellEditor ); - d->cellEditor->handleKeyPressEvent( event ); - } - else if ( d->cellEditor ) - d->cellEditor->handleKeyPressEvent( event ); - } - - TQPoint cursor = cursorPos(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); - - return; -} - -bool Canvas::processControlArrowKey( TQKeyEvent *event ) -{ - bool makingSelection = event->state() & ShiftButton; - - Sheet* sheet = activeSheet(); - Cell* cell = NULL; - Cell* lastCell; - TQPoint destination; - bool searchThroughEmpty = true; - int row; - int col; - - TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); - - /* here, we want to move to the first or last cell in the given direction that is - actually being used. Ignore empty cells and cells on hidden rows/columns */ - switch ( event->key() ) - { - //Ctrl+Key_Up - case Key_Up: - - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != 1)) - { - lastCell = cell; - row = marker.y()-1; - cell = sheet->cellAt(cell->column(), row); - while ((cell != NULL) && (row > 0) && (!cell->isEmpty()) ) - { - if (!(sheet->rowFormat(cell->row())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - row--; - if ( row > 0 ) - cell = sheet->cellAt(cell->column(), row); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellUp(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide()))) - { - cell = sheet->getNextCellUp(cell->column(), cell->row()); - } - } - - if (cell == NULL) - row = 1; - else - row = cell->row(); - - while ( sheet->rowFormat(row)->isHide() ) - { - row++; - } - - destination.setX(marker.x()); - destination.setY(row); - break; - - //Ctrl+Key_Down - case Key_Down: - - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != KS_rowMax)) - { - lastCell = cell; - row = marker.y()+1; - cell = sheet->cellAt(cell->column(), row); - while ((cell != NULL) && (row < KS_rowMax) && (!cell->isEmpty()) ) - { - if (!(sheet->rowFormat(cell->row())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - row++; - cell = sheet->cellAt(cell->column(), row); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellDown(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide()))) - { - cell = sheet->getNextCellDown(cell->column(), cell->row()); - } - } - - if (cell == NULL) - row = marker.y(); - else - row = cell->row(); - - while ( sheet->rowFormat(row)->isHide() ) - { - row--; - } - - destination.setX(marker.x()); - destination.setY(row); - break; - - //Ctrl+Key_Left - case Key_Left: - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax)) - { - lastCell = cell; - col = marker.x()+1; - cell = sheet->cellAt(col, cell->row()); - while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) ) - { - if (!(sheet->columnFormat(cell->column())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - col++; - cell = sheet->cellAt(col, cell->row()); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellRight(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) - { - cell = sheet->getNextCellRight(cell->column(), cell->row()); - } - } - - if (cell == NULL) - col = marker.x(); - else - col = cell->column(); - - while ( sheet->columnFormat(col)->isHide() ) - { - col--; - } - - destination.setX(col); - destination.setY(marker.y()); - } - else - { - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1)) - { - lastCell = cell; - col = marker.x()-1; - cell = sheet->cellAt(col, cell->row()); - while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) ) - { - if (!(sheet->columnFormat(cell->column())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - col--; - if ( col > 0 ) - cell = sheet->cellAt(col, cell->row()); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellLeft(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) - { - cell = sheet->getNextCellLeft(cell->column(), cell->row()); - } - } - - if (cell == NULL) - col = 1; - else - col = cell->column(); - - while ( sheet->columnFormat(col)->isHide() ) - { - col++; - } - - destination.setX(col); - destination.setY(marker.y()); - } - break; - - //Ctrl+Key_Right - case Key_Right: - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1)) - { - lastCell = cell; - col = marker.x()-1; - cell = sheet->cellAt(col, cell->row()); - while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) ) - { - if (!(sheet->columnFormat(cell->column())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - col--; - if ( col > 0 ) - cell = sheet->cellAt(col, cell->row()); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellLeft(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) - { - cell = sheet->getNextCellLeft(cell->column(), cell->row()); - } - } - - if (cell == NULL) - col = 1; - else - col = cell->column(); - - while ( sheet->columnFormat(col)->isHide() ) - { - col++; - } - - destination.setX(col); - destination.setY(marker.y()); - } - else - { - cell = sheet->cellAt( marker.x(), marker.y() ); - if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax)) - { - lastCell = cell; - col = marker.x()+1; - cell = sheet->cellAt(col, cell->row()); - while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) ) - { - if (!(sheet->columnFormat(cell->column())->isHide())) - { - lastCell = cell; - searchThroughEmpty = false; - } - col++; - cell = sheet->cellAt(col, cell->row()); - } - cell = lastCell; - } - if (searchThroughEmpty) - { - cell = sheet->getNextCellRight(marker.x(), marker.y()); - - while ((cell != NULL) && - (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) - { - cell = sheet->getNextCellRight(cell->column(), cell->row()); - } - } - - if (cell == NULL) - col = marker.x(); - else - col = cell->column(); - - while ( sheet->columnFormat(col)->isHide() ) - { - col--; - } - - destination.setX(col); - destination.setY(marker.y()); - } - break; - - } - - if ( marker == destination ) - { - d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); - return false; - } - - if (makingSelection) - { - (d->chooseCell ? choice() : selectionInfo())->update(destination); - } - else - { - (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); - } - return true; -} - - -void Canvas::keyPressEvent ( TQKeyEvent * _ev ) -{ - Sheet * sheet = activeSheet(); - - if ( !sheet || formatKeyPress( _ev )) - return; - - // Dont handle the remaining special keys. - if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) && - (_ev->key() != Key_Down) && - (_ev->key() != Key_Up) && - (_ev->key() != Key_Right) && - (_ev->key() != Key_Left) && - (_ev->key() != Key_Home) && - (_ev->key() != Key_Enter) && - (_ev->key() != Key_Return) && - (_ev->key() != TDEGlobalSettings::contextMenuKey())) - { - TQWidget::keyPressEvent( _ev ); - return; - } - - // Always accept so that events are not - // passed to the parent. - _ev->accept(); - - d->view->doc()->emitBeginOperation(false); - if ( _ev->key() == TDEGlobalSettings::contextMenuKey() ) { - int row = markerRow(); - int col = markerColumn(); - KoPoint kop(sheet->columnPos(col, this), sheet->rowPos(row, this)); - TQPoint p = d->view->doc()->zoomPoint(kop); - p = mapToGlobal(p); - d->view->openPopupMenu( p ); - } - switch( _ev->key() ) - { - case Key_Return: - case Key_Enter: - processEnterKey( _ev ); - return; - break; - case Key_Down: - case Key_Up: - case Key_Left: - case Key_Right: - case Key_Tab: /* a tab behaves just like a right/left arrow */ - case Key_Backtab: /* and so does Shift+Tab */ - if (_ev->state() & ControlButton) - { - if ( !processControlArrowKey( _ev ) ) - return; - } - else - { - processArrowKey( _ev ); - return; - } - break; - - case Key_Escape: - processEscapeKey( _ev ); - return; - break; - - case Key_Home: - if ( !processHomeKey( _ev ) ) - return; - break; - - case Key_End: - if ( !processEndKey( _ev ) ) - return; - break; - - case Key_Prior: /* Page Up */ - if ( !processPriorKey( _ev ) ) - return; - break; - - case Key_Next: /* Page Down */ - if ( !processNextKey( _ev ) ) - return; - break; - - case Key_Delete: - processDeleteKey( _ev ); - return; - break; - - case Key_F2: - processF2Key( _ev ); - return; - break; - - case Key_F4: - processF4Key( _ev ); - return; - break; - - default: - processOtherKey( _ev ); - return; - break; - } - - //most process*Key methods call emitEndOperation, this only gets called in some situations - // (after some move operations) - d->view->doc()->emitEndOperation( sheet->visibleRect( this ) ); - return; -} - -void Canvas::processIMEvent( TQIMEvent * event ) -{ - d->view->doc()->emitBeginOperation( false ); - if ( !d->cellEditor && !d->chooseCell ) - { - // Switch to editing mode - createEditor( CellEditor ); - d->cellEditor->handleIMEvent( event ); - } - - TQPoint cursor; - - if ( d->chooseCell ) - { - cursor = choice()->cursor(); - /* if the cursor is unset, pretend we're starting at the regular cursor */ - if (cursor.x() == 0 || cursor.y() == 0) - cursor = choice()->cursor(); - } - else - cursor = selectionInfo()->cursor(); - - d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); -} - -bool Canvas::formatKeyPress( TQKeyEvent * _ev ) -{ - if (!(_ev->state() & ControlButton )) - return false; - - int key = _ev->key(); - if ( key != Key_Exclam && key != Key_At && key != Key_Ampersand - && key != Key_Dollar && key != Key_Percent && key != Key_AsciiCircum - && key != Key_NumberSign ) - return false; - - Cell * cell = 0L; - Sheet * sheet = activeSheet(); - - d->view->doc()->emitBeginOperation(false); - - if ( !d->view->doc()->undoLocked() ) - { - TQString dummy; - UndoCellFormat * undo = new UndoCellFormat( d->view->doc(), sheet, *selectionInfo(), dummy ); - d->view->doc()->addCommand( undo ); - } - - Region::ConstIterator end(selectionInfo()->constEnd()); - for (Region::ConstIterator it = selectionInfo()->constBegin(); it != end; ++it) - { - TQRect rect = (*it)->rect().normalize(); - - int right = rect.right(); - int bottom = rect.bottom(); - - if ( util_isRowSelected(rect) ) - { - for ( int r = rect.top(); r <= bottom; ++r ) - { - cell = sheet->getFirstCellRow( r ); - while ( cell ) - { - if ( cell->isPartOfMerged() ) - { - cell = sheet->getNextCellRight( cell->column(), r ); - continue; - } - - formatCellByKey (cell, _ev->key(), rect); - - cell = sheet->getNextCellRight( cell->column(), r ); - } // while (cell) - RowFormat * rw = sheet->nonDefaultRowFormat( r ); - TQPen pen; - switch ( _ev->key() ) - { - case Key_Exclam: - rw->setFormatType (Number_format); - rw->setPrecision( 2 ); - break; - - case Key_Dollar: - rw->setFormatType (Money_format); - rw->setPrecision( d->view->doc()->locale()->fracDigits() ); - break; - - case Key_Percent: - rw->setFormatType (Percentage_format); - break; - - case Key_At: - rw->setFormatType( SecondeTime_format ); - break; - - case Key_NumberSign: - rw->setFormatType( ShortDate_format ); - break; - - case Key_AsciiCircum: - rw->setFormatType( Scientific_format ); - break; - - case Key_Ampersand: - if ( r == rect.top() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - rw->setTopBorderPen( pen ); - } - if ( r == rect.bottom() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - rw->setBottomBorderPen( pen ); - } - break; - - default: - d->view->doc()->emitEndOperation( rect ); - return false; - } - sheet->emit_updateRow( rw, r ); - } - - d->view->doc()->emitEndOperation( rect ); - return true; - } - - if ( util_isColumnSelected(rect) ) - { - for ( int c = rect.left(); c <= right; ++c ) - { - cell = sheet->getFirstCellColumn( c ); - while ( cell ) - { - if ( cell->isPartOfMerged() ) - { - cell = sheet->getNextCellDown( c, cell->row() ); - continue; - } - - formatCellByKey (cell, _ev->key(), rect); - - cell = sheet->getNextCellDown( c, cell->row() ); - } - - ColumnFormat * cw = sheet->nonDefaultColumnFormat( c ); - TQPen pen; - switch ( _ev->key() ) - { - case Key_Exclam: - cw->setFormatType( Number_format ); - cw->setPrecision( 2 ); - break; - - case Key_Dollar: - cw->setFormatType( Money_format ); - cw->setPrecision( d->view->doc()->locale()->fracDigits() ); - break; - - case Key_Percent: - cw->setFormatType( Percentage_format ); - break; - - case Key_At: - cw->setFormatType( SecondeTime_format ); - break; - - case Key_NumberSign: - cw->setFormatType( ShortDate_format ); - break; - - case Key_AsciiCircum: - cw->setFormatType( Scientific_format ); - break; - - case Key_Ampersand: - if ( c == rect.left() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cw->setLeftBorderPen( pen ); - } - if ( c == rect.right() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cw->setRightBorderPen( pen ); - } - break; - - default: - d->view->doc()->emitEndOperation( rect ); - return false; - } - sheet->emit_updateColumn( cw, c ); - } - d->view->doc()->emitEndOperation( rect ); - return true; - } - - for ( int row = rect.top(); row <= bottom; ++row ) - { - for ( int col = rect.left(); col <= right; ++ col ) - { - cell = sheet->nonDefaultCell( col, row ); - - if ( cell->isPartOfMerged() ) - continue; - - formatCellByKey (cell, _ev->key(), rect); - } // for left .. right - } // for top .. bottom - - } - _ev->accept(); - - d->view->doc()->emitEndOperation( *selectionInfo() ); - return true; -} - -bool Canvas::formatCellByKey (Cell *cell, int key, const TQRect &rect) -{ - TQPen pen; - switch (key) - { - case Key_Exclam: - cell->convertToDouble (); - cell->format()->setFormatType (Number_format); - cell->format()->setPrecision( 2 ); - break; - - case Key_Dollar: - cell->convertToMoney (); - break; - - case Key_Percent: - cell->convertToPercent (); - break; - - case Key_At: - cell->convertToTime (); - break; - - case Key_NumberSign: - cell->convertToDate (); - break; - - case Key_AsciiCircum: - cell->format()->setFormatType (Scientific_format); - cell->convertToDouble (); - break; - - case Key_Ampersand: - if ( cell->row() == rect.top() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cell->setTopBorderPen( pen ); - } - if ( cell->row() == rect.bottom() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cell->setBottomBorderPen( pen ); - } - if ( cell->column() == rect.left() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cell->setLeftBorderPen( pen ); - } - if ( cell->column() == rect.right() ) - { - pen = TQPen( d->view->borderColor(), 1, SolidLine); - cell->setRightBorderPen( pen ); - } - break; - } // switch - - return true; -} - - -void Canvas::slotAutoScroll(const TQPoint &scrollDistance) -{ - TQPoint d = scrollDistance; - horzScrollBar()->setValue( horzScrollBar()->value() + d.x() ); - vertScrollBar()->setValue( vertScrollBar()->value() + d.y() ); -} - -void Canvas::doAutoScroll() -{ - if ( !d->mousePressed ) - { - d->scrollTimer->stop(); - return; - } - bool select = false; - TQPoint pos = mapFromGlobal( TQCursor::pos() ); - - //Provide progressive scrolling depending on the mouse position - if ( pos.y() < 0 ) - { - vertScrollBar()->setValue ((int) (vertScrollBar()->value() - - autoScrollAccelerationY( - pos.y()))); - select = true; - } - else if ( pos.y() > height() ) - { - vertScrollBar()->setValue ((int) (vertScrollBar()->value() + - autoScrollAccelerationY (pos.y() - height()))); - select = true; - } - - if ( pos.x() < 0 ) - { - horzScrollBar()->setValue ((int) (horzScrollBar()->value() - - autoScrollAccelerationX( - pos.x() ))); - select = true; - } - else if ( pos.x() > width() ) - { - horzScrollBar()->setValue ((int) (horzScrollBar()->value() + - autoScrollAccelerationX( pos.x() - width()))); - select = true; - } - - if ( select ) - { - TQMouseEvent * event = new TQMouseEvent(TQEvent::MouseMove, pos, 0, 0); - mouseMoveEvent( event ); - delete event; - } - - //Restart timer - d->scrollTimer->start( 50 ); -} - -void Canvas::speakCell(TQWidget* w, const TQPoint& p, uint flags) -{ - Q_UNUSED(flags); - if (w != this) return; - Sheet* sheet = activeSheet(); - if (!sheet) return; - int row = -1; - int col = -1; - if (p == TQPoint()) { - row = markerRow(); - col = markerColumn(); - if (row == d->prevSpokenFocusRow && col == d->prevSpokenFocusCol) return; - d->prevSpokenFocusRow = row; - d->prevSpokenFocusCol = col; - } else { - TQPoint wp = w->mapFromGlobal(p); - double tmp; - double posX; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - double dwidth = d->view->doc()->unzoomItX( width() ); - posX = dwidth - d->view->doc()->unzoomItX( wp.x() ); - } - else - posX = d->view->doc()->unzoomItX( wp.x() ); - - double posY = d->view->doc()->unzoomItY( wp.y() ); - col = sheet->leftColumn( (posX + xOffset()), tmp ); - row = sheet->topRow( (posY + yOffset()), tmp ); - if (row == d->prevSpokenPointerRow && col == d->prevSpokenPointerCol) return; - d->prevSpokenPointerRow = row; - d->prevSpokenPointerCol = col; - } - if (row == d->prevSpokenRow && col == d->prevSpokenCol) return; - d->prevSpokenRow = row; - d->prevSpokenCol = col; - // kdDebug() << "Canvas::speakCell: row = " << row << " col = " << col << endl; - if (row >=0 && col >= 0) { - Cell* cell = sheet->cellAt( col, row ); - if (!cell) return; - TQString text = cell->strOutText(); - if (!text.isEmpty()) { - text.prepend(i18n("Spreadsheet cell", "Cell ") + cell->name() + " "); - if (cell->isFormula()) { - TQString f = cell->text(); - // Try to format the formula so synth can more clearly speak it. - TQString f2; - for (uint i = 0; i < f.length(); i++) f2 += f[i] + " "; - f2.replace("(", i18n("character (", "left paren")); - f2.replace(")", i18n("character )", "right paren")); - f2.replace(":", i18n("character :", "colon")); - f2.replace(";", i18n("character ;", "semicolon")); - f2.replace("=", i18n("character =", "equals")); - f2.replace(".", i18n("character .", "point")); - f2.replace(",", i18n("character ,", "comma")); - f2.replace(" . . ", i18n("characters ..", " dot dot ")); - text.append(i18n("Spreadsheet formula", " Formula ") + f2); - } - // kdDebug() << "Canvas::speakCell: text = " << text << endl; - kospeaker->sayWidget(text); - } - } -} - -double Canvas::autoScrollAccelerationX( int offset ) -{ - switch( static_cast( offset / 20 ) ) - { - case 0: return 5.0; - case 1: return 20.0; - case 2: return d->view->doc()->unzoomItX( width() ); - case 3: return d->view->doc()->unzoomItX( width() ); - default: return d->view->doc()->unzoomItX( (int) (width() * 5.0) ); - } -} - -double Canvas::autoScrollAccelerationY( int offset ) -{ - switch( static_cast( offset / 20 ) ) - { - case 0: return 5.0; - case 1: return 20.0; - case 2: return d->view->doc()->unzoomItY( height() ); - case 3: return d->view->doc()->unzoomItY( height() ); - default: return d->view->doc()->unzoomItY( (int) (height() * 5.0) ); - } -} - - -KSpread::EmbeddedObject *Canvas::getObject( const TQPoint &pos, Sheet *_sheet ) -{ - TQPoint const p ( (int) pos.x() , - (int) pos.y() ); - - TQPtrListIterator itObject( doc()->embeddedObjects() ); - for( ; itObject.current(); ++itObject ) - { - if ( itObject.current()->sheet() == _sheet ) - { - KoRect const bound = ( itObject.current() )->geometry(); - TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(), - bound.width(), - bound.height() ) ); - zoomedBound.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ), (int)( -yOffset() * doc()->zoomedResolutionY() ) ); - if ( zoomedBound.contains( p ) ) - return itObject.current(); - } - } - return 0; -} - -void Canvas::selectObject( EmbeddedObject *obj ) -{ - if ( obj->sheet() != activeSheet() || obj->isSelected() ) - return; - obj->setSelected( true ); - repaintObject( obj ); - - d->mouseSelectedObject = true; - emit objectSelectedChanged(); - deleteEditor( true ); -} - -void Canvas::deselectObject( EmbeddedObject *obj ) -{ - if ( obj->sheet() != activeSheet() || !obj->isSelected() ) - return; - obj->setSelected( false ); - repaintObject( obj ); - - d->mouseSelectedObject = false; - emit objectSelectedChanged(); -} - -void Canvas::selectAllObjects() -{ - TQPtrListIterator it( doc()->embeddedObjects() ); - for ( ; it.current() ; ++it ) - { - if ( it.current()->sheet() == activeSheet() ) - it.current()->setSelected( true ); - } - - d->mouseSelectedObject = true; -// emit objectSelectedChanged(); -} - -void Canvas::deselectAllObjects() -{ - if( activeSheet()->numSelected() == 0 ) - return; - - //lowerObject(); - - TQPtrListIterator it( doc()->embeddedObjects() ); - for ( ; it.current() ; ++it ) - deselectObject( it.current() ); - - d->mouseSelectedObject = false; -// emit objectSelectedChanged(); -} - - - -void Canvas::setMouseSelectedObject(bool b) -{ - d->mouseSelectedObject = b; - emit objectSelectedChanged(); -} - -bool Canvas::isObjectSelected() -{ - return d->mouseSelectedObject; -} - - -void Canvas::moveObjectsByMouse( KoPoint &pos, bool keepXorYunchanged ) -{ - KoRect rect( objectRect( false ) ); - KoPoint move( 0, 0 ); - double diffx = pos.x() - d->m_origMousePos.x(); - double diffy = pos.y() - d->m_origMousePos.y(); - - move = KoPoint( diffx, diffy ); - d->m_origMousePos = pos; - - // unwind last snapping - KoRect movedRect( rect ); - movedRect.moveBy( diffx, diffy ); - - // don't move object off canvas - KoPoint diffDueToBorders(0,0); -// KoRect pageRect( m_activePage->getPageRect() ); - if ( rect.left() + move.x() < 0/*pageRect.left()*/ ) - diffDueToBorders.setX( -rect.left() - move.x() ); -// else if ( rect.right() + move.x() > pageRect.right() ) -// diffDueToBorders.setX( pageRect.right() - (rect.right() + move.x()) ); - - - //kdDebug() << "rect.top() + move.y():" << rect.top() + move.y()<< endl; - if ( rect.top() + move.y() < 0 ) - diffDueToBorders.setY( -rect.top() - move.y() ); -// else if ( rect.bottom() + move.y() > pageRect.bottom() ) -// diffDueToBorders.setY( pageRect.bottom() - (rect.bottom() + move.y()) ); - -// m_moveSnapDiff += diffDueToBorders; - move += diffDueToBorders; - -// movedRect.moveBy( m_moveSnapDiff.x(), m_moveSnapDiff.y() ); - if ( keepXorYunchanged ) - { - KoPoint diff( d->m_moveStartPosMouse - movedRect.topLeft() ); - if ( fabs( diff.x() ) > fabs( diff.y() ) ) - { -// m_moveSnapDiff.setY( /*m_moveSnapDiff.y() + */m_moveStartPosMouse.y() - movedRect.y() ); - movedRect.moveTopLeft( KoPoint( movedRect.x(), d->m_moveStartPosMouse.y() ) ); - move.setY( movedRect.y() - rect.y() ); - } - else - { -// m_moveSnapDiff.setX( /*m_moveSnapDiff.x() + */m_moveStartPosMouse.x() - movedRect.x() ); - movedRect.moveTopLeft( KoPoint( d->m_moveStartPosMouse.x(), movedRect.y() ) ); - move.setX( movedRect.x() - rect.x() ); - } - } - - if ( move != KoPoint( 0, 0 ) ) - { - //kdDebug(33001) << "moveObjectsByMouse move = " << move << endl; - activeSheet()->moveObject( view(), move, false ); - } -} - - -void Canvas::resizeObject( ModifyType _modType, const KoPoint & point, bool keepRatio ) -{ - EmbeddedObject *obj = d->m_resizeObject; - - KoRect objRect = obj->geometry(); - objRect.moveBy( -xOffset(), -yOffset() ); - TQRect oldBoundingRect( doc()->zoomRect( objRect ) ); - - bool left = false; - bool right = false; - bool top = false; - bool bottom = false; - if ( _modType == MT_RESIZE_UP || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_RU ) - { - top = true; -// snapStatus |= KoGuides::SNAP_HORIZ; - } - if ( _modType == MT_RESIZE_DN || _modType == MT_RESIZE_LD || _modType == MT_RESIZE_RD ) - { - bottom = true; -// snapStatus |= KoGuides::SNAP_HORIZ; - } - if ( _modType == MT_RESIZE_LF || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_LD ) - { - left = true; -// snapStatus |= KoGuides::SNAP_VERT; - } - if ( _modType == MT_RESIZE_RT || _modType == MT_RESIZE_RU || _modType == MT_RESIZE_RD ) - { - right = true; -// snapStatus |= KoGuides::SNAP_VERT; - } - - double newLeft = objRect.left(); - double newRight = objRect.right(); - double newTop = objRect.top(); - double newBottom = objRect.bottom(); - if ( top ) - { - if ( point.y() < objRect.bottom() - MIN_SIZE ) - { - newTop = point.y(); - } - else - { - newTop = objRect.bottom() - MIN_SIZE; - } - } - if ( bottom ) - { - if ( point.y() > objRect.top() + MIN_SIZE ) - { - newBottom = point.y(); - } - else - { - newBottom = objRect.top() + MIN_SIZE; - } - } - if ( left ) - { - if ( point.x() < objRect.right() - MIN_SIZE ) - { - newLeft = point.x(); - } - else - { - newLeft = objRect.right() - MIN_SIZE; - } - } - if ( right ) - { - if ( point.x() > objRect.left() + MIN_SIZE ) - { - newRight = point.x(); - } - else - { - newRight = objRect.left() + MIN_SIZE; - } - } - - double width = newRight - newLeft; - double height = newBottom - newTop; - - if ( keepRatio && d->m_ratio != 0 ) - { - if ( ( top || bottom ) && ( right || left ) ) - { - if ( height * height * d->m_ratio > width * width / d->m_ratio ) - { - width = height * d->m_ratio; - } - else - { - height = width / d->m_ratio; - } - } - else if ( top || bottom ) - { - width = height * d->m_ratio; - } - else - { - height = width / d->m_ratio; - } - - if ( top ) - { - newTop = objRect.bottom() - height; - } - else - { - newBottom = objRect.top() + height; - } - if ( left ) - { - newLeft = objRect.right() - width; - } - else - { - newRight = objRect.right() + width; - } - } - - if ( newLeft != objRect.left() || newRight != objRect.right() || newTop != objRect.top() || newBottom != objRect.bottom() ) - { - // resizeBy and moveBy have to been used to make it work with rotated objects - obj->resizeBy( width - objRect.width(), height - objRect.height() ); - - if ( objRect.left() != newLeft || objRect.top() != newTop ) - { - obj->moveBy( KoPoint( newLeft - objRect.left(), newTop - objRect.top() ) ); - } - -// if ( doc()->showGuideLines() && !m_disableSnapping ) -// { -// KoRect rect( obj->getRealRect() ); -// KoPoint sp( rect.topLeft() ); -// if ( right ) -// { -// sp.setX( rect.right() ); -// } -// if ( bottom ) -// { -// sp.setY( rect.bottom() ); -// } -// m_gl.repaintSnapping( sp, snapStatus ); -// } - - repaint( oldBoundingRect ); - repaintObject( obj ); - emit objectSizeChanged(); - } -} - - -void Canvas::finishResizeObject( const TQString &/*name*/, bool /*layout*/ ) -{ - if ( d->m_resizeObject ) - { - KoPoint move = KoPoint( d->m_resizeObject->geometry().x() - d->m_rectBeforeResize.x(), - d->m_resizeObject->geometry().y() - d->m_rectBeforeResize.y() ); - KoSize size = KoSize( d->m_resizeObject->geometry().width() - d->m_rectBeforeResize.width(), - d->m_resizeObject->geometry().height() - d->m_rectBeforeResize.height() ); - - if ( ( d->m_resizeObject->geometry() ) != d->m_rectBeforeResize ) - { - ChangeObjectGeometryCommand *resizeCmd = new ChangeObjectGeometryCommand( d->m_resizeObject, move, size ); - // the command is not executed as the object is allready resized. - doc()->addCommand( resizeCmd ); - } - -// if ( layout ) -// doc()->layout( m_resizeObject ); - - d->m_ratio = 0.0; - d->m_isResizing = false; - repaintObject( d->m_resizeObject ); - d->m_resizeObject = NULL; - } -} - -void Canvas::raiseObject( EmbeddedObject *object ) -{ - if ( doc()->embeddedObjects().count() <= 1 ) - return; - - if ( d->m_objectDisplayAbove == 0 ) - { - if ( activeSheet()->numSelected() == 1 ) - { - d->m_objectDisplayAbove = object; - } - } -} - -void Canvas::lowerObject() -{ - d->m_objectDisplayAbove = 0; -} - -void Canvas::displayObjectList( TQPtrList &list ) -{ - list = doc()->embeddedObjects(); - list.setAutoDelete( false ); - - if ( d->m_objectDisplayAbove ) - { - // it can happen that the object is no longer there e.g. when - // the insert of the object is undone - int pos = doc()->embeddedObjects().findRef( d->m_objectDisplayAbove ); - if ( pos != -1 && d->m_objectDisplayAbove->isSelected() ) - { - list.take( pos ); - list.append( d->m_objectDisplayAbove ); - } - else - { - //tz not possible due to const. should const be removed? - //m_objectDisplayAbove = 0; - } - } -} - - -KoRect Canvas::objectRect( bool all ) const -{ - return activeSheet()->getRealRect( all ); -} - -void Canvas::deleteEditor (bool saveChanges, bool array) -{ - if ( !d->cellEditor ) - return; - - - //There may be highlighted areas on the sheet which will need to be erased - setSelectionChangePaintDirty( activeSheet() , *choice() ); - - d->editWidget->setEditMode( false ); - - TQString t = d->cellEditor->text(); - // Delete the cell editor first and after that update the document. - // That means we get a synchronous repaint after the cell editor - // widget is gone. Otherwise we may get painting errors. - delete d->cellEditor; - d->cellEditor = 0; - - if ( saveChanges ) - { - if ( t.at(0)=='=' ) - { - //a formula - int openParenthese = t.contains('(' ); - int closeParenthese = t.contains(')' ); - int diff = TQABS( openParenthese - closeParenthese ); - if ( openParenthese > closeParenthese ) - { - for (int i=0; i < diff;i++) - { - t=t+')'; - } - } - } - d->view->setText (t, array); - } - else - { - d->view->updateEditWidget(); - } - - setFocus(); -} - - -void Canvas::createEditor(bool captureArrowKeys) -{ - if (!activeSheet()) - return; - - Cell * cell = activeSheet()->nonDefaultCell( markerColumn(), markerRow(), false ); - - if ( !createEditor( CellEditor , true , captureArrowKeys ) ) - return; - if ( cell ) - d->cellEditor->setText( cell->text() ); -} - -bool Canvas::createEditor( EditorType ed, bool addFocus, bool captureArrowKeys ) -{ - Sheet * sheet = activeSheet(); - - // Set the starting sheet of the choice. - choice()->setSheet( activeSheet() ); - - if ( !d->cellEditor ) - { - Cell * cell = sheet->nonDefaultCell( marker().x(), marker().y(), false ); - - if ( sheet->isProtected() && !cell->format()->notProtected( marker().x(), marker().y() ) ) - return false; - - if ( ed == CellEditor ) - { - d->editWidget->setEditMode( true ); - d->cellEditor = new KSpread::CellEditor( cell, this, captureArrowKeys ); - } - - double w, h; - double min_w = cell->dblWidth( markerColumn() ); - double min_h = cell->dblHeight( markerRow() ); - if ( cell->isDefault() ) - { - w = min_w; - h = min_h; - //kdDebug(36001) << "DEFAULT" << endl; - } - else - { - w = cell->extraWidth(); - h = cell->extraHeight(); - //kdDebug(36001) << "HEIGHT=" << min_h << " EXTRA=" << h << endl; - } - - double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset(); - - Sheet::LayoutDirection sheetDir = sheet->layoutDirection(); - bool rtlText = cell->strOutText().isRightToLeft(); - - // if sheet and cell direction don't match, then the editor's location - // needs to be shifted backwards so that it's right above the cell's text - if ( w > 0 && ( ( sheetDir == Sheet::RightToLeft && !rtlText ) || - ( sheetDir == Sheet::LeftToRight && rtlText ) ) ) - xpos -= w - min_w; - - // paint editor above correct cell if sheet direction is RTL - if ( sheetDir == Sheet::RightToLeft ) - { - double dwidth = d->view->doc()->unzoomItX( width() ); - double w2 = TQMAX( w, min_w ); - xpos = dwidth - w2 - xpos; - } - - double ypos = sheet->dblRowPos( markerRow() ) - yOffset(); - TQPalette p = d->cellEditor->palette(); - TQColorGroup g( p.active() ); - - TQColor color = cell->format()->textColor( markerColumn(), markerRow() ); - if ( !color.isValid() ) - color = TQApplication::palette().active().text(); - g.setColor( TQColorGroup::Text, color); - - color = cell->bgColor( markerColumn(), markerRow() ); - if ( !color.isValid() ) - color = g.base(); - g.setColor( TQColorGroup::Background, color ); - - d->cellEditor->setPalette( TQPalette( g, p.disabled(), g ) ); - TQFont tmpFont = cell->format()->textFont( markerColumn(), markerRow() ); - tmpFont.setPointSizeFloat( 0.01 * d->view->doc()->zoom() * tmpFont.pointSizeFloat() ); - d->cellEditor->setFont( tmpFont ); - - KoRect rect( xpos, ypos, w, h ); //needed to circumvent rounding issue with height/width - - - TQRect zoomedRect=d->view->doc()->zoomRect( rect ); - /*zoomedRect.setLeft(zoomedRect.left()-2); - zoomedRect.setRight(zoomedRect.right()+4); - zoomedRect.setTop(zoomedRect.top()-1); - zoomedRect.setBottom(zoomedRect.bottom()+2);*/ - - d->cellEditor->setGeometry( zoomedRect ); - d->cellEditor->setMinimumSize( TQSize( d->view->doc()->zoomItX( min_w ), d->view->doc()->zoomItY( min_h ) ) ); - d->cellEditor->show(); - //kdDebug(36001) << "FOCUS1" << endl; - //Laurent 2001-12-05 - //Don't add focus when we create a new editor and - //we select text in edit widget otherwise we don't delete - //selected text. - // startChoose(); - - if ( addFocus ) - d->cellEditor->setFocus(); - - setSelectionChangePaintDirty(sheet, *selectionInfo()); - paintUpdates(); - } - - return true; -} - -void Canvas::repaintObject( EmbeddedObject *obj ) -{ - //Calculate where the object appears on the canvas widget and then repaint that part of the widget - TQRect canvasRelativeGeometry = doc()->zoomRect( obj->geometry() ); - canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , - (int)( -yOffset() * doc()->zoomedResolutionY()) ); - - update( canvasRelativeGeometry ); - - /* if ( !obj->isSelected() ) - { - KoRect g = obj->geometry(); - g.moveBy( -xOffset(), -yOffset() ); - TQRect geometry( doc()->zoomRect( g ) ); - - update( geometry ); - } - else - { - TQPainter p(this); - p.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() ); - obj->draw(&p); //this goes faster than calling repaint - p.end(); - }*/ -} - -void Canvas::copyOasisObjects() -{ - // We'll create a store (ZIP format) in memory - TQBuffer buffer; - TQCString mimeType = "application/vnd.oasis.opendocument.spreadsheet"; - KoStore* store = KoStore::createStore( TQT_TQIODEVICE(&buffer), KoStore::Write, mimeType ); - Q_ASSERT( store ); - Q_ASSERT( !store->bad() ); - KoOasisStore oasisStore( store ); - - KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType ); - - TQString plainText; - KoPicture picture; - if ( !doc()->saveOasisHelper( store, manifestWriter, Doc::SaveSelected, &plainText, &picture ) - || !oasisStore.closeManifestWriter() ) - { - delete store; - return; - } - delete store; - - KMultipleDrag* multiDrag = new KMultipleDrag(); - if ( !plainText.isEmpty() ) - multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) ); - if ( !picture.isNull() ) - multiDrag->addDragObject( picture.dragObject( 0 ) ); - KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 ); - kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl; - storeDrag->setEncodedData( buffer.buffer() ); - multiDrag->addDragObject( storeDrag ); - - //save the objects as pictures too so that other programs can access them - TQPtrListIterator itObject( doc()->embeddedObjects() ); - itObject.toFirst(); - if ( itObject.current() ) - { - KoRect kr = objectRect(false); - TQRect r( kr.toTQRect() ); - TQPixmap pixmap( r.width(), r.height() ); - pixmap.fill( "white" ); - TQPainter p(&pixmap); - for( ; itObject.current(); ++itObject ) - { - if ( itObject.current()->isSelected() ) - p.drawPixmap( itObject.current()->geometry().toTQRect().left() - r.left(), itObject.current()->geometry().toTQRect().top() - r.top(), itObject.current()->toPixmap( 1.0 , 1.0 ) ); - } - p.end(); - if (!pixmap.isNull()) - { - TQImageDrag *imagedrag = new TQImageDrag( pixmap.convertToImage() ); - multiDrag->addDragObject( imagedrag ); - } - } - - TQDragObject *dragObject = multiDrag; - TQApplication::clipboard()->setData( dragObject, TQClipboard::Clipboard ); -} - -void Canvas::closeEditor() -{ - if ( d->chooseCell ) - return; - - if ( d->cellEditor ) - { - deleteEditor( true ); // save changes - } -} - -void Canvas::updateEditor() -{ - if (!d->chooseCell) - return; - - Sheet* sheet = activeSheet(); - if (!sheet) - return; - - if (d->cellEditor) - { - if (choice()->sheet() != sheet) - { - d->cellEditor->hide(); - } - else - { - d->cellEditor->show(); - } - d->cellEditor->updateChoice(); - } -} - -void Canvas::setSelectionChangePaintDirty(Sheet* sheet, const Region& region) -{ - sheet->setRegionPaintDirty(region); // TODO should the paintDirtyList be in Canvas? -} - - -void Canvas::updatePosWidget() -{ - TQString buffer; - // No selection, or only one cell merged selected - if ( selectionInfo()->isSingular() ) - { - if (activeSheet()->getLcMode()) - { - buffer = "L" + TQString::number( markerRow() ) + - "C" + TQString::number( markerColumn() ); - } - else - { - buffer = Cell::columnName( markerColumn() ) + - TQString::number( markerRow() ); - } - } - else - { - if (activeSheet()->getLcMode()) - { - buffer = TQString::number( (selectionInfo()->lastRange().bottom()-selectionInfo()->lastRange().top()+1) )+"Lx"; - if ( util_isRowSelected( selectionInfo()->lastRange() ) ) - buffer+=TQString::number((KS_colMax-selectionInfo()->lastRange().left()+1))+"C"; - else - buffer+=TQString::number((selectionInfo()->lastRange().right()-selectionInfo()->lastRange().left()+1))+"C"; - } - else - { - //encodeColumnLabelText return @@@@ when column >KS_colMax - //=> it's not a good display - //=> for the moment I display pos of marker - buffer=Cell::columnName( selectionInfo()->lastRange().left() ) + - TQString::number(selectionInfo()->lastRange().top()) + ":" + - Cell::columnName( TQMIN( KS_colMax, selectionInfo()->lastRange().right() ) ) + - TQString::number(selectionInfo()->lastRange().bottom()); - //buffer=activeSheet()->columnLabel( m_iMarkerColumn ); - //buffer+=tmp.setNum(m_iMarkerRow); - } - } - - if (buffer != d->posWidget->lineEdit()->text()) - d->posWidget->lineEdit()->setText(buffer); -} - -void Canvas::equalizeRow() -{ - TQRect s( selection() ); - RowFormat *rl = d->view->activeSheet()->rowFormat(s.top()); - int size=rl->height(this); - if ( s.top() == s.bottom() ) - return; - for(int i=s.top()+1;i<=s.bottom();i++) - { - Sheet *sheet = activeSheet(); - if ( !sheet ) - return; - size=TQMAX(d->view->activeSheet()->rowFormat(i)->height(this),size); - } - d->view->vBorderWidget()->equalizeRow(size); -} - -void Canvas::equalizeColumn() -{ - TQRect s( selection() ); - ColumnFormat *cl = d->view->activeSheet()->columnFormat(s.left()); - int size=cl->width(this); - if ( s.left() == s.right() ) - return; - - for(int i=s.left()+1;i<=s.right();i++) - { - size=TQMAX(d->view->activeSheet()->columnFormat(i)->width(this),size); - } - d->view->hBorderWidget()->equalizeColumn(size); -} - -TQRect Canvas::cellsInArea( const TQRect area ) const -{ - KoRect unzoomedRect = d->view->doc()->unzoomRect( area ); - - unzoomedRect.moveBy( (int)xOffset(), (int)yOffset() ); - - double tmp; - int left_col = activeSheet()->leftColumn( unzoomedRect.left(), tmp ); - int right_col = activeSheet()->rightColumn( unzoomedRect.right() ); - int top_row = activeSheet()->topRow( unzoomedRect.top(), tmp ); - int bottom_row = activeSheet()->bottomRow( unzoomedRect.bottom() ); - - return TQRect( left_col, top_row, - right_col - left_col + 1, bottom_row - top_row + 1 ); -} - -TQRect Canvas::visibleCells() const -{ - return cellsInArea( TQRect(0,0,width(),height()) ); - -} - - -//--------------------------------------------- -// -// Drawing Engine -// -//--------------------------------------------- - -void Canvas::paintUpdates() -{ - if (activeSheet() == NULL) - return; - - TQPainter painter(this); - - //Save clip region - TQRegion rgnComplete( painter.clipRegion() ); - TQWMatrix matrix; - if ( d->view ) - { - matrix = d->view->matrix(); - } - else - { - matrix = painter.worldMatrix(); - } - - - paintChildren( painter, matrix ); - - painter.save(); - clipoutChildren( painter ); - - KoRect unzoomedRect = d->view->doc()->unzoomRect( TQRect( 0, 0, width(), height() ) ); - // unzoomedRect.moveBy( xOffset(), yOffset() ); - - - /* paint any visible cell that has the paintDirty flag */ - TQRect range = visibleCells(); - Cell* cell = NULL; - - double topPos = activeSheet()->dblRowPos(range.top()); - double leftPos = activeSheet()->dblColumnPos(range.left()); - - KoPoint dblCorner( leftPos - xOffset(), topPos - yOffset() ); - - int x; - int y; - - int right = range.right(); - int bottom = range.bottom(); - Sheet * sheet = activeSheet(); - -#if 0 - kdDebug(36001) - << "================================================================" - << endl; - kdDebug(36001) << "painting dirty cells " << endl; -#endif - - TQValueList mergedCellsPainted; - for ( x = range.left(); x <= right; ++x ) - { - for ( y = range.top(); y <= bottom; ++y ) - { - if ( sheet->cellIsPaintDirty( TQPoint( x, y ) ) ) - { - cell = sheet->cellAt( x, y ); - - // recalc and relayout only for non default cells - if (!cell->isDefault()) - { - if (cell->calcDirtyFlag()) cell->calc(); - if (cell->layoutDirtyFlag()) cell->makeLayout( painter, x, y ); - } - - /* bool paintBordersBottom = false; - bool paintBordersRight = false; - bool paintBordersLeft = false; - bool paintBordersTop = false; */ - - int paintBorder=Cell::Border_None; - - TQPen bottomPen( cell->effBottomBorderPen( x, y ) ); - TQPen rightPen( cell->effRightBorderPen( x, y ) ); - TQPen leftPen( cell->effLeftBorderPen( x, y ) ); - TQPen topPen( cell->effTopBorderPen( x, y ) ); - - // paint right border - // - if rightmost cell - // - if the pen is more "worth" than the left border pen of the cell - // on the left - if ( x >= KS_colMax ) - { - paintBorder |= Cell::Border_Right; - } - else - { - paintBorder |= Cell::Border_Right; - if ( cell->effRightBorderValue( x, y ) < - sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) - rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); - } - - // similiar for other borders... - // bottom border: - if ( y >= KS_rowMax ) - { - paintBorder |= Cell::Border_Bottom; - } - else - { - paintBorder |= Cell::Border_Bottom; - if ( cell->effBottomBorderValue( x, y ) < - sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1 ) ) - bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); - } - - // left border: - if ( x == 1 ) - { - paintBorder |= Cell::Border_Left; - } - else - { - paintBorder |= Cell::Border_Left; - if ( cell->effLeftBorderValue( x, y ) < - sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) - leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); - } - - // top border: - if ( y == 1 ) - { - paintBorder |= Cell::Border_Top; - } - else - { - paintBorder |= Cell::Border_Top; - if ( cell->effTopBorderValue( x, y ) < - sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) - topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); - } - - cell->paintCell( unzoomedRect, painter, d->view, dblCorner, - TQPoint( x, y), paintBorder, - rightPen,bottomPen,leftPen,topPen, - mergedCellsPainted); - } - dblCorner.setY( dblCorner.y() + sheet->rowFormat( y )->dblHeight( ) ); - } - dblCorner.setY( topPos - yOffset() ); - dblCorner.setX( dblCorner.x() + sheet->columnFormat( x )->dblWidth( ) ); - } - - /* now paint the selection */ - //Nb. No longer necessary to paint choose selection here as the cell reference highlight - //stuff takes care of this anyway - - paintHighlightedRanges(painter, unzoomedRect); - paintNormalMarker(painter, unzoomedRect); - - //restore clip region with children area - painter.restore(); - //painter.setClipRegion( rgnComplete ); -} - - - -void Canvas::clipoutChildren( TQPainter& painter ) const -{ - TQRegion rgn = painter.clipRegion(); - if ( rgn.isEmpty() ) - rgn = TQRegion( TQRect( 0, 0, width(), height() ) ); - - const double horizontalOffset = -xOffset() * doc()->zoomedResolutionX(); - const double verticalOffset = -yOffset() * doc()->zoomedResolutionY(); - - TQPtrListIterator itObject( doc()->embeddedObjects() ); - for( ; itObject.current(); ++itObject ) - { - if ( ( itObject.current() )->sheet() == activeSheet() ) - { - TQRect childGeometry = doc()->zoomRect( itObject.current()->geometry()); - - //The clipping region is given in device coordinates - //so subtract the current offset (scroll position) of the canvas - childGeometry.moveBy( (int)horizontalOffset , (int)verticalOffset ); - - if (painter.window().intersects(childGeometry)) - rgn -= childGeometry; - - //painter.fillRect( doc()->zoomRect( itObject.current()->geometry() ), TQColor("red" ) ); - } - } - - painter.setClipRegion( rgn ); -} - -TQRect Canvas::painterWindowGeometry( const TQPainter& painter ) const -{ - TQRect zoomedWindowGeometry = painter.window(); - - zoomedWindowGeometry.moveBy( (int)( xOffset() * doc()->zoomedResolutionX() ) , (int)( yOffset() * doc()->zoomedResolutionY() ) ); - - return zoomedWindowGeometry; -} - -void Canvas::paintChildren( TQPainter& painter, TQWMatrix& /*matrix*/ ) -{ - TQPtrListIterator itObject( doc()->embeddedObjects() ); - itObject.toFirst(); - if ( !itObject.current() ) - return; - - painter.save(); - painter.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() ); - - const TQRect zoomedWindowGeometry = painterWindowGeometry( painter ); - const Sheet* sheet = activeSheet(); - - for( ; itObject.current(); ++itObject ) - { - TQRect const zoomedObjectGeometry = doc()->zoomRect( itObject.current()->geometry() ); - if ( ( itObject.current() )->sheet() == activeSheet() && - zoomedWindowGeometry.intersects( zoomedObjectGeometry ) ) - { - //To prevent unnecessary redrawing of the embedded object, we only repaint - //if one or more of the cells underneath the object has been marked as 'dirty'. - - TQRect canvasRelativeGeometry = zoomedObjectGeometry; - canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , - (int)( -yOffset() * doc()->zoomedResolutionY()) ); - - const TQRect cellsUnderObject=cellsInArea( canvasRelativeGeometry ); - bool redraw=false; - - for (int x=cellsUnderObject.left();x<=cellsUnderObject.right();x++) - { - for (int y=cellsUnderObject.top();y<=cellsUnderObject.bottom();y++) - if ( sheet->cellIsPaintDirty( TQPoint(x,y) ) ) - { - redraw=true; - break; - } - if (redraw) - break; - } - - if ( redraw ) - itObject.current()->draw( &painter ); - } - } - painter.restore(); -} - -void Canvas::paintHighlightedRanges(TQPainter& painter, const KoRect& /*viewRect*/) -{ - TQValueList colors = choice()->colors(); - TQBrush nullBrush; - int index = 0; - Region::ConstIterator end(choice()->constEnd()); - for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it) - { - //Only paint ranges or cells on the current sheet - if ((*it)->sheet() != activeSheet()) - { - index++; - continue; - } - - TQRect region = (*it)->rect().normalize(); - - //double positions[4]; - //bool paintSides[4]; - KoRect unzoomedRect; - - sheetAreaToVisibleRect(region,unzoomedRect); - //Convert region from sheet coordinates to canvas coordinates for use with the painter - //retrieveMarkerInfo(region,viewRect,positions,paintSides); - - TQPen highlightPen( colors[(index) % colors.size()] ); // (*it)->color() ); - painter.setPen(highlightPen); - - //Adjust the canvas coordinate - rect to take account of zoom level - - TQRect zoomedRect; - - zoomedRect.setCoords ( d->view->doc()->zoomItX(unzoomedRect.left()), - d->view->doc()->zoomItY(unzoomedRect.top()), - d->view->doc()->zoomItX(unzoomedRect.right()), - d->view->doc()->zoomItY(unzoomedRect.bottom()) ); - - //Now adjust the highlight rectangle is slightly inside the cell borders (this means that multiple highlighted cells - //look nicer together as the borders do not clash) - - zoomedRect.setLeft(zoomedRect.left()+1); - zoomedRect.setTop(zoomedRect.top()+1); - zoomedRect.setRight(zoomedRect.right()-1); - zoomedRect.setBottom(zoomedRect.bottom()-1); - - painter.setBrush(nullBrush); - painter.drawRect(zoomedRect); - - //Now draw the size grip (the little rectangle on the bottom right-hand corner of the range which the user can - //click and drag to resize the region) - - - TQBrush sizeGripBrush( colors[(index) % colors.size()] ); // (*it)->color()); - TQPen sizeGripPen(TQt::white); - - painter.setPen(sizeGripPen); - painter.setBrush(sizeGripBrush); - - painter.drawRect(zoomedRect.right()-3,zoomedRect.bottom()-3,6,6); - index++; - } -} - -void Canvas::paintNormalMarker(TQPainter& painter, const KoRect &viewRect) -{ - //Only the active element (the one with the anchor) will be drawn with a border - - if( d->chooseCell ) - return; - - if (d->cellEditor) - return; - - Region::ConstIterator end(selectionInfo()->constEnd()); - for (Region::ConstIterator it(selectionInfo()->constBegin()); it != end; ++it) - { - TQRect range = (*it)->rect().normalize(); - - double positions[4]; - bool paintSides[4]; - - bool current = TQRect(selectionInfo()->anchor(), selectionInfo()->marker()).normalize() == range; - TQPen pen( TQt::black, 2 ); - painter.setPen( pen ); - - retrieveMarkerInfo( selectionInfo()->extendToMergedAreas(range), viewRect, positions, paintSides ); - - double left = positions[0]; - double top = positions[1]; - double right = positions[2]; - double bottom = positions[3]; - - bool paintLeft = paintSides[0]; - bool paintTop = paintSides[1]; - bool paintRight = paintSides[2]; - bool paintBottom = paintSides[3]; - - /* the extra '-1's thrown in here account for the thickness of the pen. - want to look like this: not this: - * * * * * * * * * * - * * * * - * * * * - */ - int l = 1; - - if ( paintTop ) - { - painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( right ) + l, d->view->doc()->zoomItY( top ) ); - } - if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) - { - if ( paintRight ) - { - painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) ); - } - if ( paintLeft && paintBottom && current ) - { - /* then the 'handle' in the bottom left corner is visible. */ - painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) - 3 ); - painter.drawLine( d->view->doc()->zoomItX( left ) + 4, d->view->doc()->zoomItY( bottom ), - d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) ); - painter.fillRect( d->view->doc()->zoomItX( left ) - 2, d->view->doc()->zoomItY( bottom ) -2, 5, 5, - painter.pen().color() ); - } - else - { - if ( paintLeft ) - { - painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) ); - } - if ( paintBottom ) - { - painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), - d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom )); - } - } - } - else // activeSheet()->layoutDirection()==Sheet::LeftToRight - { - if ( paintLeft ) - { - painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) ); - } - if ( paintRight && paintBottom && current ) - { - /* then the 'handle' in the bottom right corner is visible. */ - painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) - 3 ); - painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), - d->view->doc()->zoomItX( right ) - 3, d->view->doc()->zoomItY( bottom ) ); - painter.fillRect( d->view->doc()->zoomItX( right ) - 2, d->view->doc()->zoomItY( bottom ) - 2, 5, 5, - painter.pen().color() ); - } - else - { - if ( paintRight ) - { - painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), - d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) ); - } - if ( paintBottom ) - { - painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), - d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) ); - } - } - } - } -} - -void Canvas::sheetAreaToRect(const TQRect& sheetArea, KoRect& rect) -{ - Sheet* sheet=activeSheet(); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - rect.setLeft(sheet->dblColumnPos( sheetArea.right()+1 ) ); - rect.setRight(sheet->dblColumnPos( sheetArea.left() )); - } - else - { - rect.setLeft(sheet->dblColumnPos( sheetArea.left() )); - rect.setRight(sheet->dblColumnPos( sheetArea.right()+1 )); - } - - rect.setTop(sheet->dblRowPos(sheetArea.top())); - rect.setBottom(sheet->dblRowPos(sheetArea.bottom()+1)); - -} - -void Canvas::sheetAreaToVisibleRect( const TQRect& sheetArea, - KoRect& visibleRect ) -{ - Sheet* sheet=activeSheet(); - - if (!sheet) - return; - - double dwidth=d->view->doc()->unzoomItX(width()); - double xpos; - double x; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - xpos = dwidth - sheet->dblColumnPos( sheetArea.right() ) + xOffset(); - x = dwidth - sheet->dblColumnPos( sheetArea.left() ) + xOffset(); - } - else - { - xpos = sheet->dblColumnPos( sheetArea.left() ) - xOffset(); - x = sheet->dblColumnPos( sheetArea.right() ) - xOffset(); - } - - double ypos = sheet->dblRowPos(sheetArea.top())-yOffset(); - - const ColumnFormat *columnFormat = sheet->columnFormat( sheetArea.right() ); - double tw = columnFormat->dblWidth( ); - double w = x - xpos + tw; - - double y = sheet->dblRowPos( sheetArea.bottom() ) - yOffset(); - const RowFormat* rowFormat = sheet->rowFormat( sheetArea.bottom() ); - double th = rowFormat->dblHeight( ); - double h = ( y - ypos ) + th; - - /* left, top, right, bottom */ - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - visibleRect.setLeft(xpos - tw ); - visibleRect.setRight(xpos - tw + w ); - } - else - { - visibleRect.setLeft(xpos ); - visibleRect.setRight(xpos + w ); - } - visibleRect.setTop(ypos); - visibleRect.setBottom(ypos + h); -} - -void Canvas::retrieveMarkerInfo( const TQRect &marker, - const KoRect &viewRect, - double positions[], - bool paintSides[] ) -{ - - Sheet* sheet=activeSheet(); - - if (!sheet) return; - - KoRect visibleRect; - sheetAreaToVisibleRect(marker,visibleRect); - - - /* Sheet * sheet = activeSheet(); - if ( !sheet ) - return; - - double dWidth = d->view->doc()->unzoomItX( width() ); - - double xpos; - double x; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - xpos = dWidth - sheet->dblColumnPos( marker.right() ) + xOffset(); - x = dWidth - sheet->dblColumnPos( marker.left() ) + xOffset(); - } - else - { - xpos = sheet->dblColumnPos( marker.left() ) - xOffset(); - x = sheet->dblColumnPos( marker.right() ) - xOffset(); - } - double ypos = sheet->dblRowPos( marker.top() ) - yOffset(); - - const ColumnFormat *columnFormat = sheet->columnFormat( marker.right() ); - double tw = columnFormat->dblWidth( ); - double w = x - xpos + tw; - - double y = sheet->dblRowPos( marker.bottom() ) - yOffset(); - const RowFormat* rowFormat = sheet->rowFormat( marker.bottom() ); - double th = rowFormat->dblHeight( ); - double h = ( y - ypos ) + th; - - //left, top, right, bottom - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - positions[0] = xpos - tw; - positions[2] = xpos - tw + w; - } - else - { - positions[0] = xpos; - positions[2] = xpos + w; - } - positions[1] = ypos; - positions[3] = ypos + h;*/ - - /* these vars are used for clarity, the array for simpler function arguments */ - double left = visibleRect.left(); - double top = visibleRect.top(); - double right = visibleRect.right(); - double bottom = visibleRect.bottom(); - - /* left, top, right, bottom */ - paintSides[0] = (viewRect.left() <= left) && (left <= viewRect.right()) && - (bottom >= viewRect.top()) && (top <= viewRect.bottom()); - paintSides[1] = (viewRect.top() <= top) && (top <= viewRect.bottom()) - && (right >= viewRect.left()) && (left <= viewRect.right()); - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - paintSides[2] = (viewRect.left() <= right ) && - (right - 1 <= viewRect.right()) && - (bottom >= viewRect.top()) && (top <= viewRect.bottom()); - else - paintSides[2] = (viewRect.left() <= right ) && - (right <= viewRect.right()) && - (bottom >= viewRect.top()) && (top <= viewRect.bottom()); - paintSides[3] = (viewRect.top() <= bottom) && (bottom <= viewRect.bottom()) - && (right >= viewRect.left()) && (left <= viewRect.right()); - - positions[0] = TQMAX( left, viewRect.left() ); - positions[1] = TQMAX( top, viewRect.top() ); - positions[2] = TQMIN( right, viewRect.right() ); - positions[3] = TQMIN( bottom, viewRect.bottom() ); -} - - -/**************************************************************** - * - * VBorder - * - ****************************************************************/ - -VBorder::VBorder( TQWidget *_parent, Canvas *_canvas, View *_view) - : TQWidget( _parent, "", /*WNorthWestGravity*/WStaticContents | WResizeNoErase | WRepaintNoErase ) -{ - m_pView = _view; - m_pCanvas = _canvas; - m_lSize = 0L; - - setBackgroundMode( PaletteButton ); - setMouseTracking( true ); - m_bResize = false; - m_bSelection = false; - m_iSelectionAnchor=1; - m_bMousePressed = false; - - m_scrollTimer = new TQTimer( this ); - connect (m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); -} - - -VBorder::~VBorder() -{ - delete m_scrollTimer; -} - -TQSize VBorder::sizeHint() const -{ - return TQSize( 40, 10 ); -} - - -void VBorder::mousePressEvent( TQMouseEvent * _ev ) -{ - if ( !m_pView->koDocument()->isReadWrite() ) - return; - - if ( _ev->button() == Qt::LeftButton ) - m_bMousePressed = true; - - const Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); - double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() ); - m_bResize = false; - m_bSelection = false; - - // We were editing a cell -> save value and get out of editing mode - if ( m_pCanvas->editor() ) - { - m_pCanvas->deleteEditor( true ); // save changes - } - - m_scrollTimer->start( 50 ); - - // Find the first visible row and the y position of this row. - double y; - int row = sheet->topRow( m_pCanvas->yOffset(), y ); - - // Did the user click between two rows? - while ( y < ( dHeight + m_pCanvas->yOffset() ) && ( !m_bResize ) ) - { - double h = sheet->rowFormat( row )->dblHeight(); - row++; - if ( row > KS_rowMax ) - row = KS_rowMax; - if ( ( ev_PosY >= y + h - 2 ) && - ( ev_PosY <= y + h + 1 ) && - !( sheet->rowFormat( row )->isHide() && row == 1 ) ) - m_bResize = true; - y += h; - } - - //if row is hide and it's the first row - //you mustn't resize it. - double tmp2; - int tmpRow = sheet->topRow( ev_PosY - 1, tmp2 ); - if ( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) - m_bResize = false; - - // So he clicked between two rows ? - if ( m_bResize ) - { - // Determine row to resize - double tmp; - m_iResizedRow = sheet->topRow( ev_PosY - 1, tmp ); - if ( !sheet->isProtected() ) - paintSizeIndicator( _ev->pos().y(), true ); - } - else - { - m_bSelection = true; - - double tmp; - int hit_row = sheet->topRow( ev_PosY, tmp ); - if ( hit_row > KS_rowMax ) - return; - - m_iSelectionAnchor = hit_row; - - if ( !m_pView->selectionInfo()->contains( TQPoint(1, hit_row) ) || - !( _ev->button() == Qt::RightButton ) || - !m_pView->selectionInfo()->isRowSelected() ) - { - TQPoint newMarker( 1, hit_row ); - TQPoint newAnchor( KS_colMax, hit_row ); -#ifdef NONCONTIGUOUSSELECTION - if (_ev->state() == ControlButton) - { - m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker)); - } - else -#endif - if (_ev->state() == ShiftButton) - { - m_pView->selectionInfo()->update(newMarker); - } - else - { - m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker)); - } - } - - if ( _ev->button() == Qt::RightButton ) - { - TQPoint p = mapToGlobal( _ev->pos() ); - m_pView->popupRowMenu( p ); - m_bSelection = false; - } - m_pView->updateEditWidget(); - } -} - -void VBorder::mouseReleaseEvent( TQMouseEvent * _ev ) -{ - if ( m_scrollTimer->isActive() ) - m_scrollTimer->stop(); - - m_bMousePressed = false; - - if ( !m_pView->koDocument()->isReadWrite() ) - return; - - Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); - - if ( m_bResize ) - { - // Remove size indicator painted by paintSizeIndicator - TQPainter painter; - painter.begin( m_pCanvas ); - painter.setRasterOp( NotROP ); - painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); - painter.end(); - - int start = m_iResizedRow; - int end = m_iResizedRow; - TQRect rect; - rect.setCoords( 1, m_iResizedRow, KS_colMax, m_iResizedRow ); - if ( m_pView->selectionInfo()->isRowSelected() ) - { - if ( m_pView->selectionInfo()->contains( TQPoint( 1, m_iResizedRow ) ) ) - { - start = m_pView->selectionInfo()->lastRange().top(); - end = m_pView->selectionInfo()->lastRange().bottom(); - rect = m_pView->selectionInfo()->lastRange(); - } - } - - double height = 0.0; - double y = sheet->dblRowPos( m_iResizedRow ); - if ( ev_PosY - y <= 0.0 ) - height = 0.0; - else - height = ev_PosY - y; - - if ( !sheet->isProtected() ) - { - if ( !m_pCanvas->d->view->doc()->undoLocked() ) - { - //just resize - if ( height != 0.0 ) - { - // TODO Stefan: replace this - UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect ); - m_pCanvas->d->view->doc()->addCommand( undo ); - } - } - - for( int i = start; i <= end; i++ ) - { - RowFormat *rl = sheet->nonDefaultRowFormat( i ); - if ( height != 0.0 ) - { - if ( !rl->isHide() ) - rl->setDblHeight( height ); - } - else - { - sheet->hideRow(*m_pView->selectionInfo()); - } - } - - delete m_lSize; - m_lSize = 0; - } - } - else if ( m_bSelection ) - { - TQRect rect = m_pView->selectionInfo()->lastRange(); - - // TODO: please don't remove. Right now it's useless, but it's for a future feature - // Norbert - bool m_frozen = false; - if ( m_frozen ) - { - kdDebug(36001) << "selected: T " << rect.top() << " B " << rect.bottom() << endl; - - int i; - RowFormat * row; - TQValueListhiddenRows; - - for ( i = rect.top(); i <= rect.bottom(); ++i ) - { - row = m_pView->activeSheet()->rowFormat( i ); - if ( row->isHide() ) - { - hiddenRows.append(i); - } - } - - if ( hiddenRows.count() > 0 ) - m_pView->activeSheet()->showRow(*m_pView->selectionInfo()); - } - } - - m_bSelection = false; - m_bResize = false; -} - -void VBorder::equalizeRow( double resize ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - Q_ASSERT( sheet ); - - TQRect selection( m_pView->selectionInfo()->selection() ); - if ( !m_pCanvas->d->view->doc()->undoLocked() ) - { - UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection ); - m_pCanvas->d->view->doc()->addCommand( undo ); - } - RowFormat *rl; - for ( int i = selection.top(); i <= selection.bottom(); i++ ) - { - rl = sheet->nonDefaultRowFormat( i ); - resize = TQMAX( 2.0, resize); - rl->setDblHeight( resize ); - } -} - -void VBorder::mouseDoubleClickEvent(TQMouseEvent*) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() ) - return; - - sheet->adjustRow(*m_pCanvas->selectionInfo()); -} - - -void VBorder::mouseMoveEvent( TQMouseEvent * _ev ) -{ - if ( !m_pView->koDocument()->isReadWrite() ) - return; - - Sheet *sheet = m_pCanvas->activeSheet(); - - if (!sheet) - return; - - double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); - double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() ); - - // The button is pressed and we are resizing ? - if ( m_bResize ) - { - if ( !sheet->isProtected() ) - paintSizeIndicator( _ev->pos().y(), false ); - } - // The button is pressed and we are selecting ? - else if ( m_bSelection ) - { - double y; - int row = sheet->topRow( ev_PosY, y ); - if ( row > KS_rowMax ) - return; - - TQPoint newAnchor = m_pView->selectionInfo()->anchor(); - TQPoint newMarker = m_pView->selectionInfo()->marker(); - newMarker.setY( row ); - newAnchor.setY( m_iSelectionAnchor ); - m_pView->selectionInfo()->update(newMarker); - - if ( _ev->pos().y() < 0 ) - m_pCanvas->vertScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItY( ev_PosY ) ); - else if ( _ev->pos().y() > m_pCanvas->height() ) - { - if ( row < KS_rowMax ) - { - RowFormat *rl = sheet->rowFormat( row + 1 ); - y = sheet->dblRowPos( row + 1 ); - m_pCanvas->vertScrollBar()->setValue ((int) (m_pCanvas->d->view->doc()->zoomItY - (ev_PosY + rl->dblHeight()) - dHeight)); - } - } - } - // No button is pressed and the mouse is just moved - else - { - - //What is the internal size of 1 pixel - const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItY( 1 ); - double y; - int tmpRow = sheet->topRow( m_pCanvas->yOffset(), y ); - - while ( y < m_pCanvas->d->view->doc()->unzoomItY( height() ) + m_pCanvas->yOffset() ) - { - double h = sheet->rowFormat( tmpRow )->dblHeight(); - //if col is hide and it's the first column - //you mustn't resize it. - if ( ev_PosY >= y + h - 2 * unzoomedPixel && - ev_PosY <= y + h + unzoomedPixel && - !( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) ) - { - setCursor( splitVCursor ); - return; - } - y += h; - tmpRow++; - } - setCursor( arrowCursor ); - } -} - -void VBorder::doAutoScroll() -{ - if ( !m_bMousePressed ) - { - m_scrollTimer->stop(); - return; - } - - TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); - - if ( pos.y() < 0 || pos.y() > height() ) - { - TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 ); - mouseMoveEvent( event ); - delete event; - } - - //Restart timer - m_scrollTimer->start( 50 ); -} - -void VBorder::wheelEvent( TQWheelEvent* _ev ) -{ - if ( m_pCanvas->vertScrollBar() ) - TQApplication::sendEvent( m_pCanvas->vertScrollBar(), _ev ); -} - - -void VBorder::paintSizeIndicator( int mouseY, bool firstTime ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - TQPainter painter; - painter.begin( m_pCanvas ); - painter.setRasterOp( NotROP ); - - if ( !firstTime ) - painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); - - m_iResizePos = mouseY; - - // Dont make the row have a height < 2 pixel. - int y = m_pCanvas->d->view->doc()->zoomItY( sheet->dblRowPos( m_iResizedRow ) - m_pCanvas->yOffset() ); - if ( m_iResizePos < y + 2 ) - m_iResizePos = y; - - painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); - - painter.end(); - - TQString tmpSize; - if ( m_iResizePos != y ) - tmpSize = i18n("Height: %1 %2").arg( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItY( m_iResizePos - y ), - m_pView->doc()->unit() ) ) - .arg( m_pView->doc()->unitName() ); - else - tmpSize = i18n( "Hide Row" ); - - painter.begin( this ); - int len = painter.fontMetrics().width( tmpSize ); - int hei = painter.fontMetrics().height(); - painter.end(); - - if ( !m_lSize ) - { - m_lSize = new TQLabel( m_pCanvas ); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - m_lSize->setGeometry( m_pCanvas->width() - len - 5, - y + 3, len + 2, hei + 2 ); - else - m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 ); - - m_lSize->setAlignment( TQt::AlignVCenter ); - m_lSize->setText( tmpSize ); - m_lSize->setPalette( TQToolTip::palette() ); - m_lSize->show(); - } - else - { - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - m_lSize->setGeometry( m_pCanvas->width() - len - 5, - y + 3, len + 2, hei + 2 ); - else - m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 ); - - m_lSize->setText( tmpSize ); - } -} - -void VBorder::updateRows( int from, int to ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if ( !sheet ) - return; - - int y0 = sheet->rowPos( from, m_pCanvas ); - int y1 = sheet->rowPos( to+1, m_pCanvas ); - update( 0, y0, width(), y1-y0 ); -} - -void VBorder::paintEvent( TQPaintEvent* _ev ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if ( !sheet ) - return; - - TQPainter painter( this ); - TQColor highlightColor = View::highlightColor(); - TQPen pen( TQt::black, 1 ); - painter.setPen( pen ); - // painter.setBackgroundColor( colorGroup().base() ); - - // painter.eraseRect( _ev->rect() ); - - //TQFontMetrics fm = painter.fontMetrics(); - // Matthias Elter: This causes a SEGFAULT in ~TQPainter! - // Only god and the trolls know why ;-) - // bah...took me quite some time to track this one down... - - painter.setClipRect( _ev->rect() ); - - double yPos; - //Get the top row and the current y-position - int y = sheet->topRow( (m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().y() ) + m_pCanvas->yOffset()), yPos ); - //Align to the offset - yPos = yPos - m_pCanvas->yOffset(); - int width = m_pCanvas->d->view->doc()->zoomItX( YBORDER_WIDTH ); - - TQFont normalFont = painter.font(); - if ( m_pCanvas->d->view->doc()->zoom() < 100 ) - { - normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() * - normalFont.pointSizeFloat() ); - } - TQFont boldFont = normalFont; - boldFont.setBold( true ); - - //Loop through the rows, until we are out of range - while ( yPos <= m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().bottom() ) ) - { - bool selected = (m_pView->selectionInfo()->isRowSelected(y)); - bool highlighted = (!selected && m_pView->selectionInfo()->isRowAffected(y)); - - const RowFormat *row_lay = sheet->rowFormat( y ); - int zoomedYPos = m_pCanvas->d->view->doc()->zoomItY( yPos ); - int height = m_pCanvas->d->view->doc()->zoomItY( yPos + row_lay->dblHeight() ) - zoomedYPos; - - if ( selected ) - { - TQBrush fillSelected( highlightColor ); - qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150), - 1, &fillSelected ); - } - else if ( highlighted ) - { - TQBrush fillHighlighted( highlightColor ); - qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150), - 1, &fillHighlighted ); - } - else - { - TQColor c = colorGroup().background(); - TQBrush fill( c ); - qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, c.dark(150), - 1, &fill ); - } - - TQString rowText = TQString::number( y ); - - // Reset painter - painter.setFont( normalFont ); - painter.setPen( colorGroup().text() ); - - if ( selected ) - painter.setPen( colorGroup().highlightedText() ); - else if ( highlighted ) - painter.setFont( boldFont ); - - int len = painter.fontMetrics().width( rowText ); - if (!row_lay->isHide()) - painter.drawText( ( width-len )/2, zoomedYPos + - ( height + painter.fontMetrics().ascent() - - painter.fontMetrics().descent() ) / 2, rowText ); - - yPos += row_lay->dblHeight(); - y++; - } -} - - -void VBorder::focusOutEvent( TQFocusEvent* ) -{ - if ( m_scrollTimer->isActive() ) - m_scrollTimer->stop(); - m_bMousePressed = false; -} - - -/**************************************************************** - * - * HBorder - * - ****************************************************************/ - -HBorder::HBorder( TQWidget *_parent, Canvas *_canvas,View *_view ) - : TQWidget( _parent, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ) -{ - m_pView = _view; - m_pCanvas = _canvas; - m_lSize = 0L; - setBackgroundMode( PaletteButton ); - setMouseTracking( true ); - m_bResize = false; - m_bSelection = false; - m_iSelectionAnchor=1; - m_bMousePressed = false; - - m_scrollTimer = new TQTimer( this ); - connect( m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); -} - - -HBorder::~HBorder() -{ - delete m_scrollTimer; -} - -TQSize HBorder::sizeHint() const -{ - return TQSize( 40, 10 ); -} - -void HBorder::mousePressEvent( TQMouseEvent * _ev ) -{ - if (!m_pView->koDocument()->isReadWrite()) - return; - - if ( _ev->button() == Qt::LeftButton ) - m_bMousePressed = true; - - const Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - // We were editing a cell -> save value and get out of editing mode - if ( m_pCanvas->editor() ) - { - m_pCanvas->deleteEditor( true ); // save changes - } - - m_scrollTimer->start( 50 ); - - double ev_PosX; - double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - else - ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - m_bResize = false; - m_bSelection = false; - - // Find the first visible column and the x position of this column. - double x; - - const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 ); - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); - - kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", COL: " << tmpCol << endl; - while ( ev_PosX > x && ( !m_bResize ) ) - { - double w = sheet->columnFormat( tmpCol )->dblWidth(); - - kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", w: " << w << ", COL: " << tmpCol << endl; - - ++tmpCol; - if ( tmpCol > KS_colMax ) - tmpCol = KS_colMax; - //if col is hide and it's the first column - //you mustn't resize it. - - if ( ev_PosX >= x + w - unzoomedPixel && - ev_PosX <= x + w + unzoomedPixel && - !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) ) - { - m_bResize = true; - } - x += w; - } - - //if col is hide and it's the first column - //you mustn't resize it. - double tmp2; - tmpCol = sheet->leftColumn( dWidth - ev_PosX + 1, tmp2 ); - if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) - { - kdDebug() << "No resize: " << tmpCol << ", " << sheet->columnFormat( tmpCol )->isHide() << endl; - m_bResize = false; - } - - kdDebug() << "Resize: " << m_bResize << endl; - } - else - { - int col = sheet->leftColumn( m_pCanvas->xOffset(), x ); - - // Did the user click between two columns? - while ( x < ( dWidth + m_pCanvas->xOffset() ) && ( !m_bResize ) ) - { - double w = sheet->columnFormat( col )->dblWidth(); - col++; - if ( col > KS_colMax ) - col = KS_colMax; - if ( ( ev_PosX >= x + w - unzoomedPixel ) && - ( ev_PosX <= x + w + unzoomedPixel ) && - !( sheet->columnFormat( col )->isHide() && col == 1 ) ) - m_bResize = true; - x += w; - } - - //if col is hide and it's the first column - //you mustn't resize it. - double tmp2; - int tmpCol = sheet->leftColumn( ev_PosX - 1, tmp2 ); - if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) - m_bResize = false; - } - - // So he clicked between two rows ? - if ( m_bResize ) - { - // Determine the column to resize - double tmp; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp ); - // kdDebug() << "RColumn: " << m_iResizedColumn << ", PosX: " << ev_PosX << endl; - - if ( !sheet->isProtected() ) - paintSizeIndicator( _ev->pos().x(), true ); - } - else - { - m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp ); - - if ( !sheet->isProtected() ) - paintSizeIndicator( _ev->pos().x(), true ); - } - - // kdDebug() << "Column: " << m_iResizedColumn << endl; - } - else - { - m_bSelection = true; - - double tmp; - int hit_col = sheet->leftColumn( ev_PosX, tmp ); - if ( hit_col > KS_colMax ) - return; - - m_iSelectionAnchor = hit_col; - - if ( !m_pView->selectionInfo()->contains( TQPoint( hit_col, 1 ) ) || - !( _ev->button() == Qt::RightButton ) || - !m_pView->selectionInfo()->isColumnSelected() ) - { - TQPoint newMarker( hit_col, 1 ); - TQPoint newAnchor( hit_col, KS_rowMax ); -#ifdef NONCONTIGUOUSSELECTION - if (_ev->state() == ControlButton) - { - m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker)); - } - else -#endif - if (_ev->state() == ShiftButton) - { - m_pView->selectionInfo()->update(newMarker); - } - else - { - m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker)); - } - } - - if ( _ev->button() == Qt::RightButton ) - { - TQPoint p = mapToGlobal( _ev->pos() ); - m_pView->popupColumnMenu( p ); - m_bSelection = false; - } - m_pView->updateEditWidget(); - } -} - -void HBorder::mouseReleaseEvent( TQMouseEvent * _ev ) -{ - if ( m_scrollTimer->isActive() ) - m_scrollTimer->stop(); - - m_bMousePressed = false; - - if ( !m_pView->koDocument()->isReadWrite() ) - return; - - Sheet * sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - if ( m_bResize ) - { - double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); - double ev_PosX; - - // Remove size indicator painted by paintSizeIndicator - TQPainter painter; - painter.begin( m_pCanvas ); - painter.setRasterOp( NotROP ); - painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); - painter.end(); - - int start = m_iResizedColumn; - int end = m_iResizedColumn; - TQRect rect; - rect.setCoords( m_iResizedColumn, 1, m_iResizedColumn, KS_rowMax ); - if ( m_pView->selectionInfo()->isColumnSelected() ) - { - if ( m_pView->selectionInfo()->contains( TQPoint( m_iResizedColumn, 1 ) ) ) - { - start = m_pView->selectionInfo()->lastRange().left(); - end = m_pView->selectionInfo()->lastRange().right(); - rect = m_pView->selectionInfo()->lastRange(); - } - } - - double width = 0.0; - double x; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - else - ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - - x = sheet->dblColumnPos( m_iResizedColumn ); - - if ( ev_PosX - x <= 0.0 ) - width = 0.0; - else - width = ev_PosX - x; - - if ( !sheet->isProtected() ) - { - if ( !m_pCanvas->d->view->doc()->undoLocked() ) - { - //just resize - if ( width != 0.0 ) - { - // TODO Stefan: replace this - UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect ); - m_pCanvas->d->view->doc()->addCommand( undo ); - } - } - - for( int i = start; i <= end; i++ ) - { - ColumnFormat *cl = sheet->nonDefaultColumnFormat( i ); - if ( width != 0.0 ) - { - if ( !cl->isHide() ) - cl->setDblWidth( width ); - } - else - { - sheet->hideColumn(*m_pView->selectionInfo()); - } - } - - delete m_lSize; - m_lSize = 0; - } - } - else if ( m_bSelection ) - { - TQRect rect = m_pView->selectionInfo()->lastRange(); - - // TODO: please don't remove. Right now it's useless, but it's for a future feature - // Norbert - bool m_frozen = false; - if ( m_frozen ) - { - kdDebug(36001) << "selected: L " << rect.left() << " R " << rect.right() << endl; - - int i; - ColumnFormat * col; - TQValueListhiddenCols; - - for ( i = rect.left(); i <= rect.right(); ++i ) - { - col = m_pView->activeSheet()->columnFormat( i ); - if ( col->isHide() ) - { - hiddenCols.append(i); - } - } - - if ( hiddenCols.count() > 0 ) - m_pView->activeSheet()->showColumn(*m_pView->selectionInfo()); - } - } - - m_bSelection = false; - m_bResize = false; -} - -void HBorder::equalizeColumn( double resize ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - Q_ASSERT( sheet ); - - TQRect selection( m_pView->selectionInfo()->selection() ); - if ( !m_pCanvas->d->view->doc()->undoLocked() ) - { - UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection ); - m_pCanvas->d->view->doc()->addCommand( undo ); - } - ColumnFormat *cl; - for ( int i = selection.left(); i <= selection.right(); i++ ) - { - cl = sheet->nonDefaultColumnFormat( i ); - resize = TQMAX( 2.0, resize ); - cl->setDblWidth( resize ); - } - -} - -void HBorder::mouseDoubleClickEvent(TQMouseEvent*) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() ) - return; - - sheet->adjustColumn(*m_pCanvas->selectionInfo()); -} - -void HBorder::mouseMoveEvent( TQMouseEvent * _ev ) -{ - if ( !m_pView->koDocument()->isReadWrite() ) - return; - - Sheet *sheet = m_pCanvas->activeSheet(); - - if (!sheet) - return; - - double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); - double ev_PosX; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - else - ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); - - // The button is pressed and we are resizing ? - if ( m_bResize ) - { - if ( !sheet->isProtected() ) - paintSizeIndicator( _ev->pos().x(), false ); - } - // The button is pressed and we are selecting ? - else if ( m_bSelection ) - { - double x; - int col = sheet->leftColumn( ev_PosX, x ); - - if ( col > KS_colMax ) - return; - - TQPoint newMarker = m_pView->selectionInfo()->marker(); - TQPoint newAnchor = m_pView->selectionInfo()->anchor(); - newMarker.setX( col ); - newAnchor.setX( m_iSelectionAnchor ); - m_pView->selectionInfo()->update(newMarker); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - if ( _ev->pos().x() < width() - m_pCanvas->width() ) - { - ColumnFormat *cl = sheet->columnFormat( col + 1 ); - x = sheet->dblColumnPos( col + 1 ); - m_pCanvas->horzScrollBar()->setValue ( m_pCanvas->horzScrollBar()->maxValue() - (int) - (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() ))); - } - else if ( _ev->pos().x() > width() ) - m_pCanvas->horzScrollBar()->setValue( m_pCanvas->horzScrollBar()->maxValue() - m_pCanvas->d->view->doc()->zoomItX( ev_PosX - dWidth + m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() ) ) ); - } - else - { - if ( _ev->pos().x() < 0 ) - m_pCanvas->horzScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItX( ev_PosX ) ); - else if ( _ev->pos().x() > m_pCanvas->width() ) - { - if ( col < KS_colMax ) - { - ColumnFormat *cl = sheet->columnFormat( col + 1 ); - x = sheet->dblColumnPos( col + 1 ); - m_pCanvas->horzScrollBar()->setValue ((int) - (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - dWidth)); - } - } - } - - } - // No button is pressed and the mouse is just moved - else - { - //What is the internal size of 1 pixel - const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 ); - double x; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); - - while ( ev_PosX > x ) - { - double w = sheet->columnFormat( tmpCol )->dblWidth(); - ++tmpCol; - - //if col is hide and it's the first column - //you mustn't resize it. - if ( ev_PosX >= x + w - unzoomedPixel && - ev_PosX <= x + w + unzoomedPixel && - !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) ) - { - setCursor( splitHCursor ); - return; - } - x += w; - } - setCursor( arrowCursor ); - } - else - { - int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); - - while ( x < m_pCanvas->d->view->doc()->unzoomItY( width() ) + m_pCanvas->xOffset() ) - { - double w = sheet->columnFormat( tmpCol )->dblWidth(); - //if col is hide and it's the first column - //you mustn't resize it. - if ( ev_PosX >= x + w - unzoomedPixel && - ev_PosX <= x + w + unzoomedPixel && - !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) ) - { - setCursor( splitHCursor ); - return; - } - x += w; - tmpCol++; - } - setCursor( arrowCursor ); - } - } -} - -void HBorder::doAutoScroll() -{ - if ( !m_bMousePressed ) - { - m_scrollTimer->stop(); - return; - } - - TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); - - if ( pos.x() < 0 || pos.x() > width() ) - { - TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 ); - mouseMoveEvent( event ); - delete event; - } - - //Restart timer - m_scrollTimer->start( 50 ); -} - -void HBorder::wheelEvent( TQWheelEvent* _ev ) -{ - if ( m_pCanvas->horzScrollBar() ) - TQApplication::sendEvent( m_pCanvas->horzScrollBar(), _ev ); -} - -void HBorder::resizeEvent( TQResizeEvent* _ev ) -{ - // workaround to allow horizontal resizing and zoom changing when sheet - // direction and interface direction don't match (e.g. an RTL sheet on an - // LTR interface) - if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() ) - { - int dx = _ev->size().width() - _ev->oldSize().width(); - scroll(dx, 0); - } - else if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() ) - { - int dx = _ev->size().width() - _ev->oldSize().width(); - scroll(-dx, 0); - } -} - -void HBorder::paintSizeIndicator( int mouseX, bool firstTime ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if (!sheet) - return; - - TQPainter painter; - painter.begin( m_pCanvas ); - painter.setRasterOp( NotROP ); - - if ( !firstTime ) - painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - m_iResizePos = mouseX + m_pCanvas->width() - width(); - else - m_iResizePos = mouseX; - - // Dont make the column have a width < 2 pixels. - int x = m_pCanvas->d->view->doc()->zoomItX( sheet->dblColumnPos( m_iResizedColumn ) - m_pCanvas->xOffset() ); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - x = m_pCanvas->width() - x; - - if ( m_iResizePos > x - 2 ) - m_iResizePos = x; - } - else - { - if ( m_iResizePos < x + 2 ) - m_iResizePos = x; - } - - painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); - - painter.end(); - - TQString tmpSize; - if ( m_iResizePos != x ) - tmpSize = i18n("Width: %1 %2") - .arg( TDEGlobal::locale()->formatNumber( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItX( (sheet->layoutDirection()==Sheet::RightToLeft) ? x - m_iResizePos : m_iResizePos - x ), - m_pView->doc()->unit() ))) - .arg( m_pView->doc()->unitName() ); - else - tmpSize = i18n( "Hide Column" ); - - painter.begin( this ); - int len = painter.fontMetrics().width( tmpSize ); - int hei = painter.fontMetrics().height(); - painter.end(); - - if ( !m_lSize ) - { - m_lSize = new TQLabel( m_pCanvas ); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 ); - else - m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 ); - - m_lSize->setAlignment( TQt::AlignVCenter ); - m_lSize->setText( tmpSize ); - m_lSize->setPalette( TQToolTip::palette() ); - m_lSize->show(); - } - else - { - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 ); - else - m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 ); - - m_lSize->setText( tmpSize ); - } -} - -void HBorder::updateColumns( int from, int to ) -{ - Sheet *sheet = m_pCanvas->activeSheet(); - if ( !sheet ) - return; - - int x0 = sheet->columnPos( from, m_pCanvas ); - int x1 = sheet->columnPos( to+1, m_pCanvas ); - update( x0, 0, x1-x0, height() ); -} - -void HBorder::paintEvent( TQPaintEvent* _ev ) -{ - Sheet * sheet = m_pCanvas->activeSheet(); - if ( !sheet ) - return; - - TQColor highlightColor = View::highlightColor(); - TQPainter painter( this ); - TQPen pen( TQt::black, 1 ); - painter.setPen( pen ); - painter.setBackgroundColor( white ); - - painter.setClipRect( _ev->rect() ); - - // painter.eraseRect( _ev->rect() ); - - //TQFontMetrics fm = painter.fontMetrics(); - // Matthias Elter: This causes a SEGFAULT in ~TQPainter! - // Only god and the trolls know why ;-) - // bah...took me quite some time to track this one down... - - double xPos; - int x; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - //Get the left column and the current x-position - x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( width() ) - m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos ); - //Align to the offset - xPos = m_pCanvas->d->view->doc()->unzoomItX( width() ) - xPos + m_pCanvas->xOffset(); - } - else - { - //Get the left column and the current x-position - x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos ); - //Align to the offset - xPos = xPos - m_pCanvas->xOffset(); - } - - int height = m_pCanvas->d->view->doc()->zoomItY( TQFont(painter.font()).pointSizeFloat() + 5 ); - - TQFont normalFont = painter.font(); - if ( m_pCanvas->d->view->doc()->zoom() < 100 ) - { - normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() * - normalFont.pointSizeFloat() ); - } - TQFont boldFont = normalFont; - boldFont.setBold( true ); - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - if ( x > KS_colMax ) - x = KS_colMax; - - xPos -= sheet->columnFormat( x )->dblWidth(); - - //Loop through the columns, until we are out of range - while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) ) - { - bool selected = (m_pView->selectionInfo()->isColumnSelected(x)); - bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x)); - - const ColumnFormat * col_lay = sheet->columnFormat( x ); - int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos ); - int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos; - - if ( selected ) - { - TQBrush fillSelected( highlightColor ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150), - 1, &fillSelected ); - } - else if ( highlighted ) - { - TQBrush fillHighlighted( highlightColor ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150), - 1, &fillHighlighted ); - } - else - { - TQColor c = colorGroup().background(); - TQBrush fill( c ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150), - 1, &fill ); - } - - // Reset painter - painter.setFont( normalFont ); - painter.setPen( colorGroup().text() ); - - if ( selected ) - painter.setPen( colorGroup().highlightedText() ); - else if ( highlighted ) - painter.setFont( boldFont ); - if ( !m_pView->activeSheet()->getShowColumnNumber() ) - { - TQString colText = Cell::columnName( x ); - int len = painter.fontMetrics().width( colText ); - if ( !col_lay->isHide() ) - painter.drawText( zoomedXPos + ( width - len ) / 2, - ( height + painter.fontMetrics().ascent() - - painter.fontMetrics().descent() ) / 2, colText ); - } - else - { - TQString tmp; - int len = painter.fontMetrics().width( tmp.setNum(x) ); - if (!col_lay->isHide()) - painter.drawText( zoomedXPos + ( width - len ) / 2, - ( height + painter.fontMetrics().ascent() - - painter.fontMetrics().descent() ) / 2, - tmp.setNum(x) ); - } - xPos += col_lay->dblWidth(); - --x; - } - } - else - { - //Loop through the columns, until we are out of range - while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) ) - { - bool selected = (m_pView->selectionInfo()->isColumnSelected(x)); - bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x)); - - const ColumnFormat *col_lay = sheet->columnFormat( x ); - int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos ); - int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos; - - if ( selected ) - { - TQBrush fillSelected( highlightColor ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(), - 1, &fillSelected ); - } - else if ( highlighted ) - { - TQBrush fillHighlighted( highlightColor ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(), - 1, &fillHighlighted ); - } - else - { - TQColor c = colorGroup().background(); - TQBrush fill( c ); - qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150), - 1, &fill ); - } - - // Reset painter - painter.setFont( normalFont ); - painter.setPen( colorGroup().text() ); - - if ( selected ) - painter.setPen( colorGroup().highlightedText() ); - else if ( highlighted ) - painter.setFont( boldFont ); - if ( !m_pView->activeSheet()->getShowColumnNumber() ) - { - TQString colText = Cell::columnName( x ); - int len = painter.fontMetrics().width( colText ); - if (!col_lay->isHide()) - painter.drawText( zoomedXPos + ( width - len ) / 2, - ( height + painter.fontMetrics().ascent() - - painter.fontMetrics().descent() ) / 2, colText ); - } - else - { - TQString tmp; - int len = painter.fontMetrics().width( tmp.setNum(x) ); - if (!col_lay->isHide()) - painter.drawText( zoomedXPos + ( width - len ) / 2, - ( height + painter.fontMetrics().ascent() - - painter.fontMetrics().descent() ) / 2, - tmp.setNum(x) ); - } - xPos += col_lay->dblWidth(); - ++x; - } - } -} - - -void HBorder::focusOutEvent( TQFocusEvent* ) -{ - if ( m_scrollTimer->isActive() ) - m_scrollTimer->stop(); - m_bMousePressed = false; -} - -/**************************************************************** - * - * ToolTip - * - ****************************************************************/ - -ToolTip::ToolTip( Canvas* canvas ) - : TQToolTip( canvas ), m_canvas( canvas ) -{ -} - -// find the label for the tip -// this is a hack of course, because it's not available from TQToolTip -TQLabel *tip_findLabel() -{ - TQWidgetList *list = TQApplication::allWidgets(); - TQWidgetListIt it( *list ); - TQWidget * w; - while ( (w=it.current()) != 0 ) - { - if(w->isA("TQTipLabel")) - return static_cast(w); - ++it; - } - delete list; - return 0; -} - -void ToolTip::maybeTip( const TQPoint& p ) -{ - Sheet *sheet = m_canvas->activeSheet(); - if ( !sheet ) - return; - - // Over which cell is the mouse ? - double ypos, xpos; - double dwidth = m_canvas->doc()->unzoomItX( m_canvas->width() ); - int col; - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - col = sheet->leftColumn( (dwidth - m_canvas->doc()->unzoomItX( p.x() ) + - m_canvas->xOffset()), xpos ); - else - col = sheet->leftColumn( (m_canvas->doc()->unzoomItX( p.x() ) + - m_canvas->xOffset()), xpos ); - - - int row = sheet->topRow( (m_canvas->doc()->unzoomItY( p.y() ) + - m_canvas->yOffset()), ypos ); - - const Cell* cell = sheet->visibleCellAt( col, row ); - if ( !cell ) - return; - -#if 0 - // Quick cut - if( cell->strOutText().isEmpty() ) - return; -#endif - // displayed tool tip, which has the following priorities: - // - cell content if the cell dimension is too small - // - cell comment - // - hyperlink - TQString tipText; - TQString comment = cell->format()->comment( col, row ); - - // If cell is too small, show the content - if ( cell->testFlag( Cell::Flag_CellTooShortX ) || - cell->testFlag( Cell::Flag_CellTooShortY ) ) - { - tipText = cell->strOutText(); - } - - // Show hyperlink, if any - if ( tipText.isEmpty() ) - { - tipText = cell->link(); - } - - // Nothing to display, bail out - if ( tipText.isEmpty() && comment.isEmpty() ) - return; - - // Cut if the tip is ridiculously long - const unsigned maxLen = 256; - if ( tipText.length() > maxLen ) - tipText = tipText.left(maxLen).append("..."); - - // Determine position and width of the current cell. - double u = cell->dblWidth( col ); - double v = cell->dblHeight( row ); - - // Special treatment for obscured cells. - if ( cell->isObscured() && cell->isPartOfMerged() ) - { - cell = cell->obscuringCells().first(); - const int moveX = cell->column(); - const int moveY = cell->row(); - - // Use the obscuring cells dimensions - u = cell->dblWidth( moveX ); - v = cell->dblHeight( moveY ); - xpos = sheet->dblColumnPos( moveX ); - ypos = sheet->dblRowPos( moveY ); - } - - // Get the cell dimensions - TQRect marker; - bool insideMarker = false; - - if ( sheet->layoutDirection()==Sheet::RightToLeft ) - { - KoRect unzoomedMarker( dwidth - u - xpos + m_canvas->xOffset(), - ypos - m_canvas->yOffset(), - u, - v ); - - marker = m_canvas->doc()->zoomRect( unzoomedMarker ); - insideMarker = marker.contains( p ); - } - else - { - KoRect unzoomedMarker( xpos - m_canvas->xOffset(), - ypos - m_canvas->yOffset(), - u, - v ); - - marker = m_canvas->doc()->zoomRect( unzoomedMarker ); - insideMarker = marker.contains( p ); - } - - // No use if mouse is somewhere else - if ( !insideMarker ) - return; - - // Find the tipLabel - // NOTE: if we failed, check again when the tip is shown already - TQLabel* tipLabel = tip_findLabel(); - - // Ensure that it is plain text - // Not funny if (intentional or not) appears as hyperlink - if ( tipLabel ) - tipLabel->setTextFormat( TQt::PlainText ); - - TQFontMetrics fm = tipLabel ? tipLabel->fontMetrics() : m_canvas->fontMetrics(); - const TQRect r( 0, 0, 200, -1 ); - // Wrap the text if too long - if ( tipText.length() > 16 ) - { - KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, tipText ); - tipText = wrap->wrappedString(); - delete wrap; - } - // Wrap the comment if too long - if ( comment.length() > 16 ) - { - KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, comment ); - comment = wrap->wrappedString(); - delete wrap; - } - - // Show comment, if any - if ( tipText.isEmpty() ) - { - tipText = comment; - } - else if ( !comment.isEmpty() ) - { - //Add 2 extra lines and a text, when both should be in the tooltip - if ( !comment.isEmpty() ) - comment = "\n\n" + i18n("Comment:") + "\n" + comment; - - tipText += comment; - } - - // Now we shows the tip - tip( marker, tipText ); - - // Here we try to find the tip label again - // Reason: the previous tip_findLabel might fail if no tip has ever shown yet - if ( !tipLabel ) - { - tipLabel = tip_findLabel(); - if( tipLabel ) - tipLabel->setTextFormat( TQt::PlainText ); - } - -} - -#include "kspread_canvas.moc" diff --git a/kspread/kspread_canvas.cpp b/kspread/kspread_canvas.cpp new file mode 100644 index 00000000..0518e274 --- /dev/null +++ b/kspread/kspread_canvas.cpp @@ -0,0 +1,6167 @@ +/* This file is part of the KDE project + + Copyright 2006 Robert Knight + Copyright 2006 Inge Wallin + Copyright 2006 Stefan Nikolaus + Copyright 1999-2002,2004 Laurent Montel + Copyright 2002-2005 Ariya Hidayat + Copyright 1999-2004 David Faure + Copyright 2004-2005 Meni Livne + Copyright 2001-2003 Philipp Mueller + Copyright 2002-2003 Norbert Andres + Copyright 2003 Hamish Rodda + Copyright 2003 Joseph Wenninger + Copyright 2003 Lukas Tinkl + Copyright 2000-2002 Werner Trobin + Copyright 2002 Harri Porten + Copyright 2002 John Dailey + Copyright 2002 Daniel Naber + Copyright 1999-2000 Torben Weis + Copyright 1999-2000 Stephan Kulow + Copyright 2000 Bernd Wuebben + Copyright 2000 Wilco Greven + Copyright 2000 Simon Hausmann + Copyright 1999 Boris Wedl + Copyright 1999 Reginald Stadlbauer + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "commands.h" +#include "kspread_doc.h" +#include "kspread_editors.h" +#include "kspread_global.h" +#include "kspread_locale.h" +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_undo.h" +#include "kspread_util.h" +#include "kspread_view.h" +#include "selection.h" + +#include "kspread_canvas.h" + +// TODO Stefan: undefine/remove, if non-contiguous selections don't work +// properly or if we are sure, that they do. ;-) +#define NONCONTIGUOUSSELECTION + +#define MIN_SIZE 10 + +using namespace KSpread; + +class Canvas::Private +{ + public: + ComboboxLocationEditWidget *posWidget; + KSpread::EditWidget *editWidget; + KSpread::CellEditor *cellEditor; + + View *view; + TQTimer* scrollTimer; + + // Non visible range left from current screen + // Example: If the first visible column is 'E', then xOffset stores + // the width of the invisible columns 'A' to 'D'. + double xOffset; + + // Non visible range on top of the current screen + // Example: If the first visible row is '5', then yOffset stores + // the height of the invisible rows '1' to '4'. + double yOffset; + + // Used to draw the grey grid that is usually only visible on the + // screen, but not by printing on paper. + TQPen defaultGridPen; + + // see setLastEditorWithFocus, lastEditorWithFocus + Canvas::EditorType focusEditorType; + + TQLabel *validationInfo; + + // true if the user is to choose a cell. + bool chooseCell; + + // True when the mouse button is pressed + bool mousePressed; + + // If the user is dragging around with the mouse then this tells us what he is doing. + // The user may want to mark cells or he started in the lower right corner + // of the marker which is something special. The values for the 2 above + // methods are called 'Mark' and 'ResizeCell' or 'AutoFill' depending + // on the mouse button used. By default this variable holds + // the value 'NoAction'. + Canvas::MouseActions mouseAction; + + // If we use the lower right corner of the marker to start autofilling, then this + // rectangle conatins all cells that were already marker when the user started + // to mark the rectangle which he wants to become autofilled. + TQRect autoFillSource; + + // Start coordinates for drag and drop + TQPoint dragStart; + bool dragging; + + // Used to indicate whether the user started drawing a rubber band rectangle + bool rubberBandStarted; + TQPoint rubberBandStart; + TQPoint rubberBandEnd; + + // If the mouse is over some anchor ( in the sense of HTML anchors ) + TQString anchor; + + bool mouseSelectedObject; + bool drawContour; + ModifyType modType; + /** + * Saves the last mouse position during mouse move events. + */ + TQPoint m_savedMousePos; + + //---- stuff needed for resizing ---- + /// object which gets resized + EmbeddedObject *m_resizeObject; + /// ratio of the object ( width / height ) + double m_ratio; + bool m_isResizing; + /// The last position of the mouse during moving + KoPoint m_origMousePos; + + //---- stuff needed for moving ---- + bool m_isMoving; + KoPoint m_moveStartPoint; + + /// size of the object at when resizing is started + KoRect m_rectBeforeResize; + /// Start position for move with mouse + KoPoint m_moveStartPosMouse; + + /// object which is selected and should be shown above all the other objects + EmbeddedObject * m_objectDisplayAbove; + + // bool mouseOverHighlightRangeSizeGrip; + + // The row and column of 1) the last cell under mouse pointer, 2) the last focused cell, and + // the last spoken cell. + int prevSpokenPointerRow; + int prevSpokenPointerCol; + int prevSpokenFocusRow; + int prevSpokenFocusCol; + int prevSpokenRow; + int prevSpokenCol; +}; + + + +/**************************************************************** + * + * Canvas + * + ****************************************************************/ + +Canvas::Canvas (View *_view) + : TQWidget( _view, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ) +{ + d = new Private; + + d->cellEditor = 0; + d->chooseCell = false; + d->validationInfo = 0L; + + TQWidget::setFocusPolicy( TQ_StrongFocus ); + + d->dragStart = TQPoint( -1, -1 ); + d->dragging = false; + + + d->defaultGridPen.setColor( lightGray ); + d->defaultGridPen.setWidth( 1 ); + d->defaultGridPen.setStyle( Qt::SolidLine ); + + d->xOffset = 0.0; + d->yOffset = 0.0; + d->view = _view; + // m_eAction = DefaultAction; + d->mouseAction = NoAction; + d->rubberBandStarted = false; + // m_bEditDirtyFlag = false; + + //Now built afterwards(David) + //d->editWidget = d->view->editWidget(); + d->posWidget = d->view->posWidget(); + + setBackgroundMode( PaletteBase ); + + setMouseTracking( true ); + d->mousePressed = false; + d->mouseSelectedObject = false; + d->drawContour = false; + d->modType = MT_NONE; + + d->m_resizeObject = 0L; + d->m_ratio = 0.0; + d->m_isMoving = false; + d->m_objectDisplayAbove = 0; + d->m_isResizing = false; + + d->prevSpokenPointerRow = -1; + d->prevSpokenPointerCol = -1; + d->prevSpokenFocusRow = -1; + d->prevSpokenFocusCol = -1; + d->prevSpokenRow = -1; + d->prevSpokenCol = -1; + + d->scrollTimer = new TQTimer( this ); + connect (d->scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); + + if( d->view) + { + connect( d->view, TQT_SIGNAL( autoScroll( const TQPoint & )), this, TQT_SLOT( slotAutoScroll( const TQPoint &))); + } + if (kospeaker) + { + connect (kospeaker, TQT_SIGNAL(customSpeakWidget(TQWidget*, const TQPoint&, uint)), + this, TQT_SLOT(speakCell(TQWidget*, const TQPoint&, uint))); + } + + setFocus(); + installEventFilter( this ); + (void)new ToolTip( this ); + setAcceptDrops( true ); + setInputMethodEnabled( true ); // ensure using the InputMethod + + setWFlags(TQt::WNoAutoErase); +} + +Canvas::~Canvas() +{ + delete d->scrollTimer; + delete d->validationInfo; + delete d; +} + +KSpread::View* Canvas::view() const +{ + return d->view; +} + +Doc* Canvas::doc() const +{ + return d->view->doc(); +} + +void Canvas::setEditWidget( KSpread::EditWidget * ew ) +{ + d->editWidget = ew; +} + +KSpread::EditWidget* Canvas::editWidget() const +{ + return d->editWidget; +} + +CellEditor* Canvas::editor() const +{ + return d->cellEditor; +} + +double Canvas::xOffset() const +{ + return d->xOffset; +} + +double Canvas::yOffset() const +{ + return d->yOffset; +} + +void Canvas::setXOffset( double _xOffset ) +{ + d->xOffset = _xOffset; +} + +void Canvas::setYOffset( double _yOffset ) +{ + d->yOffset = _yOffset; +} + +const TQPen& Canvas::defaultGridPen() const +{ + return d->defaultGridPen; +} + +void Canvas::setLastEditorWithFocus( Canvas::EditorType type ) +{ + d->focusEditorType = type; +} + +Canvas::EditorType Canvas::lastEditorWithFocus() const +{ + return d->focusEditorType; +} + + +bool Canvas::eventFilter( TQObject *o, TQEvent *e ) +{ + /* this canvas event filter acts on events sent to the line edit as well + as events to this filter itself. + */ + if ( !o || !e ) + return true; + switch ( e->type() ) + { + case TQEvent::KeyPress: + { + TQKeyEvent * keyev = TQT_TQKEYEVENT(e); + if ((keyev->key()==Key_Tab) || (keyev->key()==Key_Backtab)) + { + keyPressEvent ( keyev ); + return true; + } + break; + } + case TQEvent::IMStart: + case TQEvent::IMCompose: + case TQEvent::IMEnd: + { + TQIMEvent * imev = static_cast(e); + processIMEvent( imev ); + break; + } + default: + break; + } + return false; +} + +bool Canvas::focusNextPrevChild( bool ) +{ + return true; // Don't allow to go out of the canvas widget by pressing "Tab" +} + +Selection* Canvas::selectionInfo() const +{ + return d->view->selectionInfo(); +} + +Selection* Canvas::choice() const +{ + return d->view->choice(); +} + +TQRect Canvas::selection() const +{ + return d->view->selectionInfo()->selection(); +} + +TQPoint Canvas::marker() const +{ + return d->view->selectionInfo()->marker(); +} + +int Canvas::markerColumn() const +{ + return d->view->selectionInfo()->marker().x(); +} + +int Canvas::markerRow() const +{ + return d->view->selectionInfo()->marker().y(); +} + +double Canvas::zoom() const +{ + return d->view->zoom(); +} + +void Canvas::setChooseMode(bool state) +{ + d->chooseCell = state; +} + +bool Canvas::chooseMode() const +{ + return d->chooseCell; +} + +void Canvas::startChoose() +{ + if ( d->chooseCell ) + return; + + choice()->clear(); + choice()->setSheet(activeSheet()); + + // It is important to enable this AFTER we set the rect! + d->chooseCell = true; +} + +void Canvas::startChoose( const TQRect& rect ) +{ + if (d->chooseCell) + return; + + choice()->setSheet(activeSheet()); + choice()->initialize(rect); + + // It is important to enable this AFTER we set the rect! + d->chooseCell = true; +} + +void Canvas::endChoose() +{ + // While entering a formula the choose mode is turned on and off. + // Clear the choice even if we are not in choose mode. Otherwise, + // cell references will stay highlighted. + if (!choice()->isEmpty()) + { + choice()->clear(); + update(); + } + + if ( !d->chooseCell ) + return; + + d->chooseCell = false; + + Sheet *sheet = choice()->sheet(); + if (sheet) + { + d->view->setActiveSheet(sheet); + } +} + +HBorder* Canvas::hBorderWidget() const +{ + return d->view->hBorderWidget(); +} + +VBorder* Canvas::vBorderWidget() const +{ + return d->view->vBorderWidget(); +} + +TQScrollBar* Canvas::horzScrollBar() const +{ + return d->view->horzScrollBar(); +} + +TQScrollBar* Canvas::vertScrollBar() const +{ + return d->view->vertScrollBar(); +} + +Sheet* Canvas::findSheet( const TQString& _name ) const +{ + return d->view->doc()->map()->findSheet( _name ); +} + +Sheet* Canvas::activeSheet() const +{ + return d->view->activeSheet(); +} + +void Canvas::validateSelection() +{ + Sheet* sheet = activeSheet(); + if (!sheet) + { + return; + } + + if ( selectionInfo()->isSingular() ) + { + int col = selectionInfo()->marker().x(); + int row = selectionInfo()->marker().y(); + Cell * cell = sheet->cellAt( col,row ); + if ( cell && cell->getValidity(0) && cell->getValidity()->displayValidationInformation) + { + TQString title = cell->getValidity(0)->titleInfo; + TQString message = cell->getValidity(0)->messageInfo; + if ( title.isEmpty() && message.isEmpty() ) + return; + + if ( !d->validationInfo ) + d->validationInfo = new TQLabel( this ); + kdDebug()<<" display info validation\n"; + double u = cell->dblWidth( col ); + double v = cell->dblHeight( row ); + double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset(); + double ypos = sheet->dblRowPos( markerRow() ) - yOffset(); + // Special treatment for obscured cells. + if ( cell->isObscured() && cell->isPartOfMerged() ) + { + cell = cell->obscuringCells().first(); + int moveX = cell->column(); + int moveY = cell->row(); + + // Use the obscuring cells dimensions + u = cell->dblWidth( moveX ); + v = cell->dblHeight( moveY ); + xpos = sheet->dblColumnPos( moveX ); + ypos = sheet->dblRowPos( moveY ); + } + //d->validationInfo->setGeometry( 3, y + 3, len + 2, hei + 2 ); + d->validationInfo->setAlignment( TQt::AlignVCenter ); + TQPainter painter; + painter.begin( this ); + int len = 0; + int hei = 0; + TQString resultText; + if ( !title.isEmpty() ) + { + len = painter.fontMetrics().width( title ); + hei = painter.fontMetrics().height(); + resultText = title + "\n"; + } + if ( !message.isEmpty() ) + { + int i = 0; + int pos = 0; + TQString t; + do + { + i = message.find( "\n", pos ); + if ( i == -1 ) + t = message.mid( pos, message.length() - pos ); + else + { + t = message.mid( pos, i - pos ); + pos = i + 1; + } + hei += painter.fontMetrics().height(); + len = TQMAX( len, painter.fontMetrics().width( t ) ); + } + while ( i != -1 ); + resultText += message; + } + painter.end(); + d->validationInfo->setText( resultText ); + + KoRect unzoomedMarker( xpos - xOffset()+u, + ypos - yOffset()+v, + len, + hei ); + TQRect marker( d->view->doc()->zoomRect( unzoomedMarker ) ); + + d->validationInfo->setGeometry( marker ); + d->validationInfo->show(); + } + else + { + delete d->validationInfo; + d->validationInfo = 0L; + } + } + else + { + delete d->validationInfo; + d->validationInfo = 0L; + } +} + + +void Canvas::scrollToCell(TQPoint location) const +{ + Sheet* sheet = activeSheet(); + if (sheet == NULL) + return; + + if (d->view->isLoading()) + return; + + // kdDebug(36001) << "------------------------------------------------" << endl; + // kdDebug(36001) << "scrollToCell(): at location [" << location.x() << "," + // << location.y() << "]" << endl; + + /* we don't need this cell ptr, but this call is necessary to update the + scroll bar correctly. I don't like having that as part of the cellAt function + but I suppose that's ok for now. + */ + Cell* cell = sheet->cellAt(location.x(), location.y(), true); + Q_UNUSED(cell); + + double unzoomedWidth = d->view->doc()->unzoomItX( width() ); + double unzoomedHeight = d->view->doc()->unzoomItY( height() ); + + //kdDebug(36001) << "Unzoomed view size: [" << unzoomedWidth << "," + // << unzoomedHeight << "]" << endl; + + // xpos is the position of the cell in the current window in unzoomed + // document coordinates. + double xpos; + if ( sheet->layoutDirection()==Sheet::LeftToRight ) + xpos = sheet->dblColumnPos( location.x() ) - xOffset(); + else + xpos = unzoomedWidth - sheet->dblColumnPos( location.x() ) + xOffset(); + double ypos = sheet->dblRowPos( location.y() ) - yOffset(); + + //kdDebug(36001) << "Position: [" << xpos << "," << ypos << "]" << endl; + + double minY = 40.0; + double maxY = unzoomedHeight - 40.0; + //kdDebug(36001) << "Canvas::scrollToCell : height=" << height() << endl; + //kdDebug(36001) << "Canvas::scrollToCell : width=" << width() << endl; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) { + // Right to left sheet. + + double minX = unzoomedWidth - 100.0; // less than that, we scroll + double maxX = 100.0; // more than that, we scroll + + // kdDebug() << "rtl2: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << ", Offset: " << xOffset() << endl; + + // Do we need to scroll left? + if ( xpos > minX ) + horzScrollBar()->setValue( horzScrollBar()->maxValue() - + d->view->doc()->zoomItX( xOffset() - xpos + minX ) ); + + // Do we need to scroll right? + else if ( xpos < maxX ) + { + double horzScrollBarValue = xOffset() - xpos + maxX; + double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth; + + //We don't want to display any area > KS_colMax widths + if ( horzScrollBarValue > horzScrollBarValueMax ) + horzScrollBarValue = horzScrollBarValueMax; + + horzScrollBar()->setValue( horzScrollBar()->maxValue() - + d->view->doc()->zoomItX( horzScrollBarValue ) ); + } + } + else { + // Left to right sheet. + + double minX = 100.0; // less than that, we scroll + double maxX = unzoomedWidth - 100.0; // more than that, we scroll + + // kdDebug() << "ltr: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << endl; + + // Do we need to scroll left? + if ( xpos < minX ) + horzScrollBar()->setValue( d->view->doc()->zoomItX( xOffset() + xpos - minX ) ); + + // Do we need to scroll right? + else if ( xpos > maxX ) + { + double horzScrollBarValue = xOffset() + xpos - maxX; + double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth; + + //We don't want to display any area > KS_colMax widths + if ( horzScrollBarValue > horzScrollBarValueMax ) + horzScrollBarValue = horzScrollBarValueMax; + + horzScrollBar()->setValue( d->view->doc()->zoomItX( horzScrollBarValue ) ); + } + } +// kdDebug() << "ltr: YPos: " << ypos << ", min: " << minY << ", maxY: " << maxY << endl; + + // do we need to scroll up + if ( ypos < minY ) + vertScrollBar()->setValue( d->view->doc()->zoomItY( yOffset() + ypos - minY ) ); + + // do we need to scroll down + else if ( ypos > maxY ) + { + double vertScrollBarValue = yOffset() + ypos - maxY; + double vertScrollBarValueMax = sheet->sizeMaxY() - unzoomedHeight; + + //We don't want to display any area > KS_rowMax heights + if ( vertScrollBarValue > vertScrollBarValueMax ) + vertScrollBarValue = vertScrollBarValueMax; + + vertScrollBar()->setValue( d->view->doc()->zoomItY( vertScrollBarValue ) ); + } +} + +void Canvas::slotScrollHorz( int _value ) +{ + Sheet * sheet = activeSheet(); + + if ( sheet == 0L ) + return; + + kdDebug(36001) << "slotScrollHorz: value = " << _value << endl; + //kdDebug(36001) << kdBacktrace() << endl; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + _value = horzScrollBar()->maxValue() - _value; + + double unzoomedValue = d->view->doc()->unzoomItX( _value ); + double dwidth = d->view->doc()->unzoomItX( width() ); + + d->view->doc()->emitBeginOperation(false); + + if ( unzoomedValue < 0.0 ) { + kdDebug (36001) + << "Canvas::slotScrollHorz: value out of range (unzoomedValue: " + << unzoomedValue << ")" << endl; + unzoomedValue = 0.0; + } + + double xpos = sheet->dblColumnPos( TQMIN( KS_colMax, d->view->activeSheet()->maxColumn()+10 ) ) - d->xOffset; + if ( unzoomedValue > ( xpos + d->xOffset ) ) + unzoomedValue = xpos + d->xOffset; + + sheet->enableScrollBarUpdates( false ); + + // Relative movement + int dx = d->view->doc()->zoomItX( d->xOffset - unzoomedValue ); + + + /* what cells will need painted now? */ + TQRect area = visibleCells(); + double tmp; + if (dx > 0) + { + area.setRight( area.left() ); + area.setLeft( sheet->leftColumn( unzoomedValue, tmp ) ); + } + else + { + area.setLeft( area.right() ); + area.setRight( sheet->rightColumn( dwidth + unzoomedValue ) ); + } + + sheet->setRegionPaintDirty(area); + + // New absolute position + kdDebug(36001) << "slotScrollHorz(): XOffset before setting: " + << d->xOffset << endl; + d->xOffset = unzoomedValue; + kdDebug(36001) << "slotScrollHorz(): XOffset after setting: " + << d->xOffset << endl; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + dx = -dx; + + scroll( dx, 0 ); + + hBorderWidget()->scroll( dx, 0 ); + + sheet->enableScrollBarUpdates( true ); + + d->view->doc()->emitEndOperation( sheet->visibleRect( this ) ); +} + +void Canvas::slotScrollVert( int _value ) +{ + if ( activeSheet() == 0L ) + return; + + d->view->doc()->emitBeginOperation(false); + double unzoomedValue = d->view->doc()->unzoomItY( _value ); + + if ( unzoomedValue < 0 ) + { + unzoomedValue = 0; + kdDebug (36001) << "Canvas::slotScrollVert: value out of range (unzoomedValue: " << + unzoomedValue << ")" << endl; + } + + double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, d->view->activeSheet()->maxRow()+10 ) ); + if ( unzoomedValue > ypos ) + unzoomedValue = ypos; + + activeSheet()->enableScrollBarUpdates( false ); + + // Relative movement + int dy = d->view->doc()->zoomItY( d->yOffset - unzoomedValue ); + + + /* what cells will need painted now? */ + TQRect area = visibleCells(); + double tmp; + if (dy > 0) + { + area.setBottom(area.top()); + area.setTop(activeSheet()->topRow(unzoomedValue, tmp)); + } + else + { + area.setTop(area.bottom()); + area.setBottom(activeSheet()->bottomRow(d->view->doc()->unzoomItY(height()) + + unzoomedValue)); + } + + activeSheet()->setRegionPaintDirty( area ); + + // New absolute position + d->yOffset = unzoomedValue; + scroll( 0, dy ); + vBorderWidget()->scroll( 0, dy ); + + activeSheet()->enableScrollBarUpdates( true ); + + d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) ); +} + +void Canvas::slotMaxColumn( int _max_column ) +{ + int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); + double xpos = activeSheet()->dblColumnPos( TQMIN( KS_colMax, _max_column + 10 ) ) - xOffset(); + double unzoomWidth = d->view->doc()->unzoomItX( width() ); + + //Don't go beyond the maximum column range (KS_colMax) + double sizeMaxX = activeSheet()->sizeMaxX(); + if ( xpos > sizeMaxX - xOffset() - unzoomWidth ) + xpos = sizeMaxX - xOffset() - unzoomWidth; + + horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( xpos + xOffset() ) ); + + if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) + horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); +} + +void Canvas::slotMaxRow( int _max_row ) +{ + double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, _max_row + 10 ) ) - yOffset(); + double unzoomHeight = d->view->doc()->unzoomItY( height() ); + + //Don't go beyond the maximum row range (KS_rowMax) + double sizeMaxY = activeSheet()->sizeMaxY(); + if ( ypos > sizeMaxY - yOffset() - unzoomHeight ) + ypos = sizeMaxY - yOffset() - unzoomHeight; + + vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( ypos + yOffset() ) ); +} + +void Canvas::mouseMoveEvent( TQMouseEvent * _ev ) +{ + // Dont allow modifications if document is readonly. Selecting is no modification + if ( (!d->view->koDocument()->isReadWrite()) && (d->mouseAction!=Mark)) + return; + + if ( d->mousePressed && d->modType != MT_NONE ) + { + KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) ); + docPoint += KoPoint( xOffset(), yOffset() ); + + if ( d->modType == MT_MOVE ) + { + if ( !d->m_isMoving ) + { + d->m_moveStartPoint = objectRect( false ).topLeft(); + d->m_isMoving = true; + } + moveObjectsByMouse( docPoint, _ev->state() & AltButton || _ev->state() & ControlButton ); + } + else if ( d->m_resizeObject ) + { + if ( !d->m_isResizing ) + d->m_isResizing = true; + + bool keepRatio = d->m_resizeObject->isKeepRatio(); + if ( _ev->state() & AltButton ) + { + keepRatio = true; + } + docPoint = KoPoint( doc()->unzoomPoint( _ev->pos() ) ); + resizeObject( d->modType, docPoint, keepRatio ); + } + return; + } + + + /*if ( d->mousePressed && d->m_resizeObject && d->modType != MT_NONE ) + { + if ( !d->m_isMoving ) + { + d->m_isMoving = true; + update(); + } + else + update( d->m_boundingRealRect ); + + + TQRect drawingRect; + + if ( d->modType == MT_MOVE ) + { + drawingRect = TQRect( _ev->pos() - d->m_origPos, d->m_origSize ); + d->m_boundingRealRect = drawingRect; + } + else + { + drawingRect = doc()->zoomRect( calculateNewGeometry(d->modType, _ev->pos().x(), _ev->pos().y() ) ); + drawingRect.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ) , (int)( -yOffset() * doc()->zoomedResolutionY() ) ); + } + + // Autoscrolling + if ( ( d->modType == MT_MOVE && drawingRect.top() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().y() < 0 ) ) + { + vertScrollBar()->setValue ((int) ( vertScrollBar()->value() - + autoScrollAccelerationY( - drawingRect.top() ) ) ); + } + else if ( ( d->modType == MT_MOVE && drawingRect.bottom() > height() ) || ( d->modType != MT_MOVE && _ev->pos().y() > height() ) ) + { + vertScrollBar()->setValue ((int) ( vertScrollBar()->value() + + autoScrollAccelerationY ( drawingRect.bottom() - height() ) ) ); + } + if ( ( d->modType == MT_MOVE && drawingRect.left() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().x() < 0 ) ) + { + horzScrollBar()->setValue ((int) ( horzScrollBar()->value() - + autoScrollAccelerationX( - drawingRect.left() ) ) ); + } + else if ( ( d->modType == MT_MOVE && drawingRect.right() > width() ) || ( d->modType != MT_MOVE && _ev->pos().x() > width() ) ) + { + horzScrollBar()->setValue ((int) (horzScrollBar()->value() + + autoScrollAccelerationX( drawingRect.right() - width() ) ) ); + } + + if ( drawingRect.left() < 0 ) + { + drawingRect.setRight( drawingRect.right() -drawingRect.left() ); + drawingRect.setLeft( 0 ); + } + if ( drawingRect.top() < 0 ) + { + drawingRect.setBottom( drawingRect.bottom() -drawingRect.top() ); + drawingRect.setTop( 0 ); + } + + d->m_boundingRealRect = drawingRect; //redraw this area next time the mouse has been moved + + //update( d->m_boundingRealRect ); + TQPainter p(this); + p.setRasterOp( NotROP ); + p.setPen( TQPen( black, 0, DotLine ) ); + p.drawRect( drawingRect ); + p.end(); + return; +}*/ + + if ( d->dragging ) + { + return; + } + if ( d->dragStart.x() != -1 ) + { + TQPoint p ( (int) _ev->pos().x() + (int) xOffset(), + (int) _ev->pos().y() + (int) yOffset() ); + + if ( ( d->dragStart - p ).manhattanLength() > 4 ) + { + d->dragging = true; + startTheDrag(); + d->dragStart.setX( -1 ); + } + d->dragging = false; + return; + } + + // Get info about where the event occurred - this is duplicated + // in ::mousePressEvent, needs to be separated into one function + Sheet *sheet = activeSheet(); + if ( !sheet ) + { + return; + } + + if ( d->mouseSelectedObject ) + { + EmbeddedObject *obj = 0; + TQPoint p ( (int) _ev->x(), + (int) _ev->y() ); + if ( ( obj = getObject( p, activeSheet() ) ) && obj->isSelected() ) + { + KoRect const bound = obj->geometry(); + TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(), + bound.width(), + bound.height() ) ); + zoomedBound.moveBy( (int)(-xOffset() * doc()->zoomedResolutionX() ), (int)(-yOffset() * doc()->zoomedResolutionY() )); + setCursor( obj->getCursor( p, d->modType, zoomedBound ) ); + return; + } + } + + double dwidth = d->view->doc()->unzoomItX( width() ); + double ev_PosX; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + } + else + { + ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + } + double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); + + // In which cell did the user click ? + double xpos; + double ypos; + int col = sheet->leftColumn( ev_PosX, xpos ); + int row = sheet->topRow( ev_PosY, ypos ); + + // you cannot move marker when col > KS_colMax or row > KS_rowMax + if ( col > KS_colMax || row > KS_rowMax ) + { + kdDebug(36001) << "Canvas::mouseMoveEvent: col or row is out of range: " + << "col: " << col << " row: " << row << endl; + return; + } + + + //*** Highlighted Range Resize Handling *** + if (d->mouseAction == ResizeSelection) + { + choice()->update(TQPoint(col,row)); + return; + } + + //Check to see if the mouse is over a highlight range size grip and if it is, change the cursor + //shape to a resize arrow + if (highlightRangeSizeGripAt(ev_PosX,ev_PosY)) + { + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + setCursor( sizeBDiagCursor ); + else + setCursor( sizeFDiagCursor ); + return; + } + + TQRect rct( (d->chooseCell ? choice() : selectionInfo())->lastRange() ); + + TQRect r1; + TQRect r2; + + double lx = sheet->dblColumnPos( rct.left() ); + double rx = sheet->dblColumnPos( rct.right() + 1 ); + double ty = sheet->dblRowPos( rct.top() ); + double by = sheet->dblRowPos( rct.bottom() + 1 ); + + r1.setLeft( (int) (lx - 1) ); + r1.setTop( (int) (ty - 1) ); + r1.setRight( (int) (rx + 1) ); + r1.setBottom( (int) (by + 1) ); + + r2.setLeft( (int) (lx + 1) ); + r2.setTop( (int) (ty + 1) ); + r2.setRight( (int) (rx - 1) ); + r2.setBottom( (int) (by - 1) ); + + // Test whether the mouse is over some anchor + { + Cell *cell = sheet->visibleCellAt( col, row ); + TQString anchor; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + anchor = cell->testAnchor( d->view->doc()->zoomItX( cell->dblWidth() - ev_PosX + xpos ), + d->view->doc()->zoomItY( ev_PosY - ypos ) ); + } + else + { + anchor = cell->testAnchor( d->view->doc()->zoomItX( ev_PosX - xpos ), + d->view->doc()->zoomItY( ev_PosY - ypos ) ); + } + if ( !anchor.isEmpty() && anchor != d->anchor ) + { + setCursor( KCursor::handCursor() ); + } + + d->anchor = anchor; + } + + // Test wether mouse is over the selection handle + TQRect selectionHandle = d->view->selectionInfo()->selectionHandleArea(); + if ( selectionHandle.contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ), + d->view->doc()->zoomItY( ev_PosY ) ) ) ) + { + //If the cursor is over the handle, than it might be already on the next cell. + //Recalculate the cell! + col = sheet->leftColumn( ev_PosX - d->view->doc()->unzoomItX( 2 ), xpos ); + row = sheet->topRow( ev_PosY - d->view->doc()->unzoomItY( 2 ), ypos ); + + if ( !sheet->isProtected() ) + { + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + setCursor( sizeBDiagCursor ); + else + setCursor( sizeFDiagCursor ); + } + } + else if ( !d->anchor.isEmpty() ) + { + if ( !sheet->isProtected() ) + setCursor( KCursor::handCursor() ); + } + else if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) + && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) ) + { + setCursor( KCursor::handCursor() ); + } + else if ( d->chooseCell ) + { + //Visual cue to indicate that the user can drag-select the choice selection + setCursor( KCursor::crossCursor() ); + } + else + { + //Nothing special is happening, use a normal arrow cursor + setCursor( arrowCursor ); + } + + // No marking, selecting etc. in progess? Then quit here. + if ( d->mouseAction == NoAction ) + return; + + // Set the new extent of the selection + (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row)); +} + +void Canvas::mouseReleaseEvent( TQMouseEvent* /*_ev*/) +{ + if ( d->scrollTimer->isActive() ) + d->scrollTimer->stop(); + + d->mousePressed = false; + d->view->disableAutoScroll(); + + if ( d->modType != MT_NONE /*&& d->m_resizeObject && d->m_resizeObject->isSelected() */) + { + switch ( d->modType ) + { + case MT_MOVE: + { + KoPoint move( objectRect( false ).topLeft() - d->m_moveStartPosMouse ); + if ( move != KoPoint( 0, 0 ) ) + { + KCommand *cmd= activeSheet()->moveObject( view(), move.x(), move.y() ); + if(cmd) + doc()->addCommand( cmd ); + } else + { + repaint(); + } + d->m_isMoving = false; + break; + } + case MT_RESIZE_UP: case MT_RESIZE_LF: case MT_RESIZE_RT: case MT_RESIZE_LU: case MT_RESIZE_LD: case MT_RESIZE_RU: case MT_RESIZE_RD: + finishResizeObject( i18n("Resize Object") ); + break; + case MT_RESIZE_DN: + finishResizeObject( i18n("Resize Object"), false ); + break; + default: + break; + } + return; + } + + Sheet *sheet = activeSheet(); + if ( !sheet ) + return; + + Selection* selectionInfo = d->view->selectionInfo(); + TQRect s( selectionInfo->lastRange() ); + + // The user started the drag in the lower right corner of the marker ? + if ( d->mouseAction == ResizeCell && !sheet->isProtected() ) + { + sheet->mergeCells(selectionInfo->lastRange()); + d->view->updateEditWidget(); + } + else if ( d->mouseAction == AutoFill && !sheet->isProtected() ) + { + TQRect dest = s; + sheet->autofill( d->autoFillSource, dest ); + + d->view->updateEditWidget(); + } + // The user started the drag in the middle of a cell ? + else if ( d->mouseAction == Mark && !d->chooseCell ) + { + d->view->updateEditWidget(); + } + + d->mouseAction = NoAction; + d->dragging = false; + d->dragStart.setX( -1 ); +} + +void Canvas::processClickSelectionHandle( TQMouseEvent *event ) +{ + // Auto fill ? That is done using the left mouse button. + if ( event->button() == Qt::LeftButton ) + { + d->mouseAction = AutoFill; + d->autoFillSource = selectionInfo()->lastRange(); + } + // Resize a cell (done with the right mouse button) ? + // But for that to work there must not be a selection. + else if ( event->button() == Qt::MidButton && selectionInfo()->isSingular()) + { + d->mouseAction = ResizeCell; + } + + return; +} + +void Canvas::processLeftClickAnchor() +{ + bool isRefLink = localReferenceAnchor( d->anchor ); + bool isLocalLink = (d->anchor.find("file:") == 0); + if ( !isRefLink ) + { + TQString type=KMimeType::findByURL(d->anchor, 0, isLocalLink)->name(); + + if ( KRun::isExecutableFile( d->anchor , type ) ) + { + //TQString question = i18n("Do you want to open this link to '%1'?\n").arg(d->anchor); + + //question += i18n("Note that opening a link to a local file may " + // "compromise your system's security."); + + TQString question = i18n("This link points to the program or script '%1'.\n" + "Malicious programs can harm your computer. Are you sure that you want to run this program?").arg(d->anchor); + // this will also start local programs, so adding a "don't warn again" + // checkbox will probably be too dangerous + int choice = KMessageBox::warningYesNo(this, question, i18n("Open Link?")); + if ( choice != KMessageBox::Yes ) + { + return; + //(void) new KRun( d->anchor ); + } + } + + new KRun(d->anchor); + } + else + { + selectionInfo()->initialize(Region(d->view, d->anchor)); + } +} + +bool Canvas::highlightRangeSizeGripAt(double x, double y) +{ + if (!d->chooseCell) + return 0; + + Region::ConstIterator end = choice()->constEnd(); + for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it) + { + // TODO Stefan: adapt to Selection::selectionHandleArea + KoRect visibleRect; + sheetAreaToRect((*it)->rect().normalize(), visibleRect); + + TQPoint bottomRight((int) visibleRect.right(), (int) visibleRect.bottom()); + TQRect handle( ( (int) bottomRight.x() - 6 ), + ( (int) bottomRight.y() - 6 ), + ( 6 ), + ( 6 ) ); + + if (handle.contains(TQPoint((int) x,(int) y))) + { + return true; + } + } + + return false; +} + +void Canvas::mousePressEvent( TQMouseEvent * _ev ) +{ + if ( _ev->button() == Qt::LeftButton ) + { + d->mousePressed = true; + d->view->enableAutoScroll(); + } + + if ( activeSheet() && _ev->button() == Qt::LeftButton) + { + d->m_moveStartPosMouse = objectRect( false ).topLeft(); + EmbeddedObject *obj = getObject( _ev->pos(), activeSheet() ); + + if ( obj ) + { + // use ctrl + Button to select / deselect object + if ( _ev->state() & ControlButton && obj->isSelected() ) + deselectObject( obj ); + else if ( _ev->state() & ControlButton ) + { + if ( d->modType == MT_NONE) + return; + + selectObject( obj ); + raiseObject( obj ); + d->m_moveStartPosMouse = objectRect( false ).topLeft(); + } + else + { + if ( d->modType != MT_MOVE || !obj->isSelected() ) + deselectAllObjects(); + + selectObject( obj ); + + raiseObject( obj ); + d->m_moveStartPosMouse = objectRect( false ).topLeft(); + } + + // start resizing + if ( d->modType != MT_MOVE && d->modType != MT_NONE && !obj->isProtect() ) + { + deselectAllObjects(); + selectObject( obj ); + raiseObject( obj ); + + d->m_resizeObject = obj; + + d->m_ratio = static_cast( obj->geometry().width() ) / + static_cast( obj->geometry().height() ); + d->m_rectBeforeResize = obj->geometry(); + } + + KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) ); + docPoint += KoPoint( xOffset(), yOffset() ); + d->m_origMousePos = docPoint; + d->m_moveStartPosMouse = objectRect( false ).topLeft(); + return; + } + else + { + d->modType = MT_NONE; + if ( !( _ev->state() & ShiftButton ) && !( _ev->state() & ControlButton ) ) + deselectAllObjects(); + } + } + + // Get info about where the event occurred - this is duplicated + // in ::mouseMoveEvent, needs to be separated into one function + Sheet *sheet = activeSheet(); + if ( !sheet ) + { + return; + } + + double dwidth = d->view->doc()->unzoomItX( width() ); + double ev_PosX; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + } + else + { + ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + } + double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); + + // In which cell did the user click ? + double xpos; + double ypos; + int col = sheet->leftColumn( ev_PosX, xpos ); + int row = sheet->topRow( ev_PosY, ypos ); + // you cannot move marker when col > KS_colMax or row > KS_rowMax + if ( col > KS_colMax || row > KS_rowMax ) + { + kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: " + << "col: " << col << " row: " << row << endl; + return; + } + + // you cannot move marker when col > KS_colMax or row > KS_rowMax + if ( col > KS_colMax || row > KS_rowMax ) + { + kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: " + << "col: " << col << " row: " << row << endl; + return; + } + + if (d->chooseCell && highlightRangeSizeGripAt(ev_PosX,ev_PosY)) + { + choice()->setActiveElement(TQPoint(col,row)); + d->mouseAction = ResizeSelection; + return; + } + + // We were editing a cell -> save value and get out of editing mode + if ( d->cellEditor && !d->chooseCell ) + { + deleteEditor( true ); // save changes + } + + d->scrollTimer->start( 50 ); + + // Did we click in the lower right corner of the marker/marked-area ? + if ( selectionInfo()->selectionHandleArea().contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ), + d->view->doc()->zoomItY( ev_PosY ) ) ) ) + { + processClickSelectionHandle( _ev ); + return; + } + + + // TODO Stefan: adapt to non-cont. selection + { + // start drag ? + TQRect rct( selectionInfo()->lastRange() ); + + TQRect r1; + TQRect r2; + { + double lx = sheet->dblColumnPos( rct.left() ); + double rx = sheet->dblColumnPos( rct.right() + 1 ); + double ty = sheet->dblRowPos( rct.top() ); + double by = sheet->dblRowPos( rct.bottom() + 1 ); + + r1.setLeft( (int) (lx - 1) ); + r1.setTop( (int) (ty - 1) ); + r1.setRight( (int) (rx + 1) ); + r1.setBottom( (int) (by + 1) ); + + r2.setLeft( (int) (lx + 1) ); + r2.setTop( (int) (ty + 1) ); + r2.setRight( (int) (rx - 1) ); + r2.setBottom( (int) (by - 1) ); + } + + d->dragStart.setX( -1 ); + + if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) + && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) ) + { + d->dragStart.setX( (int) ev_PosX ); + d->dragStart.setY( (int) ev_PosY ); + + return; + } + } + + // kdDebug() << "Clicked in cell " << col << ", " << row << endl; + + // Extending an existing selection with the shift button ? + if ((_ev->state() & ShiftButton) && + d->view->koDocument()->isReadWrite() && + !selectionInfo()->isColumnOrRowSelected()) + { + (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row)); + return; + } + + + // Go to the upper left corner of the obscuring object if cells are merged + Cell *cell = sheet->cellAt( col, row ); + if (cell->isPartOfMerged()) + { + cell = cell->obscuringCells().first(); + col = cell->column(); + row = cell->row(); + } + + switch (_ev->button()) + { + case Qt::LeftButton: + if (!d->anchor.isEmpty()) + { + // Hyperlink pressed + processLeftClickAnchor(); + } +#ifdef NONCONTIGUOUSSELECTION + else if ( _ev->state() & ControlButton ) + { + if (d->chooseCell) + { +#if 0 // TODO Stefan: remove for NCS of choices + // Start a marking action + d->mouseAction = Mark; + // extend the existing selection + choice()->extend(TQPoint(col,row), activeSheet()); +#endif + } + else + { + // Start a marking action + d->mouseAction = Mark; + // extend the existing selection + selectionInfo()->extend(TQPoint(col,row), activeSheet()); + } +// TODO Stefan: simplification, if NCS of choices is working +/* (d->chooseCell ? choice() : selectionInfo())->extend(TQPoint(col,row), activeSheet());*/ + } +#endif + else + { + // Start a marking action + d->mouseAction = Mark; + // reinitialize the selection + (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet()); + } + break; + case Qt::MidButton: + // Paste operation with the middle button? + if ( d->view->koDocument()->isReadWrite() && !sheet->isProtected() ) + { + (d->chooseCell ? choice() : selectionInfo())->initialize( TQPoint( col, row ), activeSheet() ); + sheet->paste(selectionInfo()->lastRange(), true, Paste::Normal, + Paste::OverWrite, false, 0, false, TQClipboard::Selection); + sheet->setRegionPaintDirty(*selectionInfo()); + } + break; + case Qt::RightButton: + if (!selectionInfo()->contains( TQPoint( col, row ) )) + { + // No selection or the mouse press was outside of an existing selection? + (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet()); + } + break; + default: + break; + } + + scrollToCell(selectionInfo()->marker()); + if ( !d->chooseCell ) + { + d->view->updateEditWidgetOnPress(); + } + updatePosWidget(); + + // Context menu? + if ( _ev->button() == Qt::RightButton ) + { + // TODO: Handle anchor // TODO Stefan: ??? + TQPoint p = mapToGlobal( _ev->pos() ); + d->view->openPopupMenu( p ); + } +} + +void Canvas::startTheDrag() +{ + Sheet * sheet = activeSheet(); + if ( !sheet ) + return; + + // right area for start dragging + TextDrag * d = new TextDrag( this ); + setCursor( KCursor::handCursor() ); + + TQDomDocument doc = sheet->saveCellRegion(*selectionInfo()); + + // Save to buffer + TQBuffer buffer; + buffer.open( IO_WriteOnly ); + TQTextStream str( &buffer ); + str.setEncoding( TQTextStream::UnicodeUTF8 ); + str << doc; + buffer.close(); + + d->setPlain( sheet->copyAsText( selectionInfo() ) ); + d->setKSpread( buffer.buffer() ); + + d->dragCopy(); + setCursor( KCursor::arrowCursor() ); +} + +void Canvas::mouseDoubleClickEvent( TQMouseEvent* _ev) +{ + + EmbeddedObject *obj; + if ( ( obj = getObject( _ev->pos(), activeSheet() ) ) ) + { + switch ( obj->getType() ) + { + case OBJECT_KOFFICE_PART: case OBJECT_CHART: + { + dynamic_cast(obj)->activate( view(), this ); + return; + break; + } + default: + { + view()->extraProperties(); + return; + break; + } + } + } + + if ( d->view->koDocument()->isReadWrite() && activeSheet() ) + createEditor(true); +} + +void Canvas::wheelEvent( TQWheelEvent* _ev ) +{ + if ( _ev->orientation() == Qt::Vertical ) + { + if ( vertScrollBar() ) + TQApplication::sendEvent( vertScrollBar(), _ev ); + } + else if ( horzScrollBar() ) + { + TQApplication::sendEvent( horzScrollBar(), _ev ); + } +} + +void Canvas::paintEvent( TQPaintEvent* _ev ) +{ + if ( d->view->doc()->isLoading() ) + return; + + Sheet* sheet = activeSheet(); + if ( !sheet ) + return; + + // ElapsedTime et( "Canvas::paintEvent" ); + + double dwidth = d->view->doc()->unzoomItX( width() ); + KoRect rect = d->view->doc()->unzoomRect( _ev->rect() & TQWidget::rect() ); + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + rect.moveBy( -xOffset(), yOffset() ); + else + rect.moveBy( xOffset(), yOffset() ); + + KoPoint tl = rect.topLeft(); + KoPoint br = rect.bottomRight(); + + double tmp; + int left_col; + int right_col; + //Philipp: I don't know why we need the +1, but otherwise we don't get it correctly + //Testcase: Move a dialog slowly up left. Sometimes the top/left most points are not painted + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + right_col = sheet->leftColumn( dwidth - tl.x(), tmp ); + left_col = sheet->rightColumn( dwidth - br.x() + 1.0 ); + } + else + { + left_col = sheet->leftColumn( tl.x(), tmp ); + right_col = sheet->rightColumn( br.x() + 1.0 ); + } + int top_row = sheet->topRow( tl.y(), tmp ); + int bottom_row = sheet->bottomRow( br.y() + 1.0 ); + + TQRect vr( TQPoint(left_col, top_row), + TQPoint(right_col, bottom_row) ); + d->view->doc()->emitBeginOperation( false ); + sheet->setRegionPaintDirty( vr ); + d->view->doc()->emitEndOperation( vr ); +} + +void Canvas::focusInEvent( TQFocusEvent* ) +{ + if ( !d->cellEditor ) + return; + + //kdDebug(36001) << "d->chooseCell : " << ( d->chooseCell ? "true" : "false" ) << endl; + // If we are in editing mode, we redirect the + // focus to the CellEditor or EditWidget + // And we know which, using lastEditorWithFocus. + // This screws up though (David) + if ( lastEditorWithFocus() == EditWidget ) + { + d->editWidget->setFocus(); + //kdDebug(36001) << "Focus to EditWidget" << endl; + return; + } + + //kdDebug(36001) << "Redirecting focus to editor" << endl; + d->cellEditor->setFocus(); +} + +void Canvas::focusOutEvent( TQFocusEvent* ) +{ + if ( d->scrollTimer->isActive() ) + d->scrollTimer->stop(); + d->mousePressed = false; + d->view->disableAutoScroll(); +} + +void Canvas::dragMoveEvent( TQDragMoveEvent * _ev ) +{ + Sheet * sheet = activeSheet(); + if ( !sheet ) + { + _ev->ignore(); + return; + } + + _ev->accept( TextDrag::canDecode( _ev ) ); + + double dwidth = d->view->doc()->unzoomItX( width() ); + double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() ); + double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() ); + double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this ); + double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this ); + + TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3); + + double ev_PosX; + if (sheet->layoutDirection()==Sheet::RightToLeft) + ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + else + ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + + double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); + + if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) ) + _ev->ignore( r1 ); +} + +void Canvas::dragLeaveEvent( TQDragLeaveEvent * ) +{ + if ( d->scrollTimer->isActive() ) + d->scrollTimer->stop(); +} + +void Canvas::dropEvent( TQDropEvent * _ev ) +{ + d->dragging = false; + if ( d->scrollTimer->isActive() ) + d->scrollTimer->stop(); + Sheet * sheet = activeSheet(); + if ( !sheet || sheet->isProtected() ) + { + _ev->ignore(); + return; + } + + double dwidth = d->view->doc()->unzoomItX( width() ); + double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() ); + double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() ); + double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this ); + double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this ); + + TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3); + + double ev_PosX; + if (sheet->layoutDirection()==Sheet::RightToLeft) + ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + else + ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset(); + + double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset(); + + if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) ) + { + _ev->ignore( ); + return; + } + else + _ev->accept( ); + + double tmp; + int col = sheet->leftColumn( ev_PosX, tmp ); + int row = sheet->topRow( ev_PosY, tmp ); + + if ( !TextDrag::canDecode( _ev ) ) + { + _ev->ignore(); + return; + } + + TQByteArray b; + + bool makeUndo = true; + + if ( _ev->provides( TextDrag::selectionMimeType() ) ) + { + if ( TextDrag::target() == _ev->source() ) + { + if ( !d->view->doc()->undoLocked() ) + { + UndoDragDrop * undo + = new UndoDragDrop(d->view->doc(), sheet, *selectionInfo(), + TQRect(col, row, + selectionInfo()->boundingRect().width(), + selectionInfo()->boundingRect().height())); + d->view->doc()->addCommand( undo ); + makeUndo = false; + } + sheet->deleteSelection( selectionInfo(), false ); + } + + + b = _ev->encodedData( TextDrag::selectionMimeType() ); + sheet->paste( b, TQRect( col, row, 1, 1 ), makeUndo ); + + if ( _ev->source() == this ) + _ev->acceptAction(); + _ev->accept(); + } + else + { + TQString text; + if ( !TQTextDrag::decode( _ev, text ) ) + { + _ev->ignore(); + return; + } + // if ( TextDrag::target() == _ev->source() ) + // sheet->deleteSelection( selectionInfo() ); + + sheet->pasteTextPlain( text, TQRect( col, row, 1, 1 ) ); + _ev->accept(); + if ( _ev->source() == this ) + _ev->acceptAction(); + + return; + } +} + +void Canvas::resizeEvent( TQResizeEvent* _ev ) +{ + if (!activeSheet()) + return; + + + double ev_Width = d->view->doc()->unzoomItX( _ev->size().width() ); + double ev_Height = d->view->doc()->unzoomItY( _ev->size().height() ); + + // workaround to allow horizontal resizing and zoom changing when sheet + // direction and interface direction don't match (e.g. an RTL sheet on an + // LTR interface) + if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() ) + { + int dx = _ev->size().width() - _ev->oldSize().width(); + scroll(dx, 0); + } + else if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() ) + { + int dx = _ev->size().width() - _ev->oldSize().width(); + scroll(-dx, 0); + } + + // If we rise horizontally, then check if we are still within the valid area (KS_colMax) + if ( _ev->size().width() > _ev->oldSize().width() ) + { + int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); + + if ( ( xOffset() + ev_Width ) > + d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) ) + { + horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) ); + if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) + horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); + } + } + // If we lower vertically, then check if the range should represent the maximum range + else if ( _ev->size().width() < _ev->oldSize().width() ) + { + int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value(); + + if ( horzScrollBar()->maxValue() == + int( d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) - ev_Width ) ) + { + horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) ); + if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) + horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue ); + } + } + + // If we rise vertically, then check if we are still within the valid area (KS_rowMax) + if ( _ev->size().height() > _ev->oldSize().height() ) + { + if ( ( yOffset() + ev_Height ) > + d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) ) + { + vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) ); + } + } + // If we lower vertically, then check if the range should represent the maximum range + else if ( _ev->size().height() < _ev->oldSize().height() ) + { + if ( vertScrollBar()->maxValue() == + int( d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) - ev_Height ) ) + { + vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) ); + } + } +} + +TQPoint Canvas::cursorPos() +{ + TQPoint cursor; + if (d->chooseCell && !choice()->isEmpty()) + cursor = choice()->cursor(); + else + cursor = selectionInfo()->cursor(); + + return cursor; +} + +TQRect Canvas::moveDirection( KSpread::MoveTo direction, bool extendSelection ) +{ + kdDebug(36001) << "Canvas::moveDirection" << endl; + + TQPoint destination; + TQPoint cursor = cursorPos(); + + TQPoint cellCorner = cursor; + Cell* cell = activeSheet()->cellAt(cursor.x(), cursor.y()); + + /* cell is either the same as the marker, or the cell that is forced obscuring + the marker cell + */ + if (cell->isPartOfMerged()) + { + cell = cell->obscuringCells().first(); + cellCorner = TQPoint(cell->column(), cell->row()); + } + + /* how many cells must we move to get to the next cell? */ + int offset = 0; + RowFormat *rl = NULL; + ColumnFormat *cl = NULL; + switch (direction) + /* for each case, figure out how far away the next cell is and then keep + going one row/col at a time after that until a visible row/col is found + + NEVER use cell->column() or cell->row() -- it might be a default cell + */ + { + case KSpread::Bottom: + offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide()) + { + offset++; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + } + + destination = TQPoint(cursor.x(), TQMIN(cursor.y() + offset, KS_rowMax)); + break; + case KSpread::Top: + offset = (cellCorner.y() - cursor.y()) - 1; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + while ( ((cursor.y() + offset) >= 1) && rl->isHide()) + { + offset--; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + } + destination = TQPoint(cursor.x(), TQMAX(cursor.y() + offset, 1)); + break; + case KSpread::Left: + offset = (cellCorner.x() - cursor.x()) - 1; + cl = activeSheet()->columnFormat( cursor.x() + offset ); + while ( ((cursor.x() + offset) >= 1) && cl->isHide()) + { + offset--; + cl = activeSheet()->columnFormat( cursor.x() + offset ); + } + destination = TQPoint(TQMAX(cursor.x() + offset, 1), cursor.y()); + break; + case KSpread::Right: + offset = cell->mergedXCells() - (cursor.x() - cellCorner.x()) + 1; + cl = activeSheet()->columnFormat( cursor.x() + offset ); + while ( ((cursor.x() + offset) <= KS_colMax) && cl->isHide()) + { + offset++; + cl = activeSheet()->columnFormat( cursor.x() + offset ); + } + destination = TQPoint(TQMIN(cursor.x() + offset, KS_colMax), cursor.y()); + break; + case KSpread::BottomFirst: + offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide()) + { + ++offset; + rl = activeSheet()->rowFormat( cursor.y() + offset ); + } + + destination = TQPoint( 1, TQMIN( cursor.y() + offset, KS_rowMax ) ); + break; + } + + if (extendSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + d->view->updateEditWidget(); + + return TQRect( cursor, destination ); +} + +void Canvas::processEnterKey(TQKeyEvent* event) +{ + // array is true, if ctrl+alt are pressed + bool array = (event->state() & TQt::AltButton) && + (event->state() & TQt::ControlButton); + + /* save changes to the current editor */ + if (!d->chooseCell) + { + deleteEditor(true, array); + } + + /* use the configuration setting to see which direction we're supposed to move + when enter is pressed. + */ + KSpread::MoveTo direction = d->view->doc()->getMoveToValue(); + + //if shift Button clicked inverse move direction + if (event->state() & TQt::ShiftButton) + { + switch( direction ) + { + case KSpread::Bottom: + direction = KSpread::Top; + break; + case KSpread::Top: + direction = KSpread::Bottom; + break; + case KSpread::Left: + direction = KSpread::Right; + break; + case KSpread::Right: + direction = KSpread::Left; + break; + case KSpread::BottomFirst: + direction = KSpread::BottomFirst; + break; + } + } + + /* never extend a selection with the enter key -- the shift key reverses + direction, not extends the selection + */ + TQRect r( moveDirection( direction, false ) ); + d->view->doc()->emitEndOperation( r ); +} + +void Canvas::processArrowKey( TQKeyEvent *event) +{ + /* NOTE: hitting the tab key also calls this function. Don't forget + to account for it + */ + + /* save changes to the current editor */ + if (!d->chooseCell) + { + deleteEditor( true ); + } + + KSpread::MoveTo direction = KSpread::Bottom; + bool makingSelection = event->state() & ShiftButton; + + switch (event->key()) + { + case Key_Down: + direction = KSpread::Bottom; + break; + case Key_Up: + direction = KSpread::Top; + break; + case Key_Left: + if (activeSheet()->layoutDirection()==Sheet::RightToLeft) + direction = KSpread::Right; + else + direction = KSpread::Left; + break; + case Key_Right: + if (activeSheet()->layoutDirection()==Sheet::RightToLeft) + direction = KSpread::Left; + else + direction = KSpread::Right; + break; + case Key_Tab: + direction = KSpread::Right; + break; + case Key_Backtab: + //Shift+Tab moves to the left + direction = KSpread::Left; + makingSelection = false; + break; + default: + Q_ASSERT(false); + break; + } + + TQRect r( moveDirection( direction, makingSelection ) ); + d->view->doc()->emitEndOperation( r ); +} + +void Canvas::processEscapeKey(TQKeyEvent * event) +{ + if ( d->cellEditor ) + deleteEditor( false ); + + if ( view()->isInsertingObject() ) + { + view()->resetInsertHandle(); + setCursor( arrowCursor ); + return; + } + + event->accept(); // ? + TQPoint cursor = cursorPos(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); + + if ( d->mousePressed /*&& toolEditMode == TEM_MOUSE */) + { + switch (d->modType) + { + case MT_RESIZE_UP: + case MT_RESIZE_DN: + case MT_RESIZE_LF: + case MT_RESIZE_RT: + case MT_RESIZE_LU: + case MT_RESIZE_LD: + case MT_RESIZE_RU: + case MT_RESIZE_RD: + { + TQRect oldBoundingRect = doc()->zoomRect( d->m_resizeObject->geometry()/*getRepaintRect()*/); + d->m_resizeObject->setGeometry( d->m_rectBeforeResize ); + oldBoundingRect.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , + (int)( -yOffset() * doc()->zoomedResolutionY()) ); + + activeSheet()->setRegionPaintDirty( oldBoundingRect ); + repaint( oldBoundingRect ); + repaintObject( d->m_resizeObject ); + d->m_ratio = 0.0; + d->m_resizeObject = 0; + d->m_isResizing = false; + view()->disableAutoScroll(); + d->mousePressed = false; + d->modType = MT_NONE; + break; + } + case MT_MOVE: + { + if ( d->m_isMoving ) + { + KoPoint move( d->m_moveStartPoint - objectRect( false ).topLeft() ); + activeSheet()->moveObject( view(), move, false ); + view()->disableAutoScroll(); + d->mousePressed = false; + d->modType = MT_NONE; + d->m_isMoving = false; + update(); + } + break; + } + default: + break; + } + } +} + +bool Canvas::processHomeKey(TQKeyEvent* event) +{ + bool makingSelection = event->state() & ShiftButton; + Sheet* sheet = activeSheet(); + + if ( d->cellEditor ) + // We are in edit mode -> go beginning of line + { + TQApplication::sendEvent( d->editWidget, event ); + return false; + } + else + { + TQPoint destination; + /* start at the first used cell in the row and cycle through the right until + we find a cell that has some output text. But don't look past the current + marker. + The end result we want is to move to the left to the first cell with text, + or just to the first column if there is no more text to the left. + + But why? In excel, home key sends you to the first column always. + We might want to change to that behavior. + */ + + if (event->state() & ControlButton) + { + /* ctrl + Home will always just send us to location (1,1) */ + destination = TQPoint( 1, 1 ); + } + else + { + TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); + + Cell * cell = sheet->getFirstCellRow(marker.y()); + while (cell != NULL && cell->column() < marker.x() && cell->isEmpty()) + { + cell = sheet->getNextCellRight(cell->column(), cell->row()); + } + + int col = ( cell ? cell->column() : 1 ); + if ( col == marker.x()) + col = 1; + destination = TQPoint(col, marker.y()); + } + + if ( selectionInfo()->marker() == destination ) + { + d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); + return false; + } + + if (makingSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + } + return true; +} + +bool Canvas::processEndKey( TQKeyEvent *event ) +{ + bool makingSelection = event->state() & ShiftButton; + Sheet* sheet = activeSheet(); + Cell* cell = NULL; + TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); + + // move to the last used cell in the row + // We are in edit mode -> go beginning of line + if ( d->cellEditor ) + { + TQApplication::sendEvent( d->editWidget, event ); + d->view->doc()->emitEndOperation( TQRect( marker, marker ) ); + return false; + } + else + { + int col = 1; + + cell = sheet->getLastCellRow(marker.y()); + while (cell != NULL && cell->column() > markerColumn() && cell->isEmpty()) + { + cell = sheet->getNextCellLeft(cell->column(), cell->row()); + } + + col = (cell == NULL) ? KS_colMax : cell->column(); + + TQPoint destination( col, marker.y() ); + if ( destination == marker ) + { + d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); + return false; + } + + if (makingSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + } + return true; +} + +bool Canvas::processPriorKey(TQKeyEvent *event) +{ + bool makingSelection = event->state() & ShiftButton; + if (!d->chooseCell) + { + deleteEditor( true ); + } + + TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); + + TQPoint destination(marker.x(), TQMAX(1, marker.y() - 10)); + if ( destination == marker ) + { + d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); + return false; + } + + if (makingSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + return true; +} + +bool Canvas::processNextKey(TQKeyEvent *event) +{ + bool makingSelection = event->state() & ShiftButton; + + if (!d->chooseCell) + { + deleteEditor( true /*save changes*/ ); + } + + TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); + TQPoint destination(marker.x(), TQMAX(1, marker.y() + 10)); + + if ( marker == destination ) + { + d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); + return false; + } + + if (makingSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + return true; +} + +void Canvas::processDeleteKey(TQKeyEvent* /* event */) +{ + if ( isObjectSelected() ) + { + d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) ); + d->view->deleteSelectedObjects(); + return; + } + + activeSheet()->clearTextSelection( selectionInfo() ); + d->editWidget->setText( "" ); + + TQPoint cursor = cursorPos(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); + return; +} + +void Canvas::processF2Key(TQKeyEvent* /* event */) +{ + d->editWidget->setFocus(); + if ( d->cellEditor ) + d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() - 1 ); + d->editWidget->cursorForward( false ); + + + TQPoint cursor = cursorPos(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); + return; +} + +void Canvas::processF4Key(TQKeyEvent* event) +{ + /* passes F4 to the editor (if any), which will process it + */ + if ( d->cellEditor ) + { + d->cellEditor->handleKeyPressEvent( event ); +// d->editWidget->setFocus(); + d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() ); + } + TQPoint cursor = cursorPos(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); + return; +} + +void Canvas::processOtherKey(TQKeyEvent *event) +{ + // No null character ... + if ( event->text().isEmpty() || !d->view->koDocument()->isReadWrite() + || !activeSheet() || activeSheet()->isProtected() ) + { + event->accept(); + } + else + { + if ( !d->cellEditor && !d->chooseCell ) + { + // Switch to editing mode + createEditor( CellEditor ); + d->cellEditor->handleKeyPressEvent( event ); + } + else if ( d->cellEditor ) + d->cellEditor->handleKeyPressEvent( event ); + } + + TQPoint cursor = cursorPos(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); + + return; +} + +bool Canvas::processControlArrowKey( TQKeyEvent *event ) +{ + bool makingSelection = event->state() & ShiftButton; + + Sheet* sheet = activeSheet(); + Cell* cell = NULL; + Cell* lastCell; + TQPoint destination; + bool searchThroughEmpty = true; + int row; + int col; + + TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker(); + + /* here, we want to move to the first or last cell in the given direction that is + actually being used. Ignore empty cells and cells on hidden rows/columns */ + switch ( event->key() ) + { + //Ctrl+Key_Up + case Key_Up: + + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != 1)) + { + lastCell = cell; + row = marker.y()-1; + cell = sheet->cellAt(cell->column(), row); + while ((cell != NULL) && (row > 0) && (!cell->isEmpty()) ) + { + if (!(sheet->rowFormat(cell->row())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + row--; + if ( row > 0 ) + cell = sheet->cellAt(cell->column(), row); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellUp(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide()))) + { + cell = sheet->getNextCellUp(cell->column(), cell->row()); + } + } + + if (cell == NULL) + row = 1; + else + row = cell->row(); + + while ( sheet->rowFormat(row)->isHide() ) + { + row++; + } + + destination.setX(marker.x()); + destination.setY(row); + break; + + //Ctrl+Key_Down + case Key_Down: + + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != KS_rowMax)) + { + lastCell = cell; + row = marker.y()+1; + cell = sheet->cellAt(cell->column(), row); + while ((cell != NULL) && (row < KS_rowMax) && (!cell->isEmpty()) ) + { + if (!(sheet->rowFormat(cell->row())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + row++; + cell = sheet->cellAt(cell->column(), row); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellDown(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide()))) + { + cell = sheet->getNextCellDown(cell->column(), cell->row()); + } + } + + if (cell == NULL) + row = marker.y(); + else + row = cell->row(); + + while ( sheet->rowFormat(row)->isHide() ) + { + row--; + } + + destination.setX(marker.x()); + destination.setY(row); + break; + + //Ctrl+Key_Left + case Key_Left: + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax)) + { + lastCell = cell; + col = marker.x()+1; + cell = sheet->cellAt(col, cell->row()); + while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) ) + { + if (!(sheet->columnFormat(cell->column())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + col++; + cell = sheet->cellAt(col, cell->row()); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellRight(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) + { + cell = sheet->getNextCellRight(cell->column(), cell->row()); + } + } + + if (cell == NULL) + col = marker.x(); + else + col = cell->column(); + + while ( sheet->columnFormat(col)->isHide() ) + { + col--; + } + + destination.setX(col); + destination.setY(marker.y()); + } + else + { + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1)) + { + lastCell = cell; + col = marker.x()-1; + cell = sheet->cellAt(col, cell->row()); + while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) ) + { + if (!(sheet->columnFormat(cell->column())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + col--; + if ( col > 0 ) + cell = sheet->cellAt(col, cell->row()); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellLeft(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) + { + cell = sheet->getNextCellLeft(cell->column(), cell->row()); + } + } + + if (cell == NULL) + col = 1; + else + col = cell->column(); + + while ( sheet->columnFormat(col)->isHide() ) + { + col++; + } + + destination.setX(col); + destination.setY(marker.y()); + } + break; + + //Ctrl+Key_Right + case Key_Right: + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1)) + { + lastCell = cell; + col = marker.x()-1; + cell = sheet->cellAt(col, cell->row()); + while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) ) + { + if (!(sheet->columnFormat(cell->column())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + col--; + if ( col > 0 ) + cell = sheet->cellAt(col, cell->row()); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellLeft(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) + { + cell = sheet->getNextCellLeft(cell->column(), cell->row()); + } + } + + if (cell == NULL) + col = 1; + else + col = cell->column(); + + while ( sheet->columnFormat(col)->isHide() ) + { + col++; + } + + destination.setX(col); + destination.setY(marker.y()); + } + else + { + cell = sheet->cellAt( marker.x(), marker.y() ); + if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax)) + { + lastCell = cell; + col = marker.x()+1; + cell = sheet->cellAt(col, cell->row()); + while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) ) + { + if (!(sheet->columnFormat(cell->column())->isHide())) + { + lastCell = cell; + searchThroughEmpty = false; + } + col++; + cell = sheet->cellAt(col, cell->row()); + } + cell = lastCell; + } + if (searchThroughEmpty) + { + cell = sheet->getNextCellRight(marker.x(), marker.y()); + + while ((cell != NULL) && + (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide()))) + { + cell = sheet->getNextCellRight(cell->column(), cell->row()); + } + } + + if (cell == NULL) + col = marker.x(); + else + col = cell->column(); + + while ( sheet->columnFormat(col)->isHide() ) + { + col--; + } + + destination.setX(col); + destination.setY(marker.y()); + } + break; + + } + + if ( marker == destination ) + { + d->view->doc()->emitEndOperation( TQRect( destination, destination ) ); + return false; + } + + if (makingSelection) + { + (d->chooseCell ? choice() : selectionInfo())->update(destination); + } + else + { + (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet()); + } + return true; +} + + +void Canvas::keyPressEvent ( TQKeyEvent * _ev ) +{ + Sheet * sheet = activeSheet(); + + if ( !sheet || formatKeyPress( _ev )) + return; + + // Dont handle the remaining special keys. + if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) && + (_ev->key() != Key_Down) && + (_ev->key() != Key_Up) && + (_ev->key() != Key_Right) && + (_ev->key() != Key_Left) && + (_ev->key() != Key_Home) && + (_ev->key() != Key_Enter) && + (_ev->key() != Key_Return) && + (_ev->key() != TDEGlobalSettings::contextMenuKey())) + { + TQWidget::keyPressEvent( _ev ); + return; + } + + // Always accept so that events are not + // passed to the parent. + _ev->accept(); + + d->view->doc()->emitBeginOperation(false); + if ( _ev->key() == TDEGlobalSettings::contextMenuKey() ) { + int row = markerRow(); + int col = markerColumn(); + KoPoint kop(sheet->columnPos(col, this), sheet->rowPos(row, this)); + TQPoint p = d->view->doc()->zoomPoint(kop); + p = mapToGlobal(p); + d->view->openPopupMenu( p ); + } + switch( _ev->key() ) + { + case Key_Return: + case Key_Enter: + processEnterKey( _ev ); + return; + break; + case Key_Down: + case Key_Up: + case Key_Left: + case Key_Right: + case Key_Tab: /* a tab behaves just like a right/left arrow */ + case Key_Backtab: /* and so does Shift+Tab */ + if (_ev->state() & ControlButton) + { + if ( !processControlArrowKey( _ev ) ) + return; + } + else + { + processArrowKey( _ev ); + return; + } + break; + + case Key_Escape: + processEscapeKey( _ev ); + return; + break; + + case Key_Home: + if ( !processHomeKey( _ev ) ) + return; + break; + + case Key_End: + if ( !processEndKey( _ev ) ) + return; + break; + + case Key_Prior: /* Page Up */ + if ( !processPriorKey( _ev ) ) + return; + break; + + case Key_Next: /* Page Down */ + if ( !processNextKey( _ev ) ) + return; + break; + + case Key_Delete: + processDeleteKey( _ev ); + return; + break; + + case Key_F2: + processF2Key( _ev ); + return; + break; + + case Key_F4: + processF4Key( _ev ); + return; + break; + + default: + processOtherKey( _ev ); + return; + break; + } + + //most process*Key methods call emitEndOperation, this only gets called in some situations + // (after some move operations) + d->view->doc()->emitEndOperation( sheet->visibleRect( this ) ); + return; +} + +void Canvas::processIMEvent( TQIMEvent * event ) +{ + d->view->doc()->emitBeginOperation( false ); + if ( !d->cellEditor && !d->chooseCell ) + { + // Switch to editing mode + createEditor( CellEditor ); + d->cellEditor->handleIMEvent( event ); + } + + TQPoint cursor; + + if ( d->chooseCell ) + { + cursor = choice()->cursor(); + /* if the cursor is unset, pretend we're starting at the regular cursor */ + if (cursor.x() == 0 || cursor.y() == 0) + cursor = choice()->cursor(); + } + else + cursor = selectionInfo()->cursor(); + + d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) ); +} + +bool Canvas::formatKeyPress( TQKeyEvent * _ev ) +{ + if (!(_ev->state() & ControlButton )) + return false; + + int key = _ev->key(); + if ( key != Key_Exclam && key != Key_At && key != Key_Ampersand + && key != Key_Dollar && key != Key_Percent && key != Key_AsciiCircum + && key != Key_NumberSign ) + return false; + + Cell * cell = 0L; + Sheet * sheet = activeSheet(); + + d->view->doc()->emitBeginOperation(false); + + if ( !d->view->doc()->undoLocked() ) + { + TQString dummy; + UndoCellFormat * undo = new UndoCellFormat( d->view->doc(), sheet, *selectionInfo(), dummy ); + d->view->doc()->addCommand( undo ); + } + + Region::ConstIterator end(selectionInfo()->constEnd()); + for (Region::ConstIterator it = selectionInfo()->constBegin(); it != end; ++it) + { + TQRect rect = (*it)->rect().normalize(); + + int right = rect.right(); + int bottom = rect.bottom(); + + if ( util_isRowSelected(rect) ) + { + for ( int r = rect.top(); r <= bottom; ++r ) + { + cell = sheet->getFirstCellRow( r ); + while ( cell ) + { + if ( cell->isPartOfMerged() ) + { + cell = sheet->getNextCellRight( cell->column(), r ); + continue; + } + + formatCellByKey (cell, _ev->key(), rect); + + cell = sheet->getNextCellRight( cell->column(), r ); + } // while (cell) + RowFormat * rw = sheet->nonDefaultRowFormat( r ); + TQPen pen; + switch ( _ev->key() ) + { + case Key_Exclam: + rw->setFormatType (Number_format); + rw->setPrecision( 2 ); + break; + + case Key_Dollar: + rw->setFormatType (Money_format); + rw->setPrecision( d->view->doc()->locale()->fracDigits() ); + break; + + case Key_Percent: + rw->setFormatType (Percentage_format); + break; + + case Key_At: + rw->setFormatType( SecondeTime_format ); + break; + + case Key_NumberSign: + rw->setFormatType( ShortDate_format ); + break; + + case Key_AsciiCircum: + rw->setFormatType( Scientific_format ); + break; + + case Key_Ampersand: + if ( r == rect.top() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + rw->setTopBorderPen( pen ); + } + if ( r == rect.bottom() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + rw->setBottomBorderPen( pen ); + } + break; + + default: + d->view->doc()->emitEndOperation( rect ); + return false; + } + sheet->emit_updateRow( rw, r ); + } + + d->view->doc()->emitEndOperation( rect ); + return true; + } + + if ( util_isColumnSelected(rect) ) + { + for ( int c = rect.left(); c <= right; ++c ) + { + cell = sheet->getFirstCellColumn( c ); + while ( cell ) + { + if ( cell->isPartOfMerged() ) + { + cell = sheet->getNextCellDown( c, cell->row() ); + continue; + } + + formatCellByKey (cell, _ev->key(), rect); + + cell = sheet->getNextCellDown( c, cell->row() ); + } + + ColumnFormat * cw = sheet->nonDefaultColumnFormat( c ); + TQPen pen; + switch ( _ev->key() ) + { + case Key_Exclam: + cw->setFormatType( Number_format ); + cw->setPrecision( 2 ); + break; + + case Key_Dollar: + cw->setFormatType( Money_format ); + cw->setPrecision( d->view->doc()->locale()->fracDigits() ); + break; + + case Key_Percent: + cw->setFormatType( Percentage_format ); + break; + + case Key_At: + cw->setFormatType( SecondeTime_format ); + break; + + case Key_NumberSign: + cw->setFormatType( ShortDate_format ); + break; + + case Key_AsciiCircum: + cw->setFormatType( Scientific_format ); + break; + + case Key_Ampersand: + if ( c == rect.left() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cw->setLeftBorderPen( pen ); + } + if ( c == rect.right() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cw->setRightBorderPen( pen ); + } + break; + + default: + d->view->doc()->emitEndOperation( rect ); + return false; + } + sheet->emit_updateColumn( cw, c ); + } + d->view->doc()->emitEndOperation( rect ); + return true; + } + + for ( int row = rect.top(); row <= bottom; ++row ) + { + for ( int col = rect.left(); col <= right; ++ col ) + { + cell = sheet->nonDefaultCell( col, row ); + + if ( cell->isPartOfMerged() ) + continue; + + formatCellByKey (cell, _ev->key(), rect); + } // for left .. right + } // for top .. bottom + + } + _ev->accept(); + + d->view->doc()->emitEndOperation( *selectionInfo() ); + return true; +} + +bool Canvas::formatCellByKey (Cell *cell, int key, const TQRect &rect) +{ + TQPen pen; + switch (key) + { + case Key_Exclam: + cell->convertToDouble (); + cell->format()->setFormatType (Number_format); + cell->format()->setPrecision( 2 ); + break; + + case Key_Dollar: + cell->convertToMoney (); + break; + + case Key_Percent: + cell->convertToPercent (); + break; + + case Key_At: + cell->convertToTime (); + break; + + case Key_NumberSign: + cell->convertToDate (); + break; + + case Key_AsciiCircum: + cell->format()->setFormatType (Scientific_format); + cell->convertToDouble (); + break; + + case Key_Ampersand: + if ( cell->row() == rect.top() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cell->setTopBorderPen( pen ); + } + if ( cell->row() == rect.bottom() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cell->setBottomBorderPen( pen ); + } + if ( cell->column() == rect.left() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cell->setLeftBorderPen( pen ); + } + if ( cell->column() == rect.right() ) + { + pen = TQPen( d->view->borderColor(), 1, SolidLine); + cell->setRightBorderPen( pen ); + } + break; + } // switch + + return true; +} + + +void Canvas::slotAutoScroll(const TQPoint &scrollDistance) +{ + TQPoint d = scrollDistance; + horzScrollBar()->setValue( horzScrollBar()->value() + d.x() ); + vertScrollBar()->setValue( vertScrollBar()->value() + d.y() ); +} + +void Canvas::doAutoScroll() +{ + if ( !d->mousePressed ) + { + d->scrollTimer->stop(); + return; + } + bool select = false; + TQPoint pos = mapFromGlobal( TQCursor::pos() ); + + //Provide progressive scrolling depending on the mouse position + if ( pos.y() < 0 ) + { + vertScrollBar()->setValue ((int) (vertScrollBar()->value() - + autoScrollAccelerationY( - pos.y()))); + select = true; + } + else if ( pos.y() > height() ) + { + vertScrollBar()->setValue ((int) (vertScrollBar()->value() + + autoScrollAccelerationY (pos.y() - height()))); + select = true; + } + + if ( pos.x() < 0 ) + { + horzScrollBar()->setValue ((int) (horzScrollBar()->value() - + autoScrollAccelerationX( - pos.x() ))); + select = true; + } + else if ( pos.x() > width() ) + { + horzScrollBar()->setValue ((int) (horzScrollBar()->value() + + autoScrollAccelerationX( pos.x() - width()))); + select = true; + } + + if ( select ) + { + TQMouseEvent * event = new TQMouseEvent(TQEvent::MouseMove, pos, 0, 0); + mouseMoveEvent( event ); + delete event; + } + + //Restart timer + d->scrollTimer->start( 50 ); +} + +void Canvas::speakCell(TQWidget* w, const TQPoint& p, uint flags) +{ + Q_UNUSED(flags); + if (w != this) return; + Sheet* sheet = activeSheet(); + if (!sheet) return; + int row = -1; + int col = -1; + if (p == TQPoint()) { + row = markerRow(); + col = markerColumn(); + if (row == d->prevSpokenFocusRow && col == d->prevSpokenFocusCol) return; + d->prevSpokenFocusRow = row; + d->prevSpokenFocusCol = col; + } else { + TQPoint wp = w->mapFromGlobal(p); + double tmp; + double posX; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + double dwidth = d->view->doc()->unzoomItX( width() ); + posX = dwidth - d->view->doc()->unzoomItX( wp.x() ); + } + else + posX = d->view->doc()->unzoomItX( wp.x() ); + + double posY = d->view->doc()->unzoomItY( wp.y() ); + col = sheet->leftColumn( (posX + xOffset()), tmp ); + row = sheet->topRow( (posY + yOffset()), tmp ); + if (row == d->prevSpokenPointerRow && col == d->prevSpokenPointerCol) return; + d->prevSpokenPointerRow = row; + d->prevSpokenPointerCol = col; + } + if (row == d->prevSpokenRow && col == d->prevSpokenCol) return; + d->prevSpokenRow = row; + d->prevSpokenCol = col; + // kdDebug() << "Canvas::speakCell: row = " << row << " col = " << col << endl; + if (row >=0 && col >= 0) { + Cell* cell = sheet->cellAt( col, row ); + if (!cell) return; + TQString text = cell->strOutText(); + if (!text.isEmpty()) { + text.prepend(i18n("Spreadsheet cell", "Cell ") + cell->name() + " "); + if (cell->isFormula()) { + TQString f = cell->text(); + // Try to format the formula so synth can more clearly speak it. + TQString f2; + for (uint i = 0; i < f.length(); i++) f2 += f[i] + " "; + f2.replace("(", i18n("character (", "left paren")); + f2.replace(")", i18n("character )", "right paren")); + f2.replace(":", i18n("character :", "colon")); + f2.replace(";", i18n("character ;", "semicolon")); + f2.replace("=", i18n("character =", "equals")); + f2.replace(".", i18n("character .", "point")); + f2.replace(",", i18n("character ,", "comma")); + f2.replace(" . . ", i18n("characters ..", " dot dot ")); + text.append(i18n("Spreadsheet formula", " Formula ") + f2); + } + // kdDebug() << "Canvas::speakCell: text = " << text << endl; + kospeaker->sayWidget(text); + } + } +} + +double Canvas::autoScrollAccelerationX( int offset ) +{ + switch( static_cast( offset / 20 ) ) + { + case 0: return 5.0; + case 1: return 20.0; + case 2: return d->view->doc()->unzoomItX( width() ); + case 3: return d->view->doc()->unzoomItX( width() ); + default: return d->view->doc()->unzoomItX( (int) (width() * 5.0) ); + } +} + +double Canvas::autoScrollAccelerationY( int offset ) +{ + switch( static_cast( offset / 20 ) ) + { + case 0: return 5.0; + case 1: return 20.0; + case 2: return d->view->doc()->unzoomItY( height() ); + case 3: return d->view->doc()->unzoomItY( height() ); + default: return d->view->doc()->unzoomItY( (int) (height() * 5.0) ); + } +} + + +KSpread::EmbeddedObject *Canvas::getObject( const TQPoint &pos, Sheet *_sheet ) +{ + TQPoint const p ( (int) pos.x() , + (int) pos.y() ); + + TQPtrListIterator itObject( doc()->embeddedObjects() ); + for( ; itObject.current(); ++itObject ) + { + if ( itObject.current()->sheet() == _sheet ) + { + KoRect const bound = ( itObject.current() )->geometry(); + TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(), + bound.width(), + bound.height() ) ); + zoomedBound.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ), (int)( -yOffset() * doc()->zoomedResolutionY() ) ); + if ( zoomedBound.contains( p ) ) + return itObject.current(); + } + } + return 0; +} + +void Canvas::selectObject( EmbeddedObject *obj ) +{ + if ( obj->sheet() != activeSheet() || obj->isSelected() ) + return; + obj->setSelected( true ); + repaintObject( obj ); + + d->mouseSelectedObject = true; + emit objectSelectedChanged(); + deleteEditor( true ); +} + +void Canvas::deselectObject( EmbeddedObject *obj ) +{ + if ( obj->sheet() != activeSheet() || !obj->isSelected() ) + return; + obj->setSelected( false ); + repaintObject( obj ); + + d->mouseSelectedObject = false; + emit objectSelectedChanged(); +} + +void Canvas::selectAllObjects() +{ + TQPtrListIterator it( doc()->embeddedObjects() ); + for ( ; it.current() ; ++it ) + { + if ( it.current()->sheet() == activeSheet() ) + it.current()->setSelected( true ); + } + + d->mouseSelectedObject = true; +// emit objectSelectedChanged(); +} + +void Canvas::deselectAllObjects() +{ + if( activeSheet()->numSelected() == 0 ) + return; + + //lowerObject(); + + TQPtrListIterator it( doc()->embeddedObjects() ); + for ( ; it.current() ; ++it ) + deselectObject( it.current() ); + + d->mouseSelectedObject = false; +// emit objectSelectedChanged(); +} + + + +void Canvas::setMouseSelectedObject(bool b) +{ + d->mouseSelectedObject = b; + emit objectSelectedChanged(); +} + +bool Canvas::isObjectSelected() +{ + return d->mouseSelectedObject; +} + + +void Canvas::moveObjectsByMouse( KoPoint &pos, bool keepXorYunchanged ) +{ + KoRect rect( objectRect( false ) ); + KoPoint move( 0, 0 ); + double diffx = pos.x() - d->m_origMousePos.x(); + double diffy = pos.y() - d->m_origMousePos.y(); + + move = KoPoint( diffx, diffy ); + d->m_origMousePos = pos; + + // unwind last snapping + KoRect movedRect( rect ); + movedRect.moveBy( diffx, diffy ); + + // don't move object off canvas + KoPoint diffDueToBorders(0,0); +// KoRect pageRect( m_activePage->getPageRect() ); + if ( rect.left() + move.x() < 0/*pageRect.left()*/ ) + diffDueToBorders.setX( -rect.left() - move.x() ); +// else if ( rect.right() + move.x() > pageRect.right() ) +// diffDueToBorders.setX( pageRect.right() - (rect.right() + move.x()) ); + + + //kdDebug() << "rect.top() + move.y():" << rect.top() + move.y()<< endl; + if ( rect.top() + move.y() < 0 ) + diffDueToBorders.setY( -rect.top() - move.y() ); +// else if ( rect.bottom() + move.y() > pageRect.bottom() ) +// diffDueToBorders.setY( pageRect.bottom() - (rect.bottom() + move.y()) ); + +// m_moveSnapDiff += diffDueToBorders; + move += diffDueToBorders; + +// movedRect.moveBy( m_moveSnapDiff.x(), m_moveSnapDiff.y() ); + if ( keepXorYunchanged ) + { + KoPoint diff( d->m_moveStartPosMouse - movedRect.topLeft() ); + if ( fabs( diff.x() ) > fabs( diff.y() ) ) + { +// m_moveSnapDiff.setY( /*m_moveSnapDiff.y() + */m_moveStartPosMouse.y() - movedRect.y() ); + movedRect.moveTopLeft( KoPoint( movedRect.x(), d->m_moveStartPosMouse.y() ) ); + move.setY( movedRect.y() - rect.y() ); + } + else + { +// m_moveSnapDiff.setX( /*m_moveSnapDiff.x() + */m_moveStartPosMouse.x() - movedRect.x() ); + movedRect.moveTopLeft( KoPoint( d->m_moveStartPosMouse.x(), movedRect.y() ) ); + move.setX( movedRect.x() - rect.x() ); + } + } + + if ( move != KoPoint( 0, 0 ) ) + { + //kdDebug(33001) << "moveObjectsByMouse move = " << move << endl; + activeSheet()->moveObject( view(), move, false ); + } +} + + +void Canvas::resizeObject( ModifyType _modType, const KoPoint & point, bool keepRatio ) +{ + EmbeddedObject *obj = d->m_resizeObject; + + KoRect objRect = obj->geometry(); + objRect.moveBy( -xOffset(), -yOffset() ); + TQRect oldBoundingRect( doc()->zoomRect( objRect ) ); + + bool left = false; + bool right = false; + bool top = false; + bool bottom = false; + if ( _modType == MT_RESIZE_UP || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_RU ) + { + top = true; +// snapStatus |= KoGuides::SNAP_HORIZ; + } + if ( _modType == MT_RESIZE_DN || _modType == MT_RESIZE_LD || _modType == MT_RESIZE_RD ) + { + bottom = true; +// snapStatus |= KoGuides::SNAP_HORIZ; + } + if ( _modType == MT_RESIZE_LF || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_LD ) + { + left = true; +// snapStatus |= KoGuides::SNAP_VERT; + } + if ( _modType == MT_RESIZE_RT || _modType == MT_RESIZE_RU || _modType == MT_RESIZE_RD ) + { + right = true; +// snapStatus |= KoGuides::SNAP_VERT; + } + + double newLeft = objRect.left(); + double newRight = objRect.right(); + double newTop = objRect.top(); + double newBottom = objRect.bottom(); + if ( top ) + { + if ( point.y() < objRect.bottom() - MIN_SIZE ) + { + newTop = point.y(); + } + else + { + newTop = objRect.bottom() - MIN_SIZE; + } + } + if ( bottom ) + { + if ( point.y() > objRect.top() + MIN_SIZE ) + { + newBottom = point.y(); + } + else + { + newBottom = objRect.top() + MIN_SIZE; + } + } + if ( left ) + { + if ( point.x() < objRect.right() - MIN_SIZE ) + { + newLeft = point.x(); + } + else + { + newLeft = objRect.right() - MIN_SIZE; + } + } + if ( right ) + { + if ( point.x() > objRect.left() + MIN_SIZE ) + { + newRight = point.x(); + } + else + { + newRight = objRect.left() + MIN_SIZE; + } + } + + double width = newRight - newLeft; + double height = newBottom - newTop; + + if ( keepRatio && d->m_ratio != 0 ) + { + if ( ( top || bottom ) && ( right || left ) ) + { + if ( height * height * d->m_ratio > width * width / d->m_ratio ) + { + width = height * d->m_ratio; + } + else + { + height = width / d->m_ratio; + } + } + else if ( top || bottom ) + { + width = height * d->m_ratio; + } + else + { + height = width / d->m_ratio; + } + + if ( top ) + { + newTop = objRect.bottom() - height; + } + else + { + newBottom = objRect.top() + height; + } + if ( left ) + { + newLeft = objRect.right() - width; + } + else + { + newRight = objRect.right() + width; + } + } + + if ( newLeft != objRect.left() || newRight != objRect.right() || newTop != objRect.top() || newBottom != objRect.bottom() ) + { + // resizeBy and moveBy have to been used to make it work with rotated objects + obj->resizeBy( width - objRect.width(), height - objRect.height() ); + + if ( objRect.left() != newLeft || objRect.top() != newTop ) + { + obj->moveBy( KoPoint( newLeft - objRect.left(), newTop - objRect.top() ) ); + } + +// if ( doc()->showGuideLines() && !m_disableSnapping ) +// { +// KoRect rect( obj->getRealRect() ); +// KoPoint sp( rect.topLeft() ); +// if ( right ) +// { +// sp.setX( rect.right() ); +// } +// if ( bottom ) +// { +// sp.setY( rect.bottom() ); +// } +// m_gl.repaintSnapping( sp, snapStatus ); +// } + + repaint( oldBoundingRect ); + repaintObject( obj ); + emit objectSizeChanged(); + } +} + + +void Canvas::finishResizeObject( const TQString &/*name*/, bool /*layout*/ ) +{ + if ( d->m_resizeObject ) + { + KoPoint move = KoPoint( d->m_resizeObject->geometry().x() - d->m_rectBeforeResize.x(), + d->m_resizeObject->geometry().y() - d->m_rectBeforeResize.y() ); + KoSize size = KoSize( d->m_resizeObject->geometry().width() - d->m_rectBeforeResize.width(), + d->m_resizeObject->geometry().height() - d->m_rectBeforeResize.height() ); + + if ( ( d->m_resizeObject->geometry() ) != d->m_rectBeforeResize ) + { + ChangeObjectGeometryCommand *resizeCmd = new ChangeObjectGeometryCommand( d->m_resizeObject, move, size ); + // the command is not executed as the object is allready resized. + doc()->addCommand( resizeCmd ); + } + +// if ( layout ) +// doc()->layout( m_resizeObject ); + + d->m_ratio = 0.0; + d->m_isResizing = false; + repaintObject( d->m_resizeObject ); + d->m_resizeObject = NULL; + } +} + +void Canvas::raiseObject( EmbeddedObject *object ) +{ + if ( doc()->embeddedObjects().count() <= 1 ) + return; + + if ( d->m_objectDisplayAbove == 0 ) + { + if ( activeSheet()->numSelected() == 1 ) + { + d->m_objectDisplayAbove = object; + } + } +} + +void Canvas::lowerObject() +{ + d->m_objectDisplayAbove = 0; +} + +void Canvas::displayObjectList( TQPtrList &list ) +{ + list = doc()->embeddedObjects(); + list.setAutoDelete( false ); + + if ( d->m_objectDisplayAbove ) + { + // it can happen that the object is no longer there e.g. when + // the insert of the object is undone + int pos = doc()->embeddedObjects().findRef( d->m_objectDisplayAbove ); + if ( pos != -1 && d->m_objectDisplayAbove->isSelected() ) + { + list.take( pos ); + list.append( d->m_objectDisplayAbove ); + } + else + { + //tz not possible due to const. should const be removed? + //m_objectDisplayAbove = 0; + } + } +} + + +KoRect Canvas::objectRect( bool all ) const +{ + return activeSheet()->getRealRect( all ); +} + +void Canvas::deleteEditor (bool saveChanges, bool array) +{ + if ( !d->cellEditor ) + return; + + + //There may be highlighted areas on the sheet which will need to be erased + setSelectionChangePaintDirty( activeSheet() , *choice() ); + + d->editWidget->setEditMode( false ); + + TQString t = d->cellEditor->text(); + // Delete the cell editor first and after that update the document. + // That means we get a synchronous repaint after the cell editor + // widget is gone. Otherwise we may get painting errors. + delete d->cellEditor; + d->cellEditor = 0; + + if ( saveChanges ) + { + if ( t.at(0)=='=' ) + { + //a formula + int openParenthese = t.contains('(' ); + int closeParenthese = t.contains(')' ); + int diff = TQABS( openParenthese - closeParenthese ); + if ( openParenthese > closeParenthese ) + { + for (int i=0; i < diff;i++) + { + t=t+')'; + } + } + } + d->view->setText (t, array); + } + else + { + d->view->updateEditWidget(); + } + + setFocus(); +} + + +void Canvas::createEditor(bool captureArrowKeys) +{ + if (!activeSheet()) + return; + + Cell * cell = activeSheet()->nonDefaultCell( markerColumn(), markerRow(), false ); + + if ( !createEditor( CellEditor , true , captureArrowKeys ) ) + return; + if ( cell ) + d->cellEditor->setText( cell->text() ); +} + +bool Canvas::createEditor( EditorType ed, bool addFocus, bool captureArrowKeys ) +{ + Sheet * sheet = activeSheet(); + + // Set the starting sheet of the choice. + choice()->setSheet( activeSheet() ); + + if ( !d->cellEditor ) + { + Cell * cell = sheet->nonDefaultCell( marker().x(), marker().y(), false ); + + if ( sheet->isProtected() && !cell->format()->notProtected( marker().x(), marker().y() ) ) + return false; + + if ( ed == CellEditor ) + { + d->editWidget->setEditMode( true ); + d->cellEditor = new KSpread::CellEditor( cell, this, captureArrowKeys ); + } + + double w, h; + double min_w = cell->dblWidth( markerColumn() ); + double min_h = cell->dblHeight( markerRow() ); + if ( cell->isDefault() ) + { + w = min_w; + h = min_h; + //kdDebug(36001) << "DEFAULT" << endl; + } + else + { + w = cell->extraWidth(); + h = cell->extraHeight(); + //kdDebug(36001) << "HEIGHT=" << min_h << " EXTRA=" << h << endl; + } + + double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset(); + + Sheet::LayoutDirection sheetDir = sheet->layoutDirection(); + bool rtlText = cell->strOutText().isRightToLeft(); + + // if sheet and cell direction don't match, then the editor's location + // needs to be shifted backwards so that it's right above the cell's text + if ( w > 0 && ( ( sheetDir == Sheet::RightToLeft && !rtlText ) || + ( sheetDir == Sheet::LeftToRight && rtlText ) ) ) + xpos -= w - min_w; + + // paint editor above correct cell if sheet direction is RTL + if ( sheetDir == Sheet::RightToLeft ) + { + double dwidth = d->view->doc()->unzoomItX( width() ); + double w2 = TQMAX( w, min_w ); + xpos = dwidth - w2 - xpos; + } + + double ypos = sheet->dblRowPos( markerRow() ) - yOffset(); + TQPalette p = d->cellEditor->palette(); + TQColorGroup g( p.active() ); + + TQColor color = cell->format()->textColor( markerColumn(), markerRow() ); + if ( !color.isValid() ) + color = TQApplication::palette().active().text(); + g.setColor( TQColorGroup::Text, color); + + color = cell->bgColor( markerColumn(), markerRow() ); + if ( !color.isValid() ) + color = g.base(); + g.setColor( TQColorGroup::Background, color ); + + d->cellEditor->setPalette( TQPalette( g, p.disabled(), g ) ); + TQFont tmpFont = cell->format()->textFont( markerColumn(), markerRow() ); + tmpFont.setPointSizeFloat( 0.01 * d->view->doc()->zoom() * tmpFont.pointSizeFloat() ); + d->cellEditor->setFont( tmpFont ); + + KoRect rect( xpos, ypos, w, h ); //needed to circumvent rounding issue with height/width + + + TQRect zoomedRect=d->view->doc()->zoomRect( rect ); + /*zoomedRect.setLeft(zoomedRect.left()-2); + zoomedRect.setRight(zoomedRect.right()+4); + zoomedRect.setTop(zoomedRect.top()-1); + zoomedRect.setBottom(zoomedRect.bottom()+2);*/ + + d->cellEditor->setGeometry( zoomedRect ); + d->cellEditor->setMinimumSize( TQSize( d->view->doc()->zoomItX( min_w ), d->view->doc()->zoomItY( min_h ) ) ); + d->cellEditor->show(); + //kdDebug(36001) << "FOCUS1" << endl; + //Laurent 2001-12-05 + //Don't add focus when we create a new editor and + //we select text in edit widget otherwise we don't delete + //selected text. + // startChoose(); + + if ( addFocus ) + d->cellEditor->setFocus(); + + setSelectionChangePaintDirty(sheet, *selectionInfo()); + paintUpdates(); + } + + return true; +} + +void Canvas::repaintObject( EmbeddedObject *obj ) +{ + //Calculate where the object appears on the canvas widget and then repaint that part of the widget + TQRect canvasRelativeGeometry = doc()->zoomRect( obj->geometry() ); + canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , + (int)( -yOffset() * doc()->zoomedResolutionY()) ); + + update( canvasRelativeGeometry ); + + /* if ( !obj->isSelected() ) + { + KoRect g = obj->geometry(); + g.moveBy( -xOffset(), -yOffset() ); + TQRect geometry( doc()->zoomRect( g ) ); + + update( geometry ); + } + else + { + TQPainter p(this); + p.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() ); + obj->draw(&p); //this goes faster than calling repaint + p.end(); + }*/ +} + +void Canvas::copyOasisObjects() +{ + // We'll create a store (ZIP format) in memory + TQBuffer buffer; + TQCString mimeType = "application/vnd.oasis.opendocument.spreadsheet"; + KoStore* store = KoStore::createStore( TQT_TQIODEVICE(&buffer), KoStore::Write, mimeType ); + Q_ASSERT( store ); + Q_ASSERT( !store->bad() ); + KoOasisStore oasisStore( store ); + + KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType ); + + TQString plainText; + KoPicture picture; + if ( !doc()->saveOasisHelper( store, manifestWriter, Doc::SaveSelected, &plainText, &picture ) + || !oasisStore.closeManifestWriter() ) + { + delete store; + return; + } + delete store; + + KMultipleDrag* multiDrag = new KMultipleDrag(); + if ( !plainText.isEmpty() ) + multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) ); + if ( !picture.isNull() ) + multiDrag->addDragObject( picture.dragObject( 0 ) ); + KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 ); + kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl; + storeDrag->setEncodedData( buffer.buffer() ); + multiDrag->addDragObject( storeDrag ); + + //save the objects as pictures too so that other programs can access them + TQPtrListIterator itObject( doc()->embeddedObjects() ); + itObject.toFirst(); + if ( itObject.current() ) + { + KoRect kr = objectRect(false); + TQRect r( kr.toTQRect() ); + TQPixmap pixmap( r.width(), r.height() ); + pixmap.fill( "white" ); + TQPainter p(&pixmap); + for( ; itObject.current(); ++itObject ) + { + if ( itObject.current()->isSelected() ) + p.drawPixmap( itObject.current()->geometry().toTQRect().left() - r.left(), itObject.current()->geometry().toTQRect().top() - r.top(), itObject.current()->toPixmap( 1.0 , 1.0 ) ); + } + p.end(); + if (!pixmap.isNull()) + { + TQImageDrag *imagedrag = new TQImageDrag( pixmap.convertToImage() ); + multiDrag->addDragObject( imagedrag ); + } + } + + TQDragObject *dragObject = multiDrag; + TQApplication::clipboard()->setData( dragObject, TQClipboard::Clipboard ); +} + +void Canvas::closeEditor() +{ + if ( d->chooseCell ) + return; + + if ( d->cellEditor ) + { + deleteEditor( true ); // save changes + } +} + +void Canvas::updateEditor() +{ + if (!d->chooseCell) + return; + + Sheet* sheet = activeSheet(); + if (!sheet) + return; + + if (d->cellEditor) + { + if (choice()->sheet() != sheet) + { + d->cellEditor->hide(); + } + else + { + d->cellEditor->show(); + } + d->cellEditor->updateChoice(); + } +} + +void Canvas::setSelectionChangePaintDirty(Sheet* sheet, const Region& region) +{ + sheet->setRegionPaintDirty(region); // TODO should the paintDirtyList be in Canvas? +} + + +void Canvas::updatePosWidget() +{ + TQString buffer; + // No selection, or only one cell merged selected + if ( selectionInfo()->isSingular() ) + { + if (activeSheet()->getLcMode()) + { + buffer = "L" + TQString::number( markerRow() ) + + "C" + TQString::number( markerColumn() ); + } + else + { + buffer = Cell::columnName( markerColumn() ) + + TQString::number( markerRow() ); + } + } + else + { + if (activeSheet()->getLcMode()) + { + buffer = TQString::number( (selectionInfo()->lastRange().bottom()-selectionInfo()->lastRange().top()+1) )+"Lx"; + if ( util_isRowSelected( selectionInfo()->lastRange() ) ) + buffer+=TQString::number((KS_colMax-selectionInfo()->lastRange().left()+1))+"C"; + else + buffer+=TQString::number((selectionInfo()->lastRange().right()-selectionInfo()->lastRange().left()+1))+"C"; + } + else + { + //encodeColumnLabelText return @@@@ when column >KS_colMax + //=> it's not a good display + //=> for the moment I display pos of marker + buffer=Cell::columnName( selectionInfo()->lastRange().left() ) + + TQString::number(selectionInfo()->lastRange().top()) + ":" + + Cell::columnName( TQMIN( KS_colMax, selectionInfo()->lastRange().right() ) ) + + TQString::number(selectionInfo()->lastRange().bottom()); + //buffer=activeSheet()->columnLabel( m_iMarkerColumn ); + //buffer+=tmp.setNum(m_iMarkerRow); + } + } + + if (buffer != d->posWidget->lineEdit()->text()) + d->posWidget->lineEdit()->setText(buffer); +} + +void Canvas::equalizeRow() +{ + TQRect s( selection() ); + RowFormat *rl = d->view->activeSheet()->rowFormat(s.top()); + int size=rl->height(this); + if ( s.top() == s.bottom() ) + return; + for(int i=s.top()+1;i<=s.bottom();i++) + { + Sheet *sheet = activeSheet(); + if ( !sheet ) + return; + size=TQMAX(d->view->activeSheet()->rowFormat(i)->height(this),size); + } + d->view->vBorderWidget()->equalizeRow(size); +} + +void Canvas::equalizeColumn() +{ + TQRect s( selection() ); + ColumnFormat *cl = d->view->activeSheet()->columnFormat(s.left()); + int size=cl->width(this); + if ( s.left() == s.right() ) + return; + + for(int i=s.left()+1;i<=s.right();i++) + { + size=TQMAX(d->view->activeSheet()->columnFormat(i)->width(this),size); + } + d->view->hBorderWidget()->equalizeColumn(size); +} + +TQRect Canvas::cellsInArea( const TQRect area ) const +{ + KoRect unzoomedRect = d->view->doc()->unzoomRect( area ); + + unzoomedRect.moveBy( (int)xOffset(), (int)yOffset() ); + + double tmp; + int left_col = activeSheet()->leftColumn( unzoomedRect.left(), tmp ); + int right_col = activeSheet()->rightColumn( unzoomedRect.right() ); + int top_row = activeSheet()->topRow( unzoomedRect.top(), tmp ); + int bottom_row = activeSheet()->bottomRow( unzoomedRect.bottom() ); + + return TQRect( left_col, top_row, + right_col - left_col + 1, bottom_row - top_row + 1 ); +} + +TQRect Canvas::visibleCells() const +{ + return cellsInArea( TQRect(0,0,width(),height()) ); + +} + + +//--------------------------------------------- +// +// Drawing Engine +// +//--------------------------------------------- + +void Canvas::paintUpdates() +{ + if (activeSheet() == NULL) + return; + + TQPainter painter(this); + + //Save clip region + TQRegion rgnComplete( painter.clipRegion() ); + TQWMatrix matrix; + if ( d->view ) + { + matrix = d->view->matrix(); + } + else + { + matrix = painter.worldMatrix(); + } + + + paintChildren( painter, matrix ); + + painter.save(); + clipoutChildren( painter ); + + KoRect unzoomedRect = d->view->doc()->unzoomRect( TQRect( 0, 0, width(), height() ) ); + // unzoomedRect.moveBy( xOffset(), yOffset() ); + + + /* paint any visible cell that has the paintDirty flag */ + TQRect range = visibleCells(); + Cell* cell = NULL; + + double topPos = activeSheet()->dblRowPos(range.top()); + double leftPos = activeSheet()->dblColumnPos(range.left()); + + KoPoint dblCorner( leftPos - xOffset(), topPos - yOffset() ); + + int x; + int y; + + int right = range.right(); + int bottom = range.bottom(); + Sheet * sheet = activeSheet(); + +#if 0 + kdDebug(36001) + << "================================================================" + << endl; + kdDebug(36001) << "painting dirty cells " << endl; +#endif + + TQValueList mergedCellsPainted; + for ( x = range.left(); x <= right; ++x ) + { + for ( y = range.top(); y <= bottom; ++y ) + { + if ( sheet->cellIsPaintDirty( TQPoint( x, y ) ) ) + { + cell = sheet->cellAt( x, y ); + + // recalc and relayout only for non default cells + if (!cell->isDefault()) + { + if (cell->calcDirtyFlag()) cell->calc(); + if (cell->layoutDirtyFlag()) cell->makeLayout( painter, x, y ); + } + + /* bool paintBordersBottom = false; + bool paintBordersRight = false; + bool paintBordersLeft = false; + bool paintBordersTop = false; */ + + int paintBorder=Cell::Border_None; + + TQPen bottomPen( cell->effBottomBorderPen( x, y ) ); + TQPen rightPen( cell->effRightBorderPen( x, y ) ); + TQPen leftPen( cell->effLeftBorderPen( x, y ) ); + TQPen topPen( cell->effTopBorderPen( x, y ) ); + + // paint right border + // - if rightmost cell + // - if the pen is more "worth" than the left border pen of the cell + // on the left + if ( x >= KS_colMax ) + { + paintBorder |= Cell::Border_Right; + } + else + { + paintBorder |= Cell::Border_Right; + if ( cell->effRightBorderValue( x, y ) < + sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) + rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); + } + + // similiar for other borders... + // bottom border: + if ( y >= KS_rowMax ) + { + paintBorder |= Cell::Border_Bottom; + } + else + { + paintBorder |= Cell::Border_Bottom; + if ( cell->effBottomBorderValue( x, y ) < + sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1 ) ) + bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); + } + + // left border: + if ( x == 1 ) + { + paintBorder |= Cell::Border_Left; + } + else + { + paintBorder |= Cell::Border_Left; + if ( cell->effLeftBorderValue( x, y ) < + sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) + leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); + } + + // top border: + if ( y == 1 ) + { + paintBorder |= Cell::Border_Top; + } + else + { + paintBorder |= Cell::Border_Top; + if ( cell->effTopBorderValue( x, y ) < + sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) + topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); + } + + cell->paintCell( unzoomedRect, painter, d->view, dblCorner, + TQPoint( x, y), paintBorder, + rightPen,bottomPen,leftPen,topPen, + mergedCellsPainted); + } + dblCorner.setY( dblCorner.y() + sheet->rowFormat( y )->dblHeight( ) ); + } + dblCorner.setY( topPos - yOffset() ); + dblCorner.setX( dblCorner.x() + sheet->columnFormat( x )->dblWidth( ) ); + } + + /* now paint the selection */ + //Nb. No longer necessary to paint choose selection here as the cell reference highlight + //stuff takes care of this anyway + + paintHighlightedRanges(painter, unzoomedRect); + paintNormalMarker(painter, unzoomedRect); + + //restore clip region with children area + painter.restore(); + //painter.setClipRegion( rgnComplete ); +} + + + +void Canvas::clipoutChildren( TQPainter& painter ) const +{ + TQRegion rgn = painter.clipRegion(); + if ( rgn.isEmpty() ) + rgn = TQRegion( TQRect( 0, 0, width(), height() ) ); + + const double horizontalOffset = -xOffset() * doc()->zoomedResolutionX(); + const double verticalOffset = -yOffset() * doc()->zoomedResolutionY(); + + TQPtrListIterator itObject( doc()->embeddedObjects() ); + for( ; itObject.current(); ++itObject ) + { + if ( ( itObject.current() )->sheet() == activeSheet() ) + { + TQRect childGeometry = doc()->zoomRect( itObject.current()->geometry()); + + //The clipping region is given in device coordinates + //so subtract the current offset (scroll position) of the canvas + childGeometry.moveBy( (int)horizontalOffset , (int)verticalOffset ); + + if (painter.window().intersects(childGeometry)) + rgn -= childGeometry; + + //painter.fillRect( doc()->zoomRect( itObject.current()->geometry() ), TQColor("red" ) ); + } + } + + painter.setClipRegion( rgn ); +} + +TQRect Canvas::painterWindowGeometry( const TQPainter& painter ) const +{ + TQRect zoomedWindowGeometry = painter.window(); + + zoomedWindowGeometry.moveBy( (int)( xOffset() * doc()->zoomedResolutionX() ) , (int)( yOffset() * doc()->zoomedResolutionY() ) ); + + return zoomedWindowGeometry; +} + +void Canvas::paintChildren( TQPainter& painter, TQWMatrix& /*matrix*/ ) +{ + TQPtrListIterator itObject( doc()->embeddedObjects() ); + itObject.toFirst(); + if ( !itObject.current() ) + return; + + painter.save(); + painter.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() ); + + const TQRect zoomedWindowGeometry = painterWindowGeometry( painter ); + const Sheet* sheet = activeSheet(); + + for( ; itObject.current(); ++itObject ) + { + TQRect const zoomedObjectGeometry = doc()->zoomRect( itObject.current()->geometry() ); + if ( ( itObject.current() )->sheet() == activeSheet() && + zoomedWindowGeometry.intersects( zoomedObjectGeometry ) ) + { + //To prevent unnecessary redrawing of the embedded object, we only repaint + //if one or more of the cells underneath the object has been marked as 'dirty'. + + TQRect canvasRelativeGeometry = zoomedObjectGeometry; + canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) , + (int)( -yOffset() * doc()->zoomedResolutionY()) ); + + const TQRect cellsUnderObject=cellsInArea( canvasRelativeGeometry ); + bool redraw=false; + + for (int x=cellsUnderObject.left();x<=cellsUnderObject.right();x++) + { + for (int y=cellsUnderObject.top();y<=cellsUnderObject.bottom();y++) + if ( sheet->cellIsPaintDirty( TQPoint(x,y) ) ) + { + redraw=true; + break; + } + if (redraw) + break; + } + + if ( redraw ) + itObject.current()->draw( &painter ); + } + } + painter.restore(); +} + +void Canvas::paintHighlightedRanges(TQPainter& painter, const KoRect& /*viewRect*/) +{ + TQValueList colors = choice()->colors(); + TQBrush nullBrush; + int index = 0; + Region::ConstIterator end(choice()->constEnd()); + for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it) + { + //Only paint ranges or cells on the current sheet + if ((*it)->sheet() != activeSheet()) + { + index++; + continue; + } + + TQRect region = (*it)->rect().normalize(); + + //double positions[4]; + //bool paintSides[4]; + KoRect unzoomedRect; + + sheetAreaToVisibleRect(region,unzoomedRect); + //Convert region from sheet coordinates to canvas coordinates for use with the painter + //retrieveMarkerInfo(region,viewRect,positions,paintSides); + + TQPen highlightPen( colors[(index) % colors.size()] ); // (*it)->color() ); + painter.setPen(highlightPen); + + //Adjust the canvas coordinate - rect to take account of zoom level + + TQRect zoomedRect; + + zoomedRect.setCoords ( d->view->doc()->zoomItX(unzoomedRect.left()), + d->view->doc()->zoomItY(unzoomedRect.top()), + d->view->doc()->zoomItX(unzoomedRect.right()), + d->view->doc()->zoomItY(unzoomedRect.bottom()) ); + + //Now adjust the highlight rectangle is slightly inside the cell borders (this means that multiple highlighted cells + //look nicer together as the borders do not clash) + + zoomedRect.setLeft(zoomedRect.left()+1); + zoomedRect.setTop(zoomedRect.top()+1); + zoomedRect.setRight(zoomedRect.right()-1); + zoomedRect.setBottom(zoomedRect.bottom()-1); + + painter.setBrush(nullBrush); + painter.drawRect(zoomedRect); + + //Now draw the size grip (the little rectangle on the bottom right-hand corner of the range which the user can + //click and drag to resize the region) + + + TQBrush sizeGripBrush( colors[(index) % colors.size()] ); // (*it)->color()); + TQPen sizeGripPen(TQt::white); + + painter.setPen(sizeGripPen); + painter.setBrush(sizeGripBrush); + + painter.drawRect(zoomedRect.right()-3,zoomedRect.bottom()-3,6,6); + index++; + } +} + +void Canvas::paintNormalMarker(TQPainter& painter, const KoRect &viewRect) +{ + //Only the active element (the one with the anchor) will be drawn with a border + + if( d->chooseCell ) + return; + + if (d->cellEditor) + return; + + Region::ConstIterator end(selectionInfo()->constEnd()); + for (Region::ConstIterator it(selectionInfo()->constBegin()); it != end; ++it) + { + TQRect range = (*it)->rect().normalize(); + + double positions[4]; + bool paintSides[4]; + + bool current = TQRect(selectionInfo()->anchor(), selectionInfo()->marker()).normalize() == range; + TQPen pen( TQt::black, 2 ); + painter.setPen( pen ); + + retrieveMarkerInfo( selectionInfo()->extendToMergedAreas(range), viewRect, positions, paintSides ); + + double left = positions[0]; + double top = positions[1]; + double right = positions[2]; + double bottom = positions[3]; + + bool paintLeft = paintSides[0]; + bool paintTop = paintSides[1]; + bool paintRight = paintSides[2]; + bool paintBottom = paintSides[3]; + + /* the extra '-1's thrown in here account for the thickness of the pen. + want to look like this: not this: + * * * * * * * * * * + * * * * + * * * * + */ + int l = 1; + + if ( paintTop ) + { + painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( right ) + l, d->view->doc()->zoomItY( top ) ); + } + if ( activeSheet()->layoutDirection()==Sheet::RightToLeft ) + { + if ( paintRight ) + { + painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) ); + } + if ( paintLeft && paintBottom && current ) + { + /* then the 'handle' in the bottom left corner is visible. */ + painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) - 3 ); + painter.drawLine( d->view->doc()->zoomItX( left ) + 4, d->view->doc()->zoomItY( bottom ), + d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) ); + painter.fillRect( d->view->doc()->zoomItX( left ) - 2, d->view->doc()->zoomItY( bottom ) -2, 5, 5, + painter.pen().color() ); + } + else + { + if ( paintLeft ) + { + painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) ); + } + if ( paintBottom ) + { + painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), + d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom )); + } + } + } + else // activeSheet()->layoutDirection()==Sheet::LeftToRight + { + if ( paintLeft ) + { + painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) ); + } + if ( paintRight && paintBottom && current ) + { + /* then the 'handle' in the bottom right corner is visible. */ + painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) - 3 ); + painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), + d->view->doc()->zoomItX( right ) - 3, d->view->doc()->zoomItY( bottom ) ); + painter.fillRect( d->view->doc()->zoomItX( right ) - 2, d->view->doc()->zoomItY( bottom ) - 2, 5, 5, + painter.pen().color() ); + } + else + { + if ( paintRight ) + { + painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ), + d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) ); + } + if ( paintBottom ) + { + painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ), + d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) ); + } + } + } + } +} + +void Canvas::sheetAreaToRect(const TQRect& sheetArea, KoRect& rect) +{ + Sheet* sheet=activeSheet(); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + rect.setLeft(sheet->dblColumnPos( sheetArea.right()+1 ) ); + rect.setRight(sheet->dblColumnPos( sheetArea.left() )); + } + else + { + rect.setLeft(sheet->dblColumnPos( sheetArea.left() )); + rect.setRight(sheet->dblColumnPos( sheetArea.right()+1 )); + } + + rect.setTop(sheet->dblRowPos(sheetArea.top())); + rect.setBottom(sheet->dblRowPos(sheetArea.bottom()+1)); + +} + +void Canvas::sheetAreaToVisibleRect( const TQRect& sheetArea, + KoRect& visibleRect ) +{ + Sheet* sheet=activeSheet(); + + if (!sheet) + return; + + double dwidth=d->view->doc()->unzoomItX(width()); + double xpos; + double x; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + xpos = dwidth - sheet->dblColumnPos( sheetArea.right() ) + xOffset(); + x = dwidth - sheet->dblColumnPos( sheetArea.left() ) + xOffset(); + } + else + { + xpos = sheet->dblColumnPos( sheetArea.left() ) - xOffset(); + x = sheet->dblColumnPos( sheetArea.right() ) - xOffset(); + } + + double ypos = sheet->dblRowPos(sheetArea.top())-yOffset(); + + const ColumnFormat *columnFormat = sheet->columnFormat( sheetArea.right() ); + double tw = columnFormat->dblWidth( ); + double w = x - xpos + tw; + + double y = sheet->dblRowPos( sheetArea.bottom() ) - yOffset(); + const RowFormat* rowFormat = sheet->rowFormat( sheetArea.bottom() ); + double th = rowFormat->dblHeight( ); + double h = ( y - ypos ) + th; + + /* left, top, right, bottom */ + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + visibleRect.setLeft(xpos - tw ); + visibleRect.setRight(xpos - tw + w ); + } + else + { + visibleRect.setLeft(xpos ); + visibleRect.setRight(xpos + w ); + } + visibleRect.setTop(ypos); + visibleRect.setBottom(ypos + h); +} + +void Canvas::retrieveMarkerInfo( const TQRect &marker, + const KoRect &viewRect, + double positions[], + bool paintSides[] ) +{ + + Sheet* sheet=activeSheet(); + + if (!sheet) return; + + KoRect visibleRect; + sheetAreaToVisibleRect(marker,visibleRect); + + + /* Sheet * sheet = activeSheet(); + if ( !sheet ) + return; + + double dWidth = d->view->doc()->unzoomItX( width() ); + + double xpos; + double x; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + xpos = dWidth - sheet->dblColumnPos( marker.right() ) + xOffset(); + x = dWidth - sheet->dblColumnPos( marker.left() ) + xOffset(); + } + else + { + xpos = sheet->dblColumnPos( marker.left() ) - xOffset(); + x = sheet->dblColumnPos( marker.right() ) - xOffset(); + } + double ypos = sheet->dblRowPos( marker.top() ) - yOffset(); + + const ColumnFormat *columnFormat = sheet->columnFormat( marker.right() ); + double tw = columnFormat->dblWidth( ); + double w = x - xpos + tw; + + double y = sheet->dblRowPos( marker.bottom() ) - yOffset(); + const RowFormat* rowFormat = sheet->rowFormat( marker.bottom() ); + double th = rowFormat->dblHeight( ); + double h = ( y - ypos ) + th; + + //left, top, right, bottom + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + positions[0] = xpos - tw; + positions[2] = xpos - tw + w; + } + else + { + positions[0] = xpos; + positions[2] = xpos + w; + } + positions[1] = ypos; + positions[3] = ypos + h;*/ + + /* these vars are used for clarity, the array for simpler function arguments */ + double left = visibleRect.left(); + double top = visibleRect.top(); + double right = visibleRect.right(); + double bottom = visibleRect.bottom(); + + /* left, top, right, bottom */ + paintSides[0] = (viewRect.left() <= left) && (left <= viewRect.right()) && + (bottom >= viewRect.top()) && (top <= viewRect.bottom()); + paintSides[1] = (viewRect.top() <= top) && (top <= viewRect.bottom()) + && (right >= viewRect.left()) && (left <= viewRect.right()); + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + paintSides[2] = (viewRect.left() <= right ) && + (right - 1 <= viewRect.right()) && + (bottom >= viewRect.top()) && (top <= viewRect.bottom()); + else + paintSides[2] = (viewRect.left() <= right ) && + (right <= viewRect.right()) && + (bottom >= viewRect.top()) && (top <= viewRect.bottom()); + paintSides[3] = (viewRect.top() <= bottom) && (bottom <= viewRect.bottom()) + && (right >= viewRect.left()) && (left <= viewRect.right()); + + positions[0] = TQMAX( left, viewRect.left() ); + positions[1] = TQMAX( top, viewRect.top() ); + positions[2] = TQMIN( right, viewRect.right() ); + positions[3] = TQMIN( bottom, viewRect.bottom() ); +} + + +/**************************************************************** + * + * VBorder + * + ****************************************************************/ + +VBorder::VBorder( TQWidget *_parent, Canvas *_canvas, View *_view) + : TQWidget( _parent, "", /*WNorthWestGravity*/WStaticContents | WResizeNoErase | WRepaintNoErase ) +{ + m_pView = _view; + m_pCanvas = _canvas; + m_lSize = 0L; + + setBackgroundMode( PaletteButton ); + setMouseTracking( true ); + m_bResize = false; + m_bSelection = false; + m_iSelectionAnchor=1; + m_bMousePressed = false; + + m_scrollTimer = new TQTimer( this ); + connect (m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); +} + + +VBorder::~VBorder() +{ + delete m_scrollTimer; +} + +TQSize VBorder::sizeHint() const +{ + return TQSize( 40, 10 ); +} + + +void VBorder::mousePressEvent( TQMouseEvent * _ev ) +{ + if ( !m_pView->koDocument()->isReadWrite() ) + return; + + if ( _ev->button() == Qt::LeftButton ) + m_bMousePressed = true; + + const Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); + double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() ); + m_bResize = false; + m_bSelection = false; + + // We were editing a cell -> save value and get out of editing mode + if ( m_pCanvas->editor() ) + { + m_pCanvas->deleteEditor( true ); // save changes + } + + m_scrollTimer->start( 50 ); + + // Find the first visible row and the y position of this row. + double y; + int row = sheet->topRow( m_pCanvas->yOffset(), y ); + + // Did the user click between two rows? + while ( y < ( dHeight + m_pCanvas->yOffset() ) && ( !m_bResize ) ) + { + double h = sheet->rowFormat( row )->dblHeight(); + row++; + if ( row > KS_rowMax ) + row = KS_rowMax; + if ( ( ev_PosY >= y + h - 2 ) && + ( ev_PosY <= y + h + 1 ) && + !( sheet->rowFormat( row )->isHide() && row == 1 ) ) + m_bResize = true; + y += h; + } + + //if row is hide and it's the first row + //you mustn't resize it. + double tmp2; + int tmpRow = sheet->topRow( ev_PosY - 1, tmp2 ); + if ( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) + m_bResize = false; + + // So he clicked between two rows ? + if ( m_bResize ) + { + // Determine row to resize + double tmp; + m_iResizedRow = sheet->topRow( ev_PosY - 1, tmp ); + if ( !sheet->isProtected() ) + paintSizeIndicator( _ev->pos().y(), true ); + } + else + { + m_bSelection = true; + + double tmp; + int hit_row = sheet->topRow( ev_PosY, tmp ); + if ( hit_row > KS_rowMax ) + return; + + m_iSelectionAnchor = hit_row; + + if ( !m_pView->selectionInfo()->contains( TQPoint(1, hit_row) ) || + !( _ev->button() == Qt::RightButton ) || + !m_pView->selectionInfo()->isRowSelected() ) + { + TQPoint newMarker( 1, hit_row ); + TQPoint newAnchor( KS_colMax, hit_row ); +#ifdef NONCONTIGUOUSSELECTION + if (_ev->state() == ControlButton) + { + m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker)); + } + else +#endif + if (_ev->state() == ShiftButton) + { + m_pView->selectionInfo()->update(newMarker); + } + else + { + m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker)); + } + } + + if ( _ev->button() == Qt::RightButton ) + { + TQPoint p = mapToGlobal( _ev->pos() ); + m_pView->popupRowMenu( p ); + m_bSelection = false; + } + m_pView->updateEditWidget(); + } +} + +void VBorder::mouseReleaseEvent( TQMouseEvent * _ev ) +{ + if ( m_scrollTimer->isActive() ) + m_scrollTimer->stop(); + + m_bMousePressed = false; + + if ( !m_pView->koDocument()->isReadWrite() ) + return; + + Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); + + if ( m_bResize ) + { + // Remove size indicator painted by paintSizeIndicator + TQPainter painter; + painter.begin( m_pCanvas ); + painter.setRasterOp( NotROP ); + painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); + painter.end(); + + int start = m_iResizedRow; + int end = m_iResizedRow; + TQRect rect; + rect.setCoords( 1, m_iResizedRow, KS_colMax, m_iResizedRow ); + if ( m_pView->selectionInfo()->isRowSelected() ) + { + if ( m_pView->selectionInfo()->contains( TQPoint( 1, m_iResizedRow ) ) ) + { + start = m_pView->selectionInfo()->lastRange().top(); + end = m_pView->selectionInfo()->lastRange().bottom(); + rect = m_pView->selectionInfo()->lastRange(); + } + } + + double height = 0.0; + double y = sheet->dblRowPos( m_iResizedRow ); + if ( ev_PosY - y <= 0.0 ) + height = 0.0; + else + height = ev_PosY - y; + + if ( !sheet->isProtected() ) + { + if ( !m_pCanvas->d->view->doc()->undoLocked() ) + { + //just resize + if ( height != 0.0 ) + { + // TODO Stefan: replace this + UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect ); + m_pCanvas->d->view->doc()->addCommand( undo ); + } + } + + for( int i = start; i <= end; i++ ) + { + RowFormat *rl = sheet->nonDefaultRowFormat( i ); + if ( height != 0.0 ) + { + if ( !rl->isHide() ) + rl->setDblHeight( height ); + } + else + { + sheet->hideRow(*m_pView->selectionInfo()); + } + } + + delete m_lSize; + m_lSize = 0; + } + } + else if ( m_bSelection ) + { + TQRect rect = m_pView->selectionInfo()->lastRange(); + + // TODO: please don't remove. Right now it's useless, but it's for a future feature + // Norbert + bool m_frozen = false; + if ( m_frozen ) + { + kdDebug(36001) << "selected: T " << rect.top() << " B " << rect.bottom() << endl; + + int i; + RowFormat * row; + TQValueListhiddenRows; + + for ( i = rect.top(); i <= rect.bottom(); ++i ) + { + row = m_pView->activeSheet()->rowFormat( i ); + if ( row->isHide() ) + { + hiddenRows.append(i); + } + } + + if ( hiddenRows.count() > 0 ) + m_pView->activeSheet()->showRow(*m_pView->selectionInfo()); + } + } + + m_bSelection = false; + m_bResize = false; +} + +void VBorder::equalizeRow( double resize ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + Q_ASSERT( sheet ); + + TQRect selection( m_pView->selectionInfo()->selection() ); + if ( !m_pCanvas->d->view->doc()->undoLocked() ) + { + UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection ); + m_pCanvas->d->view->doc()->addCommand( undo ); + } + RowFormat *rl; + for ( int i = selection.top(); i <= selection.bottom(); i++ ) + { + rl = sheet->nonDefaultRowFormat( i ); + resize = TQMAX( 2.0, resize); + rl->setDblHeight( resize ); + } +} + +void VBorder::mouseDoubleClickEvent(TQMouseEvent*) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() ) + return; + + sheet->adjustRow(*m_pCanvas->selectionInfo()); +} + + +void VBorder::mouseMoveEvent( TQMouseEvent * _ev ) +{ + if ( !m_pView->koDocument()->isReadWrite() ) + return; + + Sheet *sheet = m_pCanvas->activeSheet(); + + if (!sheet) + return; + + double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset(); + double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() ); + + // The button is pressed and we are resizing ? + if ( m_bResize ) + { + if ( !sheet->isProtected() ) + paintSizeIndicator( _ev->pos().y(), false ); + } + // The button is pressed and we are selecting ? + else if ( m_bSelection ) + { + double y; + int row = sheet->topRow( ev_PosY, y ); + if ( row > KS_rowMax ) + return; + + TQPoint newAnchor = m_pView->selectionInfo()->anchor(); + TQPoint newMarker = m_pView->selectionInfo()->marker(); + newMarker.setY( row ); + newAnchor.setY( m_iSelectionAnchor ); + m_pView->selectionInfo()->update(newMarker); + + if ( _ev->pos().y() < 0 ) + m_pCanvas->vertScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItY( ev_PosY ) ); + else if ( _ev->pos().y() > m_pCanvas->height() ) + { + if ( row < KS_rowMax ) + { + RowFormat *rl = sheet->rowFormat( row + 1 ); + y = sheet->dblRowPos( row + 1 ); + m_pCanvas->vertScrollBar()->setValue ((int) (m_pCanvas->d->view->doc()->zoomItY + (ev_PosY + rl->dblHeight()) - dHeight)); + } + } + } + // No button is pressed and the mouse is just moved + else + { + + //What is the internal size of 1 pixel + const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItY( 1 ); + double y; + int tmpRow = sheet->topRow( m_pCanvas->yOffset(), y ); + + while ( y < m_pCanvas->d->view->doc()->unzoomItY( height() ) + m_pCanvas->yOffset() ) + { + double h = sheet->rowFormat( tmpRow )->dblHeight(); + //if col is hide and it's the first column + //you mustn't resize it. + if ( ev_PosY >= y + h - 2 * unzoomedPixel && + ev_PosY <= y + h + unzoomedPixel && + !( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) ) + { + setCursor( splitVCursor ); + return; + } + y += h; + tmpRow++; + } + setCursor( arrowCursor ); + } +} + +void VBorder::doAutoScroll() +{ + if ( !m_bMousePressed ) + { + m_scrollTimer->stop(); + return; + } + + TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); + + if ( pos.y() < 0 || pos.y() > height() ) + { + TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 ); + mouseMoveEvent( event ); + delete event; + } + + //Restart timer + m_scrollTimer->start( 50 ); +} + +void VBorder::wheelEvent( TQWheelEvent* _ev ) +{ + if ( m_pCanvas->vertScrollBar() ) + TQApplication::sendEvent( m_pCanvas->vertScrollBar(), _ev ); +} + + +void VBorder::paintSizeIndicator( int mouseY, bool firstTime ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + TQPainter painter; + painter.begin( m_pCanvas ); + painter.setRasterOp( NotROP ); + + if ( !firstTime ) + painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); + + m_iResizePos = mouseY; + + // Dont make the row have a height < 2 pixel. + int y = m_pCanvas->d->view->doc()->zoomItY( sheet->dblRowPos( m_iResizedRow ) - m_pCanvas->yOffset() ); + if ( m_iResizePos < y + 2 ) + m_iResizePos = y; + + painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos ); + + painter.end(); + + TQString tmpSize; + if ( m_iResizePos != y ) + tmpSize = i18n("Height: %1 %2").arg( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItY( m_iResizePos - y ), + m_pView->doc()->unit() ) ) + .arg( m_pView->doc()->unitName() ); + else + tmpSize = i18n( "Hide Row" ); + + painter.begin( this ); + int len = painter.fontMetrics().width( tmpSize ); + int hei = painter.fontMetrics().height(); + painter.end(); + + if ( !m_lSize ) + { + m_lSize = new TQLabel( m_pCanvas ); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + m_lSize->setGeometry( m_pCanvas->width() - len - 5, + y + 3, len + 2, hei + 2 ); + else + m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 ); + + m_lSize->setAlignment( TQt::AlignVCenter ); + m_lSize->setText( tmpSize ); + m_lSize->setPalette( TQToolTip::palette() ); + m_lSize->show(); + } + else + { + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + m_lSize->setGeometry( m_pCanvas->width() - len - 5, + y + 3, len + 2, hei + 2 ); + else + m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 ); + + m_lSize->setText( tmpSize ); + } +} + +void VBorder::updateRows( int from, int to ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if ( !sheet ) + return; + + int y0 = sheet->rowPos( from, m_pCanvas ); + int y1 = sheet->rowPos( to+1, m_pCanvas ); + update( 0, y0, width(), y1-y0 ); +} + +void VBorder::paintEvent( TQPaintEvent* _ev ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if ( !sheet ) + return; + + TQPainter painter( this ); + TQColor highlightColor = View::highlightColor(); + TQPen pen( TQt::black, 1 ); + painter.setPen( pen ); + // painter.setBackgroundColor( colorGroup().base() ); + + // painter.eraseRect( _ev->rect() ); + + //TQFontMetrics fm = painter.fontMetrics(); + // Matthias Elter: This causes a SEGFAULT in ~TQPainter! + // Only god and the trolls know why ;-) + // bah...took me quite some time to track this one down... + + painter.setClipRect( _ev->rect() ); + + double yPos; + //Get the top row and the current y-position + int y = sheet->topRow( (m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().y() ) + m_pCanvas->yOffset()), yPos ); + //Align to the offset + yPos = yPos - m_pCanvas->yOffset(); + int width = m_pCanvas->d->view->doc()->zoomItX( YBORDER_WIDTH ); + + TQFont normalFont = painter.font(); + if ( m_pCanvas->d->view->doc()->zoom() < 100 ) + { + normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() * + normalFont.pointSizeFloat() ); + } + TQFont boldFont = normalFont; + boldFont.setBold( true ); + + //Loop through the rows, until we are out of range + while ( yPos <= m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().bottom() ) ) + { + bool selected = (m_pView->selectionInfo()->isRowSelected(y)); + bool highlighted = (!selected && m_pView->selectionInfo()->isRowAffected(y)); + + const RowFormat *row_lay = sheet->rowFormat( y ); + int zoomedYPos = m_pCanvas->d->view->doc()->zoomItY( yPos ); + int height = m_pCanvas->d->view->doc()->zoomItY( yPos + row_lay->dblHeight() ) - zoomedYPos; + + if ( selected ) + { + TQBrush fillSelected( highlightColor ); + qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150), + 1, &fillSelected ); + } + else if ( highlighted ) + { + TQBrush fillHighlighted( highlightColor ); + qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150), + 1, &fillHighlighted ); + } + else + { + TQColor c = colorGroup().background(); + TQBrush fill( c ); + qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, c.dark(150), + 1, &fill ); + } + + TQString rowText = TQString::number( y ); + + // Reset painter + painter.setFont( normalFont ); + painter.setPen( colorGroup().text() ); + + if ( selected ) + painter.setPen( colorGroup().highlightedText() ); + else if ( highlighted ) + painter.setFont( boldFont ); + + int len = painter.fontMetrics().width( rowText ); + if (!row_lay->isHide()) + painter.drawText( ( width-len )/2, zoomedYPos + + ( height + painter.fontMetrics().ascent() - + painter.fontMetrics().descent() ) / 2, rowText ); + + yPos += row_lay->dblHeight(); + y++; + } +} + + +void VBorder::focusOutEvent( TQFocusEvent* ) +{ + if ( m_scrollTimer->isActive() ) + m_scrollTimer->stop(); + m_bMousePressed = false; +} + + +/**************************************************************** + * + * HBorder + * + ****************************************************************/ + +HBorder::HBorder( TQWidget *_parent, Canvas *_canvas,View *_view ) + : TQWidget( _parent, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ) +{ + m_pView = _view; + m_pCanvas = _canvas; + m_lSize = 0L; + setBackgroundMode( PaletteButton ); + setMouseTracking( true ); + m_bResize = false; + m_bSelection = false; + m_iSelectionAnchor=1; + m_bMousePressed = false; + + m_scrollTimer = new TQTimer( this ); + connect( m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) ); +} + + +HBorder::~HBorder() +{ + delete m_scrollTimer; +} + +TQSize HBorder::sizeHint() const +{ + return TQSize( 40, 10 ); +} + +void HBorder::mousePressEvent( TQMouseEvent * _ev ) +{ + if (!m_pView->koDocument()->isReadWrite()) + return; + + if ( _ev->button() == Qt::LeftButton ) + m_bMousePressed = true; + + const Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + // We were editing a cell -> save value and get out of editing mode + if ( m_pCanvas->editor() ) + { + m_pCanvas->deleteEditor( true ); // save changes + } + + m_scrollTimer->start( 50 ); + + double ev_PosX; + double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + else + ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + m_bResize = false; + m_bSelection = false; + + // Find the first visible column and the x position of this column. + double x; + + const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 ); + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); + + kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", COL: " << tmpCol << endl; + while ( ev_PosX > x && ( !m_bResize ) ) + { + double w = sheet->columnFormat( tmpCol )->dblWidth(); + + kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", w: " << w << ", COL: " << tmpCol << endl; + + ++tmpCol; + if ( tmpCol > KS_colMax ) + tmpCol = KS_colMax; + //if col is hide and it's the first column + //you mustn't resize it. + + if ( ev_PosX >= x + w - unzoomedPixel && + ev_PosX <= x + w + unzoomedPixel && + !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) ) + { + m_bResize = true; + } + x += w; + } + + //if col is hide and it's the first column + //you mustn't resize it. + double tmp2; + tmpCol = sheet->leftColumn( dWidth - ev_PosX + 1, tmp2 ); + if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) + { + kdDebug() << "No resize: " << tmpCol << ", " << sheet->columnFormat( tmpCol )->isHide() << endl; + m_bResize = false; + } + + kdDebug() << "Resize: " << m_bResize << endl; + } + else + { + int col = sheet->leftColumn( m_pCanvas->xOffset(), x ); + + // Did the user click between two columns? + while ( x < ( dWidth + m_pCanvas->xOffset() ) && ( !m_bResize ) ) + { + double w = sheet->columnFormat( col )->dblWidth(); + col++; + if ( col > KS_colMax ) + col = KS_colMax; + if ( ( ev_PosX >= x + w - unzoomedPixel ) && + ( ev_PosX <= x + w + unzoomedPixel ) && + !( sheet->columnFormat( col )->isHide() && col == 1 ) ) + m_bResize = true; + x += w; + } + + //if col is hide and it's the first column + //you mustn't resize it. + double tmp2; + int tmpCol = sheet->leftColumn( ev_PosX - 1, tmp2 ); + if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) + m_bResize = false; + } + + // So he clicked between two rows ? + if ( m_bResize ) + { + // Determine the column to resize + double tmp; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp ); + // kdDebug() << "RColumn: " << m_iResizedColumn << ", PosX: " << ev_PosX << endl; + + if ( !sheet->isProtected() ) + paintSizeIndicator( _ev->pos().x(), true ); + } + else + { + m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp ); + + if ( !sheet->isProtected() ) + paintSizeIndicator( _ev->pos().x(), true ); + } + + // kdDebug() << "Column: " << m_iResizedColumn << endl; + } + else + { + m_bSelection = true; + + double tmp; + int hit_col = sheet->leftColumn( ev_PosX, tmp ); + if ( hit_col > KS_colMax ) + return; + + m_iSelectionAnchor = hit_col; + + if ( !m_pView->selectionInfo()->contains( TQPoint( hit_col, 1 ) ) || + !( _ev->button() == Qt::RightButton ) || + !m_pView->selectionInfo()->isColumnSelected() ) + { + TQPoint newMarker( hit_col, 1 ); + TQPoint newAnchor( hit_col, KS_rowMax ); +#ifdef NONCONTIGUOUSSELECTION + if (_ev->state() == ControlButton) + { + m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker)); + } + else +#endif + if (_ev->state() == ShiftButton) + { + m_pView->selectionInfo()->update(newMarker); + } + else + { + m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker)); + } + } + + if ( _ev->button() == Qt::RightButton ) + { + TQPoint p = mapToGlobal( _ev->pos() ); + m_pView->popupColumnMenu( p ); + m_bSelection = false; + } + m_pView->updateEditWidget(); + } +} + +void HBorder::mouseReleaseEvent( TQMouseEvent * _ev ) +{ + if ( m_scrollTimer->isActive() ) + m_scrollTimer->stop(); + + m_bMousePressed = false; + + if ( !m_pView->koDocument()->isReadWrite() ) + return; + + Sheet * sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + if ( m_bResize ) + { + double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); + double ev_PosX; + + // Remove size indicator painted by paintSizeIndicator + TQPainter painter; + painter.begin( m_pCanvas ); + painter.setRasterOp( NotROP ); + painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); + painter.end(); + + int start = m_iResizedColumn; + int end = m_iResizedColumn; + TQRect rect; + rect.setCoords( m_iResizedColumn, 1, m_iResizedColumn, KS_rowMax ); + if ( m_pView->selectionInfo()->isColumnSelected() ) + { + if ( m_pView->selectionInfo()->contains( TQPoint( m_iResizedColumn, 1 ) ) ) + { + start = m_pView->selectionInfo()->lastRange().left(); + end = m_pView->selectionInfo()->lastRange().right(); + rect = m_pView->selectionInfo()->lastRange(); + } + } + + double width = 0.0; + double x; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + else + ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + + x = sheet->dblColumnPos( m_iResizedColumn ); + + if ( ev_PosX - x <= 0.0 ) + width = 0.0; + else + width = ev_PosX - x; + + if ( !sheet->isProtected() ) + { + if ( !m_pCanvas->d->view->doc()->undoLocked() ) + { + //just resize + if ( width != 0.0 ) + { + // TODO Stefan: replace this + UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect ); + m_pCanvas->d->view->doc()->addCommand( undo ); + } + } + + for( int i = start; i <= end; i++ ) + { + ColumnFormat *cl = sheet->nonDefaultColumnFormat( i ); + if ( width != 0.0 ) + { + if ( !cl->isHide() ) + cl->setDblWidth( width ); + } + else + { + sheet->hideColumn(*m_pView->selectionInfo()); + } + } + + delete m_lSize; + m_lSize = 0; + } + } + else if ( m_bSelection ) + { + TQRect rect = m_pView->selectionInfo()->lastRange(); + + // TODO: please don't remove. Right now it's useless, but it's for a future feature + // Norbert + bool m_frozen = false; + if ( m_frozen ) + { + kdDebug(36001) << "selected: L " << rect.left() << " R " << rect.right() << endl; + + int i; + ColumnFormat * col; + TQValueListhiddenCols; + + for ( i = rect.left(); i <= rect.right(); ++i ) + { + col = m_pView->activeSheet()->columnFormat( i ); + if ( col->isHide() ) + { + hiddenCols.append(i); + } + } + + if ( hiddenCols.count() > 0 ) + m_pView->activeSheet()->showColumn(*m_pView->selectionInfo()); + } + } + + m_bSelection = false; + m_bResize = false; +} + +void HBorder::equalizeColumn( double resize ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + Q_ASSERT( sheet ); + + TQRect selection( m_pView->selectionInfo()->selection() ); + if ( !m_pCanvas->d->view->doc()->undoLocked() ) + { + UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection ); + m_pCanvas->d->view->doc()->addCommand( undo ); + } + ColumnFormat *cl; + for ( int i = selection.left(); i <= selection.right(); i++ ) + { + cl = sheet->nonDefaultColumnFormat( i ); + resize = TQMAX( 2.0, resize ); + cl->setDblWidth( resize ); + } + +} + +void HBorder::mouseDoubleClickEvent(TQMouseEvent*) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() ) + return; + + sheet->adjustColumn(*m_pCanvas->selectionInfo()); +} + +void HBorder::mouseMoveEvent( TQMouseEvent * _ev ) +{ + if ( !m_pView->koDocument()->isReadWrite() ) + return; + + Sheet *sheet = m_pCanvas->activeSheet(); + + if (!sheet) + return; + + double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() ); + double ev_PosX; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + else + ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset(); + + // The button is pressed and we are resizing ? + if ( m_bResize ) + { + if ( !sheet->isProtected() ) + paintSizeIndicator( _ev->pos().x(), false ); + } + // The button is pressed and we are selecting ? + else if ( m_bSelection ) + { + double x; + int col = sheet->leftColumn( ev_PosX, x ); + + if ( col > KS_colMax ) + return; + + TQPoint newMarker = m_pView->selectionInfo()->marker(); + TQPoint newAnchor = m_pView->selectionInfo()->anchor(); + newMarker.setX( col ); + newAnchor.setX( m_iSelectionAnchor ); + m_pView->selectionInfo()->update(newMarker); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + if ( _ev->pos().x() < width() - m_pCanvas->width() ) + { + ColumnFormat *cl = sheet->columnFormat( col + 1 ); + x = sheet->dblColumnPos( col + 1 ); + m_pCanvas->horzScrollBar()->setValue ( m_pCanvas->horzScrollBar()->maxValue() - (int) + (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() ))); + } + else if ( _ev->pos().x() > width() ) + m_pCanvas->horzScrollBar()->setValue( m_pCanvas->horzScrollBar()->maxValue() - m_pCanvas->d->view->doc()->zoomItX( ev_PosX - dWidth + m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() ) ) ); + } + else + { + if ( _ev->pos().x() < 0 ) + m_pCanvas->horzScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItX( ev_PosX ) ); + else if ( _ev->pos().x() > m_pCanvas->width() ) + { + if ( col < KS_colMax ) + { + ColumnFormat *cl = sheet->columnFormat( col + 1 ); + x = sheet->dblColumnPos( col + 1 ); + m_pCanvas->horzScrollBar()->setValue ((int) + (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - dWidth)); + } + } + } + + } + // No button is pressed and the mouse is just moved + else + { + //What is the internal size of 1 pixel + const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 ); + double x; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); + + while ( ev_PosX > x ) + { + double w = sheet->columnFormat( tmpCol )->dblWidth(); + ++tmpCol; + + //if col is hide and it's the first column + //you mustn't resize it. + if ( ev_PosX >= x + w - unzoomedPixel && + ev_PosX <= x + w + unzoomedPixel && + !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) ) + { + setCursor( splitHCursor ); + return; + } + x += w; + } + setCursor( arrowCursor ); + } + else + { + int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x ); + + while ( x < m_pCanvas->d->view->doc()->unzoomItY( width() ) + m_pCanvas->xOffset() ) + { + double w = sheet->columnFormat( tmpCol )->dblWidth(); + //if col is hide and it's the first column + //you mustn't resize it. + if ( ev_PosX >= x + w - unzoomedPixel && + ev_PosX <= x + w + unzoomedPixel && + !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) ) + { + setCursor( splitHCursor ); + return; + } + x += w; + tmpCol++; + } + setCursor( arrowCursor ); + } + } +} + +void HBorder::doAutoScroll() +{ + if ( !m_bMousePressed ) + { + m_scrollTimer->stop(); + return; + } + + TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); + + if ( pos.x() < 0 || pos.x() > width() ) + { + TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 ); + mouseMoveEvent( event ); + delete event; + } + + //Restart timer + m_scrollTimer->start( 50 ); +} + +void HBorder::wheelEvent( TQWheelEvent* _ev ) +{ + if ( m_pCanvas->horzScrollBar() ) + TQApplication::sendEvent( m_pCanvas->horzScrollBar(), _ev ); +} + +void HBorder::resizeEvent( TQResizeEvent* _ev ) +{ + // workaround to allow horizontal resizing and zoom changing when sheet + // direction and interface direction don't match (e.g. an RTL sheet on an + // LTR interface) + if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() ) + { + int dx = _ev->size().width() - _ev->oldSize().width(); + scroll(dx, 0); + } + else if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() ) + { + int dx = _ev->size().width() - _ev->oldSize().width(); + scroll(-dx, 0); + } +} + +void HBorder::paintSizeIndicator( int mouseX, bool firstTime ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if (!sheet) + return; + + TQPainter painter; + painter.begin( m_pCanvas ); + painter.setRasterOp( NotROP ); + + if ( !firstTime ) + painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + m_iResizePos = mouseX + m_pCanvas->width() - width(); + else + m_iResizePos = mouseX; + + // Dont make the column have a width < 2 pixels. + int x = m_pCanvas->d->view->doc()->zoomItX( sheet->dblColumnPos( m_iResizedColumn ) - m_pCanvas->xOffset() ); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + x = m_pCanvas->width() - x; + + if ( m_iResizePos > x - 2 ) + m_iResizePos = x; + } + else + { + if ( m_iResizePos < x + 2 ) + m_iResizePos = x; + } + + painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() ); + + painter.end(); + + TQString tmpSize; + if ( m_iResizePos != x ) + tmpSize = i18n("Width: %1 %2") + .arg( TDEGlobal::locale()->formatNumber( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItX( (sheet->layoutDirection()==Sheet::RightToLeft) ? x - m_iResizePos : m_iResizePos - x ), + m_pView->doc()->unit() ))) + .arg( m_pView->doc()->unitName() ); + else + tmpSize = i18n( "Hide Column" ); + + painter.begin( this ); + int len = painter.fontMetrics().width( tmpSize ); + int hei = painter.fontMetrics().height(); + painter.end(); + + if ( !m_lSize ) + { + m_lSize = new TQLabel( m_pCanvas ); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 ); + else + m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 ); + + m_lSize->setAlignment( TQt::AlignVCenter ); + m_lSize->setText( tmpSize ); + m_lSize->setPalette( TQToolTip::palette() ); + m_lSize->show(); + } + else + { + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 ); + else + m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 ); + + m_lSize->setText( tmpSize ); + } +} + +void HBorder::updateColumns( int from, int to ) +{ + Sheet *sheet = m_pCanvas->activeSheet(); + if ( !sheet ) + return; + + int x0 = sheet->columnPos( from, m_pCanvas ); + int x1 = sheet->columnPos( to+1, m_pCanvas ); + update( x0, 0, x1-x0, height() ); +} + +void HBorder::paintEvent( TQPaintEvent* _ev ) +{ + Sheet * sheet = m_pCanvas->activeSheet(); + if ( !sheet ) + return; + + TQColor highlightColor = View::highlightColor(); + TQPainter painter( this ); + TQPen pen( TQt::black, 1 ); + painter.setPen( pen ); + painter.setBackgroundColor( white ); + + painter.setClipRect( _ev->rect() ); + + // painter.eraseRect( _ev->rect() ); + + //TQFontMetrics fm = painter.fontMetrics(); + // Matthias Elter: This causes a SEGFAULT in ~TQPainter! + // Only god and the trolls know why ;-) + // bah...took me quite some time to track this one down... + + double xPos; + int x; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + //Get the left column and the current x-position + x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( width() ) - m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos ); + //Align to the offset + xPos = m_pCanvas->d->view->doc()->unzoomItX( width() ) - xPos + m_pCanvas->xOffset(); + } + else + { + //Get the left column and the current x-position + x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos ); + //Align to the offset + xPos = xPos - m_pCanvas->xOffset(); + } + + int height = m_pCanvas->d->view->doc()->zoomItY( TQFont(painter.font()).pointSizeFloat() + 5 ); + + TQFont normalFont = painter.font(); + if ( m_pCanvas->d->view->doc()->zoom() < 100 ) + { + normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() * + normalFont.pointSizeFloat() ); + } + TQFont boldFont = normalFont; + boldFont.setBold( true ); + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + if ( x > KS_colMax ) + x = KS_colMax; + + xPos -= sheet->columnFormat( x )->dblWidth(); + + //Loop through the columns, until we are out of range + while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) ) + { + bool selected = (m_pView->selectionInfo()->isColumnSelected(x)); + bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x)); + + const ColumnFormat * col_lay = sheet->columnFormat( x ); + int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos ); + int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos; + + if ( selected ) + { + TQBrush fillSelected( highlightColor ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150), + 1, &fillSelected ); + } + else if ( highlighted ) + { + TQBrush fillHighlighted( highlightColor ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150), + 1, &fillHighlighted ); + } + else + { + TQColor c = colorGroup().background(); + TQBrush fill( c ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150), + 1, &fill ); + } + + // Reset painter + painter.setFont( normalFont ); + painter.setPen( colorGroup().text() ); + + if ( selected ) + painter.setPen( colorGroup().highlightedText() ); + else if ( highlighted ) + painter.setFont( boldFont ); + if ( !m_pView->activeSheet()->getShowColumnNumber() ) + { + TQString colText = Cell::columnName( x ); + int len = painter.fontMetrics().width( colText ); + if ( !col_lay->isHide() ) + painter.drawText( zoomedXPos + ( width - len ) / 2, + ( height + painter.fontMetrics().ascent() - + painter.fontMetrics().descent() ) / 2, colText ); + } + else + { + TQString tmp; + int len = painter.fontMetrics().width( tmp.setNum(x) ); + if (!col_lay->isHide()) + painter.drawText( zoomedXPos + ( width - len ) / 2, + ( height + painter.fontMetrics().ascent() - + painter.fontMetrics().descent() ) / 2, + tmp.setNum(x) ); + } + xPos += col_lay->dblWidth(); + --x; + } + } + else + { + //Loop through the columns, until we are out of range + while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) ) + { + bool selected = (m_pView->selectionInfo()->isColumnSelected(x)); + bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x)); + + const ColumnFormat *col_lay = sheet->columnFormat( x ); + int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos ); + int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos; + + if ( selected ) + { + TQBrush fillSelected( highlightColor ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(), + 1, &fillSelected ); + } + else if ( highlighted ) + { + TQBrush fillHighlighted( highlightColor ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(), + 1, &fillHighlighted ); + } + else + { + TQColor c = colorGroup().background(); + TQBrush fill( c ); + qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150), + 1, &fill ); + } + + // Reset painter + painter.setFont( normalFont ); + painter.setPen( colorGroup().text() ); + + if ( selected ) + painter.setPen( colorGroup().highlightedText() ); + else if ( highlighted ) + painter.setFont( boldFont ); + if ( !m_pView->activeSheet()->getShowColumnNumber() ) + { + TQString colText = Cell::columnName( x ); + int len = painter.fontMetrics().width( colText ); + if (!col_lay->isHide()) + painter.drawText( zoomedXPos + ( width - len ) / 2, + ( height + painter.fontMetrics().ascent() - + painter.fontMetrics().descent() ) / 2, colText ); + } + else + { + TQString tmp; + int len = painter.fontMetrics().width( tmp.setNum(x) ); + if (!col_lay->isHide()) + painter.drawText( zoomedXPos + ( width - len ) / 2, + ( height + painter.fontMetrics().ascent() - + painter.fontMetrics().descent() ) / 2, + tmp.setNum(x) ); + } + xPos += col_lay->dblWidth(); + ++x; + } + } +} + + +void HBorder::focusOutEvent( TQFocusEvent* ) +{ + if ( m_scrollTimer->isActive() ) + m_scrollTimer->stop(); + m_bMousePressed = false; +} + +/**************************************************************** + * + * ToolTip + * + ****************************************************************/ + +ToolTip::ToolTip( Canvas* canvas ) + : TQToolTip( canvas ), m_canvas( canvas ) +{ +} + +// find the label for the tip +// this is a hack of course, because it's not available from TQToolTip +TQLabel *tip_findLabel() +{ + TQWidgetList *list = TQApplication::allWidgets(); + TQWidgetListIt it( *list ); + TQWidget * w; + while ( (w=it.current()) != 0 ) + { + if(w->isA("TQTipLabel")) + return static_cast(w); + ++it; + } + delete list; + return 0; +} + +void ToolTip::maybeTip( const TQPoint& p ) +{ + Sheet *sheet = m_canvas->activeSheet(); + if ( !sheet ) + return; + + // Over which cell is the mouse ? + double ypos, xpos; + double dwidth = m_canvas->doc()->unzoomItX( m_canvas->width() ); + int col; + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + col = sheet->leftColumn( (dwidth - m_canvas->doc()->unzoomItX( p.x() ) + + m_canvas->xOffset()), xpos ); + else + col = sheet->leftColumn( (m_canvas->doc()->unzoomItX( p.x() ) + + m_canvas->xOffset()), xpos ); + + + int row = sheet->topRow( (m_canvas->doc()->unzoomItY( p.y() ) + + m_canvas->yOffset()), ypos ); + + const Cell* cell = sheet->visibleCellAt( col, row ); + if ( !cell ) + return; + +#if 0 + // Quick cut + if( cell->strOutText().isEmpty() ) + return; +#endif + // displayed tool tip, which has the following priorities: + // - cell content if the cell dimension is too small + // - cell comment + // - hyperlink + TQString tipText; + TQString comment = cell->format()->comment( col, row ); + + // If cell is too small, show the content + if ( cell->testFlag( Cell::Flag_CellTooShortX ) || + cell->testFlag( Cell::Flag_CellTooShortY ) ) + { + tipText = cell->strOutText(); + } + + // Show hyperlink, if any + if ( tipText.isEmpty() ) + { + tipText = cell->link(); + } + + // Nothing to display, bail out + if ( tipText.isEmpty() && comment.isEmpty() ) + return; + + // Cut if the tip is ridiculously long + const unsigned maxLen = 256; + if ( tipText.length() > maxLen ) + tipText = tipText.left(maxLen).append("..."); + + // Determine position and width of the current cell. + double u = cell->dblWidth( col ); + double v = cell->dblHeight( row ); + + // Special treatment for obscured cells. + if ( cell->isObscured() && cell->isPartOfMerged() ) + { + cell = cell->obscuringCells().first(); + const int moveX = cell->column(); + const int moveY = cell->row(); + + // Use the obscuring cells dimensions + u = cell->dblWidth( moveX ); + v = cell->dblHeight( moveY ); + xpos = sheet->dblColumnPos( moveX ); + ypos = sheet->dblRowPos( moveY ); + } + + // Get the cell dimensions + TQRect marker; + bool insideMarker = false; + + if ( sheet->layoutDirection()==Sheet::RightToLeft ) + { + KoRect unzoomedMarker( dwidth - u - xpos + m_canvas->xOffset(), + ypos - m_canvas->yOffset(), + u, + v ); + + marker = m_canvas->doc()->zoomRect( unzoomedMarker ); + insideMarker = marker.contains( p ); + } + else + { + KoRect unzoomedMarker( xpos - m_canvas->xOffset(), + ypos - m_canvas->yOffset(), + u, + v ); + + marker = m_canvas->doc()->zoomRect( unzoomedMarker ); + insideMarker = marker.contains( p ); + } + + // No use if mouse is somewhere else + if ( !insideMarker ) + return; + + // Find the tipLabel + // NOTE: if we failed, check again when the tip is shown already + TQLabel* tipLabel = tip_findLabel(); + + // Ensure that it is plain text + // Not funny if (intentional or not) appears as hyperlink + if ( tipLabel ) + tipLabel->setTextFormat( TQt::PlainText ); + + TQFontMetrics fm = tipLabel ? tipLabel->fontMetrics() : m_canvas->fontMetrics(); + const TQRect r( 0, 0, 200, -1 ); + // Wrap the text if too long + if ( tipText.length() > 16 ) + { + KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, tipText ); + tipText = wrap->wrappedString(); + delete wrap; + } + // Wrap the comment if too long + if ( comment.length() > 16 ) + { + KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, comment ); + comment = wrap->wrappedString(); + delete wrap; + } + + // Show comment, if any + if ( tipText.isEmpty() ) + { + tipText = comment; + } + else if ( !comment.isEmpty() ) + { + //Add 2 extra lines and a text, when both should be in the tooltip + if ( !comment.isEmpty() ) + comment = "\n\n" + i18n("Comment:") + "\n" + comment; + + tipText += comment; + } + + // Now we shows the tip + tip( marker, tipText ); + + // Here we try to find the tip label again + // Reason: the previous tip_findLabel might fail if no tip has ever shown yet + if ( !tipLabel ) + { + tipLabel = tip_findLabel(); + if( tipLabel ) + tipLabel->setTextFormat( TQt::PlainText ); + } + +} + +#include "kspread_canvas.moc" diff --git a/kspread/kspread_cell.cc b/kspread/kspread_cell.cc deleted file mode 100644 index fca76bbe..00000000 --- a/kspread/kspread_cell.cc +++ /dev/null @@ -1,7348 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2006 Stefan Nikolaus - Copyright 2005 Raphael Langerhorst - Copyright 2004-2005 Tomas Mecir - Copyright 2004-2006 Inge Wallin - Copyright 1999-2002,2004,2005 Laurent Montel - Copyright 2002-2005 Ariya Hidayat - Copyright 2001-2003 Philipp Mueller - Copyright 2002-2003 Norbert Andres - Copyright 2003 Reinhart Geiser - Copyright 2003-2005 Meni Livne - Copyright 2003 Peter Simonsson - Copyright 1999-2002 David Faure - Copyright 2000-2002 Werner Trobin - Copyright 1999,2002 Harri Porten - Copyright 2002 John Dailey - Copyright 1998-2000 Torben Weis - Copyright 2000 Bernd Wuebben - Copyright 2000 Simon Hausmann - Copyright 1999 Michael Reiher - Copyright 1999 Boris Wedl - Copyright 1998-1999 Reginald Stadlbauer - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include "kspread_canvas.h" -#include "kspread_condition.h" -#include "kspread_doc.h" -#include "kspread_format.h" -#include "kspread_global.h" -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_util.h" -#include "ksploadinginfo.h" -#include "kspread_genvalidationstyle.h" -#include "kspread_locale.h" -#include "kspread_value.h" -#include "kspread_view.h" -#include "kspread_value.h" -#include "formula.h" -#include "selection.h" -#include "valueconverter.h" -#include "valueformatter.h" -#include "valueparser.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include - -using namespace KSpread; - -#define BORDER_SPACE 1 - - -/** - * A pointer to the decimal separator - */ - -namespace Cell_LNS -{ - TQChar decimal_point = '\0'; -} - -using namespace Cell_LNS; - - -// Some variables are placed in Cell::Extra because normally they're -// not required in simple case of cell(s). For example, most plain -// text cells don't need to store information about spanned columns -// and rows, as this is only the case with merged cells. -// -// When the cell is getting complex (e.g. merged with other cells, -// contains rich text, has validation criteria, etc), this Cell::Extra -// is allocated by Cell::Private and starts to be -// available. Otherwise, it won't exist at all. - -class Cell::Extra -{ -public: - Extra() {} - - // Not empty when the cell holds a link - TQString link; - - // Number of cells explicitly merged by the user in X and Y directions. - int mergedXCells; - int mergedYCells; - - // Number of additional cells. - int extraXCells; - int extraYCells; - - // If this cell overlaps other cells, then we have the cells width and - // height stored here. These values do not mean anything unless - // extraXCells and/or extraYCells are different from 0. - double extraWidth; - double extraHeight; - - // A list of cells that obscure this one. - // If this list is not empty, then this cell is obscured by another - // enlarged object. This means that we have to call this object in order - // of painting it for example instead of painting 'this'. - // - // FIXME (comment): If the list consists of more than one obscuring - // element, then is there an order between them that - // is important? - TQValueList obscuringCells; - - // If non-NULL, contains a pointer to a condition or a validity test. - Conditions *conditions; - Validity *validity; - - // Store the number of line when multirow is used (default is 0) - int nbLines; - -private: - // Don't allow implicit copy. - Extra& operator=( const Extra& ); -}; - - -class Cell::Private -{ -public: - - Private(); - ~Private(); - -public: - - // This cell's row and column. If either of them is 0, this is the - // default cell and its row/column can not be determined. Note that - // in the isDefault() method, only column is tested. - int row; - int column; - - // Value of the cell, either typed by user or as result of formula - Value value; - - // Holds the user's input. - // - // FIXME: - // Eventually, we'll want to get rid of strText and generate - // user's input on-the-fly. Then, for normal cells, we'll generate - // this string using converter()->asString - // (value()). - // - // Here the problem is, that strText also holds the formula - - // we'll need to provide some method to generate it from the - // parsed version, created in KSpread::Formula. Hence, we won't be - // able to get rid of strText until we switch to the new formula - // parser and until we write some method that re-generates the - // input formula... - // - // Alternately, we can keep using strText for formulas and - // generate it dynamically for static cells... - // - // /Tomas - // - TQString strText; - - // This is the text we want to display. Not necessarily the same - // as strText, e.g. strText="1" and strOutText="1.00" Also holds - // value that we got from calculation, formerly known as - // strFormulaOut - TQString strOutText; - - // the Formula object for the cell - KSpread::Formula *formula; - - // Position and dimension of displayed text. - // FIXME (comment): Which coordinate system? pixels? mm/cm? zoom? - double textX; - double textY; - double textWidth; - double textHeight; - - // result of "fm.ascent()" in makeLayout. used in offsetAlign. - int fmAscent; - - // Pointers to neighboring cells. - // FIXME (comment): Which order? - Cell *nextCell; - Cell *previousCell; - - bool hasExtra() const { return (cellExtra != 0); }; - Extra *extra(); - - Format *format; - TQ_UINT32 flags; - -private: - // "Extra stuff", see explanation for Cell::Extra. - Extra *cellExtra; -}; - - -Cell::Private::Private() -{ - // Some basic data. - row = 0; - column = 0; - value = Value::empty(); - formula = 0; - - // Formatting - textX = 0.0; - textY = 0.0; - textWidth = 0.0; - textHeight = 0.0; - fmAscent = 0; - - nextCell = 0; - previousCell = 0; - - // Default is to not have the "extra" stuff in a cell. - cellExtra = 0; - format = 0; - flags = 0; -} - - -Cell::Private::~Private() -{ - delete cellExtra; - delete formula; -} - - -Cell::Extra* Cell::Private::extra() -{ - if ( !cellExtra ) { - cellExtra = new Extra; - cellExtra->conditions = 0; - cellExtra->validity = 0; - - cellExtra->mergedXCells = 0; - cellExtra->mergedYCells = 0; - cellExtra->extraXCells = 0; - cellExtra->extraYCells = 0; - cellExtra->extraWidth = 0.0; - cellExtra->extraHeight = 0.0; - cellExtra->nbLines = 0; -// cellExtra->highlight = TQColor(0,0,0); - } - - return cellExtra; -} - - -/***************************************************************************** - * - * Cell - * - *****************************************************************************/ - - -Cell::Cell( Sheet * _sheet, int _column, int _row ) -{ - d = new Private; - d->row = _row; - d->column = _column; - d->format = new Format(_sheet, _sheet->doc()->styleManager()->defaultStyle()); - d->format->setCell(this); - clearAllErrors(); -} - - -Cell::Cell( Sheet * _sheet, Style * _style, int _column, int _row ) -{ - d = new Private; - d->row = _row; - d->column = _column; - d->format = new Format( _sheet, _style ); - d->format->setCell(this); - - clearAllErrors(); -} - -Format* Cell::format() const -{ - return d->format; -} - -// Return the sheet that this cell belongs to. -Sheet * Cell::sheet() const -{ - return d->format->sheet(); -} - -// Return true if this is the default cell. -bool Cell::isDefault() const -{ - return ( d->column == 0 ); -} - -// Return the row number of this cell. -int Cell::row() const -{ - // Make sure this isn't called for the default cell. This assert - // can save you (could have saved me!) the hassle of some very - // obscure bugs. - - if ( isDefault() ) - { - kdWarning(36001) << "Error: Calling Cell::row() for default cell" << endl; - return 0; - } - - return d->row; -} - - -// Return the column number of this cell. -// -int Cell::column() const -{ - // Make sure this isn't called for the default cell. This assert - // can save you (could have saved me!) the hassle of some very - // obscure bugs. - if ( isDefault() ) - { - kdWarning(36001) << "Error: Calling Cell::column() for default cell" << endl; - return 0; - } - return d->column; -} - - -// Return the name of this cell, i.e. the string that the user would -// use to reference it. Example: A1, BZ16 -// -TQString Cell::name() const -{ - return name( d->column, d->row ); -} - - -// Return the name of any cell given by (col, row). -// -TQString Cell::name( int col, int row ) -{ - return columnName( col ) + TQString::number( row ); -} - - -// Return the name of this cell, including the sheet name. -// Example: sheet1!A5 -// -TQString Cell::fullName() const -{ - return fullName( sheet(), d->column, d->row ); -} - - -// Return the full name of any cell given a sheet and (col, row). -// -TQString Cell::fullName( const Sheet* s, int col, int row ) -{ - return s->sheetName() + "!" + name( col, row ); -} - - -// Return the symbolic name of the column of this cell. Examples: A, BB. -// -TQString Cell::columnName() const -{ - return columnName( d->column ); -} - -TDELocale* Cell::locale() const -{ - return d->format->sheet()->doc()->locale(); -} - -// Return the symbolic name of any column. -// -TQString Cell::columnName( uint column ) -{ - TQString str; - unsigned digits = 1; - unsigned offset = 0; - - column--; - - if( column > 4058115285U ) return TQString("@@@"); - - for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ ) - offset += limit; - - for( unsigned c = column - offset; digits; --digits, c/=26 ) - str.prepend( TQChar( 'A' + (c%26) ) ); - - return str; -} - - -// Return true if this cell is a formula. -// -bool Cell::isFormula() const -{ - return d->strText[0] == '='; -} - - -// Return the input text of this cell. This could, for instance, be a -// formula. -// -// FIXME: These two functions are inconsistently named. It should be -// either text() and outText() or strText() and strOutText(). -// -TQString Cell::text() const -{ - return d->strText; -} - - -// Return the out text, i.e. the text that is visible in the cells -// square when shown. This could, for instance, be the calculated -// result of a formula. -// -TQString Cell::strOutText() const -{ - return d->strOutText; -} - -Formula *Cell::formula () const -{ - return d->formula; -} - - -// Return the value of this cell. -// -const Value Cell::value() const -{ - return d->value; -} - - -// Set the value of this cell. It also clears all errors if the value -// itself is not an error. -// -// In addition to this, it calculates the outstring and sets the dirty -// flags so that a redraw is forced. -// -void Cell::setValue( const Value& v ) -{ - if (v.type() != Value::Error) - clearAllErrors(); - - //If the value has not changed then we don't need to do anything - //(ie. no need to relayout, update dependant cells etc.), - //unless this cell contains a formula, in which case its dependancies might have changed - //even though the value has not. For example, if this cell was previously empty (and its value is - //therefore empty) and a new dependency upon an empty cell has been added. The new value would still - //be empty, but the dependencies need to be updated (via the call to valueChanged() below). - if ( ( d->value == v ) && ( !isFormula() ) ) - return; - - d->value = v; - - setFlag(Flag_LayoutDirty); - setFlag(Flag_TextFormatDirty); - - // Format and set the outText. - setOutputText(); - - // Set the displayed text, if we hold an error value. - if (d->value.type() == Value::Error) - d->strOutText = d->value.errorMessage (); - - // Value of the cell has changed - trigger necessary actions - valueChanged (); - - if ( !format()->sheet()->isLoading() ) - format()->sheet()->setRegionPaintDirty(cellRect()); -} - -void Cell::setCellValue (const Value &v, FormatType fmtType, const TQString &txt) -{ - if ( !txt.isNull() ) - { - d->strText = txt; - if ( isFormula() ) - makeFormula(); - } - else if ( !isFormula() ) - d->strText = sheet()->doc()->converter()->asString (v).asString(); - if (fmtType != No_format) - format()->setFormatType (fmtType); - setValue (v); -} - -// FIXME: Continue commenting and cleaning here (ingwa) - - -Cell* Cell::previousCell() const -{ - return d->previousCell; -} - -Cell* Cell::nextCell() const -{ - return d->nextCell; -} - -void Cell::setPreviousCell( Cell* c ) -{ - d->previousCell = c; -} - -void Cell::setNextCell( Cell* c ) -{ - d->nextCell = c; -} - -Validity* Cell::getValidity( int newStruct ) -{ - if ( (!newStruct) && (!d->hasExtra())) - //we don't have validity struct and we don't want one - return 0; - - if( ( d->extra()->validity == 0 ) && ( newStruct == -1 ) ) - d->extra()->validity = new Validity; - return d->extra()->validity; -} - -void Cell::removeValidity() -{ - if (!d->hasExtra()) - return; - - delete d->extra()->validity; - d->extra()->validity = 0; -} - - -void Cell::copyFormat( const int column , const int row ) -{ - const Cell * cell = format()->sheet()->cellAt( column , row ); - - copyFormat( cell ); -} - -void Cell::copyFormat( const Cell* cell ) -{ - - Q_ASSERT(cell); - - d->value.setFormat(cell->d->value.format()); - format()->copy(*(cell->format())); - - /*format()->setAlign( cell->format()->align( _column, _row ) ); - format()->setAlignY( cell->format()->alignY( _column, _row ) ); - format()->setTextFont( cell->format()->textFont( _column, _row ) ); - format()->setTextColor( cell->format()->textColor( _column, _row ) ); - format()->setBgColor( cell->bgColor( _column, _row) ); - setLeftBorderPen( cell->leftBorderPen( _column, _row ) ); - setTopBorderPen( cell->topBorderPen( _column, _row ) ); - setBottomBorderPen( cell->bottomBorderPen( _column, _row ) ); - setRightBorderPen( cell->rightBorderPen( _column, _row ) ); - format()->setFallDiagonalPen( cell->format()->fallDiagonalPen( _column, _row ) ); - format()->setGoUpDiagonalPen( cell->format()->goUpDiagonalPen( _column, _row ) ); - format()->setBackGroundBrush( cell->backGroundBrush( _column, _row) ); - format()->setPrecision( cell->format()->precision( _column, _row ) ); - format()->setPrefix( cell->format()->prefix( _column, _row ) ); - format()->setPostfix( cell->format()->postfix( _column, _row ) ); - format()->setFloatFormat( cell->format()->floatFormat( _column, _row ) ); - format()->setFloatColor( cell->format()->floatColor( _column, _row ) ); - format()->setMultiRow( cell->format()->multiRow( _column, _row ) ); - format()->setVerticalText( cell->format()->verticalText( _column, _row ) ); - format()->setDontPrintText( cell->format()->getDontprintText(_column, _row ) ); - format()->setNotProtected( cell->format()->notProtected(_column, _row ) ); - format()->setHideAll(cell->format()->isHideAll(_column, _row ) ); - format()->setHideFormula(cell->format()->isHideFormula(_column, _row ) ); - format()->setIndent( cell->format()->getIndent(_column, _row ) ); - format()->setAngle( cell->format()->getAngle(_column, _row) ); - format()->setFormatType( cell->format()->getFormatType(_column, _row) ); - Format::Currency c; - if ( cell->format()->currencyInfo( c ) ) - format()->setCurrency( c );*/ - - TQValueList conditionList = cell->conditionList(); - if (d->hasExtra()) - delete d->extra()->conditions; - if ( cell->d->hasExtra() && cell->d->extra()->conditions ) - setConditionList( conditionList ); - else - if (d->hasExtra()) - d->extra()->conditions = 0; - - /*format()->setComment( cell->format()->comment( _column, _row ) );*/ -} - -void Cell::copyAll( Cell *cell ) -{ - Q_ASSERT( !isDefault() ); // trouble ahead... - copyFormat( cell ); - copyContent( cell ); -} - -void Cell::copyContent( const Cell* cell ) -{ - Q_ASSERT( !isDefault() ); // trouble ahead... - - if (cell->isFormula() && cell->column() > 0 && cell->row() > 0) - { - // change all the references, e.g. from A1 to A3 if copying - // from e.g. B2 to B4 - TQString d = cell->encodeFormula(); - setCellText( cell->decodeFormula( d ) ); - } - else - setCellText( cell->text() ); - -} - -void Cell::defaultStyle() -{ - format()->defaultStyleFormat(); - - if (!d->hasExtra()) - return; - - if ( d->extra()->conditions ) - { - delete d->extra()->conditions; - d->extra()->conditions = 0; - } - - delete d->extra()->validity; - d->extra()->validity = 0L; -} - - -// Merge a number of cells, i.e. make this cell obscure a number of -// other cells. If _x and _y == 0, then the merging is removed. - -void Cell::mergeCells( int _col, int _row, int _x, int _y ) -{ - // Start by unobscuring the cells that we obscure right now - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; - for ( int x = _col; x <= _col + extraXCells; ++x ) { - for ( int y = _row; y <= _row + extraYCells; ++y ) { - if ( x != _col || y != _row ) - format()->sheet()->nonDefaultCell( x, y )->unobscure(this); - } - } - - // If no merging, then remove all traces, and return. - if ( _x == 0 && _y == 0 ) { - clearFlag( Flag_Merged ); - if (d->hasExtra()) { - d->extra()->extraXCells = 0; - d->extra()->extraYCells = 0; - d->extra()->extraWidth = 0.0; - d->extra()->extraHeight = 0.0; - d->extra()->mergedXCells = 0; - d->extra()->mergedYCells = 0; - } - - // Refresh the layout - setFlag( Flag_LayoutDirty ); - return; - } - - // At this point, we know that we will merge some cells. - setFlag(Flag_Merged); - d->extra()->extraXCells = _x; - d->extra()->extraYCells = _y; - d->extra()->mergedXCells = _x; - d->extra()->mergedYCells = _y; - - // Obscure the cells - for ( int x = _col; x <= _col + _x; ++x ) { - for ( int y = _row; y <= _row + _y; ++y ) { - if ( x != _col || y != _row ) - format()->sheet()->nonDefaultCell( x, y )->obscure( this, true ); - } - } - - // Refresh the layout - setFlag( Flag_LayoutDirty ); -} - -void Cell::move( int col, int row ) -{ - setLayoutDirtyFlag(); - setCalcDirtyFlag(); - setDisplayDirtyFlag(); - - //int ex = extraXCells(); - //int ey = d->extra()->extraYCells(); - - if (d->hasExtra()) - d->extra()->obscuringCells.clear(); - - // Unobscure the objects we obscure right now - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; - for( int x = d->column; x <= d->column + extraXCells; ++x ) - for( int y = d->row; y <= d->row + extraYCells; ++y ) - if ( x != d->column || y != d->row ) - { - Cell *cell = format()->sheet()->nonDefaultCell( x, y ); - cell->unobscure(this); - } - - d->column = col; - d->row = row; - - if (d->hasExtra()) - { - // d->extra()->extraXCells = 0; - // d->extra()->extraYCells = 0; - d->extra()->mergedXCells = 0; - d->extra()->mergedYCells = 0; - } - - // Cell value has been changed (because we're another cell now). - valueChanged (); -} - -void Cell::setLayoutDirtyFlag( bool format ) -{ - setFlag( Flag_LayoutDirty ); - if ( format ) - setFlag( Flag_TextFormatDirty ); - - if (!d->hasExtra()) - return; - - TQValueList::iterator it = d->extra()->obscuringCells.begin(); - TQValueList::iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - (*it)->setLayoutDirtyFlag( format ); - } -} - -bool Cell::needsPrinting() const -{ - if ( isDefault() ) - return false; - - if ( !d->strText.stripWhiteSpace().isEmpty() ) { - return true; - } - - // Cell borders? - if ( format()->hasProperty( Format::PTopBorder ) - || format()->hasProperty( Format::PLeftBorder ) - || format()->hasProperty( Format::PRightBorder ) - || format()->hasProperty( Format::PBottomBorder ) - || format()->hasProperty( Format::PFallDiagonal ) - || format()->hasProperty( Format::PGoUpDiagonal ) ) { - return true; - } - - // Background color or brush? - if ( format()->hasProperty( Format::PBackgroundBrush ) ) { - - const TQBrush& brush=backGroundBrush(column(),row()); - - //Only brushes that are visible (ie. they have a brush style and are not white) - //need to be drawn - if ( (brush.style() != TQt::NoBrush) && - (brush.color() != TQt::white || brush.pixmap()) ) - return true; - - } - - if ( format()->hasProperty( Format::PBackgroundColor ) ) { - kdDebug() << "needsPrinting: Has background colour" << endl; - TQColor backgroundColor=bgColor(column(),row()); - - //We don't need to print anything if the background is white - if (backgroundColor != TQt::white) - return true; - } - - return false; -} - -bool Cell::isEmpty() const -{ - return isDefault() || d->strText.isEmpty(); -} - - -// Return true if this cell is obscured by some other cell. - -bool Cell::isObscured() const -{ - if (!d->hasExtra()) - return false; - - return !( d->extra()->obscuringCells.isEmpty() ); -} - - -// Return true if this cell is part of a merged cell, but not the -// master cell. - -bool Cell::isPartOfMerged() const -{ - if (!d->hasExtra()) - return false; - - TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); - TQValueList::const_iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - Cell *cell = *it; - - if (cell->doesMergeCells()) { - // The cell might merge extra cells, and then overlap even - // beyond that so just knowing that the obscuring cell merges - // extra isn't enough. We have to know that this cell is one of - // the ones it is forcing over. - if (column() <= cell->column() + cell->d->extra()->mergedXCells - && row() <= cell->row() + cell->mergedYCells() ) - return true; - } - } - - return false; -} - - -// Return the cell that obscures this one. If no cell is obscuring, -// then return this. This method is slightly complicated because we -// can have several layers of obscuring. -// -// Update: it seems that if we do an actual merge, then the obscuring -// cell is prepended and if just expanding, then it is appended. This -// means that we should be able to just look at the first one. - -Cell *Cell::ultimateObscuringCell() const -{ - if (!d->hasExtra()) - return (Cell *) this; - - else if (d->extra()->obscuringCells.isEmpty()) - return (Cell *) this; - - else - return d->extra()->obscuringCells.first(); - -#if 0 - TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); - TQValueList::const_iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - Cell *cell = *it; - - if (cell->doesMergeCells()) { - // The cell might merge extra cells, and then overlap even - // beyond that so just knowing that the obscuring cell merges - // extra isn't enough. We have to know that this cell is one of - // the ones it is forcing over. - if (column() <= cell->column() + cell->d->extra()->mergedXCells - && row() <= cell->row() + cell->mergedYCells() ) - return true; - } - } - - return false; -#endif -} - - -TQValueList Cell::obscuringCells() const -{ - if (!d->hasExtra()) - { - TQValueList empty; - return empty; - } - return d->extra()->obscuringCells; -} - -void Cell::clearObscuringCells() -{ - if (!d->hasExtra()) - return; - d->extra()->obscuringCells.clear(); -} - -void Cell::obscure( Cell *cell, bool isForcing ) -{ - if (d->hasExtra()) - { - d->extra()->obscuringCells.remove( cell ); // removes *all* occurrences - cell->clearObscuringCells(); - } - if ( isForcing ) - { - d->extra()->obscuringCells.prepend( cell ); - } - else - { - d->extra()->obscuringCells.append( cell ); - } - setFlag(Flag_LayoutDirty); - format()->sheet()->setRegionPaintDirty( cellRect() ); -} - -void Cell::unobscure( Cell * cell ) -{ - if (d->hasExtra()) - d->extra()->obscuringCells.remove( cell ); - setFlag( Flag_LayoutDirty ); - format()->sheet()->setRegionPaintDirty( cellRect() ); -} - -TQString Cell::encodeFormula( bool _era, int _col, int _row ) const -{ - if ( _col == -1 ) - _col = d->column; - if ( _row == -1 ) - _row = d->row; - - TQString erg = ""; - - if(d->strText.isEmpty()) - return d->strText; - - bool fix1 = false; - bool fix2 = false; - bool onNumber = false; - unsigned int pos = 0; - const unsigned int length = d->strText.length(); - - // All this can surely be made 10 times faster, but I just "ported" it to TQString - // without any attempt to optimize things -- this is really brittle (Werner) - while ( pos < length ) - { - if ( d->strText[pos] == '"' ) - { - erg += d->strText[pos++]; - while ( pos < length && d->strText[pos] != '"' ) // till the end of the world^H^H^H "string" - { - erg += d->strText[pos++]; - // Allow escaped double quotes (\") - if ( pos < length && d->strText[pos] == '\\' && d->strText[pos+1] == '"' ) - { - erg += d->strText[pos++]; - erg += d->strText[pos++]; - } - } - if ( pos < length ) // also copy the trailing double quote - erg += d->strText[pos++]; - - onNumber = false; - } - else if ( d->strText[pos].isDigit() ) - { - erg += d->strText[pos++]; - fix1 = fix2 = false; - onNumber = true; - } - else if ( d->strText[pos] != '$' && !d->strText[pos].isLetter() ) - { - erg += d->strText[pos++]; - fix1 = fix2 = false; - onNumber = false; - } - else - { - TQString tmp = ""; - if ( d->strText[pos] == '$' ) - { - tmp = "$"; - pos++; - fix1 = true; - } - if ( d->strText[pos].isLetter() ) - { - TQString buffer; - unsigned int pos2 = 0; - while ( pos < length && d->strText[pos].isLetter() ) - { - tmp += d->strText[pos]; - buffer[pos2++] = d->strText[pos++]; - } - if ( d->strText[pos] == '$' ) - { - tmp += "$"; - pos++; - fix2 = true; - } - if ( d->strText[pos].isDigit() ) - { - const unsigned int oldPos = pos; - while ( pos < length && d->strText[pos].isDigit() ) ++pos; - int row = 0; - if ( pos != oldPos ) - row = d->strText.mid(oldPos, pos-oldPos).toInt(); - // Is it a sheet name || is it a function name like DEC2HEX - /* or if we're parsing a number, this could just be the - exponential part of it (1.23E4) */ - if ( ( d->strText[pos] == '!' ) || - d->strText[pos].isLetter() || - onNumber ) - { - erg += tmp; - fix1 = fix2 = false; - pos = oldPos; - } - else // It must be a cell identifier - { - //now calculate the row as integer value - int col = 0; - col = util_decodeColumnLabelText( buffer ); - if ( fix1 ) - erg += TQString( "$%1" ).arg( col ); - else - if (_era) - erg += TQChar(0xA7) + TQString( "%1" ).arg( col ); - else - erg += TQString( "#%1" ).arg( col - _col ); - - if ( fix2 ) - erg += TQString( "$%1#").arg( row ); - else - if (_era) - erg += TQChar(0xA7) + TQString( "%1#" ).arg( row ); - else - erg += TQString( "#%1#" ).arg( row - _row ); - } - } - else - { - erg += tmp; - fix1 = fix2 = false; - } - } - else - { - erg += tmp; - fix1 = false; - } - onNumber = false; - } - } - - return erg; -} - -TQString Cell::decodeFormula( const TQString &_text, int _col, int _row) const -{ - if ( _col == -1 ) - _col = d->column; - if ( _row == -1 ) - _row = d->row; - - TQString erg = ""; - unsigned int pos = 0; - const unsigned int length = _text.length(); - - if ( _text.isEmpty() ) - return TQString(); - - while ( pos < length ) - { - if ( _text[pos] == '"' ) - { - erg += _text[pos++]; - while ( pos < length && _text[pos] != '"' ) - { - erg += _text[pos++]; - // Allow escaped double quotes (\") - if ( pos < length && _text[pos] == '\\' && _text[pos+1] == '"' ) - { - erg += _text[pos++]; - erg += _text[pos++]; - } - } - if ( pos < length ) - erg += _text[pos++]; - } - else if ( _text[pos] == '#' || _text[pos] == '$' || _text[pos] == TQChar(0xA7)) - { - bool abs1 = false; - bool abs2 = false; - bool era1 = false; // if 1st is relative but encoded absolutely - bool era2 = false; - - TQChar _t = _text[pos++]; - if ( _t == '$' ) - abs1 = true; - else if ( _t == TQChar(0xA7) ) - era1 = true; - - int col = 0; - unsigned int oldPos = pos; - while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos; - if ( pos != oldPos ) - col = _text.mid(oldPos, pos-oldPos).toInt(); - if ( !abs1 && !era1 ) - col += _col; - // Skip '#' or '$' - - _t = _text[pos++]; - if ( _t == '$' ) - abs2 = true; - else if ( _t == TQChar(0xA7) ) - era2 = true; - - int row = 0; - oldPos = pos; - while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos; - if ( pos != oldPos ) - row = _text.mid(oldPos, pos-oldPos).toInt(); - if ( !abs2 && !era2) - row += _row; - // Skip '#' or '$' - ++pos; - if ( row < 1 || col < 1 || row > KS_rowMax || col > KS_colMax ) - { - kdDebug(36001) << "Cell::decodeFormula: row or column out of range (col: " << col << " | row: " << row << ")" << endl; - erg = "=\"#### " + i18n("REFERENCE TO COLUMN OR ROW IS OUT OF RANGE") + "\""; - return erg; - } - if ( abs1 ) - erg += "$"; - erg += Cell::columnName(col); //Get column text - - if ( abs2 ) - erg += "$"; - erg += TQString::number( row ); - } - else - erg += _text[pos++]; - } - - return erg; -} - - -void Cell::freeAllObscuredCells() -{ - // - // Free all obscured cells. - // - - if (!d->hasExtra()) - return; - - for ( int x = d->column + d->extra()->mergedXCells; - x <= d->column + d->extra()->extraXCells; ++x ) { - for ( int y = d->row + d->extra()->mergedYCells; - y <= d->row + d->extra()->extraYCells; ++y ) { - if ( x != d->column || y != d->row ) { - Cell *cell = format()->sheet()->cellAt( x, y ); - cell->unobscure(this); - } - } - } - - d->extra()->extraXCells = d->extra()->mergedXCells; - d->extra()->extraYCells = d->extra()->mergedYCells; - -} - - -// ---------------------------------------------------------------- -// Layout - - -// Recalculate the entire layout. This includes the following members: -// -// d->textX, d->textY -// d->textWidth, d->textHeight -// d->fmAscent -// d->extra()->extraXCells, d->extra()->extraYCells -// d->extra()->extraWidth, d->extra()->extraHeight -// d->extra()->nbLines (if multirow) -// -// and, of course, -// -// d->strOutText -// - -void Cell::makeLayout( TQPainter &_painter, int _col, int _row ) -{ - // Are _col and _row really needed ? - // - // Yes they are: they are useful if this is the default layout, in - // which case d->row and d->column are 0 and 0, but _col and _row - // are the real coordinates of the cell. - - // There is no need to remake the layout if it hasn't changed. - if ( !testFlag( Flag_LayoutDirty ) ) - return; - - // Some initializations. - if (d->hasExtra()) - d->extra()->nbLines = 0; - clearFlag( Flag_CellTooShortX ); - clearFlag( Flag_CellTooShortY ); - - // Initiate the cells that this one is obscuring to the ones that - // are actually merged. - freeAllObscuredCells(); - if (d->hasExtra()) - mergeCells( d->column, d->row, - d->extra()->mergedXCells, d->extra()->mergedYCells ); - - // If the column for this cell is hidden or the row is too low, - // there is no use in remaking the layout. - ColumnFormat *cl1 = format()->sheet()->columnFormat( _col ); - RowFormat *rl1 = format()->sheet()->rowFormat( _row ); - if ( cl1->isHide() - || ( rl1->dblHeight() <= format()->sheet()->doc()->unzoomItY( 2 ) ) ) { - clearFlag( Flag_LayoutDirty ); - return; - } - - // Recalculate the output text, d->strOutText. - setOutputText(); - - // Empty text? Reset the outstring and, if this is the default - // cell, return. - if ( d->strOutText.isEmpty() ) { - d->strOutText = TQString(); - - if ( isDefault() ) { - clearFlag( Flag_LayoutDirty ); - return; - } - } - - // Up to here, we have just cared about the contents, not the - // painting of it. Now it is time to see if the contents fits into - // the cell and, if not, maybe rearrange the outtext a bit. - // - // First, Determine the correct font with zoom taken into account, - // and apply it to _painter. Then calculate text dimensions, i.e. - // d->textWidth and d->textHeight. - applyZoomedFont( _painter, _col, _row ); - textSize( _painter ); - - // - // Calculate the size of the cell - // - RowFormat *rl = format()->sheet()->rowFormat( d->row ); - ColumnFormat *cl = format()->sheet()->columnFormat( d->column ); - - double width = cl->dblWidth(); - double height = rl->dblHeight(); - - // Calculate extraWidth and extraHeight if we have a merged cell. - if ( testFlag( Flag_Merged ) ) { - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; - - // FIXME: Introduce double extraWidth/Height here and use them - // instead (see FIXME about this in paintCell()). - - for ( int x = _col + 1; x <= _col + extraXCells; x++ ) - width += format()->sheet()->columnFormat( x )->dblWidth(); - - for ( int y = _row + 1; y <= _row + extraYCells; y++ ) - height += format()->sheet()->rowFormat( y )->dblHeight(); - } - - // Cache the newly calculated extraWidth and extraHeight if we have - // already allocated a struct for it. Otherwise it will be zero, so - // don't bother. - if (d->hasExtra()) { - d->extra()->extraWidth = width; - d->extra()->extraHeight = height; - } - - TQFontMetrics fm = _painter.fontMetrics(); - d->fmAscent = fm.ascent(); - - // Check if we need to break the line into multiple lines and are - // allowed to do so. If so, set `lines' to the number of lines that - // are needed to fit into the total width of the combined cell. - // - // Also recalculate d->textHeight, d->textWidth, d->extra->nbLines - // and d->strOutText. - // - int lines = 1; - if ( d->textWidth > (width - 2 * BORDER_SPACE - - format()->leftBorderWidth( _col, _row ) - - format()->rightBorderWidth( _col, _row ) ) - && format()->multiRow( _col, _row ) ) - { - // Copy of d->strOutText but without the newlines. -// TQString o = d->strOutText.replace( TQChar('\n'), " " ); - - // don't remove the existing LF, these are intended line wraps (whishlist #9881) - TQString o = d->strOutText; - - // Break the line at appropriate places, i.e. spaces, if - // necessary. This means to change the spaces where breaks occur - // into newlines. - if ( o.find(' ') != -1 ) - { - d->strOutText = ""; - - // Make sure that we have a space at the end. - o += ' '; - - int start = 0; // Start of the line we are handling now - int breakpos = 0; // The next candidate pos to break the string - int pos1 = 0; - int availableWidth = (int) ( width - 2 * BORDER_SPACE - - format()->leftBorderWidth( _col, _row ) - - format()->rightBorderWidth( _col, _row ) ); - - do { - - breakpos = o.find( ' ', breakpos ); - int linefeed = o.find( '\n', pos1 ); - -// kdDebug() << "start: " << start << "; breakpos: " << breakpos << "; pos1: " << pos1 << "; linefeed: " << linefeed << endl; - - //don't miss LF as a position to calculate current lineWidth - int work_breakpos = breakpos; - if (pos1 < linefeed && linefeed < breakpos) - work_breakpos = linefeed; - - double lineWidth = format()->sheet()->doc() - ->unzoomItX( fm.width( d->strOutText.mid( start, (pos1 - start) ) - + o.mid( pos1, work_breakpos - pos1 ) ) ); - - //linefeed could be -1 when no linefeed is found! - if (breakpos > linefeed && linefeed > 0) - { -// kdDebug() << "applying linefeed to start;" << endl; - start = linefeed; - lines++; - } - - if ( lineWidth <= availableWidth ) { - // We have room for the rest of the line. End it here. - d->strOutText += o.mid( pos1, breakpos - pos1 ); - pos1 = breakpos; - } - else { - // Still not enough room. Try to split further. - if ( o.at( pos1 ) == ' ' ) - pos1++; - - if ( pos1 != 0 && breakpos != -1 ) { - d->strOutText += "\n" + o.mid( pos1, breakpos - pos1 ); - lines++; - } - else - d->strOutText += o.mid( pos1, breakpos - pos1 ); - - start = pos1; - pos1 = breakpos; - } - - breakpos++; - } while( o.find( ' ', breakpos ) != -1 ); - } - else - { - lines = o.contains('\n'); - } - - d->textHeight *= lines; - if (lines > 1) - d->extra()->nbLines = lines; - - d->textX = 0.0; - - // Calculate the maximum width, taking into account linebreaks, - // and put it in d->textWidth. - TQString t; - int i; - int pos = 0; - d->textWidth = 0.0; - do { - i = d->strOutText.find( "\n", pos ); - - if ( i == -1 ) - t = d->strOutText.mid( pos, d->strOutText.length() - pos ); - else { - t = d->strOutText.mid( pos, i - pos ); - pos = i + 1; - } - - double tw = format()->sheet()->doc()->unzoomItX( fm.width( t ) ); - if ( tw > d->textWidth ) - d->textWidth = tw; - } while ( i != -1 ); - } - - // Calculate d->textX and d->textY - offsetAlign( _col, _row ); - - int a = effAlignX(); - - // Get indentation. This is only used for left aligned text. - double indent = 0.0; - if ( a == Format::Left && !isEmpty() ) - indent = format()->getIndent( _col, _row ); - - // Set Flag_CellTooShortX if the text is vertical or angled, and too - // high for the cell. - if ( format()->verticalText( _col, _row ) || format()->getAngle( _col, _row ) != 0 ) { - //RowFormat *rl = format()->sheet()->rowFormat( _row ); - - if ( d->textHeight >= height/*rl->dblHeight()*/ ) - setFlag( Flag_CellTooShortX ); - } - - // Do we have to occupy additional cells to the right? This is only - // done for cells that have no merged cells in the Y direction. - // - // FIXME: Check if all cells along the merged edge to the right are - // empty and use the extra space? No, probably not. - // - if ( d->textWidth + indent > ( width - 2 * BORDER_SPACE - - format()->leftBorderWidth( _col, _row ) - - format()->rightBorderWidth( _col, _row ) ) - && ( !d->hasExtra() || d->extra()->mergedYCells == 0 ) ) - { - int c = d->column; - - // Find free cells to the right of this one. - int end = 0; - while ( !end ) { - ColumnFormat *cl2 = format()->sheet()->columnFormat( c + 1 ); - Cell *cell = format()->sheet()->visibleCellAt( c + 1, d->row ); - - if ( cell->isEmpty() ) { - width += cl2->dblWidth() - 1; - c++; - - // Enough space? - if ( d->textWidth + indent <= ( width - 2 * BORDER_SPACE - - format()->leftBorderWidth( _col, _row ) - - format()->rightBorderWidth( _col, _row ) ) ) - end = 1; - } - else - // Not enough space, but the next cell is not empty - end = -1; - } - - // Try to use additional space from the neighboring cells that - // were calculated in the last step. This is the place that we - // set d->extra()->extraXCells and d->extra()->extraWidth. - // - // Currently this is only done for left aligned cells. We have to - // check to make sure we haven't already force-merged enough cells - // - // FIXME: Why not right/center aligned text? - // - // FIXME: Shouldn't we check to see if end == -1 here before - // setting Flag_CellTooShortX? - // - if ( format()->align( _col, _row ) == Format::Left - || ( format()->align( _col, _row ) == Format::Undefined - && !value().isNumber() ) ) - { - if ( c - d->column > d->extra()->mergedXCells ) { - d->extra()->extraXCells = c - d->column; - d->extra()->extraWidth = width; - for ( int i = d->column + 1; i <= c; ++i ) { - Cell *cell = format()->sheet()->nonDefaultCell( i, d->row ); - cell->obscure( this ); - } - - // Not enough space - if ( end == -1 ) - setFlag( Flag_CellTooShortX ); - } - else - setFlag( Flag_CellTooShortX ); - } - else - setFlag( Flag_CellTooShortX ); - } - - // Do we have to occupy additional cells at the bottom ? - // - // FIXME: Setting to make the current cell grow. - // - if ( format()->multiRow( _col, _row ) - && d->textHeight > ( height - 2 * BORDER_SPACE - - format()->topBorderWidth( _col, _row ) - - format()->bottomBorderWidth( _col, _row ) ) ) - { - int r = d->row; - int end = 0; - - // Find free cells bottom to this one - while ( !end ) { - RowFormat *rl2 = format()->sheet()->rowFormat( r + 1 ); - Cell *cell = format()->sheet()->visibleCellAt( d->column, r + 1 ); - - if ( cell->isEmpty() ) { - height += rl2->dblHeight() - 1.0; - r++; - - // Enough space ? - if ( d->textHeight <= ( height - 2 * BORDER_SPACE - - format()->topBorderWidth( _col, _row ) - - format()->bottomBorderWidth( _col, _row ) ) ) - end = 1; - } - else - // Not enough space, but the next cell is not empty. - end = -1; - } - - // Check to make sure we haven't already force-merged enough cells. - if ( r - d->row > d->extra()->mergedYCells ) - { - d->extra()->extraYCells = r - d->row; - d->extra()->extraHeight = height; - - for ( int i = d->row + 1; i <= r; ++i ) - { - Cell *cell = format()->sheet()->nonDefaultCell( d->column, i ); - cell->obscure( this ); - } - - // Not enough space? - if ( end == -1 ) - setFlag( Flag_CellTooShortY ); - } - else - setFlag( Flag_CellTooShortY ); - } - - clearFlag( Flag_LayoutDirty ); - - return; -} - - -void Cell::valueChanged () -{ - update(); - - format()->sheet()->valueChanged (this); -} - - -// Recalculate d->strOutText. -// - -void Cell::setOutputText() -{ - if ( isDefault() ) { - d->strOutText = TQString(); - - if ( d->hasExtra() && d->extra()->conditions ) - d->extra()->conditions->checkMatches(); - - return; - } - - // If nothing has changed, we don't need to remake the text layout. - if ( !testFlag(Flag_TextFormatDirty) ) - return; - - // We don't want to remake the layout unnecessarily. - clearFlag( Flag_TextFormatDirty ); - - // Display a formula if warranted. If not, display the value instead; - // this is the most common case. - if ( (!hasError()) && isFormula() && format()->sheet()->getShowFormula() - && !( format()->sheet()->isProtected() && format()->isHideFormula( d->column, d->row ) ) - || isEmpty() ) - d->strOutText = d->strText; - else { - d->strOutText = sheet()->doc()->formatter()->formatText (this, - formatType()); - } - - // Check conditions if needed. - if ( d->hasExtra() && d->extra()->conditions ) - d->extra()->conditions->checkMatches(); -} - - -// Recalculate d->textX and d->textY. -// -// Used in makeLayout() and calculateTextParameters(). -// - -void Cell::offsetAlign( int _col, int _row ) -{ - int a; - Format::AlignY ay; - int tmpAngle; - bool tmpVerticalText; - bool tmpMultiRow; - - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - { - Style *style = d->extra()->conditions->matchedStyle(); - - if ( style->hasFeature( Style::SAlignX, true ) ) - a = style->alignX(); - else - a = format()->align( _col, _row ); - - if ( style->hasFeature( Style::SVerticalText, true ) ) - tmpVerticalText = style->hasProperty( Style::PVerticalText ); - else - tmpVerticalText = format()->verticalText( _col, _row ); - - if ( style->hasFeature( Style::SMultiRow, true ) ) - tmpMultiRow = style->hasProperty( Style::PMultiRow ); - else - tmpMultiRow = format()->multiRow( _col, _row ); - - if ( style->hasFeature( Style::SAlignY, true ) ) - ay = style->alignY(); - else - ay = format()->alignY( _col, _row ); - - if ( style->hasFeature( Style::SAngle, true ) ) - tmpAngle = style->rotateAngle(); - else - tmpAngle = format()->getAngle( _col, _row ); - } - else { - a = format()->align( _col, _row ); - ay = format()->alignY( _col, _row ); - tmpAngle = format()->getAngle( _col, _row ); - tmpVerticalText = format()->verticalText( _col, _row ); - tmpMultiRow = format()->multiRow( _col, _row ); - } - - RowFormat *rl = format()->sheet()->rowFormat( _row ); - ColumnFormat *cl = format()->sheet()->columnFormat( _col ); - - double w = cl->dblWidth(); - double h = rl->dblHeight(); - - if ( d->hasExtra() ) { - if ( d->extra()->extraXCells ) w = d->extra()->extraWidth; - if ( d->extra()->extraYCells ) h = d->extra()->extraHeight; - } - - const double effTop = BORDER_SPACE + 0.5 * effTopBorderPen( _col, _row ).width(); - const double effBottom = h - BORDER_SPACE - 0.5 * effBottomBorderPen( _col, _row ).width(); - - // Calculate d->textY based on the vertical alignment and a few - // other inputs. - switch( ay ) - { - case Format::Top: - { - if ( tmpAngle == 0 ) - { - d->textY = effTop + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else if ( tmpAngle < 0 ) - { - d->textY = effTop; - } - else - { - d->textY = effTop - + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY(); - } - break; - } - case Format::Bottom: - { - if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) - { - d->textY = effBottom; - } - else if ( tmpAngle != 0 ) - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - if ( tmpAngle < 0 ) - { - d->textY = effBottom - d->textHeight; - } - else - { - d->textY = effBottom - d->textHeight - + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() ); - } - } - else - { - if ( tmpAngle < 0 ) - { - d->textY = effTop; - } - else - { - d->textY = effTop - + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) - / format()->sheet()->doc()->zoomedResolutionY() ); - } - } - } - else if ( tmpMultiRow && !tmpVerticalText ) - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - d->textY = effBottom - d->textHeight - + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else - { - d->textY = effTop - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - } - else - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - d->textY = effBottom - d->textHeight - + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else - { - d->textY = effTop - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - } - break; - } - case Format::Middle: - case Format::UndefinedY: - { - if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) - { - d->textY = ( h - d->textHeight ) / 2 - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else if ( tmpAngle != 0 ) - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - if ( tmpAngle < 0 ) - { - d->textY = ( h - d->textHeight ) / 2; - } - else - { - d->textY = ( h - d->textHeight ) / 2 - + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY(); - } - } - else - { - if ( tmpAngle < 0 ) - { - d->textY = effTop; - } - else - { - d->textY = effTop - + ( (double)d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() ); - } - } - } - else if ( tmpMultiRow && !tmpVerticalText ) - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - d->textY = ( h - d->textHeight ) / 2 - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else - { - d->textY = effTop - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - } - else - { - // Is enough place available? - if ( effBottom - effTop - d->textHeight > 0 ) - { - d->textY = ( h - d->textHeight ) / 2 - + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - else - d->textY = effTop - + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); - } - break; - } - } - - a = effAlignX(); - if ( format()->sheet()->getShowFormula() && - !( format()->sheet()->isProtected() && format()->isHideFormula( _col, _row ) ) ) - { - a = Format::Left; - } - - // Calculate d->textX based on alignment and textwidth. - switch ( a ) { - case Format::Left: - d->textX = 0.5 * effLeftBorderPen( _col, _row ).width() + BORDER_SPACE; - break; - case Format::Right: - d->textX = w - BORDER_SPACE - d->textWidth - - 0.5 * effRightBorderPen( _col, _row ).width(); - break; - case Format::Center: - d->textX = 0.5 * ( w - BORDER_SPACE - d->textWidth - - 0.5 * effRightBorderPen( _col, _row ).width() ); - break; - } -} - - -// Recalculate the current text dimensions, i.e. d->textWidth and -// d->textHeight. -// -// Used in makeLayout() and calculateTextParameters(). -// -void Cell::textSize( TQPainter &_paint ) -{ - TQFontMetrics fm = _paint.fontMetrics(); - // Horizontal text ? - - int tmpAngle; - int _row = row(); - int _col = column(); - bool tmpVerticalText; - bool fontUnderlined; - Format::AlignY ay; - - // Set tmpAngle, tmpeVerticalText, ay and fontUnderlined according - // to if there is a matching condition or not. - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - { - Style *style = d->extra()->conditions->matchedStyle(); - - if ( style->hasFeature( Style::SAngle, true ) ) - tmpAngle = style->rotateAngle(); - else - tmpAngle = format()->getAngle( _col, _row ); - - if ( style->hasFeature( Style::SVerticalText, true ) ) - tmpVerticalText = style->hasProperty( Style::PVerticalText ); - else - tmpVerticalText = format()->verticalText( _col, _row ); - - if ( style->hasFeature( Style::SAlignY, true ) ) - ay = style->alignY(); - else - ay = format()->alignY( _col, _row ); - - if ( style->hasFeature( Style::SFontFlag, true ) ) - fontUnderlined = ( style->fontFlags() & (uint) Style::FUnderline ); - else - fontUnderlined = format()->textFontUnderline( _col, _row ); - } - else { - // The cell has no condition with a maxed style. - tmpAngle = format()->getAngle( _col, _row ); - tmpVerticalText = format()->verticalText( _col, _row ); - ay = format()->alignY( _col, _row ); - fontUnderlined = format()->textFontUnderline( _col, _row ); - } - - // Set d->textWidth and d->textHeight to correct values according to - // if the text is horizontal, vertical or rotated. - if ( !tmpVerticalText && !tmpAngle ) { - // Horizontal text. - - d->textWidth = format()->sheet()->doc()->unzoomItX( fm.width( d->strOutText ) ); - int offsetFont = 0; - if ( ( ay == Format::Bottom ) && fontUnderlined ) { - offsetFont = fm.underlinePos() + 1; - } - - d->textHeight = format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent() - + offsetFont ); - } - else if ( tmpAngle!= 0 ) { - // Rotated text. - - d->textHeight = format()->sheet()->doc() - ->unzoomItY( int( cos( tmpAngle * M_PI / 180 ) - * ( fm.ascent() + fm.descent() ) - + abs( int( ( fm.width( d->strOutText ) - * sin( tmpAngle * M_PI / 180 ) ) ) ) ) ); - - d->textWidth = format()->sheet()->doc() - ->unzoomItX( int( abs( int( ( sin( tmpAngle * M_PI / 180 ) - * ( fm.ascent() + fm.descent() ) ) ) ) - + fm.width( d->strOutText ) - * cos ( tmpAngle * M_PI / 180 ) ) ); - } - else { - // Vertical text. - int width = 0; - for ( unsigned int i = 0; i < d->strOutText.length(); i++ ) - width = TQMAX( width, fm.width( d->strOutText.at( i ) ) ); - - d->textWidth = format()->sheet()->doc()->unzoomItX( width ); - d->textHeight = format()->sheet()->doc()->unzoomItY( ( fm.ascent() + fm.descent() ) - * d->strOutText.length() ); - } -} - - -// Get the effective font to use after the zooming and apply it to `painter'. -// -// Used in makeLayout() and calculateTextParameters(). -// - -void Cell::applyZoomedFont( TQPainter &painter, int _col, int _row ) -{ - TQFont tmpFont( format()->textFont( _col, _row ) ); - - // If there is a matching condition on this cell then set the - // according style parameters. - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) { - - Style * s = d->extra()->conditions->matchedStyle(); - - // Other size? - if ( s->hasFeature( Style::SFontSize, true ) ) - tmpFont.setPointSizeFloat( s->fontSize() ); - - // Other attributes? - if ( s->hasFeature( Style::SFontFlag, true ) ) { - uint flags = s->fontFlags(); - - tmpFont.setBold( flags & (uint) Style::FBold ); - tmpFont.setUnderline( flags & (uint) Style::FUnderline ); - tmpFont.setItalic( flags & (uint) Style::FItalic ); - tmpFont.setStrikeOut( flags & (uint) Style::FStrike ); - } - - // Other family? - if ( s->hasFeature( Style::SFontFamily, true ) ) - tmpFont.setFamily( s->fontFamily() ); - } -#if 0 - else - /* - * could somebody please explaint why we check for isProtected or isHideFormula here - */ - if ( d->extra()->conditions - && d->extra()->conditions->currentCondition( condition ) - && !(format()->sheet()->getShowFormula() - && !( format()->sheet()->isProtected() - && format()->isHideFormula( d->column, d->row ) ) ) ) - { - if ( condition.fontcond ) - tmpFont = *(condition.fontcond); - else - tmpFont = condition.style->font(); - } -#endif - - // Scale the font size according to the current zoom. - tmpFont.setPointSizeFloat( 0.01 * format()->sheet()->doc()->zoom() - * tmpFont.pointSizeFloat() ); - - painter.setFont( tmpFont ); -} - - -//used in Sheet::adjustColumnHelper and Sheet::adjustRow -void Cell::calculateTextParameters( TQPainter &_painter, - int _col, int _row ) -{ - // Apply the correct font to _painter. - applyZoomedFont( _painter, _col, _row ); - - // Recalculate d->textWidth and d->textHeight - textSize( _painter ); - - // Recalculate d->textX and d->textY. - offsetAlign( _col, _row ); -} - - -// ---------------------------------------------------------------- -// Formula handling - - -bool Cell::makeFormula() -{ - clearFormula (); - - d->formula = new KSpread::Formula (sheet(), this); - d->formula->setExpression (d->strText); - - if (!d->formula->isValid ()) { - // Did a syntax error occur ? - clearFormula(); - - if (format()->sheet()->doc()->getShowMessageError()) - { - TQString tmp(i18n("Error in cell %1\n\n")); - tmp = tmp.arg( fullName() ); - KMessageBox::error( (TQWidget*)0L, tmp); - } - setFlag(Flag_ParseError); - Value v; - v.setError ( "####" ); - setValue (v); - return false; - } - - // we must recalc - setCalcDirtyFlag (); - - return true; -} - -void Cell::clearFormula() -{ - delete d->formula; - d->formula = 0L; -} - -bool Cell::calc(bool delay) -{ - if ( !isFormula() ) - return true; - - if (d->formula == 0) - { - if ( testFlag( Flag_ParseError ) ) // there was a parse error - return false; - else - { - /* we were probably at a "isLoading() = true" state when we originally - * parsed - */ - makeFormula (); - - if ( d->formula == 0 ) // there was a parse error - return false; - } - } - - if ( !testFlag( Flag_CalcDirty ) ) - return true; - - if ( delay ) - { - if ( format()->sheet()->doc()->delayCalculation() ) - return true; - } - - setFlag(Flag_LayoutDirty); - setFlag(Flag_TextFormatDirty); - clearFlag(Flag_CalcDirty); - - Value result = d->formula->eval (); - setValue (result); - if (result.isNumber()) - checkNumberFormat(); // auto-chooses number or scientific - - clearFlag(Flag_CalcDirty); - setFlag(Flag_LayoutDirty); - - return true; -} - - -// ================================================================ -// Painting - - -// Paint the cell. This is the main function that calls a lot of -// helper functions. -// -// `rect' is the rectangle that we should paint on. If the cell -// does not overlap this rectangle, we can return immediately. -// `coordinate' is the origin (the upper left) of the cell in document -// coordinates. -// - -void Cell::paintCell( const KoRect &rect, TQPainter & painter, - View *view, - const KoPoint &coordinate, - const TQPoint &cellRef, - int paintBorder, - TQPen & rightPen, TQPen & bottomPen, - TQPen & leftPen, TQPen & topPen, - TQValueList &mergedCellsPainted, - bool drawCursor ) -{ - bool paintBorderRight = paintBorder & Border_Right; - bool paintBorderBottom = paintBorder & Border_Bottom; - bool paintBorderLeft = paintBorder & Border_Left; - bool paintBorderTop = paintBorder & Border_Top; - - // If we are already painting this cell, then return immediately. - // This avoids infinite recursion. - if ( testFlag( Flag_PaintingCell ) ) - return; - - // Indicate that we are painting this cell now. - setFlag( Flag_PaintingCell ); - - // This flag indicates that we are working on drawing the cells that - // another cell is obscuring. The value is the number of levels down we - // are currently working -- i.e. a cell obscured by a cell which is - // obscured by a cell. - static int paintingObscured = 0; - -#if 0 - if (paintingObscured == 0) - kdDebug(36001) << "painting cell " << name() << endl; - else - kdDebug(36001) << " painting obscured cell " << name() << endl; -#endif - - // Sanity check: If we're working on drawing an obscured cell, that - // means this cell should have a cell that obscures it. - Q_ASSERT(!(paintingObscured > 0 && d->extra()->obscuringCells.isEmpty())); - - // The parameter cellref should be *this, unless this is the default cell. - Q_ASSERT(isDefault() - || (((cellRef.x() == d->column) && (cellRef.y() == d->row)))); - - Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); - - double left = coordinate.x(); - - ColumnFormat * colFormat = format()->sheet()->columnFormat( cellRef.x() ); - RowFormat * rowFormat = format()->sheet()->rowFormat( cellRef.y() ); - - // Set width, height to the total width and height that this cell - // covers, including obscured cells, and width0, height0 to the - // width and height of this cell, maybe merged but never implicitly - // extended. - double width0 = colFormat->dblWidth(); - double height0 = rowFormat->dblHeight(); - double width = width0; - double height = height0; - - // Handle right-to-left layout. - // In an RTL sheet the cells have to be painted at their opposite horizontal - // location on the canvas, meaning that column A will be the rightmost column - // on screen, column B will be to the left of it and so on. Here we change - // the horizontal coordinate at which we start painting the cell in case the - // sheet's direction is RTL. We do this only if paintingObscured is 0, - // otherwise the cell's painting location will flip back and forth in - // consecutive calls to paintCell when painting obscured cells. - if ( sheetDir == Sheet::RightToLeft && paintingObscured == 0 - && view && view->canvasWidget() ) - { - double dwidth = view->doc()->unzoomItX(view->canvasWidget()->width()); - left = dwidth - coordinate.x() - width; - } - - // See if this cell is merged or has overflown into neighbor cells. - // In that case, the width/height is greater than just the cell - // itself. - if (d->hasExtra()) { - if (d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0) { - // merged cell extends to the left if sheet is RTL - if ( sheetDir == Sheet::RightToLeft ) { - left -= d->extra()->extraWidth - width; - } - width0 = d->extra()->extraWidth; - height0 = d->extra()->extraHeight; - width = d->extra()->extraWidth; - height = d->extra()->extraHeight; - } - else { -#if 0 - width += d->extra()->extraXCells ? d->extra()->extraWidth : 0; - height += d->extra()->extraYCells ? d->extra()->extraHeight : 0; -#else - // FIXME: Make extraWidth/Height really contain the *extra* width/height. - if ( d->extra()->extraXCells ) - width = d->extra()->extraWidth; - if ( d->extra()->extraYCells ) - height = d->extra()->extraHeight; -#endif - } - } - - // Check if the cell is "selected", i.e. it should be drawn with the - // color that indicates selection (dark blue). If more than one - // square is selected, the last one uses the ordinary colors. In - // that case, "selected" will be set to false even though the cell - // itself really is selected. - bool selected = false; - if ( view != NULL ) { - selected = view->selectionInfo()->contains( cellRef ); - - // But the cell doesn't look selected if this is the marker cell. - Cell *cell = format()->sheet()->cellAt( view->selectionInfo()->marker() ); - TQPoint bottomRight( view->selectionInfo()->marker().x() + cell->extraXCells(), - view->selectionInfo()->marker().y() + cell->extraYCells() ); - TQRect markerArea( view->selectionInfo()->marker(), bottomRight ); - selected = selected && !( markerArea.contains( cellRef ) ); - - // Don't draw any selection at all when printing. - if ( painter.device()->isExtDev() || !drawCursor ) - selected = false; - } - - // Need to make a new layout ? - // - // FIXME: We have already used (at least) extraWidth/Height above, - // and now we are recalculating the layout. This has to be - // moved up above all uses. - // - // FIXME: This needs to be taken out eventually - it is done in - // canvas::paintUpdates(). - if ( testFlag( Flag_LayoutDirty ) ) - makeLayout( painter, cellRef.x(), cellRef.y() ); - - // ---------------- Start the actual painting. ---------------- - - // If the rect of this cell doesn't intersect the rect that should - // be painted, we can skip the rest and return. (Note that we need - // to calculate `left' first before we can do this.) - const KoRect cellRect( left, coordinate.y(), width, height ); - const KoRect cellRect0( left, coordinate.y(), width0, height0 ); - if ( !cellRect.intersects( rect ) ) { - clearFlag( Flag_PaintingCell ); - return; - } - - // Get the background color. - // - // If there is a condition giving the background color for this cell - // (and it matches), use that one, otherwise get the standard - // background. - TQColor backgroundColor; - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundColor, true ) ) - backgroundColor = d->extra()->conditions->matchedStyle()->bgColor(); - else - backgroundColor = bgColor( cellRef.x(), cellRef.y() ); - - // 1. Paint the background. - if ( !isPartOfMerged() ) - paintBackground( painter, cellRect0, cellRef, selected, backgroundColor ); - - // 2. Paint the default borders if we are on screen or if we are printing - // and the checkbox to do this is checked. - if ( painter.device()->devType() != TQInternal::Printer - || format()->sheet()->print()->printGrid()) - paintDefaultBorders( painter, rect, cellRect, cellRef, - paintBorderRight, paintBorderBottom, - paintBorderLeft, paintBorderTop, - rightPen, bottomPen, leftPen, topPen ); - - // 3. Paint all the cells that this one obscures. They may only be - // partially obscured. - // - // The `paintingObscured' variable is used to avoid infinite - // recursion since cells sometimes paint their obscuring cell as - // well. - paintingObscured++; - - if (d->hasExtra() && (d->extra()->extraXCells > 0 - || d->extra()->extraYCells > 0)) { - //kdDebug(36001) << "painting obscured cells for " << name() << endl; - - paintObscuredCells( rect, painter, view, cellRect, cellRef, - paintBorderRight, paintBorderBottom, - paintBorderLeft, paintBorderTop, - rightPen, bottomPen, leftPen, topPen, - mergedCellsPainted); - - // FIXME: Is this the right place for this? - if ( d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0 ) - mergedCellsPainted.prepend( cellRef ); - } - paintingObscured--; - - // 4. Paint the borders of the cell if no other cell is forcing this - // one, i.e. this cell is not part of a merged cell. - // - - // If we print pages, then we disable clipping, otherwise borders are - // cut in the middle at the page borders. - if ( painter.device()->isExtDev() ) - painter.setClipping( false ); - - // Paint the borders if this cell is not part of another merged cell. - if ( !isPartOfMerged() ) { - // if (!testFlag(Flag_Highlight)) - paintCellBorders( painter, rect, cellRect0, - cellRef, - paintBorderRight, paintBorderBottom, - paintBorderLeft, paintBorderTop, - rightPen, bottomPen, leftPen, topPen ); - } - - // Turn clipping back on. - if ( painter.device()->isExtDev() ) - painter.setClipping( true ); - - // 5. Paint diagonal lines and page borders. - paintCellDiagonalLines( painter, cellRect0, cellRef ); - - paintPageBorders( painter, cellRect0, cellRef, - paintBorderRight, paintBorderBottom ); - - - // 6. Now paint the content, if this cell isn't obscured. - if ( !isObscured() ) { - - // 6a. Paint possible comment indicator. - if ( !painter.device()->isExtDev() - || format()->sheet()->print()->printCommentIndicator() ) - paintCommentIndicator( painter, cellRect, cellRef, backgroundColor ); - - // 6b. Paint possible formula indicator. - if ( !painter.device()->isExtDev() - || format()->sheet()->print()->printFormulaIndicator() ) - paintFormulaIndicator( painter, cellRect, backgroundColor ); - - // 6c. Paint possible indicator for clipped text. - paintMoreTextIndicator( painter, cellRect, backgroundColor ); - - //6c. Paint cell highlight -#if 0 - if (highlightBorder != Border_None) - paintCellHighlight ( painter, cellRect, cellRef, highlightBorder, - rightHighlightPen, bottomHighlightPen, - leftHighlightPen, topHighlightPen ); -#endif - - // 6d. Paint the text in the cell unless: - // a) it is empty - // b) something indicates that the text should not be painted - // c) the sheet is protected and the cell is hidden. - if ( !d->strOutText.isEmpty() - && ( !painter.device()->isExtDev() - || !format()->getDontprintText( cellRef.x(), cellRef.y() ) ) - && !( format()->sheet()->isProtected() - && format()->isHideAll( cellRef.x(), cellRef.y() ) ) ) - { - paintText( painter, cellRect, cellRef ); - } - } - - // 7. If this cell is obscured and we are not already painting obscured - // cells, then paint the obscuring cell(s). Otherwise don't do - // anything so that we don't cause an infinite loop. - if ( isObscured() && paintingObscured == 0 && - !( sheetDir == Sheet::RightToLeft && painter.device()->isExtDev() ) ) - { - - //kdDebug(36001) << "painting cells that obscure " << name() << endl; - - // Store the obscuringCells list in a list of TQPoint(column, row) - // This avoids crashes during the iteration through - // obscuringCells, when the cells may get non valid or the list - // itself gets changed during a call of obscuringCell->paintCell - // (this happens e.g. when there is an updateDepend) - if (d->hasExtra()) { - TQValueList listPoints; - TQValueList::iterator it = d->extra()->obscuringCells.begin(); - TQValueList::iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - Cell *obscuringCell = *it; - - listPoints.append( TQPoint( obscuringCell->column(), obscuringCell->row() ) ); - } - - TQValueList::iterator it1 = listPoints.begin(); - TQValueList::iterator end1 = listPoints.end(); - for ( ; it1 != end1; ++it1 ) { - TQPoint obscuringCellRef = *it1; - - // Only paint those obscuring cells that haven't been already - // painted yet. - // - // This optimization removes an O(n^4) behaviour where n is - // the number of cells on one edge in a merged cell. - if ( mergedCellsPainted.contains( obscuringCellRef ) ) - continue; - - Cell *obscuringCell = format()->sheet()->cellAt( obscuringCellRef.x(), - obscuringCellRef.y() ); - - if ( obscuringCell != 0 ) { - double x = format()->sheet()->dblColumnPos( obscuringCellRef.x() ); - double y = format()->sheet()->dblRowPos( obscuringCellRef.y() ); - if ( view != 0 ) { - x -= view->canvasWidget()->xOffset(); - y -= view->canvasWidget()->yOffset(); - } - - KoPoint corner( x, y ); - painter.save(); - - // Get the effective pens for the borders. These are - // determined by possible conditions on the cell with - // associated styles. - TQPen rp( obscuringCell->effRightBorderPen( obscuringCellRef.x(), - obscuringCellRef.y() ) ); - TQPen bp( obscuringCell->effBottomBorderPen( obscuringCellRef.x(), - obscuringCellRef.y() ) ); - TQPen lp( obscuringCell->effLeftBorderPen( obscuringCellRef.x(), - obscuringCellRef.y() ) ); - TQPen tp( obscuringCell->effTopBorderPen( obscuringCellRef.x(), - obscuringCellRef.y() ) ); - - - //kdDebug(36001) << " painting obscuring cell " - // << obscuringCell->name() << endl; - // TQPen highlightPen; - - //Note: Painting of highlight isn't quite right. If several - // cells are merged, then the whole merged cell will be - // painted with the colour of the last cell referenced - // which is inside the merged range. - obscuringCell->paintCell( rect, painter, view, - corner, obscuringCellRef, - Border_Left|Border_Top|Border_Right|Border_Bottom, - rp, bp, lp, tp, - mergedCellsPainted); // new pens - painter.restore(); - } - } - } - } - - // We are done with the painting, so remove the flag on the cell. - clearFlag( Flag_PaintingCell ); -} - - - -// The following code was commented out in the above function. I'll -// leave it here in case this functionality is ever re-implemented and -// someone wants some code to start from. -// -#if 0 - - /** - * Modification for drawing the button - */ - if ( d->style == Cell::ST_Button ) { - TQBrush fill( TQt::lightGray ); - TQApplication::style().drawControl( TQStyle::CE_PushButton, &_painter, this, - TQRect( _tx + 1, _ty + 1, w2 - 1, h2 - 1 ), - defaultColorGroup ); //, selected, &fill ); - } - - /** - * Modification for drawing the combo box - */ - else if ( d->style == Cell::ST_Select ) { - TQApplication::style().drawComboButton( &_painter, _tx + 1, _ty + 1, - w2 - 1, h2 - 1, - defaultColorGroup, selected ); - } -#endif - - -#if 0 - void Cell::paintCellHighlight(TQPainter& painter, - const KoRect& cellRect, - const TQPoint& cellRef, - const int highlightBorder, - const TQPen& rightPen, - const TQPen& bottomPen, - const TQPen& leftPen, - const TQPen& topPen - ) -{ - //painter.drawLine(cellRect.left(),cellRect.top(),cellRect.right(),cellRect.bottom()); - //TQPen pen(d->extra()->highlight); - //painter.setPen(highlightPen); - - TQBrush nullBrush; - painter.setBrush(nullBrush); - - TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect ); - - //The highlight rect is just inside the main cell rect - //This saves the hassle of repainting nearby cells when the highlight is changed as the highlight areas - //do not overlap - zoomedCellRect.setLeft(zoomedCellRect.left()+1); - //zoomedCellRect.setRight(zoomedCellRect.right()-1); - zoomedCellRect.setTop(zoomedCellRect.top()+1); - //zoomedCellRect.setBottom(zoomedCellRect.bottom()-1); - - if ( cellRef.x() != KS_colMax ) - zoomedCellRect.setWidth( zoomedCellRect.width() - 1 ); - if ( cellRef.y() != KS_rowMax ) - zoomedCellRect.setHeight( zoomedCellRect.height() - 1 ); - - if (highlightBorder & Border_Top) - { - painter.setPen(topPen); - painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.top()); - } - if (highlightBorder & Border_Left) - { - painter.setPen(leftPen); - painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.left(),zoomedCellRect.bottom()); - } - if (highlightBorder & Border_Right) - { - painter.setPen(rightPen); - painter.drawLine(zoomedCellRect.right(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.bottom()); - } - if (highlightBorder & Border_Bottom) - { - painter.setPen(bottomPen); - painter.drawLine(zoomedCellRect.left(),zoomedCellRect.bottom(),zoomedCellRect.right(),zoomedCellRect.bottom()); - } - - if (highlightBorder & Border_SizeGrip) - { - TQBrush brush(rightPen.color()); - painter.setBrush(brush); - painter.setPen(rightPen); - painter.drawRect(zoomedCellRect.right()-3,zoomedCellRect.bottom()-3,4,4); - } - - //painter.drawRect(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.width(),zoomedCellRect.height()); -} -#endif - - -// Paint all the cells that this cell obscures (helper function to paintCell). -// -void Cell::paintObscuredCells(const KoRect& rect, TQPainter& painter, - View* view, - const KoRect &cellRect, - const TQPoint &cellRef, - bool paintBorderRight, - bool _paintBorderBottom, - bool paintBorderLeft, - bool _paintBorderTop, - TQPen & rightPen, TQPen & _bottomPen, - TQPen & leftPen, TQPen & _topPen, - TQValueList &mergedCellsPainted) -{ - // If there are no obscured cells, return. - if ( !extraXCells() && !extraYCells() ) - return; - - double ypos = cellRect.y(); - int maxY = extraYCells(); - int maxX = extraXCells(); - - // Loop through the rectangle of squares that we obscure and paint them. - for ( int y = 0; y <= maxY; ++y ) { - double xpos = cellRect.x(); - RowFormat* rl = format()->sheet()->rowFormat( cellRef.y() + y ); - - for( int x = 0; x <= maxX; ++ x ) { - ColumnFormat * cl = format()->sheet()->columnFormat( cellRef.x() + x ); - if ( y != 0 || x != 0 ) { - uint column = cellRef.x() + x; - uint row = cellRef.y() + y; - - TQPen topPen; - TQPen bottomPen; - bool paintBorderTop; - bool paintBorderBottom; - - Cell *cell = format()->sheet()->cellAt( column, row ); - KoPoint corner( xpos, ypos ); - - // Check if the upper and lower borders should be painted, and - // if so which pens we should use. There used to be a nasty - // bug here (#61452). - // Check top pen. Only check if this is not on the top row. - topPen = _topPen; - paintBorderTop = _paintBorderTop; - if ( row > 1 && !cell->isPartOfMerged() ) { - Cell *cellUp = format()->sheet()->cellAt( column, row - 1 ); - - if ( cellUp->isDefault() ) - paintBorderTop = false; - else { - // If the cell towards the top is part of a merged cell, get - // the pointer to the master cell. - cellUp = cellUp->ultimateObscuringCell(); - - topPen = cellUp->effBottomBorderPen( cellUp->column(), - cellUp->row() ); - -#if 0 - int penWidth = TQMAX(1, sheet()->doc()->zoomItY( topPen.width() )); - topPen.setWidth( penWidth ); -#endif - } - } - - // FIXME: I thought we had to check bottom pen as well. - // However, it looks as if we don't need to. It works anyway. - bottomPen = _bottomPen; - paintBorderBottom = _paintBorderBottom; - - int paintBorder = Border_None; - if (paintBorderLeft) paintBorder |= Cell::Border_Left; - if (paintBorderRight) paintBorder |= Cell::Border_Right; - if (paintBorderTop) paintBorder |= Cell::Border_Top; - if (paintBorderBottom) paintBorder |= Cell::Border_Bottom; - - /*Cell::BorderSides highlightBorder = Border_None; - TQPen highlightPen;*/ - - - //kdDebug(36001) << "calling paintcell for obscured cell " - // << cell->name() << endl; - cell->paintCell( rect, painter, view, - corner, - TQPoint( cellRef.x() + x, cellRef.y() + y ), - paintBorder, - rightPen, bottomPen, leftPen, topPen, - mergedCellsPainted); - } - xpos += cl->dblWidth(); - } - - ypos += rl->dblHeight(); - } -} - - -// Paint the background of this cell. -// -void Cell::paintBackground( TQPainter& painter, const KoRect &cellRect, - const TQPoint &cellRef, bool selected, - TQColor &backgroundColor ) -{ - TQColorGroup defaultColorGroup = TQApplication::palette().active(); - TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect ); - - // If this is not the KS_rowMax and/or KS_colMax, then we reduce - // width and/or height by one. This is due to the fact that the - // right/bottom most pixel is shared with the left/top most pixel of - // the following cell. Only in the case of KS_colMax/KS_rowMax we - // need to draw even this pixel, as there isn't a following cell to - // draw the background pixel. - if ( cellRef.x() != KS_colMax ) - zoomedCellRect.setWidth( zoomedCellRect.width() - 1 ); - if ( cellRef.y() != KS_rowMax ) - zoomedCellRect.setHeight( zoomedCellRect.height() - 1 ); - - // Determine the correct background color - if ( selected ) - { - //If the cell's background color is too bright, use the default highlight color - //Otherwise use a lighter version of the cell's background color. - TQColor c; - - int averageColor = (backgroundColor.red() + backgroundColor.green() + backgroundColor.blue()) / 3; - - if (averageColor > 180) - if (averageColor > 225) - c = View::highlightColor(); - else - c = backgroundColor.light( 115 ); //15% lighter - else - c = backgroundColor.light( 125 ); //25% lighter - - painter.setBackgroundColor( c ); - } - else { - TQColor bg( backgroundColor ); - - // Handle printers separately. - if ( !painter.device()->isExtDev() ) { - if ( bg.isValid() ) - painter.setBackgroundColor( bg ); - else - painter.setBackgroundColor( defaultColorGroup.base() ); - } - else { - //bad hack but there is a qt bug - //so I can print backgroundcolor - TQBrush bb( bg ); - if ( !bg.isValid() ) - bb.setColor( TQt::white ); - - painter.fillRect( zoomedCellRect, bb ); - return; - } - } - - // Erase the background of the cell. - if ( !painter.device()->isExtDev() ) - painter.eraseRect( zoomedCellRect ); - - // Get a background brush - TQBrush bb; - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundBrush, true ) ) - bb = d->extra()->conditions->matchedStyle()->backGroundBrush(); - else - bb = backGroundBrush( cellRef.x(), cellRef.y() ); - - // Draw background pattern if necessary. - if ( bb.style() != TQt::NoBrush ) - painter.fillRect( zoomedCellRect, bb ); - - backgroundColor = painter.backgroundColor(); -} - - -// Paint the standard light grey borders that are always visible. -// -void Cell::paintDefaultBorders( TQPainter& painter, const KoRect &rect, - const KoRect &cellRect, - const TQPoint &cellRef, - bool paintBorderRight, bool /*paintBorderBottom*/, - bool paintBorderLeft, bool paintBorderTop, - TQPen const & rightPen, TQPen const & /*bottomPen*/, - TQPen const & leftPen, TQPen const & topPen ) -{ - /* - *** Notes about optimisation *** - - This function was painting the top , left , right & bottom lines in almost all cells previously, contrary to what the comment - below says should happen. There doesn't appear to be a UI option to enable or disable showing of the grid when printing at the moment, - so I have disabled drawing of right and bottom borders for all cells. - - I also couldn't work out under what conditions the variables dt / db would come out as anything other than 0 in the code - for painting the various borders. The effTopBorderPen / effBottomBorderPen calls were taking up a lot of time - according some profiling I did. If that code really is necessary, we need to find a more efficient way of getting the widths - than grabbing the whole TQPen object and asking it. - - - --Robert Knight (robertknight@gmail.com) - */ - Doc* doc = sheet()->doc(); - - Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); - bool paintingToExternalDevice = painter.device()->isExtDev(); - - // Each cell is responsible for drawing it's top and left portions - // of the "default" grid. --Or not drawing it if it shouldn't be - // there. It's also responsible to paint the right and bottom, if - // it is the last cell on a print out. - - bool paintTop; - bool paintLeft; - bool paintBottom=false; - bool paintRight=false; - - paintLeft = ( paintBorderLeft && leftPen.style() == TQt::NoPen - && sheet()->getShowGrid() && sheetDir==Sheet::LeftToRight ); - paintRight = ( paintBorderRight && rightPen.style() == TQt::NoPen - && sheet()->getShowGrid() && sheetDir==Sheet::RightToLeft ); - paintTop = ( paintBorderTop && topPen.style() == TQt::NoPen - && sheet()->getShowGrid() ); -// paintBottom = ( paintBorderBottom && sheet()->getShowGrid() -// && bottomPen.style() == TQt::NoPen ); - - - //Set the single-pixel with pen for drawing the borders with. - painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); - - // If there are extra cells, there might be more conditions. - if (d->hasExtra()) { - TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); - TQValueList::const_iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - Cell *cell = *it; - - paintTop = paintTop && ( cell->row() == cellRef.y() ); - paintBottom = false; - - if ( sheetDir == Sheet::RightToLeft ) { - paintRight = paintRight && ( cell->column() == cellRef.x() ); - paintLeft = false; - } - else { - paintLeft = paintLeft && ( cell->column() == cellRef.x() ); - paintRight = false; - } - } - } - - // The left border. - if ( paintLeft ) { - int dt = 0; - int db = 0; - - #if 0 - if ( cellRef.x() > 1 ) { - Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1, - cellRef.y() ); - TQPen t = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() ); - TQPen b = cell_west->effBottomBorderPen( cellRef.x() - 1, cellRef.y() ); - - if ( t.style() != TQt::NoPen ) - dt = ( t.width() + 1 )/2; - if ( b.style() != TQt::NoPen ) - db = ( t.width() / 2); - } - #endif - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( paintingToExternalDevice ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); - else - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() + dt ), - doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.bottom() - db ) ); - else - painter.drawLine( doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.y() + dt ), - doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.bottom() - db ) ); - } - } - - - // The top border. - if ( paintTop ) { - int dl = 0; - int dr = 0; - - #if 0 - if ( cellRef.y() > 1 ) { - Cell *cell_north = format()->sheet()->cellAt( cellRef.x(), - cellRef.y() - 1 ); - - TQPen l = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 ); - TQPen r = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); - - if ( l.style() != TQt::NoPen ) - dl = ( l.width() - 1 ) / 2 + 1; - if ( r.style() != TQt::NoPen ) - dr = r.width() / 2; - } - #endif - - - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( paintingToExternalDevice ) { - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.y() ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.y() ) ) ); - } - else { - painter.drawLine( doc->zoomItX( cellRect.x() + dl ), - doc->zoomItY( cellRect.y() ), - doc->zoomItX( cellRect.right() - dr ), - doc->zoomItY( cellRect.y() ) ); - } - } - - - // The right border. - if ( paintRight ) { - int dt = 0; - int db = 0; - - #if 0 - if ( cellRef.x() < KS_colMax ) { - Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1, - cellRef.y() ); - - TQPen t = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() ); - TQPen b = cell_east->effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); - - if ( t.style() != TQt::NoPen ) - dt = ( t.width() + 1 ) / 2; - if ( b.style() != TQt::NoPen ) - db = ( t.width() / 2); - } - #endif - - //painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); - else - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.y() + dt ), - doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.bottom() - db ) ); - else - painter.drawLine( doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() + dt ), - doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.bottom() - db ) ); - } - } - - // The bottom border. - /*if ( paintBottom ) { - int dl = 0; - int dr = 0; - if ( cellRef.y() < KS_rowMax ) { - Cell *cell_south = format()->sheet()->cellAt( cellRef.x(), - cellRef.y() + 1 ); - - TQPen l = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); - TQPen r = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); - - if ( l.style() != TQt::NoPen ) - dl = ( l.width() - 1 ) / 2 + 1; - if ( r.style() != TQt::NoPen ) - dr = r.width() / 2; - } - - painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ), - doc->zoomItY( TQMAX( rect.top(), cellRect.bottom() ) ), - doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ), - doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() ) ) ); - } - else { - painter.drawLine( doc->zoomItX( cellRect.x() + dl ), - doc->zoomItY( cellRect.bottom() ), - doc->zoomItX( cellRect.right() - dr ), - doc->zoomItY( cellRect.bottom() ) ); - } - }*/ -} - - -// Paint a comment indicator if the cell has a comment. -// -void Cell::paintCommentIndicator( TQPainter& painter, - const KoRect &cellRect, - const TQPoint &/*cellRef*/, - TQColor &backgroundColor ) -{ - Doc * doc = sheet()->doc(); - - // Point the little corner if there is a comment attached - // to this cell. - if ( ( format()->propertiesMask() & (uint) Format::PComment ) - && cellRect.width() > 10.0 - && cellRect.height() > 10.0 - && ( sheet()->print()->printCommentIndicator() - || ( !painter.device()->isExtDev() && sheet()->getShowCommentIndicator() ) ) ) { - TQColor penColor = TQt::red; - - // If background has high red part, switch to blue. - if ( tqRed( backgroundColor.rgb() ) > 127 && - tqGreen( backgroundColor.rgb() ) < 80 && - tqBlue( backgroundColor.rgb() ) < 80 ) - { - penColor = TQt::blue; - } - - // Get the triangle. - TQPointArray point( 3 ); - if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) { - point.setPoint( 0, doc->zoomItX( cellRect.x() + 6.0 ), - doc->zoomItY( cellRect.y() ) ); - point.setPoint( 1, doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.y() ) ); - point.setPoint( 2, doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.y() + 6.0 ) ); - } - else { - point.setPoint( 0, doc->zoomItX( cellRect.right() - 5.0 ), - doc->zoomItY( cellRect.y() ) ); - point.setPoint( 1, doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() ) ); - point.setPoint( 2, doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() + 5.0 ) ); - } - - // And draw it. - painter.setBrush( TQBrush( penColor ) ); - painter.setPen( TQt::NoPen ); - painter.drawPolygon( point ); - } -} - - - -// Paint a small rectangle if this cell holds a formula. -// -void Cell::paintFormulaIndicator( TQPainter& painter, - const KoRect &cellRect, - TQColor &backgroundColor ) -{ - if ( isFormula() && - format()->sheet()->getShowFormulaIndicator() && - cellRect.width() > 10.0 && - cellRect.height() > 10.0 ) - { - Doc* doc = sheet()->doc(); - - TQColor penColor = TQt::blue; - // If background has high blue part, switch to red. - if ( tqRed( backgroundColor.rgb() ) < 80 && - tqGreen( backgroundColor.rgb() ) < 80 && - tqBlue( backgroundColor.rgb() ) > 127 ) - { - penColor = TQt::red; - } - - // Get the triangle... - TQPointArray point( 3 ); - if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) { - point.setPoint( 0, doc->zoomItX( cellRect.right() - 6.0 ), - doc->zoomItY( cellRect.bottom() ) ); - point.setPoint( 1, doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.bottom() ) ); - point.setPoint( 2, doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.bottom() - 6.0 ) ); - } - else { - point.setPoint( 0, doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.bottom() - 6.0 ) ); - point.setPoint( 1, doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.bottom() ) ); - point.setPoint( 2, doc->zoomItX( cellRect.x() + 6.0 ), - doc->zoomItY( cellRect.bottom() ) ); - } - - // ...and draw it. - painter.setBrush( TQBrush( penColor ) ); - painter.setPen( TQt::NoPen ); - painter.drawPolygon( point ); - } -} - - -// Paint an indicator that the text in the cell is cut. -// -void Cell::paintMoreTextIndicator( TQPainter& painter, - const KoRect &cellRect, - TQColor &backgroundColor ) -{ - // Show a red triangle when it's not possible to write all text in cell. - // Don't print the red triangle if we're printing. - if( testFlag( Flag_CellTooShortX ) && - !painter.device()->isExtDev() && - cellRect.height() > 4.0 && - cellRect.width() > 4.0 ) - { - Doc* doc = sheet()->doc(); - - TQColor penColor = TQt::red; - // If background has high red part, switch to blue. - if ( tqRed( backgroundColor.rgb() ) > 127 - && tqGreen( backgroundColor.rgb() ) < 80 - && tqBlue( backgroundColor.rgb() ) < 80 ) - { - penColor = TQt::blue; - } - - // Get the triangle... - TQPointArray point( 3 ); - if ( d->strOutText.isRightToLeft() ) { - point.setPoint( 0, doc->zoomItX( cellRect.left() + 4.0 ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 -4.0 ) ); - point.setPoint( 1, doc->zoomItX( cellRect.left() ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 )); - point.setPoint( 2, doc->zoomItX( cellRect.left() + 4.0 ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 +4.0 ) ); - } - else { - point.setPoint( 0, doc->zoomItX( cellRect.right() - 4.0 ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 - 4.0 ) ); - point.setPoint( 1, doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ) ); - point.setPoint( 2, doc->zoomItX( cellRect.right() - 4.0 ), - doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 + 4.0 ) ); - } - - // ...and paint it. - painter.setBrush( TQBrush( penColor ) ); - painter.setPen( TQt::NoPen ); - painter.drawPolygon( point ); - } -} - - -// Paint the real contents of a cell - the text. -// -void Cell::paintText( TQPainter& painter, - const KoRect &cellRect, - const TQPoint &cellRef ) -{ - Doc *doc = sheet()->doc(); - - ColumnFormat *colFormat = format()->sheet()->columnFormat( cellRef.x() ); - - TQColorGroup defaultColorGroup = TQApplication::palette().active(); - TQColor textColorPrint = effTextColor( cellRef.x(), cellRef.y() ); - - // Resolve the text color if invalid (=default). - if ( !textColorPrint.isValid() ) { - if ( painter.device()->isExtDev() ) - textColorPrint = TQt::black; - else - textColorPrint = TQApplication::palette().active().text(); - } - - TQPen tmpPen( textColorPrint ); - - // Set the font according to the current zoom. - applyZoomedFont( painter, cellRef.x(), cellRef.y() ); - - // Check for red font color for negative values. - if ( !d->hasExtra() - || !d->extra()->conditions - || !d->extra()->conditions->matchedStyle() ) { - if ( value().isNumber() - && !( format()->sheet()->getShowFormula() - && !( format()->sheet()->isProtected() - && format()->isHideFormula( d->column, d->row ) ) ) ) - { - double v = value().asFloat(); - if ( format()->floatColor( cellRef.x(), cellRef.y()) == Format::NegRed - && v < 0.0 ) - tmpPen.setColor( TQt::red ); - } - } - - // Check for blue color, for hyperlink. - if ( !link().isEmpty() ) { - tmpPen.setColor( TQApplication::palette().active().link() ); - TQFont f = painter.font(); - f.setUnderline( true ); - painter.setFont( f ); - } - -#if 0 -/**** - - For now I am commenting this out -- with the default color display you - can read normal text through a highlighted background. Maybe this isn't - always the case, though, and we can put the highlighted text color back in. - In that case, we need to somewhere in here figure out if the text overlaps - another cell outside of the selection, otherwise that portion of the text - will be printed white on white. So just that portion would need to be - painted again in the normal color. - - This should probably be done eventually, anyway, because I like using the - reverse text color for highlighted cells. I just don't like extending the - cell 'highlight' background outside of the selection rectangle because it - looks REALLY ugly. -*/ - - if ( selected && ( cellRef.x() != marker.x() || cellRef.y() != marker.y() ) ) - { - TQPen p( tmpPen ); - p.setColor( defaultColorGroup.highlightedText() ); - painter.setPen( p ); - } - else { - painter.setPen(tmpPen); - } -#endif - painter.setPen( tmpPen ); - - TQString tmpText = d->strOutText; - double tmpHeight = d->textHeight; - double tmpWidth = d->textWidth; - - // If the cell is to narrow to paint the whole contents, then pick - // out a part of the content that we paint. The result of this is - // dependent on the data type of the content. - // - // FIXME: Make this dependent on the height as well. - // - if ( testFlag( Flag_CellTooShortX ) ) { - d->strOutText = textDisplaying( painter ); - - // Recalculate the text width and the offset. - textSize( painter ); - offsetAlign( column(), row() ); - } - - // Hide zero. - if ( format()->sheet()->getHideZero() - && value().isNumber() - && value().asFloat() == 0 ) { - d->strOutText = TQString(); - } - - // Clear extra cell if column or row is hidden - // - // FIXME: I think this should be done before the call to - // textDisplaying() above. - // - if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) { - freeAllObscuredCells(); /* TODO: This looks dangerous...must check when I - have time */ - d->strOutText = ""; - } - - double indent = 0.0; - double offsetCellTooShort = 0.0; - int a = effAlignX(); - - // Apply indent if text is align to left not when text is at right or middle. - if ( a == Format::Left && !isEmpty() ) { - // FIXME: The following condition should be remade into a call to - // a new convenience function: - // if ( hasConditionStyleFeature( Style::SIndent, true )... - // This should be done throughout the entire file. - // - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SIndent, true ) ) - indent = d->extra()->conditions->matchedStyle()->indent(); - else - indent = format()->getIndent( column(), row() ); - } - - // Made an offset, otherwise ### is under red triangle. - if ( a == Format::Right && !isEmpty() && testFlag( Flag_CellTooShortX ) ) - offsetCellTooShort = format()->sheet()->doc()->unzoomItX( 4 ); - - TQFontMetrics fm2 = painter.fontMetrics(); - double offsetFont = 0.0; - - if ( format()->alignY( column(), row() ) == Format::Bottom - && format()->textFontUnderline( column(), row() ) ) - offsetFont = format()->sheet()->doc()->unzoomItX( fm2.underlinePos() + 1 ); - - int tmpAngle; - bool tmpMultiRow; - bool tmpVerticalText; - - // Check for angled or vertical text. - if ( d->hasExtra() - && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - { - Style *matchedStyle = d->extra()->conditions->matchedStyle(); - - if ( matchedStyle->hasFeature( Style::SAngle, true ) ) - tmpAngle = d->extra()->conditions->matchedStyle()->rotateAngle(); - else - tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() ); - - if ( matchedStyle->hasFeature( Style::SVerticalText, true ) ) - tmpVerticalText = matchedStyle->hasProperty( Style::PVerticalText ); - else - tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() ); - - if ( matchedStyle->hasFeature( Style::SMultiRow, true ) ) - tmpMultiRow = matchedStyle->hasProperty( Style::PMultiRow ); - else - tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() ); - } - else { - tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() ); - tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() ); - tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() ); - } - - // Actually paint the text. - // There are 4 possible cases: - // - One line of text , horizontal - // - Angled text - // - Multiple rows of text , horizontal - // - Vertical text - if ( !tmpMultiRow && !tmpVerticalText && !tmpAngle ) { - // Case 1: The simple case, one line, no angle. - - painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX - offsetCellTooShort ), - doc->zoomItY( cellRect.y() + d->textY - offsetFont ), d->strOutText ); - } - else if ( tmpAngle != 0 ) { - // Case 2: an angle. - - int angle = tmpAngle; - TQFontMetrics fm = painter.fontMetrics(); - - painter.rotate( angle ); - double x; - if ( angle > 0 ) - x = indent + cellRect.x() + d->textX; - else - x = indent + cellRect.x() + d->textX - - doc->unzoomItX((int) (( fm.descent() + fm.ascent() ) * sin( angle * M_PI / 180 ))); - double y; - if ( angle > 0 ) - y = cellRect.y() + d->textY; - else - y = cellRect.y() + d->textY + d->textHeight; - painter.drawText( doc->zoomItX( x * cos( angle * M_PI / 180 ) + - y * sin( angle * M_PI / 180 ) ), - doc->zoomItY( -x * sin( angle * M_PI / 180 ) + - y * cos( angle * M_PI / 180 ) ), - d->strOutText ); - painter.rotate( -angle ); - } - else if ( tmpMultiRow && !tmpVerticalText ) { - // Case 3: Multiple rows, but horizontal. - - TQString t; - int i; - int pos = 0; - double dy = 0.0; - TQFontMetrics fm = painter.fontMetrics(); - do { - i = d->strOutText.find( "\n", pos ); - if ( i == -1 ) - t = d->strOutText.mid( pos, d->strOutText.length() - pos ); - else { - t = d->strOutText.mid( pos, i - pos ); - pos = i + 1; - } - - int align = effAlignX(); - if ( format()->sheet()->getShowFormula() - && !( format()->sheet()->isProtected() - && format()->isHideFormula( d->column, d->row ) ) ) - align = Format::Left; - - // #### Torben: This looks duplicated for me - switch ( align ) { - case Format::Left: - d->textX = effLeftBorderPen( cellRef.x(), cellRef.y() ).width() + BORDER_SPACE; - break; - - case Format::Right: - d->textX = cellRect.width() - BORDER_SPACE - doc->unzoomItX( fm.width( t ) ) - - effRightBorderPen( cellRef.x(), cellRef.y() ).width(); - break; - - case Format::Center: - d->textX = ( cellRect.width() - doc->unzoomItX( fm.width( t ) ) ) / 2; - } - - painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ), - doc->zoomItY( cellRect.y() + d->textY + dy ), t ); - dy += doc->unzoomItY( fm.descent() + fm.ascent() ); - } while ( i != -1 ); - } - else if ( tmpVerticalText && !d->strOutText.isEmpty() ) { - // Case 4: Vertical text. - - TQString t; - int i = 0; - int len = 0; - double dy = 0.0; - TQFontMetrics fm = painter.fontMetrics(); - do { - len = d->strOutText.length(); - t = d->strOutText.at( i ); - painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ), - doc->zoomItY( cellRect.y() + d->textY + dy ), t ); - dy += doc->unzoomItY( fm.descent() + fm.ascent() ); - i++; - } while ( i != len ); - } - - // Check for too short cell and set the outText for future reference. - if ( testFlag( Flag_CellTooShortX ) ) { - d->strOutText = tmpText; - d->textHeight = tmpHeight; - d->textWidth = tmpWidth; - } - - if ( format()->sheet()->getHideZero() && value().isNumber() - && value().asFloat() == 0 ) - d->strOutText = tmpText; - - if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) - d->strOutText = tmpText; -} - - -// Paint page borders on the page. Only do this on the screen. -// -void Cell::paintPageBorders( TQPainter& painter, - const KoRect &cellRect, - const TQPoint &cellRef, - bool paintBorderRight, - bool paintBorderBottom ) -{ - // Not screen? Return immediately. - if ( painter.device()->isExtDev() ) - return; - - if ( ! format()->sheet()->isShowPageBorders() ) - return; - - SheetPrint* print = format()->sheet()->print(); - - Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); - - Doc* doc = sheet()->doc(); - int zcellRect_left = doc->zoomItX (cellRect.left()); - int zcellRect_right = doc->zoomItX (cellRect.right()); - int zcellRect_top = doc->zoomItY (cellRect.top()); - int zcellRect_bottom = doc->zoomItY (cellRect.bottom()); - - // Draw page borders - - if ( cellRef.x() >= print->printRange().left() - && cellRef.x() <= print->printRange().right() + 1 - && cellRef.y() >= print->printRange().top() - && cellRef.y() <= print->printRange().bottom() + 1 ) - { - if ( print->isOnNewPageX( cellRef.x() ) - && cellRef.y() <= print->printRange().bottom() ) - { - painter.setPen( sheet()->doc()->pageBorderColor() ); - - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_right, zcellRect_top, - zcellRect_right, zcellRect_bottom ); - else - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_left, zcellRect_bottom ); - } - - if ( print->isOnNewPageY( cellRef.y() ) && - ( cellRef.x() <= print->printRange().right() ) ) - { - painter.setPen( sheet()->doc()->pageBorderColor() ); - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_right, zcellRect_top ); - } - - if ( paintBorderRight ) { - if ( print->isOnNewPageX( cellRef.x() + 1 ) - && cellRef.y() <= print->printRange().bottom() ) { - painter.setPen( sheet()->doc()->pageBorderColor() ); - - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_left, zcellRect_bottom ); - else - painter.drawLine( zcellRect_right, zcellRect_top, - zcellRect_right, zcellRect_bottom ); - } - } - - if ( paintBorderBottom ) { - if ( print->isOnNewPageY( cellRef.y() + 1 ) - && cellRef.x() <= print->printRange().right() ) { - painter.setPen( sheet()->doc()->pageBorderColor() ); - painter.drawLine( zcellRect_left, zcellRect_bottom, - zcellRect_right, zcellRect_bottom ); - } - } - } -} - - -// Paint the cell borders. -// -void Cell::paintCellBorders( TQPainter& painter, const KoRect& rect, - const KoRect &cellRect, - const TQPoint &cellRef, - bool paintRight, bool paintBottom, - bool paintLeft, bool paintTop, - TQPen & _rightPen, TQPen & _bottomPen, - TQPen & _leftPen, TQPen & _topPen ) -{ - - //Sanity check: If we are not painting any of the borders then the function - //really shouldn't be called at all. - if ( (!paintLeft) && (!paintRight) && (!paintTop) && (!paintBottom) ) - return; - - Doc * doc = sheet()->doc(); - - Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); - - // compute zoomed rectangles - // I don't use KoRect, because that ends up producing lots of warnings - // about double->int conversions in calls to painter.drawLine - int zrect_left (doc->zoomItX (rect.left())); - int zrect_right (doc->zoomItX (rect.right())); - int zrect_top (doc->zoomItY (rect.top())); - int zrect_bottom (doc->zoomItY (rect.bottom())); - int zcellRect_left (doc->zoomItX (cellRect.left())); - int zcellRect_right (doc->zoomItX (cellRect.right())); - int zcellRect_top (doc->zoomItY (cellRect.top())); - int zcellRect_bottom (doc->zoomItY (cellRect.bottom())); - - /* we might not paint some borders if this cell is merged with another in - that direction - bool paintLeft = paintBorderLeft; - bool paintRight = paintBorderRight; - bool paintTop = paintBorderTop; - bool paintBottom = paintBorderBottom; - */ - - // paintRight = paintRight && ( extraXCells() == 0 ); - // paintBottom = paintBottom && ( d->extra()->extraYCells() == 0 ); - - if (d->hasExtra()) { - TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); - TQValueList::const_iterator end = d->extra()->obscuringCells.end(); - for ( ; it != end; ++it ) { - Cell* cell = *it; - - int xDiff = cellRef.x() - cell->column(); - int yDiff = cellRef.y() - cell->row(); - paintLeft = paintLeft && xDiff == 0; - paintTop = paintTop && yDiff == 0; - - // Paint the border(s) if either this one should or if we have a - // merged cell with this cell as its border. - paintRight = paintRight && cell->mergedXCells() == xDiff; - paintBottom = paintBottom && cell->mergedYCells() == yDiff; - } - } - - // Must create copies of these since otherwise the zoomIt() - // operation will be performed on them repeatedly. - TQPen leftPen( _leftPen ); - TQPen rightPen( _rightPen ); - TQPen topPen( _topPen ); - TQPen bottomPen( _bottomPen ); - - // Determine the pens that should be used for drawing - // the borders. - // - int left_penWidth = TQMAX( 1, doc->zoomItX( leftPen.width() ) ); - int right_penWidth = TQMAX( 1, doc->zoomItX( rightPen.width() ) ); - int top_penWidth = TQMAX( 1, doc->zoomItY( topPen.width() ) ); - int bottom_penWidth = TQMAX( 1, doc->zoomItY( bottomPen.width() ) ); - - leftPen.setWidth( left_penWidth ); - rightPen.setWidth( right_penWidth ); - topPen.setWidth( top_penWidth ); - bottomPen.setWidth( bottom_penWidth ); - - if ( paintLeft && leftPen.style() != TQt::NoPen ) { - int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 + - ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 ); - int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1; - - painter.setPen( leftPen ); - - //kdDebug(36001) << " painting left border of cell " << name() << endl; - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - // FIXME: There is probably Cut&Paste bugs here as well as below. - // The TQMIN/TQMAX and left/right pairs don't really make sense. - // - // UPDATE: In fact, most of these TQMIN/TQMAX combinations - // are TOTALLY BOGUS. For one thing, the idea - // that we always have full cells on paper is wrong - // since we can have embedded sheets in e.g. kword, - // and those can be arbitrarily clipped. WE HAVE TO - // REVISE THIS WHOLE BORDER PAINTING SECTION! - // - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMIN( zrect_right, zcellRect_right ), - TQMAX( zrect_top, zcellRect_top - top ), - TQMIN( zrect_right, zcellRect_right ), - TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); - else - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_top - top ), - TQMAX( zrect_left, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_right, - zcellRect_top - top, - zcellRect_right, - zcellRect_bottom + bottom ); - else - painter.drawLine( zcellRect_left, - zcellRect_top - top, - zcellRect_left, - zcellRect_bottom + bottom ); - } - } - - if ( paintRight && rightPen.style() != TQt::NoPen ) { - int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 + - ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 ); - int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1; - - painter.setPen( rightPen ); - - //kdDebug(36001) << " painting right border of cell " << name() << endl; - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_top - top ), - TQMAX( zrect_left, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); - else { - // FIXME: This is the way all these things should look. - // Make it so. - // - // Only print the right border if it is visible. - if ( zcellRect_right <= zrect_right + right_penWidth / 2) - painter.drawLine( zcellRect_right, - TQMAX( zrect_top, zcellRect_top - top ), - zcellRect_right, - TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); - } - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_left, - zcellRect_top - top, - zcellRect_left, - zcellRect_bottom + bottom ); - else - painter.drawLine( zcellRect_right, - zcellRect_top - top, - zcellRect_right, - zcellRect_bottom + bottom ); - } - } - - if ( paintTop && topPen.style() != TQt::NoPen ) { - painter.setPen( topPen ); - - //kdDebug(36001) << " painting top border of cell " << name() - // << " [" << zcellRect_left << "," << zcellRect_right - // << ": " << zcellRect_right - zcellRect_left << "]" << endl; - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( zcellRect_top >= zrect_top + top_penWidth / 2) - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - zcellRect_top, - TQMIN( zrect_right, zcellRect_right ), - zcellRect_top ); - } - else { - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_right, zcellRect_top ); - } - } - - if ( paintBottom && bottomPen.style() != TQt::NoPen ) { - painter.setPen( bottomPen ); - - //kdDebug(36001) << " painting bottom border of cell " << name() - // << " [" << zcellRect_left << "," << zcellRect_right - // << ": " << zcellRect_right - zcellRect_left << "]" << endl; - - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( zcellRect_bottom <= zrect_bottom + bottom_penWidth / 2) - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - zcellRect_bottom, - TQMIN( zrect_right, zcellRect_right ), - zcellRect_bottom ); - } - else { - painter.drawLine( zcellRect_left, zcellRect_bottom, - zcellRect_right, zcellRect_bottom ); - } - } - - // FIXME: Look very closely at when the following code is really needed. - // I can't really see any case, but I might be wrong. - // Since the code below is buggy, and incredibly complex, - // I am currently disabling it. If somebody wants to enable - // it again, then please also solve bug 68977: "Embedded KSpread - // document printing problem" at the same time. - return; - -#if 0 - // Look at the cells on our corners. It may happen that we - // just erased parts of their borders corner, so we might need - // to repaint these corners. - // - TQPen vert_pen, horz_pen; - int vert_penWidth, horz_penWidth; - - // Some useful referenses. - Cell *cell_north = format()->sheet()->cellAt( cellRef.x(), - cellRef.y() - 1 ); - Cell *cell_northwest = format()->sheet()->cellAt( cellRef.x() - 1, - cellRef.y() - 1 ); - Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1, - cellRef.y() ); - Cell *cell_northeast = format()->sheet()->cellAt( cellRef.x() + 1, - cellRef.y() - 1 ); - Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1, - cellRef.y() ); - Cell *cell_south = format()->sheet()->cellAt( cellRef.x(), - cellRef.y() + 1 ); - Cell *cell_southwest = format()->sheet()->cellAt( cellRef.x() - 1, - cellRef.y() + 1 ); - Cell *cell_southeast = format()->sheet()->cellAt( cellRef.x() + 1, - cellRef.y() + 1 ); - - // Fix the borders which meet at the top left corner - if ( cell_north->effLeftBorderValue( cellRef.x(), cellRef.y() - 1 ) - >= cell_northwest->effRightBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) ) - vert_pen = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 ); - else - vert_pen = cell_northwest->effRightBorderPen( cellRef.x() - 1, - cellRef.y() - 1 ); - - vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) ); - vert_pen.setWidth( vert_penWidth ); - - if ( vert_pen.style() != TQt::NoPen ) { - if ( cell_west->effTopBorderValue( cellRef.x() - 1, cellRef.y() ) - >= cell_northwest->effBottomBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) ) - horz_pen = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() ); - else - horz_pen = cell_northwest->effBottomBorderPen( cellRef.x() - 1, - cellRef.y() - 1 ); - - horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) ); - int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1; - - painter.setPen( vert_pen ); - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMAX( zrect_left, zcellRect_right ), - TQMAX( zrect_top, zcellRect_top ), - TQMIN( zrect_right, zcellRect_right ), - TQMIN( zrect_bottom, zcellRect_top + bottom ) ); - else - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_top ), - TQMIN( zrect_right, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_top + bottom ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_right, zcellRect_top, - zcellRect_right, zcellRect_top + bottom ); - else - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_left, zcellRect_top + bottom ); - } - } - - // Fix the borders which meet at the top right corner - if ( cell_north->effRightBorderValue( cellRef.x(), cellRef.y() - 1 ) - >= cell_northeast->effLeftBorderValue( cellRef.x() + 1, - cellRef.y() - 1 ) ) - vert_pen = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); - else - vert_pen = cell_northeast->effLeftBorderPen( cellRef.x() + 1, - cellRef.y() - 1 ); - - // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); - vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) ); - vert_pen.setWidth( vert_penWidth ); - if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) { - if ( cell_east->effTopBorderValue( cellRef.x() + 1, cellRef.y() ) - >= cell_northeast->effBottomBorderValue( cellRef.x() + 1, - cellRef.y() - 1 ) ) - horz_pen = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() ); - else - horz_pen = cell_northeast->effBottomBorderPen( cellRef.x() + 1, - cellRef.y() - 1 ); - - // horz_pen = effTopBorderPen( cellRef.x() + 1, cellRef.y() ); - horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) ); - int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1; - - painter.setPen( vert_pen ); - //If we are on paper printout, we limit the length of the lines - //On paper, we always have full cells, on screen not - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_top ), - TQMIN( zrect_right, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_top + bottom ) ); - else - painter.drawLine( TQMAX( zrect_left, zcellRect_right ), - TQMAX( zrect_top, zcellRect_top ), - TQMIN( zrect_right, zcellRect_right ), - TQMIN( zrect_bottom, zcellRect_top + bottom ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_left, zcellRect_top, - zcellRect_left, zcellRect_top + bottom ); - else - painter.drawLine( zcellRect_right, zcellRect_top, - zcellRect_right, zcellRect_top + bottom ); - } - } - - // Bottom - if ( cellRef.y() < KS_rowMax ) { - // Fix the borders which meet at the bottom left corner - if ( cell_south->effLeftBorderValue( cellRef.x(), cellRef.y() + 1 ) - >= cell_southwest->effRightBorderValue( cellRef.x() - 1, - cellRef.y() + 1 ) ) - vert_pen = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); - else - vert_pen = cell_southwest->effRightBorderPen( cellRef.x() - 1, - cellRef.y() + 1 ); - - // vert_pen = effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); - vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) ); - vert_pen.setWidth( vert_penWidth ); - if ( vert_pen.style() != TQt::NoPen ) { - if ( cell_west->effBottomBorderValue( cellRef.x() - 1, cellRef.y() ) - >= cell_southwest->effTopBorderValue( cellRef.x() - 1, - cellRef.y() + 1 ) ) - horz_pen = cell_west->effBottomBorderPen( cellRef.x() - 1, - cellRef.y() ); - else - horz_pen = cell_southwest->effTopBorderPen( cellRef.x() - 1, - cellRef.y() + 1 ); - - // horz_pen = effBottomBorderPen( cellRef.x() - 1, cellRef.y() ); - horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) ); - int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2; - - painter.setPen( vert_pen ); - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMAX( zrect_left, zcellRect_right ), - TQMAX( zrect_top, zcellRect_bottom - bottom ), - TQMIN( zrect_right, zcellRect_right ), - TQMIN( zrect_bottom, zcellRect_bottom ) ); - else - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_bottom - bottom ), - TQMIN( zrect_right, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_bottom ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_right, zcellRect_bottom - bottom, - zcellRect_right, zcellRect_bottom ); - else - painter.drawLine( zcellRect_left, zcellRect_bottom - bottom, - zcellRect_left, zcellRect_bottom ); - } - } - - // Fix the borders which meet at the bottom right corner - if ( cell_south->effRightBorderValue( cellRef.x(), cellRef.y() + 1 ) - >= cell_southeast->effLeftBorderValue( cellRef.x() + 1, - cellRef.y() + 1 ) ) - vert_pen = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); - else - vert_pen = cell_southeast->effLeftBorderPen( cellRef.x() + 1, - cellRef.y() + 1 ); - - // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); - vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) ); - vert_pen.setWidth( vert_penWidth ); - if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) { - if ( cell_east ->effBottomBorderValue( cellRef.x() + 1, cellRef.y() ) - >= cell_southeast->effTopBorderValue( cellRef.x() + 1, - cellRef.y() + 1 ) ) - - horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() ) - ->effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); - else - horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() + 1 ) - ->effTopBorderPen( cellRef.x() + 1, cellRef.y() + 1 ); - - // horz_pen = effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); - horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) ); - int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2; - - painter.setPen( vert_pen ); - // If we are on paper printout, we limit the length of the lines. - // On paper, we always have full cells, on screen not. - if ( painter.device()->isExtDev() ) { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( TQMAX( zrect_left, zcellRect_left ), - TQMAX( zrect_top, zcellRect_bottom - bottom ), - TQMIN( zrect_right, zcellRect_left ), - TQMIN( zrect_bottom, zcellRect_bottom ) ); - else - painter.drawLine( TQMAX( zrect_left, zcellRect_right ), - TQMAX( zrect_top, zcellRect_bottom - bottom ), - TQMIN( zrect_right, zcellRect_right ), - TQMIN( zrect_bottom, zcellRect_bottom ) ); - } - else { - if ( sheetDir == Sheet::RightToLeft ) - painter.drawLine( zcellRect_left, zcellRect_bottom - bottom, - zcellRect_left, zcellRect_bottom ); - else - painter.drawLine( zcellRect_right, zcellRect_bottom - bottom, - zcellRect_right, zcellRect_bottom ); - } - } - } - #endif -} - - -// Paint diagonal lines through the cell. -// -void Cell::paintCellDiagonalLines( TQPainter& painter, - const KoRect &cellRect, - const TQPoint &cellRef ) -{ - if ( isPartOfMerged() ) - return; - - Doc* doc = sheet()->doc(); - - if ( effFallDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) { - painter.setPen( effFallDiagonalPen( cellRef.x(), cellRef.y() ) ); - painter.drawLine( doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.y() ), - doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.bottom() ) ); - } - - if ( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) { - painter.setPen( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ) ); - painter.drawLine( doc->zoomItX( cellRect.x() ), - doc->zoomItY( cellRect.bottom() ), - doc->zoomItX( cellRect.right() ), - doc->zoomItY( cellRect.y() ) ); - } -} - - -// End of Painting -// ================================================================ - - -int Cell::defineAlignX() -{ - int a = format()->align( column(), row() ); - if ( a == Format::Undefined ) - { - //numbers should be right-aligned by default, as well as BiDi text - if ((formatType() == Text_format) || value().isString()) - a = (d->strOutText.isRightToLeft()) ? - Format::Right : Format::Left; - else { - Value val = value(); - while (val.isArray()) val = val.element (0, 0); - if (val.isBoolean() || val.isNumber()) - a = Format::Right; - else - a = Format::Left; - } - } - return a; -} - -int Cell::effAlignX() -{ - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SAlignX, true ) ) - return d->extra()->conditions->matchedStyle()->alignX(); - - return defineAlignX(); -} - -// Cut strOutText, so that it only holds the part that can be displayed. -// -// Used in paintText(). -// - -TQString Cell::textDisplaying( TQPainter &_painter ) -{ - TQFontMetrics fm = _painter.fontMetrics(); - int a = format()->align( column(), row() ); - - bool isNumeric = value().isNumber(); - - if ( !format()->verticalText( column(),row() ) ) { - // Non-vertical text: the ordinary case. - - // Not enough space but align to left - double len = 0.0; - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - - for ( int i = column(); i <= column() + extraXCells; i++ ) { - ColumnFormat *cl2 = format()->sheet()->columnFormat( i ); - len += cl2->dblWidth() - 1.0; //-1.0 because the pixel in between 2 cells is shared between both cells - } - - TQString tmp; - double tmpIndent = 0.0; - if ( !isEmpty() ) - tmpIndent = format()->getIndent( column(), row() ); - - // Start out with the whole text, cut one character at a time, and - // when the text finally fits, return it. - for ( int i = d->strOutText.length(); i != 0; i-- ) - { - //Note that numbers are always treated as left-aligned since if we have to cut digits off, they should - //always be the least significant ones at the end of the string - if ( a == Format::Left || a == Format::Undefined || isNumeric) - tmp = d->strOutText.left(i); - else if ( a == Format::Right) - tmp = d->strOutText.right(i); - else - tmp = d->strOutText.mid( ( d->strOutText.length() - i ) / 2, i); - - if (isNumeric) - { - //For numeric values, we can cut off digits after the decimal point to make it fit, - //but not the integer part of the number. - //If this number still contains a fraction part then we don't need to do anything, if we have run - //out of space to fit even the integer part of the number then display ######### - //TODO Perhaps try to display integer part in standard form if there is not enough room for it? - - if (!tmp.contains('.')) - d->strOutText=TQString().fill('#',20); - } - - // 4 equal length of red triangle +1 point. - if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) + tmpIndent - < len - 4.0 - 1.0 ) - { - if ( format()->getAngle( column(), row() ) != 0 ) - { - TQString tmp2; - RowFormat *rl = format()->sheet()->rowFormat( row() ); - if ( d->textHeight > rl->dblHeight() ) - { - for ( int j = d->strOutText.length(); j != 0; j-- ) - { - tmp2 = d->strOutText.left( j ); - if ( format()->sheet()->doc()->unzoomItY( fm.width( tmp2 ) ) < rl->dblHeight() - 1.0 ) - { - return d->strOutText.left( TQMIN( tmp.length(), tmp2.length() ) ); - } - } - } - else - return tmp; - - } - else - return tmp; - } - } - return TQString( "" ); - } - else if ( format()->verticalText( column(), row() ) ) { - // Vertical text. - - RowFormat *rl = format()->sheet()->rowFormat( row() ); - double tmpIndent = 0.0; - - // Not enough space but align to left. - double len = 0.0; - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - - for ( int i = column(); i <= column() + extraXCells; i++ ) { - ColumnFormat *cl2 = format()->sheet()->columnFormat( i ); - - // -1.0 because the pixel in between 2 cells is shared between both cells - len += cl2->dblWidth() - 1.0; - } - - if ( !isEmpty() ) - tmpIndent = format()->getIndent( column(), row() ); - - if ( ( d->textWidth + tmpIndent > len ) || d->textWidth == 0.0 ) - return TQString( "" ); - - for ( int i = d->strOutText.length(); i != 0; i-- ) { - if ( format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent() ) * i - < rl->dblHeight() - 1.0 ) - return d->strOutText.left( i ); - } - - return TQString( "" ); - } - - ColumnFormat *cl = format()->sheet()->columnFormat( column() ); - double w = cl->dblWidth(); - - if ( d->hasExtra() && (d->extra()->extraWidth != 0.0) ) - w = d->extra()->extraWidth; - - TQString tmp; - for ( int i = d->strOutText.length(); i != 0; i-- ) { - tmp = d->strOutText.left( i ); - - // 4 equals length of red triangle +1 pixel - if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) < w - 4.0 - 1.0 ) - return tmp; - } - - return TQString(); -} - - -double Cell::dblWidth( int _col, const Canvas *_canvas ) const -{ - if ( _col < 0 ) - _col = d->column; - - if ( _canvas ) - { - if ( testFlag(Flag_Merged) ) - return d->extra()->extraWidth; - - const ColumnFormat *cl = format()->sheet()->columnFormat( _col ); - return cl->dblWidth( _canvas ); - } - - if ( testFlag(Flag_Merged) ) - return d->extra()->extraWidth; - - const ColumnFormat *cl = format()->sheet()->columnFormat( _col ); - return cl->dblWidth(); -} - -int Cell::width( int _col, const Canvas *_canvas ) const -{ - return int( dblWidth( _col, _canvas ) ); -} - -double Cell::dblHeight( int _row, const Canvas *_canvas ) const -{ - if ( _row < 0 ) - _row = d->row; - - if ( _canvas ) - { - if ( testFlag(Flag_Merged) ) - return d->extra()->extraHeight; - - const RowFormat *rl = format()->sheet()->rowFormat( _row ); - return rl->dblHeight( _canvas ); - } - - if ( testFlag(Flag_Merged) ) - return d->extra()->extraHeight; - - const RowFormat *rl = format()->sheet()->rowFormat( _row ); - return rl->dblHeight(); -} - -int Cell::height( int _row, const Canvas *_canvas ) const -{ - return int( dblHeight( _row, _canvas ) ); -} - -/////////////////////////////////////////// -// -// Misc Properties. -// Reimplementation of Format methods. -// -/////////////////////////////////////////// - -const TQBrush& Cell::backGroundBrush( int _col, int _row ) const -{ - if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) ) - { - const Cell* cell = d->extra()->obscuringCells.first(); - return cell->backGroundBrush( cell->column(), cell->row() ); - } - - return format()->backGroundBrush( _col, _row ); -} - -const TQColor& Cell::bgColor( int _col, int _row ) const -{ - if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) ) - { - const Cell* cell = d->extra()->obscuringCells.first(); - return cell->bgColor( cell->column(), cell->row() ); - } - - return format()->bgColor( _col, _row ); -} - -/////////////////////////////////////////// -// -// Borders. -// Reimplementation of Format methods. -// -/////////////////////////////////////////// - -void Cell::setLeftBorderPen( const TQPen& p ) -{ - if ( column() == 1 ) - { - Cell* cell = format()->sheet()->cellAt( column() - 1, row() ); - if ( cell && cell->format()->hasProperty( Format::PRightBorder ) - && format()->sheet()->cellAt( column(), row() ) == this ) - cell->format()->clearProperty( Format::PRightBorder ); - } - - format()->setLeftBorderPen( p ); -} - -void Cell::setTopBorderPen( const TQPen& p ) -{ - if ( row() == 1 ) - { - Cell* cell = format()->sheet()->cellAt( column(), row() - 1 ); - if ( cell && cell->format()->hasProperty( Format::PBottomBorder ) - && format()->sheet()->cellAt( column(), row() ) == this ) - cell->format()->clearProperty( Format::PBottomBorder ); - } - format()->setTopBorderPen( p ); -} - -void Cell::setRightBorderPen( const TQPen& p ) -{ - Cell* cell = 0L; - if ( column() < KS_colMax ) - cell = format()->sheet()->cellAt( column() + 1, row() ); - - if ( cell && cell->format()->hasProperty( Format::PLeftBorder ) - && format()->sheet()->cellAt( column(), row() ) == this ) - cell->format()->clearProperty( Format::PLeftBorder ); - - format()->setRightBorderPen( p ); -} - -void Cell::setBottomBorderPen( const TQPen& p ) -{ - Cell* cell = 0L; - if ( row() < KS_rowMax ) - cell = format()->sheet()->cellAt( column(), row() + 1 ); - - if ( cell && cell->format()->hasProperty( Format::PTopBorder ) - && format()->sheet()->cellAt( column(), row() ) == this ) - cell->format()->clearProperty( Format::PTopBorder ); - - format()->setBottomBorderPen( p ); -} - -const TQPen& Cell::rightBorderPen( int _col, int _row ) const -{ - if ( !format()->hasProperty( Format::PRightBorder ) && ( _col < KS_colMax ) ) - { - Cell * cell = format()->sheet()->cellAt( _col + 1, _row ); - if ( cell && cell->format()->hasProperty( Format::PLeftBorder ) ) - return cell->leftBorderPen( _col + 1, _row ); - } - - return format()->rightBorderPen( _col, _row ); -} - -const TQPen& Cell::leftBorderPen( int _col, int _row ) const -{ - if ( !format()->hasProperty( Format::PLeftBorder ) ) - { - const Cell * cell = format()->sheet()->cellAt( _col - 1, _row ); - if ( cell && cell->format()->hasProperty( Format::PRightBorder ) ) - return cell->rightBorderPen( _col - 1, _row ); - } - - return format()->leftBorderPen( _col, _row ); -} - -const TQPen& Cell::bottomBorderPen( int _col, int _row ) const -{ - if ( !format()->hasProperty( Format::PBottomBorder ) && ( _row < KS_rowMax ) ) - { - const Cell * cell = format()->sheet()->cellAt( _col, _row + 1 ); - if ( cell && cell->format()->hasProperty( Format::PTopBorder ) ) - return cell->topBorderPen( _col, _row + 1 ); - } - - return format()->bottomBorderPen( _col, _row ); -} - -const TQPen& Cell::topBorderPen( int _col, int _row ) const -{ - if ( !format()->hasProperty( Format::PTopBorder ) ) - { - const Cell * cell = format()->sheet()->cellAt( _col, _row - 1 ); - if ( cell->format()->hasProperty( Format::PBottomBorder ) ) - return cell->bottomBorderPen( _col, _row - 1 ); - } - - return format()->topBorderPen( _col, _row ); -} - -const TQColor & Cell::effTextColor( int col, int row ) const -{ - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::STextPen, true ) ) - return d->extra()->conditions->matchedStyle()->pen().color(); - - return format()->textColor( col, row ); -} - -const TQPen& Cell::effLeftBorderPen( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effLeftBorderPen( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SLeftBorder, true ) ) - return d->extra()->conditions->matchedStyle()->leftBorderPen(); - - return leftBorderPen( col, row ); -} - -const TQPen& Cell::effTopBorderPen( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effTopBorderPen( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::STopBorder, true ) ) - return d->extra()->conditions->matchedStyle()->topBorderPen(); - - return topBorderPen( col, row ); -} - -const TQPen& Cell::effRightBorderPen( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effRightBorderPen( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SRightBorder, true ) ) - return d->extra()->conditions->matchedStyle()->rightBorderPen(); - - return rightBorderPen( col, row ); -} - -const TQPen& Cell::effBottomBorderPen( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effBottomBorderPen( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBottomBorder, true ) ) - return d->extra()->conditions->matchedStyle()->bottomBorderPen(); - - return bottomBorderPen( col, row ); -} - -const TQPen & Cell::effGoUpDiagonalPen( int col, int row ) const -{ - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SGoUpDiagonal, true ) ) - return d->extra()->conditions->matchedStyle()->goUpDiagonalPen(); - - return format()->goUpDiagonalPen( col, row ); -} - -const TQPen & Cell::effFallDiagonalPen( int col, int row ) const -{ - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() - && d->extra()->conditions->matchedStyle()->hasFeature( Style::SFallDiagonal, true ) ) - return d->extra()->conditions->matchedStyle()->fallDiagonalPen(); - - return format()->fallDiagonalPen( col, row ); -} - -uint Cell::effBottomBorderValue( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effBottomBorderValue( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - return d->extra()->conditions->matchedStyle()->bottomPenValue(); - - return format()->bottomBorderValue( col, row ); -} - -uint Cell::effRightBorderValue( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effRightBorderValue( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - return d->extra()->conditions->matchedStyle()->rightPenValue(); - - return format()->rightBorderValue( col, row ); -} - -uint Cell::effLeftBorderValue( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effLeftBorderValue( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - return d->extra()->conditions->matchedStyle()->leftPenValue(); - - return format()->leftBorderValue( col, row ); -} - -uint Cell::effTopBorderValue( int col, int row ) const -{ - if ( isPartOfMerged() ) - { - Cell * cell = d->extra()->obscuringCells.first(); - return cell->effTopBorderValue( cell->column(), cell->row() ); - } - - if ( d->hasExtra() && d->extra()->conditions - && d->extra()->conditions->matchedStyle() ) - return d->extra()->conditions->matchedStyle()->topPenValue(); - - return format()->topBorderValue( col, row ); -} - -/////////////////////////////////////////// -// -// Precision -// -/////////////////////////////////////////// - -void Cell::incPrecision() -{ - //TODO: This is ugly. Why not simply regenerate the text to display? Tomas - - if ( !value().isNumber() ) - return; - int tmpPreci = format()->precision( column(), row() ); - - if ( tmpPreci == -1 ) - { - int pos = d->strOutText.find(decimal_point); - if ( pos == -1 ) - pos = d->strOutText.find('.'); - if ( pos == -1 ) - format()->setPrecision(1); - else - { - int start = 0; - if ( d->strOutText.find('%') != -1 ) - start = 2; - else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) ) - start = locale()->currencySymbol().length() + 1; - else if ( (start=d->strOutText.find('E')) != -1 ) - start = d->strOutText.length() - start; - - //kdDebug(36001) << "start=" << start << " pos=" << pos << " length=" << d->strOutText.length() << endl; - format()->setPrecision( TQMAX( 0, (int)d->strOutText.length() - start - pos ) ); - } - } - else if ( tmpPreci < 10 ) - { - format()->setPrecision( ++tmpPreci ); - } - setFlag(Flag_LayoutDirty); -} - -void Cell::decPrecision() -{ - //TODO: This is ugly. Why not simply regenerate the text to display? Tomas - - if ( !value().isNumber() ) - return; - int preciTmp = format()->precision( column(), row() ); -// kdDebug(36001) << "decPrecision: tmpPreci = " << tmpPreci << endl; - if ( format()->precision(column(),row()) == -1 ) - { - int pos = d->strOutText.find( decimal_point ); - int start = 0; - if ( d->strOutText.find('%') != -1 ) - start = 2; - else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) ) - start = locale()->currencySymbol().length() + 1; - else if ( (start = d->strOutText.find('E')) != -1 ) - start = d->strOutText.length() - start; - else - start = 0; - - if ( pos == -1 ) - return; - - format()->setPrecision(d->strOutText.length() - pos - 2 - start); - // if ( preciTmp < 0 ) - // format()->setPrecision( preciTmp ); - } - else if ( preciTmp > 0 ) - { - format()->setPrecision( --preciTmp ); - } - setFlag( Flag_LayoutDirty ); -} - -//set numerical value -//used in Sheet::setSeries (nowhere else yet) -void Cell::setNumber( double number ) -{ - setValue( Value( number ) ); - - d->strText.setNum( number ); - setDisplayText(d->strText); - checkNumberFormat(); -} - -void Cell::setCellText( const TQString& _text, bool asText ) -{ - // TQString ctext = _text; - -// (Tomas) is this trim necessary for anything ? -// if( ctext.length() > 5000 ) -// ctext = ctext.left( 5000 ); - - // empty string ? - if (_text.length() == 0) { - d->strOutText = d->strText = ""; - setValue (Value::empty()); - return; - } - - // as text ? - if (asText) { - d->strOutText = _text; - d->strText = _text; - setValue (Value (_text)); - - return; - } - - TQString oldText = d->strText; - setDisplayText( _text ); - if(!format()->sheet()->isLoading() && !testValidity() ) - { - //reapply old value if action == stop - setDisplayText( oldText ); - } -} - -void Cell::setDisplayText( const TQString& _text ) -{ - bool isLoading = format()->sheet()->isLoading(); - - if (!isLoading) - format()->sheet()->doc()->emitBeginOperation( false ); - - d->strText = _text; - - /** - * A real formula "=A1+A2*3" was entered. - */ - if ( !d->strText.isEmpty() && d->strText[0] == '=' ) - { - setFlag(Flag_LayoutDirty); - setFlag(Flag_TextFormatDirty); - - if ( !makeFormula() ) - kdError(36001) << "ERROR: Syntax ERROR" << endl; - setCalcDirtyFlag (); - } - - /** - * Some numeric value or a string. - */ - else - { - // Find out what data type it is - checkTextInput(); - - setFlag(Flag_LayoutDirty); - setFlag(Flag_TextFormatDirty); - } - - if ( !isLoading ) - format()->sheet()->doc()->emitEndOperation( TQRect( d->column, d->row, 1, 1 ) ); -} - -void Cell::setLink( const TQString& link ) -{ - d->extra()->link = link; - - if( !link.isEmpty() && d->strText.isEmpty() ) - setCellText( link ); -} - -TQString Cell::link() const -{ - return d->hasExtra() ? d->extra()->link : TQString(); -} - -void Cell::update() -{ - /* those obscuring us need to redo their layout cause they can't obscure us - now that we've got text. - This includes cells obscuring cells that we are obscuring - */ - for (int x = d->column; x <= d->column + extraXCells(); x++) - { - for (int y = d->row; y <= d->row + extraYCells(); y++) - { - Cell* cell = format()->sheet()->cellAt(x,y); - cell->setLayoutDirtyFlag(); - } - } - - setCalcDirtyFlag(); - - /* TODO - is this a good place for this? */ - updateChart(true); -} - -bool Cell::testValidity() const -{ - bool valid = false; - if( d->hasExtra() && d->extra()->validity && d->extra()->validity->m_restriction != Restriction::None ) - { - //fixme - if ( d->extra()->validity->allowEmptyCell && d->strText.isEmpty() ) - return true; - - if( value().isNumber() && - (d->extra()->validity->m_restriction == Restriction::Number || - (d->extra()->validity->m_restriction == Restriction::Integer && - value().asFloat() == ceil(value().asFloat())))) - { - switch( d->extra()->validity->m_cond) - { - case Conditional::Equal: - valid = ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON - && value().asFloat() - d->extra()->validity->valMin > - (0.0 - DBL_EPSILON)); - break; - case Conditional::DifferentTo: - valid = !( ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON - && value().asFloat() - d->extra()->validity->valMin > - (0.0 - DBL_EPSILON)) ); - break; - case Conditional::Superior: - valid = ( value().asFloat() > d->extra()->validity->valMin); - break; - case Conditional::Inferior: - valid = ( value().asFloat() extra()->validity->valMin); - break; - case Conditional::SuperiorEqual: - valid = ( value().asFloat() >= d->extra()->validity->valMin); - break; - case Conditional::InferiorEqual: - valid = (value().asFloat() <= d->extra()->validity->valMin); - break; - case Conditional::Between: - valid = ( value().asFloat() >= d->extra()->validity->valMin && - value().asFloat() <= d->extra()->validity->valMax); - break; - case Conditional::Different: - valid = (value().asFloat() < d->extra()->validity->valMin || - value().asFloat() > d->extra()->validity->valMax); - break; - default : - break; - } - } - else if(d->extra()->validity->m_restriction==Restriction::Text) - { - valid = value().isString(); - } - else if ( d->extra()->validity->m_restriction == Restriction::List ) - { - //test int value - if ( value().isString() && d->extra()->validity->listValidity.contains( value().asString() ) ) - valid = true; - } - else if(d->extra()->validity->m_restriction==Restriction::TextLength) - { - if( value().isString() ) - { - int len = d->strOutText.length(); - switch( d->extra()->validity->m_cond) - { - case Conditional::Equal: - if (len == d->extra()->validity->valMin) - valid = true; - break; - case Conditional::DifferentTo: - if (len != d->extra()->validity->valMin) - valid = true; - break; - case Conditional::Superior: - if(len > d->extra()->validity->valMin) - valid = true; - break; - case Conditional::Inferior: - if(len < d->extra()->validity->valMin) - valid = true; - break; - case Conditional::SuperiorEqual: - if(len >= d->extra()->validity->valMin) - valid = true; - break; - case Conditional::InferiorEqual: - if(len <= d->extra()->validity->valMin) - valid = true; - break; - case Conditional::Between: - if(len >= d->extra()->validity->valMin && len <= d->extra()->validity->valMax) - valid = true; - break; - case Conditional::Different: - if(len extra()->validity->valMin || len >d->extra()->validity->valMax) - valid = true; - break; - default : - break; - } - } - } - else if(d->extra()->validity->m_restriction == Restriction::Time && isTime()) - { - switch( d->extra()->validity->m_cond) - { - case Conditional::Equal: - valid = (value().asTime() == d->extra()->validity->timeMin); - break; - case Conditional::DifferentTo: - valid = (value().asTime() != d->extra()->validity->timeMin); - break; - case Conditional::Superior: - valid = (value().asTime() > d->extra()->validity->timeMin); - break; - case Conditional::Inferior: - valid = (value().asTime() < d->extra()->validity->timeMin); - break; - case Conditional::SuperiorEqual: - valid = (value().asTime() >= d->extra()->validity->timeMin); - break; - case Conditional::InferiorEqual: - valid = (value().asTime() <= d->extra()->validity->timeMin); - break; - case Conditional::Between: - valid = (value().asTime() >= d->extra()->validity->timeMin && - value().asTime() <= d->extra()->validity->timeMax); - break; - case Conditional::Different: - valid = (value().asTime() < d->extra()->validity->timeMin || - value().asTime() > d->extra()->validity->timeMax); - break; - default : - break; - - } - } - else if(d->extra()->validity->m_restriction == Restriction::Date && isDate()) - { - switch( d->extra()->validity->m_cond) - { - case Conditional::Equal: - valid = (value().asDate() == d->extra()->validity->dateMin); - break; - case Conditional::DifferentTo: - valid = (value().asDate() != d->extra()->validity->dateMin); - break; - case Conditional::Superior: - valid = (value().asDate() > d->extra()->validity->dateMin); - break; - case Conditional::Inferior: - valid = (value().asDate() < d->extra()->validity->dateMin); - break; - case Conditional::SuperiorEqual: - valid = (value().asDate() >= d->extra()->validity->dateMin); - break; - case Conditional::InferiorEqual: - valid = (value().asDate() <= d->extra()->validity->dateMin); - break; - case Conditional::Between: - valid = (value().asDate() >= d->extra()->validity->dateMin && - value().asDate() <= d->extra()->validity->dateMax); - break; - case Conditional::Different: - valid = (value().asDate() < d->extra()->validity->dateMin || - value().asDate() > d->extra()->validity->dateMax); - break; - default : - break; - - } - } - } - else - { - valid= true; - } - - if(!valid &&d->extra()->validity != NULL && d->extra()->validity->displayMessage) - { - switch (d->extra()->validity->m_action ) - { - case Action::Stop: - KMessageBox::error((TQWidget*)0L, d->extra()->validity->message, - d->extra()->validity->title); - break; - case Action::Warning: - KMessageBox::warningYesNo((TQWidget*)0L, d->extra()->validity->message, - d->extra()->validity->title); - break; - case Action::Information: - KMessageBox::information((TQWidget*)0L, d->extra()->validity->message, - d->extra()->validity->title); - break; - } - } - if (!d->hasExtra()) - return true; //okay if there's no validity - return (valid || d->extra()->validity == NULL || d->extra()->validity->m_action != Action::Stop); -} - -FormatType Cell::formatType() const -{ - return format()->getFormatType( d->column, d->row ); -} - -double Cell::textWidth() const -{ - return d->textWidth; -} - -double Cell::textHeight() const -{ - return d->textHeight; -} - -int Cell::mergedXCells() const -{ - return d->hasExtra() ? d->extra()->mergedXCells : 0; -} - -int Cell::mergedYCells() const -{ - return d->hasExtra() ? d->extra()->mergedYCells : 0; -} - -int Cell::extraXCells() const -{ - return d->hasExtra() ? d->extra()->extraXCells : 0; -} - -int Cell::extraYCells() const -{ - return d->hasExtra() ? d->extra()->extraYCells : 0; -} - -double Cell::extraWidth() const -{ - return d->hasExtra() ? d->extra()->extraWidth : 0; -} - -double Cell::extraHeight() const -{ - return d->hasExtra() ? d->extra()->extraHeight : 0; -} - - -bool Cell::isDate() const -{ - FormatType ft = formatType(); - - return (formatIsDate (ft) || ((ft == Generic_format) && - (value().format() == Value::fmt_Date))); -} - -bool Cell::isTime() const -{ - FormatType ft = formatType(); - - return (formatIsTime (ft) || ((ft == Generic_format) && - (value().format() == Value::fmt_Time))); -} - -void Cell::setCalcDirtyFlag() -{ - if ( !isFormula() ) - { - //don't set the flag if we don't hold a formula - clearFlag(Flag_CalcDirty); - return; - } - setFlag(Flag_CalcDirty); - format()->sheet()->setRegionPaintDirty(cellRect()); -} - - -bool Cell::updateChart(bool refresh) -{ - // Update a chart for example if it depends on this cell. - if ( d->row != 0 && d->column != 0 ) - { - CellBinding *bind; - for ( bind = format()->sheet()->firstCellBinding(); bind != 0L; bind = format()->sheet()->nextCellBinding() ) - { - if ( bind->contains( d->column, d->row ) ) - { - if (!refresh) - return true; - - bind->cellChanged( this ); - } - } - return true; - } - return false; - -} - -double Cell::getDouble () -{ - if (isDefault()) - return 0.0; - //(Tomas) umm can't we simply call value().asFloat() ? - if (isDate()) - { - TQDate date = value().asDate(); - TQDate dummy (1900, 1, 1); - return (dummy.daysTo (date) + 1); - } - if (isTime()) - { - TQTime time = value().asTime(); - TQTime dummy; - return dummy.secsTo( time ); - } - if (value().isNumber()) - return value().asFloat(); - - return 0.0; -} - -void Cell::convertToDouble () -{ - if (isDefault()) - return; - - setValue (getDouble ()); -} - -void Cell::convertToPercent () -{ - if (isDefault()) - return; - - setValue (getDouble ()); - d->value.setFormat (Value::fmt_Percent); -} - -void Cell::convertToMoney () -{ - if (isDefault()) - return; - - setValue (getDouble ()); - d->value.setFormat (Value::fmt_Money); - format()->setPrecision (locale()->fracDigits()); -} - -void Cell::convertToTime () -{ - //(Tomas) This is weird. And I mean *REALLY* weird. First, we - //generate a time (TQTime), then we convert it to text, then - //we give the text to the cell and ask it to parse it. Weird... - - if (isDefault() || isEmpty()) - return; - - setValue (getDouble ()); - TQTime time = value().asDateTime().time(); - int msec = (int) ( (value().asFloat() - (int) value().asFloat()) * 1000 ); - time = time.addMSecs( msec ); - setCellText( time.toString() ); -} - -void Cell::convertToDate () -{ - //(Tomas) This is weird. And I mean *REALLY* weird. First, we - //generate a date (TQDate), then we convert it to text, then - //we give the text to the cell and ask it to parse it. Weird... - - if (isDefault() || isEmpty()) - return; - - setValue (getDouble ()); - - //TODO: why did we call setValue(), when we override it here? - TQDate date(1900, 1, 1); - date = date.addDays( (int) value().asFloat() - 1 ); - date = value().asDateTime().date(); - setCellText (locale()->formatDate (date, true)); -} - -void Cell::checkTextInput() -{ - // Goal of this method: determine the value of the cell - clearAllErrors(); - - d->value = Value::empty(); - - // Get the text from that cell - TQString str = d->strText; - - sheet()->doc()->parser()->parse (str, this); - - // Parsing as time acts like an autoformat: we even change d->strText - // [h]:mm:ss -> might get set by ValueParser - if (isTime() && (formatType() != Time_format7)) - d->strText = locale()->formatTime( value().asDateTime().time(), true); - - // convert first letter to uppercase ? - if (format()->sheet()->getFirstLetterUpper() && value().isString() && - (!d->strText.isEmpty())) - { - TQString str = value().asString(); - setValue( Value( str[0].upper() + str.right( str.length()-1 ) ) ); - } -} - -//used in calc, setNumber, ValueParser -void Cell::checkNumberFormat() -{ - if ( formatType() == Number_format && value().isNumber() ) - { - if ( value().asFloat() > 1e+10 ) - format()->setFormatType( Scientific_format ); - } -} - - -// ================================================================ -// Saving and loading - - -TQDomElement Cell::save( TQDomDocument& doc, - int _x_offset, int _y_offset, - bool force, bool copy, bool era ) -{ - // Save the position of this cell - TQDomElement cell = doc.createElement( "cell" ); - cell.setAttribute( "row", d->row - _y_offset ); - cell.setAttribute( "column", d->column - _x_offset ); - // - // Save the formatting information - // - TQDomElement formatElement = format()->save( doc, d->column, d->row, force, copy ); - if ( formatElement.hasChildNodes() || formatElement.attributes().length() ) // don't save empty tags - cell.appendChild( formatElement ); - - if ( doesMergeCells() ) - { - if ( extraXCells() ) - formatElement.setAttribute( "colspan", extraXCells() ); - if ( extraYCells() ) - formatElement.setAttribute( "rowspan", extraYCells() ); - } - - if ( d->hasExtra() && d->extra()->conditions ) - { - TQDomElement conditionElement = d->extra()->conditions->saveConditions( doc ); - - if ( !conditionElement.isNull() ) - cell.appendChild( conditionElement ); - } - - if ( d->hasExtra() && (d->extra()->validity != 0) ) - { - TQDomElement validity = doc.createElement("validity"); - - TQDomElement param=doc.createElement("param"); - param.setAttribute("cond",(int)d->extra()->validity->m_cond); - param.setAttribute("action",(int)d->extra()->validity->m_action); - param.setAttribute("allow",(int)d->extra()->validity->m_restriction); - param.setAttribute("valmin",d->extra()->validity->valMin); - param.setAttribute("valmax",d->extra()->validity->valMax); - param.setAttribute("displaymessage",d->extra()->validity->displayMessage); - param.setAttribute("displayvalidationinformation",d->extra()->validity->displayValidationInformation); - param.setAttribute("allowemptycell",d->extra()->validity->allowEmptyCell); - if ( !d->extra()->validity->listValidity.isEmpty() ) - param.setAttribute( "listvalidity", d->extra()->validity->listValidity.join( ";" ) ); - validity.appendChild(param); - TQDomElement title = doc.createElement( "title" ); - title.appendChild( doc.createTextNode( d->extra()->validity->title ) ); - validity.appendChild( title ); - TQDomElement message = doc.createElement( "message" ); - message.appendChild( doc.createCDATASection( d->extra()->validity->message ) ); - validity.appendChild( message ); - - TQDomElement inputTitle = doc.createElement( "inputtitle" ); - inputTitle.appendChild( doc.createTextNode( d->extra()->validity->titleInfo ) ); - validity.appendChild( inputTitle ); - - TQDomElement inputMessage = doc.createElement( "inputmessage" ); - inputMessage.appendChild( doc.createTextNode( d->extra()->validity->messageInfo ) ); - validity.appendChild( inputMessage ); - - - - TQString tmp; - if ( d->extra()->validity->timeMin.isValid() ) - { - TQDomElement timeMin = doc.createElement( "timemin" ); - tmp=d->extra()->validity->timeMin.toString(); - timeMin.appendChild( doc.createTextNode( tmp ) ); - validity.appendChild( timeMin ); - } - if ( d->extra()->validity->timeMax.isValid() ) - { - TQDomElement timeMax = doc.createElement( "timemax" ); - tmp=d->extra()->validity->timeMax.toString(); - timeMax.appendChild( doc.createTextNode( tmp ) ); - validity.appendChild( timeMax ); - } - - if ( d->extra()->validity->dateMin.isValid() ) - { - TQDomElement dateMin = doc.createElement( "datemin" ); - TQString tmp("%1/%2/%3"); - tmp = tmp.arg(d->extra()->validity->dateMin.year()).arg(d->extra()->validity->dateMin.month()).arg(d->extra()->validity->dateMin.day()); - dateMin.appendChild( doc.createTextNode( tmp ) ); - validity.appendChild( dateMin ); - } - if ( d->extra()->validity->dateMax.isValid() ) - { - TQDomElement dateMax = doc.createElement( "datemax" ); - TQString tmp("%1/%2/%3"); - tmp = tmp.arg(d->extra()->validity->dateMax.year()).arg(d->extra()->validity->dateMax.month()).arg(d->extra()->validity->dateMax.day()); - dateMax.appendChild( doc.createTextNode( tmp ) ); - validity.appendChild( dateMax ); - } - - cell.appendChild( validity ); - } - - if ( format()->comment() ) - { - TQDomElement comment = doc.createElement( "comment" ); - comment.appendChild( doc.createCDATASection( *format()->comment() ) ); - cell.appendChild( comment ); - } - - // - // Save the text - // - if ( !d->strText.isEmpty() ) - { - // Formulas need to be encoded to ensure that they - // are position independent. - if ( isFormula() ) - { - TQDomElement text = doc.createElement( "text" ); - // if we are cutting to the clipboard, relative references need to be encoded absolutely - text.appendChild( doc.createTextNode( encodeFormula( era ) ) ); - cell.appendChild( text ); - - /* we still want to save the results of the formula */ - TQDomElement formulaResult = doc.createElement( "result" ); - saveCellResult( doc, formulaResult, d->strOutText ); - cell.appendChild( formulaResult ); - - } - else if ( !link().isEmpty() ) - { - // KSpread pre 1.4 saves link as rich text, marked with first char ' - // Have to be saved in some CDATA section because of too many special charatcers. - TQDomElement text = doc.createElement( "text" ); - TQString qml = "!" + d->strText + ""; - text.appendChild( doc.createCDATASection( qml ) ); - cell.appendChild( text ); - } - else - { - // Save the cell contents (in a locale-independent way) - TQDomElement text = doc.createElement( "text" ); - saveCellResult( doc, text, d->strText ); - cell.appendChild( text ); - } - } - if ( cell.hasChildNodes() || cell.attributes().length() > 2 ) // don't save empty tags - // (the >2 is due to "row" and "column" attributes) - return cell; - else - return TQDomElement(); -} - -bool Cell::saveCellResult( TQDomDocument& doc, TQDomElement& result, - TQString str ) -{ - TQString dataType = "Other"; // fallback - - if ( value().isNumber() ) - { - if ( isDate() ) - { - // serial number of date - TQDate dd = value().asDateTime().date(); - dataType = "Date"; - str = "%1/%2/%3"; - str = str.arg(dd.year()).arg(dd.month()).arg(dd.day()); - } - else if( isTime() ) - { - // serial number of time - dataType = "Time"; - str = value().asDateTime().time().toString(); - } - else - { - // real number - dataType = "Num"; - if (value().isInteger()) - str = TQString::number(value().asInteger()); - else - str = TQString::number(value().asFloat(), 'g', DBL_DIG); - } - } - - if ( value().isBoolean() ) - { - dataType = "Bool"; - str = value().asBoolean() ? "true" : "false"; - } - - if ( value().isString() ) - { - dataType = "Str"; - str = value().asString(); - } - - result.setAttribute( "dataType", dataType ); - if ( !d->strOutText.isEmpty() ) - result.setAttribute( "outStr", d->strOutText ); - result.appendChild( doc.createTextNode( str ) ); - - return true; /* really isn't much of a way for this function to fail */ -} - -void Cell::saveOasisAnnotation( KoXmlWriter &xmlwriter ) -{ - if ( format()->comment() ) - { - // - xmlwriter.startElement( "office:annotation" ); - TQStringList text = TQStringList::split( "\n", *format()->comment() ); - for ( TQStringList::Iterator it = text.begin(); it != text.end(); ++it ) { - xmlwriter.startElement( "text:p" ); - xmlwriter.addTextNode( *it ); - xmlwriter.endElement(); - } - xmlwriter.endElement(); - } -} - - - -TQString Cell::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles ) -{ - if ( d->hasExtra() && d->extra()->conditions ) - { - // this has to be an automatic style - currentCellStyle = KoGenStyle( Doc::STYLE_CELL_AUTO, "table-cell" ); - d->extra()->conditions->saveOasisConditions( currentCellStyle ); - } - return format()->saveOasisCellStyle( currentCellStyle, mainStyles ); -} - - -bool Cell::saveOasis( KoXmlWriter& xmlwriter, KoGenStyles &mainStyles, - int row, int column, int &repeated, - GenValidationStyles &valStyle ) -{ - if ( !isPartOfMerged() ) - xmlwriter.startElement( "table:table-cell" ); - else - xmlwriter.startElement( "table:covered-table-cell" ); -#if 0 - //add font style - TQFont font; - Value const value( cell->value() ); - if ( !cell->isDefault() ) - { - font = cell->format()->textFont( i, row ); - m_styles.addFont( font ); - - if ( cell->format()->hasProperty( Format::PComment ) ) - hasComment = true; - } -#endif - // NOTE save the value before the style as long as the Formatter does not work correctly - if ( link().isEmpty() ) - saveOasisValue (xmlwriter); - - KoGenStyle currentCellStyle; // the type determined in saveOasisCellStyle - saveOasisCellStyle( currentCellStyle,mainStyles ); - // skip 'table:style-name' attribute for the default style - if ( !currentCellStyle.isDefaultStyle() ) - xmlwriter.addAttribute( "table:style-name", mainStyles.styles()[currentCellStyle] ); - - // group empty cells with the same style - if ( isEmpty() && !format()->hasProperty( Format::PComment ) && - !isPartOfMerged() && !doesMergeCells() ) - { - bool refCellIsDefault = isDefault(); - int j = column + 1; - Cell *nextCell = format()->sheet()->getNextCellRight( column, row ); - while ( nextCell ) - { - // if - // the next cell is not the adjacent one - // or - // the next cell is not empty - if ( nextCell->column() != j || !nextCell->isEmpty() ) - { - if ( refCellIsDefault ) - { - // if the origin cell was a default cell, - // we count the default cells - repeated = nextCell->column() - j + 1; - } - // otherwise we just stop here to process the adjacent - // cell in the next iteration of the outer loop - // (in Sheet::saveOasisCells) - break; - } - - KoGenStyle nextCellStyle; // the type is determined in saveOasisCellStyle - nextCell->saveOasisCellStyle( nextCellStyle,mainStyles ); - - if ( nextCell->isPartOfMerged() || nextCell->doesMergeCells() || - nextCell->format()->hasProperty( Format::PComment ) || - !(nextCellStyle == currentCellStyle) ) - { - break; - } - ++repeated; - // get the next cell and set the index to the adjacent cell - nextCell = format()->sheet()->getNextCellRight( j++, row ); - } - kdDebug() << "Cell::saveOasis: empty cell in column " << column << " " - << "repeated " << repeated << " time(s)" << endl; - - if ( repeated > 1 ) - xmlwriter.addAttribute( "table:number-columns-repeated", TQString::number( repeated ) ); - } - - - if (d->hasExtra() && d->extra()->validity) - { - GenValidationStyle styleVal(d->extra()->validity); - xmlwriter.addAttribute( "table:validation-name", valStyle.lookup( styleVal ) ); - } - if ( isFormula() ) - { - //kdDebug() << "Formula found" << endl; - TQString formula( convertFormulaToOasisFormat( text() ) ); - xmlwriter.addAttribute( "table:formula", formula ); - } - else if ( !link().isEmpty() ) - { - //kdDebug()<<"Link found \n"; - xmlwriter.startElement( "text:p" ); - xmlwriter.startElement( "text:a" ); - //Reference cell is started by "#" - if ( localReferenceAnchor( link() ) ) - xmlwriter.addAttribute( " xlink:href", ( "#"+link() ) ); - else - xmlwriter.addAttribute( " xlink:href", link() ); - xmlwriter.addTextNode( text() ); - xmlwriter.endElement(); - xmlwriter.endElement(); - } - - if ( doesMergeCells() ) - { - int colSpan = mergedXCells() + 1; - int rowSpan = mergedYCells() + 1; - - if ( colSpan > 1 ) - xmlwriter.addAttribute( "table:number-columns-spanned", TQString::number( colSpan ) ); - - if ( rowSpan > 1 ) - xmlwriter.addAttribute( "table:number-rows-spanned", TQString::number( rowSpan ) ); - } - - if ( !isEmpty() && link().isEmpty() ) - { - xmlwriter.startElement( "text:p" ); - xmlwriter.addTextNode( strOutText().utf8() ); - xmlwriter.endElement(); - } - - saveOasisAnnotation( xmlwriter ); - - xmlwriter.endElement(); - return true; -} - -void Cell::saveOasisValue (KoXmlWriter &xmlWriter) -{ - switch (value().format()) - { - case Value::fmt_None: break; //NOTHING HERE - case Value::fmt_Boolean: - { - xmlWriter.addAttribute( "office:value-type", "boolean" ); - xmlWriter.addAttribute( "office:boolean-value", ( value().asBoolean() ? - "true" : "false" ) ); - break; - } - case Value::fmt_Number: - { - xmlWriter.addAttribute( "office:value-type", "float" ); - if (value().isInteger()) - xmlWriter.addAttribute( "office:value", TQString::number( value().asInteger() ) ); - else - xmlWriter.addAttribute( "office:value", TQString::number( value().asFloat(), 'g', DBL_DIG ) ); - break; - } - case Value::fmt_Percent: - { - xmlWriter.addAttribute( "office:value-type", "percentage" ); - xmlWriter.addAttribute( "office:value", - TQString::number( value().asFloat() ) ); - break; - } - case Value::fmt_Money: - { - xmlWriter.addAttribute( "office:value-type", "currency" ); - Format::Currency currency; - if (format()->currencyInfo(currency)) - xmlWriter.addAttribute( "office:currency", Currency::getCurrencyCode(currency.type) ); - xmlWriter.addAttribute( "office:value", - TQString::number( value().asFloat() ) ); - break; - } - case Value::fmt_DateTime: break; //NOTHING HERE - case Value::fmt_Date: - { - xmlWriter.addAttribute( "office:value-type", "date" ); - xmlWriter.addAttribute( "office:date-value", - value().asDate().toString( Qt::ISODate ) ); - break; - } - case Value::fmt_Time: - { - xmlWriter.addAttribute( "office:value-type", "time" ); - xmlWriter.addAttribute( "office:time-value", - value().asTime().toString( "PThhHmmMssS" ) ); - break; - } - case Value::fmt_String: - { - xmlWriter.addAttribute( "office:value-type", "string" ); - xmlWriter.addAttribute( "office:string-value", value().asString() ); - break; - } - }; -} - -TQString Cell::convertFormulaToOasisFormat( const TQString & formula ) const -{ - TQString s; - TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)"); - int n = exp.search( formula, 0 ); - kdDebug() << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length() - << ", Matched length: " << exp.matchedLength() << endl; - - bool inQuote1 = false; - bool inQuote2 = false; - int i = 0; - int l = (int) formula.length(); - if ( l <= 0 ) - return formula; - while ( i < l ) - { - if ( ( n != -1 ) && ( n < i ) ) - { - n = exp.search( formula, i ); - kdDebug() << "Exp: " << formula.right( l - i ) << ", n: " << n << endl; - } - if ( formula[i] == '"' ) - { - inQuote1 = !inQuote1; - s += formula[i]; - ++i; - continue; - } - if ( formula[i] == '\'' ) - { - // named area - inQuote2 = !inQuote2; - ++i; - continue; - } - if ( inQuote1 || inQuote2 ) - { - s += formula[i]; - ++i; - continue; - } - if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) ) - { - s += '='; - ++i;++i; - continue; - } - if ( formula[i] == '!' ) - { - insertBracket( s ); - s += '.'; - ++i; - continue; - } - if ( formula[i] == ',' ) - { - s += '.'; - ++i; - continue; - } - if ( n == i ) - { - int ml = exp.matchedLength(); - if ( formula[ i + ml ] == '!' ) - { - kdDebug() << "No cell ref but sheet name" << endl; - s += formula[i]; - ++i; - continue; - } - if ( ( i > 0 ) && ( formula[i - 1] != '!' ) ) - s += "[."; - for ( int j = 0; j < ml; ++j ) - { - s += formula[i]; - ++i; - } - s += ']'; - continue; - } - - s += formula[i]; - ++i; - } - - return s; -} - -void Cell::loadOasisConditional( TQDomElement * style ) -{ - if ( style )//safe - { - TQDomElement e; - forEachElement( e, style->toElement() ) - { - if ( e.localName() == "map" && e.namespaceURI() == KoXmlNS::style ) - { - if (d->hasExtra()) - delete d->extra()->conditions; - d->extra()->conditions = new Conditions( this ); - d->extra()->conditions->loadOasisConditions( e ); - d->extra()->conditions->checkMatches(); - // break here - // Conditions::loadOasisConditions finishes the iteration - break; - } - } - } -} - -bool Cell::loadOasis( const TQDomElement& element , KoOasisLoadingContext& oasisContext , Style* style ) -{ - kdDebug() << "*** Loading cell properties ***** at " << column() << "," << row () << endl; - - if ( element.hasAttributeNS( KoXmlNS::table, "style-name" ) ) - { - kdDebug()<<" table:style-name: "<( cellStyle ) ); - } - - if (style) - { - format()->setStyle( style ); - } - - //Search and load each paragraph of text. Each paragraph is separated by a line break. - loadOasisCellText( element ); - - // - // formula - // - bool isFormula = false; - if ( element.hasAttributeNS( KoXmlNS::table, "formula" ) ) - { - kdDebug()<<" formula :"<strText.at(0) == '=' ) //prepend ' to the text to avoid = to be painted - d->strText.prepend('\''); - - // - // validation - // - if ( element.hasAttributeNS( KoXmlNS::table, "validation-name" ) ) - { - kdDebug()<<" validation-name: "<strText.isEmpty()) - { - TQString str = locale()->formatNumber( value, 15 ); - setCellText( str ); - } - } - - // currency value - else if( valuetype == "currency" ) - { - bool ok = false; - double value = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok ); - if( ok ) - { - setCellValue( value, Money_format ); - - if (element.hasAttributeNS( KoXmlNS::office, "currency" ) ) - { - Currency currency(element.attributeNS( KoXmlNS::office, "currency", TQString() ) ); - format()->setCurrency( currency.getIndex(), currency.getDisplayCode() ); - } - } - } - else if( valuetype == "percentage" ) - { - bool ok = false; - double v = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok ); - if( ok ) - { - Value value; - value.setValue (v); - value.setFormat (Value::fmt_Percent); - setCellValue( value ); - - if ( !isFormula && d->strText.isEmpty()) - { - TQString str = locale()->formatNumber( v, 15 ); - setCellText( str ); - } - - format()->setFormatType (Percentage_format); - } - } - else if ( valuetype == "date" ) - { - TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); - if ( value.isEmpty() ) - value = element.attributeNS( KoXmlNS::office, "date-value", TQString() ); - kdDebug() << "Type: date, value: " << value << endl; - - // "1980-10-15" - int year = 0, month = 0, day = 0; - bool ok = false; - - int p1 = value.find( '-' ); - if ( p1 > 0 ) - year = value.left( p1 ).toInt( &ok ); - - kdDebug() << "year: " << value.left( p1 ) << endl; - - int p2 = value.find( '-', ++p1 ); - - if ( ok ) - month = value.mid( p1, p2 - p1 ).toInt( &ok ); - - kdDebug() << "month: " << value.mid( p1, p2 - p1 ) << endl; - - if ( ok ) - day = value.right( value.length() - p2 - 1 ).toInt( &ok ); - - kdDebug() << "day: " << value.right( value.length() - p2 ) << endl; - - if ( ok ) - { - setCellValue( TQDate( year, month, day ) ); - if ( style ) - format()->setFormatType (style->formatType()); - kdDebug() << "Set TQDate: " << year << " - " << month << " - " << day << endl; - } - - } - else if ( valuetype == "time" ) - { - TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); - if ( value.isEmpty() ) - value = element.attributeNS( KoXmlNS::office, "time-value", TQString() ); - kdDebug() << "Type: time: " << value << endl; - // "PT15H10M12S" - int hours = 0, minutes = 0, seconds = 0; - int l = value.length(); - TQString num; - bool ok = false; - for ( int i = 0; i < l; ++i ) - { - if ( value[i].isNumber() ) - { - num += value[i]; - continue; - } - else if ( value[i] == 'H' ) - hours = num.toInt( &ok ); - else if ( value[i] == 'M' ) - minutes = num.toInt( &ok ); - else if ( value[i] == 'S' ) - seconds = num.toInt( &ok ); - else - continue; - - kdDebug() << "Num: " << num << endl; - - num = ""; - if ( !ok ) - break; - } - kdDebug() << "Hours: " << hours << ", " << minutes << ", " << seconds << endl; - - if ( ok ) - { - // Value kval( timeToNum( hours, minutes, seconds ) ); - // cell->setValue( kval ); - setCellValue( TQTime( hours % 24, minutes, seconds ) ); - if ( style ) - format()->setFormatType (style->formatType()); - } - } - else if( valuetype == "string" ) - { - TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); - if ( value.isEmpty() && element.hasAttributeNS( KoXmlNS::office, "string-value" )) - { - //if there is not string-value entry don't overwrite value stored into - value = element.attributeNS( KoXmlNS::office, "string-value", TQString() ); - setCellValue( value ); - } - format()->setFormatType (Text_format); - } - else - kdDebug()<<" type of value found : "< 1 || rowSpan > 1 ) - mergeCells( d->column, d->row, colSpan - 1, rowSpan - 1 ); - - // - // cell comment/annotation - // - TQDomElement annotationElement = KoDom::namedItemNS( element, KoXmlNS::office, "annotation" ); - if ( !annotationElement.isNull() ) - { - TQString comment; - TQDomNode node = annotationElement.firstChild(); - while( !node.isNull() ) - { - TQDomElement commentElement = node.toElement(); - if( !commentElement.isNull() ) - if( commentElement.localName() == "p" && commentElement.namespaceURI() == KoXmlNS::text ) - { - if( !comment.isEmpty() ) comment.append( '\n' ); - comment.append( commentElement.text() ); - } - - node = node.nextSibling(); - } - - if( !comment.isEmpty() ) - format()->setComment( comment ); - } - - TQDomElement frame = KoDom::namedItemNS( element, KoXmlNS::draw, "frame" ); - if ( !frame.isNull() ) - loadOasisObjects( frame, oasisContext ); - - if (isFormula) - setCalcDirtyFlag (); // formulas must be recalculated - - return true; -} - -void Cell::loadOasisCellText( const TQDomElement& parent ) -{ - //Search and load each paragraph of text. Each paragraph is separated by a line break - TQDomElement textParagraphElement; - TQString cellText; - - bool multipleTextParagraphsFound=false; - - forEachElement( textParagraphElement , parent ) - { - if ( textParagraphElement.localName()=="p" && - textParagraphElement.namespaceURI()== KoXmlNS::text ) - { - // our text, could contain formating for value or result of formul - if (cellText.isEmpty()) - cellText = textParagraphElement.text(); - else - { - cellText += "\n"+textParagraphElement.text(); - multipleTextParagraphsFound=true; - } - - TQDomElement textA = KoDom::namedItemNS( textParagraphElement, KoXmlNS::text, "a" ); - if( !textA.isNull() ) - { - if ( textA.hasAttributeNS( KoXmlNS::xlink, "href" ) ) - { - TQString link = textA.attributeNS( KoXmlNS::xlink, "href", TQString() ); - cellText = textA.text(); - setCellText( cellText ); - setValue( cellText ); - if ( link[0]=='#' ) - link=link.remove( 0, 1 ); - setLink( link ); - } - } - } - } - - if (!cellText.isNull()) - { - setCellText( cellText ); - setValue( cellText ); - } - - //Enable word wrapping if multiple lines of text have been found. - if ( multipleTextParagraphsFound ) - { - format()->setMultiRow(true); - } -} - -void Cell::loadOasisObjects( const TQDomElement &parent, KoOasisLoadingContext& oasisContext ) -{ - for( TQDomElement e = parent; !e.isNull(); e = e.nextSibling().toElement() ) - { - if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw ) - { - EmbeddedObject *obj = 0; - TQDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" ); - if ( !object.isNull() ) - { - if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", TQString()).isNull() ) - obj = new EmbeddedChart( sheet()->doc(), sheet() ); - else - obj = new EmbeddedKOfficeObject( sheet()->doc(), sheet() ); - } - else - { - TQDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" ); - if ( !image.isNull() ) - obj = new EmbeddedPictureObject( sheet(), sheet()->doc()->pictureCollection() ); - else - kdDebug() << "Object type wasn't loaded!" << endl; - } - - if ( obj ) - { - obj->loadOasis( e, oasisContext ); - sheet()->doc()->insertObject( obj ); - - TQString ref = e.attributeNS( KoXmlNS::table, "end-cell-address", TQString() ); - if ( ref.isNull() ) - continue; - - ref = Oasis::decodeFormula( ref ); - Point point( ref ); - if ( !point.isValid() ) - continue; - - KoRect geometry = obj->geometry(); - geometry.setLeft( geometry.left() + sheet()->columnPos( d->column, 0 ) ); - geometry.setTop( geometry.top() + sheet()->rowPos( d->row, 0 ) ); - - TQString str = e.attributeNS( KoXmlNS::table, "end-x", TQString() ); - if ( !str.isNull() ) - { - uint end_x = (uint) KoUnit::parseValue( str ); - geometry.setRight( sheet()->columnPos( point.column(), 0) + end_x ); - } - - str = e.attributeNS( KoXmlNS::table, "end-y", TQString() ); - if ( !str.isNull() ) - { - uint end_y = (uint) KoUnit::parseValue( str ); - geometry.setBottom( sheet()->rowPos( point.row(), 0) + end_y ); - } - - obj->setGeometry( geometry ); - } - } - } -} - -void Cell::loadOasisValidation( const TQString& validationName ) -{ - TQDomElement element = sheet()->doc()->loadingInfo()->validation( validationName); - if (d->hasExtra()) - delete d->extra()->validity; - d->extra()->validity = new Validity; - if ( element.hasAttributeNS( KoXmlNS::table, "condition" ) ) - { - TQString valExpression = element.attributeNS( KoXmlNS::table, "condition", TQString() ); - kdDebug()<<" element.attribute( table:condition ) "<' | '<=' | '>=' | '=' | '!=' - //Value ::= NumberValue | String | Formula - //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information. - //A String comprises one or more characters surrounded by quotation marks. - //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater. - - //ExtendedTrueCondition - if ( valExpression.contains( "cell-content-text-length()" ) ) - { - //"cell-content-text-length()>45" - valExpression = valExpression.remove("oooc:cell-content-text-length()" ); - kdDebug()<<" valExpression = :"<extra()->validity->m_restriction = Restriction::TextLength; - - loadOasisValidationCondition( valExpression ); - } - else if ( valExpression.contains( "cell-content-is-text()" ) ) - { - d->extra()->validity->m_restriction = Restriction::Text; - } - //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value) | cell-content-is-in-list( StringList ) - else if ( valExpression.contains( "cell-content-text-length-is-between" ) ) - { - d->extra()->validity->m_restriction = Restriction::TextLength; - d->extra()->validity->m_cond = Conditional::Between; - valExpression = valExpression.remove( "oooc:cell-content-text-length-is-between(" ); - kdDebug()<<" valExpression :"<extra()->validity->m_restriction = Restriction::TextLength; - d->extra()->validity->m_cond = Conditional::Different; - valExpression = valExpression.remove( "oooc:cell-content-text-length-is-not-between(" ); - kdDebug()<<" valExpression :"<extra()->validity->m_restriction = Restriction::List; - valExpression = valExpression.remove( "oooc:cell-content-is-in-list(" ); - kdDebug()<<" valExpression :"<extra()->validity->listValidity = TQStringList::split( ";", valExpression ); - - } - //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time() - else - { - if (valExpression.contains( "cell-content-is-whole-number()" ) ) - { - d->extra()->validity->m_restriction = Restriction::Number; - valExpression = valExpression.remove( "oooc:cell-content-is-whole-number() and " ); - } - else if (valExpression.contains( "cell-content-is-decimal-number()" ) ) - { - d->extra()->validity->m_restriction = Restriction::Integer; - valExpression = valExpression.remove( "oooc:cell-content-is-decimal-number() and " ); - } - else if (valExpression.contains( "cell-content-is-date()" ) ) - { - d->extra()->validity->m_restriction = Restriction::Date; - valExpression = valExpression.remove( "oooc:cell-content-is-date() and " ); - } - else if (valExpression.contains( "cell-content-is-time()" ) ) - { - d->extra()->validity->m_restriction = Restriction::Time; - valExpression = valExpression.remove( "oooc:cell-content-is-time() and " ); - } - kdDebug()<<"valExpression :"<extra()->validity->m_cond = Conditional::Between; - } - if ( valExpression.contains( "cell-content-is-not-between(" ) ) - { - valExpression = valExpression.remove( "cell-content-is-not-between(" ); - valExpression = valExpression.remove( ")" ); - TQStringList listVal = TQStringList::split( ",", valExpression ); - loadOasisValidationValue( listVal ); - d->extra()->validity->m_cond = Conditional::Different; - } - } - } - if ( element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" ) ) - { - kdDebug()<<" element.hasAttribute( table:allow-empty-cell ) :"<extra()->validity->allowEmptyCell = ( ( element.attributeNS( KoXmlNS::table, "allow-empty-cell", TQString() )=="true" ) ? true : false ); - } - if ( element.hasAttributeNS( KoXmlNS::table, "base-cell-address" ) ) - { - //todo what is it ? - } - - TQDomElement help = KoDom::namedItemNS( element, KoXmlNS::table, "help-message" ); - if ( !help.isNull() ) - { - if ( help.hasAttributeNS( KoXmlNS::table, "title" ) ) - { - kdDebug()<<"help.attribute( table:title ) :"<extra()->validity->titleInfo = help.attributeNS( KoXmlNS::table, "title", TQString() ); - } - if ( help.hasAttributeNS( KoXmlNS::table, "display" ) ) - { - kdDebug()<<"help.attribute( table:display ) :"<extra()->validity->displayValidationInformation = ( ( help.attributeNS( KoXmlNS::table, "display", TQString() )=="true" ) ? true : false ); - } - TQDomElement attrText = KoDom::namedItemNS( help, KoXmlNS::text, "p" ); - if ( !attrText.isNull() ) - { - kdDebug()<<"help text :"<extra()->validity->messageInfo = attrText.text(); - } - } - - TQDomElement error = KoDom::namedItemNS( element, KoXmlNS::table, "error-message" ); - if ( !error.isNull() ) - { - if ( error.hasAttributeNS( KoXmlNS::table, "title" ) ) - d->extra()->validity->title = error.attributeNS( KoXmlNS::table, "title", TQString() ); - if ( error.hasAttributeNS( KoXmlNS::table, "message-type" ) ) - { - TQString str = error.attributeNS( KoXmlNS::table, "message-type", TQString() ); - if ( str == "warning" ) - d->extra()->validity->m_action = Action::Warning; - else if ( str == "information" ) - d->extra()->validity->m_action = Action::Information; - else if ( str == "stop" ) - d->extra()->validity->m_action = Action::Stop; - else - kdDebug()<<"validation : message type unknown :"<extra()->validity->displayMessage = (error.attributeNS( KoXmlNS::table, "display", TQString() )=="true"); - } - TQDomElement attrText = KoDom::namedItemNS( error, KoXmlNS::text, "p" ); - if ( !attrText.isNull() ) - d->extra()->validity->message = attrText.text(); - } -} - - -void Cell::loadOasisValidationValue( const TQStringList &listVal ) -{ - bool ok = false; - kdDebug()<<" listVal[0] :"<extra()->validity->m_restriction == Restriction::Date ) - { - d->extra()->validity->dateMin = TQDate::fromString( listVal[0] ); - d->extra()->validity->dateMax = TQDate::fromString( listVal[1] ); - } - else if ( d->extra()->validity->m_restriction == Restriction::Time ) - { - d->extra()->validity->timeMin = TQTime::fromString( listVal[0] ); - d->extra()->validity->timeMax = TQTime::fromString( listVal[1] ); - } - else - { - d->extra()->validity->valMin = listVal[0].toDouble(&ok); - if ( !ok ) - { - d->extra()->validity->valMin = listVal[0].toInt(&ok); - if ( !ok ) - kdDebug()<<" Try to parse this value :"<extra()->validity->valMin = listVal[0]; -#endif - } - ok=false; - d->extra()->validity->valMax = listVal[1].toDouble(&ok); - if ( !ok ) - { - d->extra()->validity->valMax = listVal[1].toInt(&ok); - if ( !ok ) - kdDebug()<<" Try to parse this value :"<extra()->validity->valMax = listVal[1]; -#endif - } - } -} - -void Cell::loadOasisValidationCondition( TQString &valExpression ) -{ - TQString value; - if (valExpression.find( "<=" )==0 ) - { - value = valExpression.remove( 0,2 ); - d->extra()->validity->m_cond = Conditional::InferiorEqual; - } - else if (valExpression.find( ">=" )==0 ) - { - value = valExpression.remove( 0,2 ); - d->extra()->validity->m_cond = Conditional::SuperiorEqual; - } - else if (valExpression.find( "!=" )==0 ) - { - //add Differentto attribute - value = valExpression.remove( 0,2 ); - d->extra()->validity->m_cond = Conditional::DifferentTo; - } - else if ( valExpression.find( "<" )==0 ) - { - value = valExpression.remove( 0,1 ); - d->extra()->validity->m_cond = Conditional::Inferior; - } - else if(valExpression.find( ">" )==0 ) - { - value = valExpression.remove( 0,1 ); - d->extra()->validity->m_cond = Conditional::Superior; - } - else if (valExpression.find( "=" )==0 ) - { - value = valExpression.remove( 0,1 ); - d->extra()->validity->m_cond = Conditional::Equal; - } - else - kdDebug()<<" I don't know how to parse it :"<extra()->validity->m_restriction == Restriction::Date ) - { - d->extra()->validity->dateMin = TQDate::fromString( value ); - } - else if (d->extra()->validity->m_restriction == Restriction::Date ) - { - d->extra()->validity->timeMin = TQTime::fromString( value ); - } - else - { - bool ok = false; - d->extra()->validity->valMin = value.toDouble(&ok); - if ( !ok ) - { - d->extra()->validity->valMin = value.toInt(&ok); - if ( !ok ) - kdDebug()<<" Try to parse this value :"<extra()->validity->valMin = value; -#endif - } - } -} - - -bool Cell::load( const TQDomElement & cell, int _xshift, int _yshift, - Paste::Mode pm, Paste::Operation op, bool paste ) -{ - bool ok; - - // - // First of all determine in which row and column this - // cell belongs. - // - d->row = cell.attribute( "row" ).toInt( &ok ) + _yshift; - if ( !ok ) return false; - d->column = cell.attribute( "column" ).toInt( &ok ) + _xshift; - if ( !ok ) return false; - - // Validation - if ( d->row < 1 || d->row > KS_rowMax ) - { - kdDebug(36001) << "Cell::load: Value out of Range Cell:row=" << d->row << endl; - return false; - } - if ( d->column < 1 || d->column > KS_colMax ) - { - kdDebug(36001) << "Cell::load: Value out of Range Cell:column=" << d->column << endl; - return false; - } - - // - // Load formatting information. - // - TQDomElement f = cell.namedItem( "format" ).toElement(); - if ( !f.isNull() - && ( (pm == Paste::Normal) || (pm == Paste::Format) || (pm == Paste::NoBorder) ) ) - { - // send pm parameter. Didn't load Borders if pm==NoBorder - - if ( !format()->load( f, pm, paste ) ) - return false; - - if ( f.hasAttribute( "colspan" ) ) - { - int i = f.attribute("colspan").toInt( &ok ); - if ( !ok ) return false; - // Validation - if ( i < 0 || i > KS_spanMax ) - { - kdDebug(36001) << "Value out of range Cell::colspan=" << i << endl; - return false; - } - if (i || d->hasExtra()) - d->extra()->extraXCells = i; - if ( i > 0 ) - { - setFlag(Flag_Merged); - } - } - - if ( f.hasAttribute( "rowspan" ) ) - { - int i = f.attribute("rowspan").toInt( &ok ); - if ( !ok ) return false; - // Validation - if ( i < 0 || i > KS_spanMax ) - { - kdDebug(36001) << "Value out of range Cell::rowspan=" << i << endl; - return false; - } - if (i || d->hasExtra()) - d->extra()->extraYCells = i; - if ( i > 0 ) - { - setFlag(Flag_Merged); - } - } - - if ( testFlag( Flag_Merged ) ) - { - if (d->hasExtra()) - mergeCells( d->column, d->row, d->extra()->extraXCells, d->extra()->extraYCells ); - } - - } - - // - // Load the condition section of a cell. - // - TQDomElement conditionsElement = cell.namedItem( "condition" ).toElement(); - if ( !conditionsElement.isNull()) - { - if (d->hasExtra()) - delete d->extra()->conditions; - d->extra()->conditions = new Conditions( this ); - d->extra()->conditions->loadConditions( conditionsElement ); - d->extra()->conditions->checkMatches(); - } - else if ((pm == Paste::Normal) || (pm == Paste::NoBorder)) - { - //clear the conditional formatting - if (d->hasExtra()) - { - delete d->extra()->conditions; - d->extra()->conditions = 0; - } - } - - TQDomElement validity = cell.namedItem( "validity" ).toElement(); - if ( !validity.isNull()) - { - TQDomElement param = validity.namedItem( "param" ).toElement(); - if(!param.isNull()) - { - d->extra()->validity = new Validity; - if ( param.hasAttribute( "cond" ) ) - { - d->extra()->validity->m_cond = (Conditional::Type) param.attribute("cond").toInt( &ok ); - if ( !ok ) - return false; - } - if ( param.hasAttribute( "action" ) ) - { - d->extra()->validity->m_action = (Action::Type) param.attribute("action").toInt( &ok ); - if ( !ok ) - return false; - } - if ( param.hasAttribute( "allow" ) ) - { - d->extra()->validity->m_restriction = (Restriction::Type) param.attribute("allow").toInt( &ok ); - if ( !ok ) - return false; - } - if ( param.hasAttribute( "valmin" ) ) - { - d->extra()->validity->valMin = param.attribute("valmin").toDouble( &ok ); - if ( !ok ) - return false; - } - if ( param.hasAttribute( "valmax" ) ) - { - d->extra()->validity->valMax = param.attribute("valmax").toDouble( &ok ); - if ( !ok ) - return false; - } - if ( param.hasAttribute( "displaymessage" ) ) - { - d->extra()->validity->displayMessage = ( bool )param.attribute("displaymessage").toInt(); - } - if ( param.hasAttribute( "displayvalidationinformation" ) ) - { - d->extra()->validity->displayValidationInformation = ( bool )param.attribute("displayvalidationinformation").toInt(); - } - if ( param.hasAttribute( "allowemptycell" ) ) - { - d->extra()->validity->allowEmptyCell = ( bool )param.attribute("allowemptycell").toInt(); - } - if ( param.hasAttribute("listvalidity") ) - { - d->extra()->validity->listValidity=TQStringList::split(";", param.attribute("listvalidity") ); - } - } - TQDomElement inputTitle = validity.namedItem( "inputtitle" ).toElement(); - if (!inputTitle.isNull()) - { - d->extra()->validity->titleInfo = inputTitle.text(); - } - TQDomElement inputMessage = validity.namedItem( "inputmessage" ).toElement(); - if (!inputMessage.isNull()) - { - d->extra()->validity->messageInfo = inputMessage.text(); - } - - TQDomElement title = validity.namedItem( "title" ).toElement(); - if (!title.isNull()) - { - d->extra()->validity->title = title.text(); - } - TQDomElement message = validity.namedItem( "message" ).toElement(); - if (!message.isNull()) - { - d->extra()->validity->message = message.text(); - } - TQDomElement timeMin = validity.namedItem( "timemin" ).toElement(); - if ( !timeMin.isNull() ) - { - d->extra()->validity->timeMin = toTime(timeMin); - } - TQDomElement timeMax = validity.namedItem( "timemax" ).toElement(); - if ( !timeMax.isNull() ) - { - d->extra()->validity->timeMax = toTime(timeMax); - } - TQDomElement dateMin = validity.namedItem( "datemin" ).toElement(); - if ( !dateMin.isNull() ) - { - d->extra()->validity->dateMin = toDate(dateMin); - } - TQDomElement dateMax = validity.namedItem( "datemax" ).toElement(); - if ( !dateMax.isNull() ) - { - d->extra()->validity->dateMax = toDate(dateMax); - } - } - else if ((pm == Paste::Normal) || (pm == Paste::NoBorder)) - { - // clear the validity - removeValidity(); - } - - // - // Load the comment - // - TQDomElement comment = cell.namedItem( "comment" ).toElement(); - if ( !comment.isNull() && ( pm == Paste::Normal || pm == Paste::Comment || pm == Paste::NoBorder )) - { - TQString t = comment.text(); - //t = t.stripWhiteSpace(); - format()->setComment( t ); - } - - // - // The real content of the cell is loaded here. It is stored in - // the "text" tag, which contains either a text or a CDATA section. - // - // TODO: make this suck less. We set data twice, in loadCellData, and - // also here. Not good. - TQDomElement text = cell.namedItem( "text" ).toElement(); - - if ( !text.isNull() && - ( pm == Paste::Normal || pm == Paste::Text || pm == Paste::NoBorder || pm == Paste::Result ) ) - { - /* older versions mistakenly put the datatype attribute on the cell - instead of the text. Just move it over in case we're parsing - an old document */ - if ( cell.hasAttribute( "dataType" ) ) // new docs - text.setAttribute( "dataType", cell.attribute( "dataType" ) ); - - TQDomElement result = cell.namedItem( "result" ).toElement(); - TQString txt = text.text(); - if ((pm == Paste::Result) && (txt[0] == '=')) - // paste text of the element, if we want to paste result - // and the source cell contains a formula - // note that we mustn't use setCellValue after this, or else we lose - // all the formulas ... - d->strText = result.text(); - else - //otherwise copy everything - loadCellData(text, op); - - if ( !result.isNull() ) - { - TQString dataType; - TQString t = result.text(); - - if ( result.hasAttribute( "dataType" ) ) - dataType = result.attribute( "dataType" ); - if ( result.hasAttribute( "outStr" ) ) - { - d->strOutText = result.attribute( "outStr" ); - if ( !d->strOutText.isEmpty() ) - clearFlag( Flag_TextFormatDirty ); - } - - bool clear = true; - // boolean ? - if( dataType == "Bool" ) - { - if ( t == "false" ) - setValue( false ); - else if ( t == "true" ) - setValue( true ); - else - clear = false; - } - else if( dataType == "Num" ) - { - bool ok = false; - double dd = t.toDouble( &ok ); - if ( ok ) - setValue ( dd ); - else - clear = false; - } - else if( dataType == "Date" ) - { - bool ok = false; - double dd = t.toDouble( &ok ); - if ( ok ) - setValue ( dd ); - else - { - int pos = t.find( '/' ); - int year = t.mid( 0, pos ).toInt(); - int pos1 = t.find( '/', pos + 1 ); - int month = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt(); - int day = t.right( t.length() - pos1 - 1 ).toInt(); - TQDate date( year, month, day ); - if ( date.isValid() ) - setValue( date ); - else - clear = false; - } - } - else if( dataType == "Time" ) - { - bool ok = false; - double dd = t.toDouble( &ok ); - if ( ok ) - setCellValue( dd ); - else - { - int hours = -1; - int minutes = -1; - int second = -1; - int pos, pos1; - pos = t.find( ':' ); - hours = t.mid( 0, pos ).toInt(); - pos1 = t.find( ':', pos + 1 ); - minutes = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt(); - second = t.right( t.length() - pos1 - 1 ).toInt(); - TQTime time( hours, minutes, second ); - if ( time.isValid() ) - setValue( time ); - else - clear = false; - } - } - else - { - setValue( t ); - } - - // if ( clear ) - // clearFlag( Flag_CalcDirty ); - } - } - - return true; -} - -bool Cell::loadCellData(const TQDomElement & text, Paste::Operation op ) -{ - //TODO: use converter()->asString() to generate strText - - TQString t = text.text(); - t = t.stripWhiteSpace(); - - setFlag(Flag_LayoutDirty); - setFlag(Flag_TextFormatDirty); - - // A formula like =A1+A2 ? - if( t[0] == '=' ) - { - t = decodeFormula( t, d->column, d->row ); - setCellText (pasteOperation( t, d->strText, op )); - - setFlag(Flag_CalcDirty); - clearAllErrors(); - - if ( !makeFormula() ) - kdError(36001) << "ERROR: Syntax ERROR" << endl; - } - // rich text ? - else if (t[0] == '!' ) - { - // KSpread pre 1.4 stores hyperlink as rich text (first char is '!') - // extract the link and the correspoding text - // This is a rather dirty hack, but enough for KSpread generated XML - bool inside_tag = false; - TQString qml_text; - TQString tag; - TQString qml_link; - - for( unsigned i = 1; i < t.length(); i++ ) - { - TQChar ch = t[i]; - if( ch == '<' ) - { - if( !inside_tag ) - { - inside_tag = true; - tag = TQString(); - } - } - else if( ch == '>' ) - { - if( inside_tag ) - { - inside_tag = false; - if( tag.startsWith( "a href=\"", true ) ) - if( tag.endsWith( "\"" ) ) - qml_link = tag.mid( 8, tag.length()-9 ); - tag = TQString(); - } - } - else - { - if( !inside_tag ) - qml_text += ch; - else - tag += ch; - } - } - - if( !qml_link.isEmpty() ) - d->extra()->link = qml_link; - d->strText = qml_text; - setValue( d->strText ); - } - else - { - bool newStyleLoading = true; - TQString dataType; - - if ( text.hasAttribute( "dataType" ) ) // new docs - { - dataType = text.attribute( "dataType" ); - } - else // old docs: do the ugly solution of calling checkTextInput to parse the text - { - // ...except for date/time - if (isDate() && ( t.contains('/') == 2 )) - dataType = "Date"; - else if (isTime() && ( t.contains(':') == 2 ) ) - dataType = "Time"; - else - { - d->strText = pasteOperation( t, d->strText, op ); - checkTextInput(); - //kdDebug(36001) << "Cell::load called checkTextInput, got dataType=" << dataType << " t=" << t << endl; - newStyleLoading = false; - } - } - - if ( newStyleLoading ) - { - d->value = Value::empty(); - clearAllErrors(); - - // boolean ? - if( dataType == "Bool" ) - { - bool val = (t.lower() == "true"); - setCellValue (val); - } - - // number ? - else if( dataType == "Num" ) - { - bool ok = false; - if (t.contains('.')) - setValue ( Value( t.toDouble(&ok) ) ); // We save in non-localized format - else - setValue ( Value( t.toLong(&ok) ) ); - if ( !ok ) - { - kdWarning(36001) << "Couldn't parse '" << t << "' as number." << endl; - } - /* We will need to localize the text version of the number */ - TDELocale* locale = format()->sheet()->doc()->locale(); - - /* TDELocale::formatNumber requires the precision we want to return. - */ - int precision = t.length() - t.find('.') - 1; - - if ( formatType() == Percentage_format ) - { - if (value().isInteger()) - t = locale->formatNumber( value().asInteger() * 100 ); - else - t = locale->formatNumber( value().asFloat() * 100.0, precision ); - d->strText = pasteOperation( t, d->strText, op ); - d->strText += '%'; - } - else - { - if (value().isInteger()) - t = locale->formatLong(value().asInteger()); - else - t = locale->formatNumber(value().asFloat(), precision); - d->strText = pasteOperation( t, d->strText, op ); - } - } - - // date ? - else if( dataType == "Date" ) - { - int pos = t.find('/'); - int year = t.mid(0,pos).toInt(); - int pos1 = t.find('/',pos+1); - int month = t.mid(pos+1,((pos1-1)-pos)).toInt(); - int day = t.right(t.length()-pos1-1).toInt(); - setValue( TQDate(year,month,day) ); - if ( value().asDate().isValid() ) // Should always be the case for new docs - d->strText = locale()->formatDate( value().asDate(), true ); - else // This happens with old docs, when format is set wrongly to date - { - d->strText = pasteOperation( t, d->strText, op ); - checkTextInput(); - } - } - - // time ? - else if( dataType == "Time" ) - { - int hours = -1; - int minutes = -1; - int second = -1; - int pos, pos1; - pos = t.find(':'); - hours = t.mid(0,pos).toInt(); - pos1 = t.find(':',pos+1); - minutes = t.mid(pos+1,((pos1-1)-pos)).toInt(); - second = t.right(t.length()-pos1-1).toInt(); - setValue( TQTime(hours,minutes,second) ); - if ( value().asTime().isValid() ) // Should always be the case for new docs - d->strText = locale()->formatTime( value().asTime(), true ); - else // This happens with old docs, when format is set wrongly to time - { - d->strText = pasteOperation( t, d->strText, op ); - checkTextInput(); - } - } - - else - { - // Set the cell's text - d->strText = pasteOperation( t, d->strText, op ); - setValue( d->strText ); - } - } - } - - if ( text.hasAttribute( "outStr" ) ) // very new docs - { - d->strOutText = text.attribute( "outStr" ); - if ( !d->strOutText.isEmpty() ) - clearFlag( Flag_TextFormatDirty ); - } - - if ( !format()->sheet()->isLoading() ) - setCellText( d->strText ); - - if ( d->hasExtra() && d->extra()->conditions ) - d->extra()->conditions->checkMatches(); - - return true; -} - -TQTime Cell::toTime(const TQDomElement &element) -{ - //TODO: can't we use tryParseTime (after modification) instead? - TQString t = element.text(); - t = t.stripWhiteSpace(); - int hours = -1; - int minutes = -1; - int second = -1; - int pos, pos1; - pos = t.find(':'); - hours = t.mid(0,pos).toInt(); - pos1 = t.find(':',pos+1); - minutes = t.mid(pos+1,((pos1-1)-pos)).toInt(); - second = t.right(t.length()-pos1-1).toInt(); - setValue( Value( TQTime(hours,minutes,second)) ); - return value().asTime(); -} - -TQDate Cell::toDate(const TQDomElement &element) -{ - TQString t = element.text(); - int pos; - int pos1; - int year = -1; - int month = -1; - int day = -1; - pos = t.find('/'); - year = t.mid(0,pos).toInt(); - pos1 = t.find('/',pos+1); - month = t.mid(pos+1,((pos1-1)-pos)).toInt(); - day = t.right(t.length()-pos1-1).toInt(); - setValue( Value( TQDate(year,month,day) ) ); - return value().asDate(); -} - -TQString Cell::pasteOperation( const TQString &new_text, const TQString &old_text, Paste::Operation op ) -{ - if ( op == Paste::OverWrite ) - return new_text; - - TQString tmp_op; - TQString tmp; - TQString old; - - if( !new_text.isEmpty() && new_text[0] == '=' ) - { - tmp = new_text.right( new_text.length() - 1 ); - } - else - { - tmp = new_text; - } - - if ( old_text.isEmpty() && - ( op == Paste::Add || op == Paste::Mul || op == Paste::Sub || op == Paste::Div ) ) - { - old = "=0"; - } - - if( !old_text.isEmpty() && old_text[0] == '=' ) - { - old = old_text.right( old_text.length() - 1 ); - } - else - { - old = old_text; - } - - bool b1, b2; - tmp.toDouble( &b1 ); - old.toDouble( &b2 ); - if (b1 && !b2 && old.length() == 0) - { - old = "0"; - b2 = true; - } - - if( b1 && b2 ) - { - switch( op ) - { - case Paste::Add: - tmp_op = TQString::number(old.toDouble()+tmp.toDouble()); - break; - case Paste::Mul : - tmp_op = TQString::number(old.toDouble()*tmp.toDouble()); - break; - case Paste::Sub: - tmp_op = TQString::number(old.toDouble()-tmp.toDouble()); - break; - case Paste::Div: - tmp_op = TQString::number(old.toDouble()/tmp.toDouble()); - break; - default: - Q_ASSERT( 0 ); - } - - setFlag(Flag_LayoutDirty); - clearAllErrors(); - - return tmp_op; - } - else if ( ( new_text[0] == '=' && old_text[0] == '=' ) || - ( b1 && old_text[0] == '=' ) || ( new_text[0] == '=' && b2 ) ) - { - switch( op ) - { - case Paste::Add : - tmp_op="=("+old+")+"+"("+tmp+")"; - break; - case Paste::Mul : - tmp_op="=("+old+")*"+"("+tmp+")"; - break; - case Paste::Sub: - tmp_op="=("+old+")-"+"("+tmp+")"; - break; - case Paste::Div: - tmp_op="=("+old+")/"+"("+tmp+")"; - break; - default : - Q_ASSERT( 0 ); - } - - tmp_op = decodeFormula( tmp_op, d->column, d->row ); - setFlag(Flag_LayoutDirty); - clearAllErrors(); - - return tmp_op; - } - - tmp = decodeFormula( new_text, d->column, d->row ); - setFlag(Flag_LayoutDirty); - clearAllErrors(); - - return tmp; -} - -TQString Cell::testAnchor( int x, int y ) const -{ - if( link().isEmpty() ) - return TQString(); - - const Doc* doc = format()->sheet()->doc(); - int x1 = doc->zoomItX( d->textX ); - int y1 = doc->zoomItX( d->textY - d->textHeight ); - int x2 = doc->zoomItX( d->textX + d->textWidth ); - int y2 = doc->zoomItX( d->textY ); - - if( x > x1 ) if( x < x2 ) - if( y > y1 ) if( y < y2 ) - return link(); - - return TQString(); -} - -void Cell::sheetDies() -{ - // Avoid unobscuring the cells in the destructor. - if (d->hasExtra()) - { - d->extra()->extraXCells = 0; - d->extra()->extraYCells = 0; - d->extra()->mergedXCells = 0; - d->extra()->mergedYCells = 0; - } - - //d->nextCell = 0; - //d->previousCell = 0; -} - -Cell::~Cell() -{ - if ( d->nextCell ) - d->nextCell->setPreviousCell( d->previousCell ); - if ( d->previousCell ) - d->previousCell->setNextCell( d->nextCell ); - - if (d->hasExtra()) - { - delete d->extra()->validity; - } - - // Unobscure cells. - int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; - int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; - for( int x = 0; x <= extraXCells; ++x ) - for( int y = (x == 0) ? 1 : 0; // avoid looking at (+0,+0) - y <= extraYCells; ++y ) - { - Cell* cell = format()->sheet()->cellAt( d->column + x, d->row + y ); - if ( cell ) - cell->unobscure(this); - } - - d->value = Value::empty(); - - if (!isDefault()) - valueChanged (); //our value has been changed (is now null), but only if we aren't default - - delete d->format; - delete d; -} - -bool Cell::operator > ( const Cell & cell ) const -{ - if ( value().isNumber() ) // ### what about bools ? - { - if ( cell.value().isNumber() ) - return value().asFloat() > cell.value().asFloat(); - else - return false; // numbers are always < than texts - } - else if(isDate()) - { - if( cell.isDate() ) - return value().asDate() > cell.value().asDate(); - else if (cell.value().isNumber()) - return true; - else - return false; //date are always < than texts and time - } - else if(isTime()) - { - if( cell.isTime() ) - return value().asTime() > cell.value().asTime(); - else if( cell.isDate()) - return true; //time are always > than date - else if( cell.value().isNumber()) - return true; - else - return false; //time are always < than texts - } - else - { - if ( Map::respectCase ) - return value().asString().compare(cell.value().asString()) > 0; - else - return ( value().asString() ).lower().compare(cell.value().asString().lower()) > 0; - } -} - -bool Cell::operator < ( const Cell & cell ) const -{ - if ( value().isNumber() ) - { - if ( cell.value().isNumber() ) - return value().asFloat() < cell.value().asFloat(); - else - return true; // numbers are always < than texts - } - else if(isDate()) - { - if( cell.isDate() ) - return value().asDateTime().date() < cell.value().asDateTime().date(); - else if( cell.value().isNumber()) - return false; - else - return true; //date are always < than texts and time - } - else if(isTime()) - { - if( cell.isTime() ) - return value().asDateTime().time() < cell.value().asDateTime().time(); - else if(cell.isDate()) - return false; //time are always > than date - else if( cell.value().isNumber()) - return false; - else - return true; //time are always < than texts - } - else - { - if ( Map::respectCase ) - return value().asString().compare(cell.value().asString()) < 0; - else - return ( value().asString() ).lower().compare(cell.value().asString().lower()) < 0; - } -} - -bool Cell::operator==( const Cell& other ) const -{ - if ( d->strText != other.d->strText ) - return false; - if ( d->value != other.d->value ) - return false; - if ( *d->format != *other.d->format ) - return false; - if ( d->hasExtra() ) - { - if ( !other.d->hasExtra() ) - return false; - if ( d->extra()->link != other.d->extra()->link ) - return false; - if ( d->extra()->mergedXCells != other.d->extra()->mergedXCells ) - return false; - if ( d->extra()->mergedYCells != other.d->extra()->mergedYCells ) - return false; - if ( d->extra()->conditions ) - { - if ( !other.d->extra()->conditions ) - return false; - if ( *d->extra()->conditions != *other.d->extra()->conditions ) - return false; - } - if ( d->extra()->validity ) - { - if ( !other.d->extra()->validity ) - return false; - if ( *d->extra()->validity != *other.d->extra()->validity ) - return false; - } - } - return true; -} - -TQRect Cell::cellRect() -{ - Q_ASSERT(!isDefault()); - return TQRect(TQPoint(d->column, d->row), TQPoint(d->column, d->row)); -} - -TQValueList Cell::conditionList() const -{ - if ( !d->hasExtra() || !d->extra()->conditions ) - { - TQValueList emptyList; - return emptyList; - } - - return d->extra()->conditions->conditionList(); -} - -void Cell::setConditionList( const TQValueList & newList ) -{ - if (d->hasExtra()) - delete d->extra()->conditions; - d->extra()->conditions = new Conditions( this ); - d->extra()->conditions->setConditionList( newList ); - d->extra()->conditions->checkMatches(); -} - -bool Cell::hasError() const -{ - return ( testFlag(Flag_ParseError) || - testFlag(Flag_CircularCalculation) || - testFlag(Flag_DependancyError)); -} - -void Cell::clearAllErrors() -{ - clearFlag( Flag_ParseError ); - clearFlag( Flag_CircularCalculation ); - clearFlag( Flag_DependancyError ); -} - -bool Cell::calcDirtyFlag() -{ - return isFormula() ? testFlag( Flag_CalcDirty ) : false; -} - -bool Cell::layoutDirtyFlag() const -{ - return testFlag( Flag_LayoutDirty ); -} - -void Cell::clearDisplayDirtyFlag() -{ - clearFlag( Flag_DisplayDirty ); -} - -void Cell::setDisplayDirtyFlag() -{ - setFlag( Flag_DisplayDirty ); -} - -bool Cell::doesMergeCells() const -{ - return testFlag( Flag_Merged ); -} - -void Cell::clearFlag( CellFlags flag ) -{ - d->flags &= ~(TQ_UINT32)flag; -} - -void Cell::setFlag( CellFlags flag ) -{ - d->flags |= (TQ_UINT32)flag; -} - -bool Cell::testFlag( CellFlags flag ) const -{ - return ( d->flags & (TQ_UINT32)flag ); -} - - -void Cell::checkForNamedAreas( TQString & formula ) const -{ - KSPLoadingInfo* loadinginfo = sheet()->doc()->loadingInfo(); - if(! loadinginfo) { - kdDebug() << "Cell::checkForNamedAreas loadinginfo is NULL" << endl; - return; - } - - int l = formula.length(); - int i = 0; - TQString word; - int start = 0; - while ( i < l ) - { - if ( formula[i].isLetterOrNumber() ) - { - word += formula[i]; - ++i; - continue; - } - if ( !word.isEmpty() ) - { - if ( loadinginfo->findWordInAreaList(word) ) - { - formula = formula.replace( start, word.length(), "'" + word + "'" ); - l = formula.length(); - ++i; - kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <findWordInAreaList(word) ) - { - formula = formula.replace( start, word.length(), "'" + word + "'" ); - l = formula.length(); - ++i; - kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 < + Copyright 2005 Raphael Langerhorst + Copyright 2004-2005 Tomas Mecir + Copyright 2004-2006 Inge Wallin + Copyright 1999-2002,2004,2005 Laurent Montel + Copyright 2002-2005 Ariya Hidayat + Copyright 2001-2003 Philipp Mueller + Copyright 2002-2003 Norbert Andres + Copyright 2003 Reinhart Geiser + Copyright 2003-2005 Meni Livne + Copyright 2003 Peter Simonsson + Copyright 1999-2002 David Faure + Copyright 2000-2002 Werner Trobin + Copyright 1999,2002 Harri Porten + Copyright 2002 John Dailey + Copyright 1998-2000 Torben Weis + Copyright 2000 Bernd Wuebben + Copyright 2000 Simon Hausmann + Copyright 1999 Michael Reiher + Copyright 1999 Boris Wedl + Copyright 1998-1999 Reginald Stadlbauer + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "kspread_canvas.h" +#include "kspread_condition.h" +#include "kspread_doc.h" +#include "kspread_format.h" +#include "kspread_global.h" +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_util.h" +#include "ksploadinginfo.h" +#include "kspread_genvalidationstyle.h" +#include "kspread_locale.h" +#include "kspread_value.h" +#include "kspread_view.h" +#include "kspread_value.h" +#include "formula.h" +#include "selection.h" +#include "valueconverter.h" +#include "valueformatter.h" +#include "valueparser.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace KSpread; + +#define BORDER_SPACE 1 + + +/** + * A pointer to the decimal separator + */ + +namespace Cell_LNS +{ + TQChar decimal_point = '\0'; +} + +using namespace Cell_LNS; + + +// Some variables are placed in Cell::Extra because normally they're +// not required in simple case of cell(s). For example, most plain +// text cells don't need to store information about spanned columns +// and rows, as this is only the case with merged cells. +// +// When the cell is getting complex (e.g. merged with other cells, +// contains rich text, has validation criteria, etc), this Cell::Extra +// is allocated by Cell::Private and starts to be +// available. Otherwise, it won't exist at all. + +class Cell::Extra +{ +public: + Extra() {} + + // Not empty when the cell holds a link + TQString link; + + // Number of cells explicitly merged by the user in X and Y directions. + int mergedXCells; + int mergedYCells; + + // Number of additional cells. + int extraXCells; + int extraYCells; + + // If this cell overlaps other cells, then we have the cells width and + // height stored here. These values do not mean anything unless + // extraXCells and/or extraYCells are different from 0. + double extraWidth; + double extraHeight; + + // A list of cells that obscure this one. + // If this list is not empty, then this cell is obscured by another + // enlarged object. This means that we have to call this object in order + // of painting it for example instead of painting 'this'. + // + // FIXME (comment): If the list consists of more than one obscuring + // element, then is there an order between them that + // is important? + TQValueList obscuringCells; + + // If non-NULL, contains a pointer to a condition or a validity test. + Conditions *conditions; + Validity *validity; + + // Store the number of line when multirow is used (default is 0) + int nbLines; + +private: + // Don't allow implicit copy. + Extra& operator=( const Extra& ); +}; + + +class Cell::Private +{ +public: + + Private(); + ~Private(); + +public: + + // This cell's row and column. If either of them is 0, this is the + // default cell and its row/column can not be determined. Note that + // in the isDefault() method, only column is tested. + int row; + int column; + + // Value of the cell, either typed by user or as result of formula + Value value; + + // Holds the user's input. + // + // FIXME: + // Eventually, we'll want to get rid of strText and generate + // user's input on-the-fly. Then, for normal cells, we'll generate + // this string using converter()->asString + // (value()). + // + // Here the problem is, that strText also holds the formula - + // we'll need to provide some method to generate it from the + // parsed version, created in KSpread::Formula. Hence, we won't be + // able to get rid of strText until we switch to the new formula + // parser and until we write some method that re-generates the + // input formula... + // + // Alternately, we can keep using strText for formulas and + // generate it dynamically for static cells... + // + // /Tomas + // + TQString strText; + + // This is the text we want to display. Not necessarily the same + // as strText, e.g. strText="1" and strOutText="1.00" Also holds + // value that we got from calculation, formerly known as + // strFormulaOut + TQString strOutText; + + // the Formula object for the cell + KSpread::Formula *formula; + + // Position and dimension of displayed text. + // FIXME (comment): Which coordinate system? pixels? mm/cm? zoom? + double textX; + double textY; + double textWidth; + double textHeight; + + // result of "fm.ascent()" in makeLayout. used in offsetAlign. + int fmAscent; + + // Pointers to neighboring cells. + // FIXME (comment): Which order? + Cell *nextCell; + Cell *previousCell; + + bool hasExtra() const { return (cellExtra != 0); }; + Extra *extra(); + + Format *format; + TQ_UINT32 flags; + +private: + // "Extra stuff", see explanation for Cell::Extra. + Extra *cellExtra; +}; + + +Cell::Private::Private() +{ + // Some basic data. + row = 0; + column = 0; + value = Value::empty(); + formula = 0; + + // Formatting + textX = 0.0; + textY = 0.0; + textWidth = 0.0; + textHeight = 0.0; + fmAscent = 0; + + nextCell = 0; + previousCell = 0; + + // Default is to not have the "extra" stuff in a cell. + cellExtra = 0; + format = 0; + flags = 0; +} + + +Cell::Private::~Private() +{ + delete cellExtra; + delete formula; +} + + +Cell::Extra* Cell::Private::extra() +{ + if ( !cellExtra ) { + cellExtra = new Extra; + cellExtra->conditions = 0; + cellExtra->validity = 0; + + cellExtra->mergedXCells = 0; + cellExtra->mergedYCells = 0; + cellExtra->extraXCells = 0; + cellExtra->extraYCells = 0; + cellExtra->extraWidth = 0.0; + cellExtra->extraHeight = 0.0; + cellExtra->nbLines = 0; +// cellExtra->highlight = TQColor(0,0,0); + } + + return cellExtra; +} + + +/***************************************************************************** + * + * Cell + * + *****************************************************************************/ + + +Cell::Cell( Sheet * _sheet, int _column, int _row ) +{ + d = new Private; + d->row = _row; + d->column = _column; + d->format = new Format(_sheet, _sheet->doc()->styleManager()->defaultStyle()); + d->format->setCell(this); + clearAllErrors(); +} + + +Cell::Cell( Sheet * _sheet, Style * _style, int _column, int _row ) +{ + d = new Private; + d->row = _row; + d->column = _column; + d->format = new Format( _sheet, _style ); + d->format->setCell(this); + + clearAllErrors(); +} + +Format* Cell::format() const +{ + return d->format; +} + +// Return the sheet that this cell belongs to. +Sheet * Cell::sheet() const +{ + return d->format->sheet(); +} + +// Return true if this is the default cell. +bool Cell::isDefault() const +{ + return ( d->column == 0 ); +} + +// Return the row number of this cell. +int Cell::row() const +{ + // Make sure this isn't called for the default cell. This assert + // can save you (could have saved me!) the hassle of some very + // obscure bugs. + + if ( isDefault() ) + { + kdWarning(36001) << "Error: Calling Cell::row() for default cell" << endl; + return 0; + } + + return d->row; +} + + +// Return the column number of this cell. +// +int Cell::column() const +{ + // Make sure this isn't called for the default cell. This assert + // can save you (could have saved me!) the hassle of some very + // obscure bugs. + if ( isDefault() ) + { + kdWarning(36001) << "Error: Calling Cell::column() for default cell" << endl; + return 0; + } + return d->column; +} + + +// Return the name of this cell, i.e. the string that the user would +// use to reference it. Example: A1, BZ16 +// +TQString Cell::name() const +{ + return name( d->column, d->row ); +} + + +// Return the name of any cell given by (col, row). +// +TQString Cell::name( int col, int row ) +{ + return columnName( col ) + TQString::number( row ); +} + + +// Return the name of this cell, including the sheet name. +// Example: sheet1!A5 +// +TQString Cell::fullName() const +{ + return fullName( sheet(), d->column, d->row ); +} + + +// Return the full name of any cell given a sheet and (col, row). +// +TQString Cell::fullName( const Sheet* s, int col, int row ) +{ + return s->sheetName() + "!" + name( col, row ); +} + + +// Return the symbolic name of the column of this cell. Examples: A, BB. +// +TQString Cell::columnName() const +{ + return columnName( d->column ); +} + +TDELocale* Cell::locale() const +{ + return d->format->sheet()->doc()->locale(); +} + +// Return the symbolic name of any column. +// +TQString Cell::columnName( uint column ) +{ + TQString str; + unsigned digits = 1; + unsigned offset = 0; + + column--; + + if( column > 4058115285U ) return TQString("@@@"); + + for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ ) + offset += limit; + + for( unsigned c = column - offset; digits; --digits, c/=26 ) + str.prepend( TQChar( 'A' + (c%26) ) ); + + return str; +} + + +// Return true if this cell is a formula. +// +bool Cell::isFormula() const +{ + return d->strText[0] == '='; +} + + +// Return the input text of this cell. This could, for instance, be a +// formula. +// +// FIXME: These two functions are inconsistently named. It should be +// either text() and outText() or strText() and strOutText(). +// +TQString Cell::text() const +{ + return d->strText; +} + + +// Return the out text, i.e. the text that is visible in the cells +// square when shown. This could, for instance, be the calculated +// result of a formula. +// +TQString Cell::strOutText() const +{ + return d->strOutText; +} + +Formula *Cell::formula () const +{ + return d->formula; +} + + +// Return the value of this cell. +// +const Value Cell::value() const +{ + return d->value; +} + + +// Set the value of this cell. It also clears all errors if the value +// itself is not an error. +// +// In addition to this, it calculates the outstring and sets the dirty +// flags so that a redraw is forced. +// +void Cell::setValue( const Value& v ) +{ + if (v.type() != Value::Error) + clearAllErrors(); + + //If the value has not changed then we don't need to do anything + //(ie. no need to relayout, update dependant cells etc.), + //unless this cell contains a formula, in which case its dependancies might have changed + //even though the value has not. For example, if this cell was previously empty (and its value is + //therefore empty) and a new dependency upon an empty cell has been added. The new value would still + //be empty, but the dependencies need to be updated (via the call to valueChanged() below). + if ( ( d->value == v ) && ( !isFormula() ) ) + return; + + d->value = v; + + setFlag(Flag_LayoutDirty); + setFlag(Flag_TextFormatDirty); + + // Format and set the outText. + setOutputText(); + + // Set the displayed text, if we hold an error value. + if (d->value.type() == Value::Error) + d->strOutText = d->value.errorMessage (); + + // Value of the cell has changed - trigger necessary actions + valueChanged (); + + if ( !format()->sheet()->isLoading() ) + format()->sheet()->setRegionPaintDirty(cellRect()); +} + +void Cell::setCellValue (const Value &v, FormatType fmtType, const TQString &txt) +{ + if ( !txt.isNull() ) + { + d->strText = txt; + if ( isFormula() ) + makeFormula(); + } + else if ( !isFormula() ) + d->strText = sheet()->doc()->converter()->asString (v).asString(); + if (fmtType != No_format) + format()->setFormatType (fmtType); + setValue (v); +} + +// FIXME: Continue commenting and cleaning here (ingwa) + + +Cell* Cell::previousCell() const +{ + return d->previousCell; +} + +Cell* Cell::nextCell() const +{ + return d->nextCell; +} + +void Cell::setPreviousCell( Cell* c ) +{ + d->previousCell = c; +} + +void Cell::setNextCell( Cell* c ) +{ + d->nextCell = c; +} + +Validity* Cell::getValidity( int newStruct ) +{ + if ( (!newStruct) && (!d->hasExtra())) + //we don't have validity struct and we don't want one + return 0; + + if( ( d->extra()->validity == 0 ) && ( newStruct == -1 ) ) + d->extra()->validity = new Validity; + return d->extra()->validity; +} + +void Cell::removeValidity() +{ + if (!d->hasExtra()) + return; + + delete d->extra()->validity; + d->extra()->validity = 0; +} + + +void Cell::copyFormat( const int column , const int row ) +{ + const Cell * cell = format()->sheet()->cellAt( column , row ); + + copyFormat( cell ); +} + +void Cell::copyFormat( const Cell* cell ) +{ + + Q_ASSERT(cell); + + d->value.setFormat(cell->d->value.format()); + format()->copy(*(cell->format())); + + /*format()->setAlign( cell->format()->align( _column, _row ) ); + format()->setAlignY( cell->format()->alignY( _column, _row ) ); + format()->setTextFont( cell->format()->textFont( _column, _row ) ); + format()->setTextColor( cell->format()->textColor( _column, _row ) ); + format()->setBgColor( cell->bgColor( _column, _row) ); + setLeftBorderPen( cell->leftBorderPen( _column, _row ) ); + setTopBorderPen( cell->topBorderPen( _column, _row ) ); + setBottomBorderPen( cell->bottomBorderPen( _column, _row ) ); + setRightBorderPen( cell->rightBorderPen( _column, _row ) ); + format()->setFallDiagonalPen( cell->format()->fallDiagonalPen( _column, _row ) ); + format()->setGoUpDiagonalPen( cell->format()->goUpDiagonalPen( _column, _row ) ); + format()->setBackGroundBrush( cell->backGroundBrush( _column, _row) ); + format()->setPrecision( cell->format()->precision( _column, _row ) ); + format()->setPrefix( cell->format()->prefix( _column, _row ) ); + format()->setPostfix( cell->format()->postfix( _column, _row ) ); + format()->setFloatFormat( cell->format()->floatFormat( _column, _row ) ); + format()->setFloatColor( cell->format()->floatColor( _column, _row ) ); + format()->setMultiRow( cell->format()->multiRow( _column, _row ) ); + format()->setVerticalText( cell->format()->verticalText( _column, _row ) ); + format()->setDontPrintText( cell->format()->getDontprintText(_column, _row ) ); + format()->setNotProtected( cell->format()->notProtected(_column, _row ) ); + format()->setHideAll(cell->format()->isHideAll(_column, _row ) ); + format()->setHideFormula(cell->format()->isHideFormula(_column, _row ) ); + format()->setIndent( cell->format()->getIndent(_column, _row ) ); + format()->setAngle( cell->format()->getAngle(_column, _row) ); + format()->setFormatType( cell->format()->getFormatType(_column, _row) ); + Format::Currency c; + if ( cell->format()->currencyInfo( c ) ) + format()->setCurrency( c );*/ + + TQValueList conditionList = cell->conditionList(); + if (d->hasExtra()) + delete d->extra()->conditions; + if ( cell->d->hasExtra() && cell->d->extra()->conditions ) + setConditionList( conditionList ); + else + if (d->hasExtra()) + d->extra()->conditions = 0; + + /*format()->setComment( cell->format()->comment( _column, _row ) );*/ +} + +void Cell::copyAll( Cell *cell ) +{ + Q_ASSERT( !isDefault() ); // trouble ahead... + copyFormat( cell ); + copyContent( cell ); +} + +void Cell::copyContent( const Cell* cell ) +{ + Q_ASSERT( !isDefault() ); // trouble ahead... + + if (cell->isFormula() && cell->column() > 0 && cell->row() > 0) + { + // change all the references, e.g. from A1 to A3 if copying + // from e.g. B2 to B4 + TQString d = cell->encodeFormula(); + setCellText( cell->decodeFormula( d ) ); + } + else + setCellText( cell->text() ); + +} + +void Cell::defaultStyle() +{ + format()->defaultStyleFormat(); + + if (!d->hasExtra()) + return; + + if ( d->extra()->conditions ) + { + delete d->extra()->conditions; + d->extra()->conditions = 0; + } + + delete d->extra()->validity; + d->extra()->validity = 0L; +} + + +// Merge a number of cells, i.e. make this cell obscure a number of +// other cells. If _x and _y == 0, then the merging is removed. + +void Cell::mergeCells( int _col, int _row, int _x, int _y ) +{ + // Start by unobscuring the cells that we obscure right now + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; + for ( int x = _col; x <= _col + extraXCells; ++x ) { + for ( int y = _row; y <= _row + extraYCells; ++y ) { + if ( x != _col || y != _row ) + format()->sheet()->nonDefaultCell( x, y )->unobscure(this); + } + } + + // If no merging, then remove all traces, and return. + if ( _x == 0 && _y == 0 ) { + clearFlag( Flag_Merged ); + if (d->hasExtra()) { + d->extra()->extraXCells = 0; + d->extra()->extraYCells = 0; + d->extra()->extraWidth = 0.0; + d->extra()->extraHeight = 0.0; + d->extra()->mergedXCells = 0; + d->extra()->mergedYCells = 0; + } + + // Refresh the layout + setFlag( Flag_LayoutDirty ); + return; + } + + // At this point, we know that we will merge some cells. + setFlag(Flag_Merged); + d->extra()->extraXCells = _x; + d->extra()->extraYCells = _y; + d->extra()->mergedXCells = _x; + d->extra()->mergedYCells = _y; + + // Obscure the cells + for ( int x = _col; x <= _col + _x; ++x ) { + for ( int y = _row; y <= _row + _y; ++y ) { + if ( x != _col || y != _row ) + format()->sheet()->nonDefaultCell( x, y )->obscure( this, true ); + } + } + + // Refresh the layout + setFlag( Flag_LayoutDirty ); +} + +void Cell::move( int col, int row ) +{ + setLayoutDirtyFlag(); + setCalcDirtyFlag(); + setDisplayDirtyFlag(); + + //int ex = extraXCells(); + //int ey = d->extra()->extraYCells(); + + if (d->hasExtra()) + d->extra()->obscuringCells.clear(); + + // Unobscure the objects we obscure right now + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; + for( int x = d->column; x <= d->column + extraXCells; ++x ) + for( int y = d->row; y <= d->row + extraYCells; ++y ) + if ( x != d->column || y != d->row ) + { + Cell *cell = format()->sheet()->nonDefaultCell( x, y ); + cell->unobscure(this); + } + + d->column = col; + d->row = row; + + if (d->hasExtra()) + { + // d->extra()->extraXCells = 0; + // d->extra()->extraYCells = 0; + d->extra()->mergedXCells = 0; + d->extra()->mergedYCells = 0; + } + + // Cell value has been changed (because we're another cell now). + valueChanged (); +} + +void Cell::setLayoutDirtyFlag( bool format ) +{ + setFlag( Flag_LayoutDirty ); + if ( format ) + setFlag( Flag_TextFormatDirty ); + + if (!d->hasExtra()) + return; + + TQValueList::iterator it = d->extra()->obscuringCells.begin(); + TQValueList::iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + (*it)->setLayoutDirtyFlag( format ); + } +} + +bool Cell::needsPrinting() const +{ + if ( isDefault() ) + return false; + + if ( !d->strText.stripWhiteSpace().isEmpty() ) { + return true; + } + + // Cell borders? + if ( format()->hasProperty( Format::PTopBorder ) + || format()->hasProperty( Format::PLeftBorder ) + || format()->hasProperty( Format::PRightBorder ) + || format()->hasProperty( Format::PBottomBorder ) + || format()->hasProperty( Format::PFallDiagonal ) + || format()->hasProperty( Format::PGoUpDiagonal ) ) { + return true; + } + + // Background color or brush? + if ( format()->hasProperty( Format::PBackgroundBrush ) ) { + + const TQBrush& brush=backGroundBrush(column(),row()); + + //Only brushes that are visible (ie. they have a brush style and are not white) + //need to be drawn + if ( (brush.style() != TQt::NoBrush) && + (brush.color() != TQt::white || brush.pixmap()) ) + return true; + + } + + if ( format()->hasProperty( Format::PBackgroundColor ) ) { + kdDebug() << "needsPrinting: Has background colour" << endl; + TQColor backgroundColor=bgColor(column(),row()); + + //We don't need to print anything if the background is white + if (backgroundColor != TQt::white) + return true; + } + + return false; +} + +bool Cell::isEmpty() const +{ + return isDefault() || d->strText.isEmpty(); +} + + +// Return true if this cell is obscured by some other cell. + +bool Cell::isObscured() const +{ + if (!d->hasExtra()) + return false; + + return !( d->extra()->obscuringCells.isEmpty() ); +} + + +// Return true if this cell is part of a merged cell, but not the +// master cell. + +bool Cell::isPartOfMerged() const +{ + if (!d->hasExtra()) + return false; + + TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); + TQValueList::const_iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + Cell *cell = *it; + + if (cell->doesMergeCells()) { + // The cell might merge extra cells, and then overlap even + // beyond that so just knowing that the obscuring cell merges + // extra isn't enough. We have to know that this cell is one of + // the ones it is forcing over. + if (column() <= cell->column() + cell->d->extra()->mergedXCells + && row() <= cell->row() + cell->mergedYCells() ) + return true; + } + } + + return false; +} + + +// Return the cell that obscures this one. If no cell is obscuring, +// then return this. This method is slightly complicated because we +// can have several layers of obscuring. +// +// Update: it seems that if we do an actual merge, then the obscuring +// cell is prepended and if just expanding, then it is appended. This +// means that we should be able to just look at the first one. + +Cell *Cell::ultimateObscuringCell() const +{ + if (!d->hasExtra()) + return (Cell *) this; + + else if (d->extra()->obscuringCells.isEmpty()) + return (Cell *) this; + + else + return d->extra()->obscuringCells.first(); + +#if 0 + TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); + TQValueList::const_iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + Cell *cell = *it; + + if (cell->doesMergeCells()) { + // The cell might merge extra cells, and then overlap even + // beyond that so just knowing that the obscuring cell merges + // extra isn't enough. We have to know that this cell is one of + // the ones it is forcing over. + if (column() <= cell->column() + cell->d->extra()->mergedXCells + && row() <= cell->row() + cell->mergedYCells() ) + return true; + } + } + + return false; +#endif +} + + +TQValueList Cell::obscuringCells() const +{ + if (!d->hasExtra()) + { + TQValueList empty; + return empty; + } + return d->extra()->obscuringCells; +} + +void Cell::clearObscuringCells() +{ + if (!d->hasExtra()) + return; + d->extra()->obscuringCells.clear(); +} + +void Cell::obscure( Cell *cell, bool isForcing ) +{ + if (d->hasExtra()) + { + d->extra()->obscuringCells.remove( cell ); // removes *all* occurrences + cell->clearObscuringCells(); + } + if ( isForcing ) + { + d->extra()->obscuringCells.prepend( cell ); + } + else + { + d->extra()->obscuringCells.append( cell ); + } + setFlag(Flag_LayoutDirty); + format()->sheet()->setRegionPaintDirty( cellRect() ); +} + +void Cell::unobscure( Cell * cell ) +{ + if (d->hasExtra()) + d->extra()->obscuringCells.remove( cell ); + setFlag( Flag_LayoutDirty ); + format()->sheet()->setRegionPaintDirty( cellRect() ); +} + +TQString Cell::encodeFormula( bool _era, int _col, int _row ) const +{ + if ( _col == -1 ) + _col = d->column; + if ( _row == -1 ) + _row = d->row; + + TQString erg = ""; + + if(d->strText.isEmpty()) + return d->strText; + + bool fix1 = false; + bool fix2 = false; + bool onNumber = false; + unsigned int pos = 0; + const unsigned int length = d->strText.length(); + + // All this can surely be made 10 times faster, but I just "ported" it to TQString + // without any attempt to optimize things -- this is really brittle (Werner) + while ( pos < length ) + { + if ( d->strText[pos] == '"' ) + { + erg += d->strText[pos++]; + while ( pos < length && d->strText[pos] != '"' ) // till the end of the world^H^H^H "string" + { + erg += d->strText[pos++]; + // Allow escaped double quotes (\") + if ( pos < length && d->strText[pos] == '\\' && d->strText[pos+1] == '"' ) + { + erg += d->strText[pos++]; + erg += d->strText[pos++]; + } + } + if ( pos < length ) // also copy the trailing double quote + erg += d->strText[pos++]; + + onNumber = false; + } + else if ( d->strText[pos].isDigit() ) + { + erg += d->strText[pos++]; + fix1 = fix2 = false; + onNumber = true; + } + else if ( d->strText[pos] != '$' && !d->strText[pos].isLetter() ) + { + erg += d->strText[pos++]; + fix1 = fix2 = false; + onNumber = false; + } + else + { + TQString tmp = ""; + if ( d->strText[pos] == '$' ) + { + tmp = "$"; + pos++; + fix1 = true; + } + if ( d->strText[pos].isLetter() ) + { + TQString buffer; + unsigned int pos2 = 0; + while ( pos < length && d->strText[pos].isLetter() ) + { + tmp += d->strText[pos]; + buffer[pos2++] = d->strText[pos++]; + } + if ( d->strText[pos] == '$' ) + { + tmp += "$"; + pos++; + fix2 = true; + } + if ( d->strText[pos].isDigit() ) + { + const unsigned int oldPos = pos; + while ( pos < length && d->strText[pos].isDigit() ) ++pos; + int row = 0; + if ( pos != oldPos ) + row = d->strText.mid(oldPos, pos-oldPos).toInt(); + // Is it a sheet name || is it a function name like DEC2HEX + /* or if we're parsing a number, this could just be the + exponential part of it (1.23E4) */ + if ( ( d->strText[pos] == '!' ) || + d->strText[pos].isLetter() || + onNumber ) + { + erg += tmp; + fix1 = fix2 = false; + pos = oldPos; + } + else // It must be a cell identifier + { + //now calculate the row as integer value + int col = 0; + col = util_decodeColumnLabelText( buffer ); + if ( fix1 ) + erg += TQString( "$%1" ).arg( col ); + else + if (_era) + erg += TQChar(0xA7) + TQString( "%1" ).arg( col ); + else + erg += TQString( "#%1" ).arg( col - _col ); + + if ( fix2 ) + erg += TQString( "$%1#").arg( row ); + else + if (_era) + erg += TQChar(0xA7) + TQString( "%1#" ).arg( row ); + else + erg += TQString( "#%1#" ).arg( row - _row ); + } + } + else + { + erg += tmp; + fix1 = fix2 = false; + } + } + else + { + erg += tmp; + fix1 = false; + } + onNumber = false; + } + } + + return erg; +} + +TQString Cell::decodeFormula( const TQString &_text, int _col, int _row) const +{ + if ( _col == -1 ) + _col = d->column; + if ( _row == -1 ) + _row = d->row; + + TQString erg = ""; + unsigned int pos = 0; + const unsigned int length = _text.length(); + + if ( _text.isEmpty() ) + return TQString(); + + while ( pos < length ) + { + if ( _text[pos] == '"' ) + { + erg += _text[pos++]; + while ( pos < length && _text[pos] != '"' ) + { + erg += _text[pos++]; + // Allow escaped double quotes (\") + if ( pos < length && _text[pos] == '\\' && _text[pos+1] == '"' ) + { + erg += _text[pos++]; + erg += _text[pos++]; + } + } + if ( pos < length ) + erg += _text[pos++]; + } + else if ( _text[pos] == '#' || _text[pos] == '$' || _text[pos] == TQChar(0xA7)) + { + bool abs1 = false; + bool abs2 = false; + bool era1 = false; // if 1st is relative but encoded absolutely + bool era2 = false; + + TQChar _t = _text[pos++]; + if ( _t == '$' ) + abs1 = true; + else if ( _t == TQChar(0xA7) ) + era1 = true; + + int col = 0; + unsigned int oldPos = pos; + while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos; + if ( pos != oldPos ) + col = _text.mid(oldPos, pos-oldPos).toInt(); + if ( !abs1 && !era1 ) + col += _col; + // Skip '#' or '$' + + _t = _text[pos++]; + if ( _t == '$' ) + abs2 = true; + else if ( _t == TQChar(0xA7) ) + era2 = true; + + int row = 0; + oldPos = pos; + while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos; + if ( pos != oldPos ) + row = _text.mid(oldPos, pos-oldPos).toInt(); + if ( !abs2 && !era2) + row += _row; + // Skip '#' or '$' + ++pos; + if ( row < 1 || col < 1 || row > KS_rowMax || col > KS_colMax ) + { + kdDebug(36001) << "Cell::decodeFormula: row or column out of range (col: " << col << " | row: " << row << ")" << endl; + erg = "=\"#### " + i18n("REFERENCE TO COLUMN OR ROW IS OUT OF RANGE") + "\""; + return erg; + } + if ( abs1 ) + erg += "$"; + erg += Cell::columnName(col); //Get column text + + if ( abs2 ) + erg += "$"; + erg += TQString::number( row ); + } + else + erg += _text[pos++]; + } + + return erg; +} + + +void Cell::freeAllObscuredCells() +{ + // + // Free all obscured cells. + // + + if (!d->hasExtra()) + return; + + for ( int x = d->column + d->extra()->mergedXCells; + x <= d->column + d->extra()->extraXCells; ++x ) { + for ( int y = d->row + d->extra()->mergedYCells; + y <= d->row + d->extra()->extraYCells; ++y ) { + if ( x != d->column || y != d->row ) { + Cell *cell = format()->sheet()->cellAt( x, y ); + cell->unobscure(this); + } + } + } + + d->extra()->extraXCells = d->extra()->mergedXCells; + d->extra()->extraYCells = d->extra()->mergedYCells; + +} + + +// ---------------------------------------------------------------- +// Layout + + +// Recalculate the entire layout. This includes the following members: +// +// d->textX, d->textY +// d->textWidth, d->textHeight +// d->fmAscent +// d->extra()->extraXCells, d->extra()->extraYCells +// d->extra()->extraWidth, d->extra()->extraHeight +// d->extra()->nbLines (if multirow) +// +// and, of course, +// +// d->strOutText +// + +void Cell::makeLayout( TQPainter &_painter, int _col, int _row ) +{ + // Are _col and _row really needed ? + // + // Yes they are: they are useful if this is the default layout, in + // which case d->row and d->column are 0 and 0, but _col and _row + // are the real coordinates of the cell. + + // There is no need to remake the layout if it hasn't changed. + if ( !testFlag( Flag_LayoutDirty ) ) + return; + + // Some initializations. + if (d->hasExtra()) + d->extra()->nbLines = 0; + clearFlag( Flag_CellTooShortX ); + clearFlag( Flag_CellTooShortY ); + + // Initiate the cells that this one is obscuring to the ones that + // are actually merged. + freeAllObscuredCells(); + if (d->hasExtra()) + mergeCells( d->column, d->row, + d->extra()->mergedXCells, d->extra()->mergedYCells ); + + // If the column for this cell is hidden or the row is too low, + // there is no use in remaking the layout. + ColumnFormat *cl1 = format()->sheet()->columnFormat( _col ); + RowFormat *rl1 = format()->sheet()->rowFormat( _row ); + if ( cl1->isHide() + || ( rl1->dblHeight() <= format()->sheet()->doc()->unzoomItY( 2 ) ) ) { + clearFlag( Flag_LayoutDirty ); + return; + } + + // Recalculate the output text, d->strOutText. + setOutputText(); + + // Empty text? Reset the outstring and, if this is the default + // cell, return. + if ( d->strOutText.isEmpty() ) { + d->strOutText = TQString(); + + if ( isDefault() ) { + clearFlag( Flag_LayoutDirty ); + return; + } + } + + // Up to here, we have just cared about the contents, not the + // painting of it. Now it is time to see if the contents fits into + // the cell and, if not, maybe rearrange the outtext a bit. + // + // First, Determine the correct font with zoom taken into account, + // and apply it to _painter. Then calculate text dimensions, i.e. + // d->textWidth and d->textHeight. + applyZoomedFont( _painter, _col, _row ); + textSize( _painter ); + + // + // Calculate the size of the cell + // + RowFormat *rl = format()->sheet()->rowFormat( d->row ); + ColumnFormat *cl = format()->sheet()->columnFormat( d->column ); + + double width = cl->dblWidth(); + double height = rl->dblHeight(); + + // Calculate extraWidth and extraHeight if we have a merged cell. + if ( testFlag( Flag_Merged ) ) { + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; + + // FIXME: Introduce double extraWidth/Height here and use them + // instead (see FIXME about this in paintCell()). + + for ( int x = _col + 1; x <= _col + extraXCells; x++ ) + width += format()->sheet()->columnFormat( x )->dblWidth(); + + for ( int y = _row + 1; y <= _row + extraYCells; y++ ) + height += format()->sheet()->rowFormat( y )->dblHeight(); + } + + // Cache the newly calculated extraWidth and extraHeight if we have + // already allocated a struct for it. Otherwise it will be zero, so + // don't bother. + if (d->hasExtra()) { + d->extra()->extraWidth = width; + d->extra()->extraHeight = height; + } + + TQFontMetrics fm = _painter.fontMetrics(); + d->fmAscent = fm.ascent(); + + // Check if we need to break the line into multiple lines and are + // allowed to do so. If so, set `lines' to the number of lines that + // are needed to fit into the total width of the combined cell. + // + // Also recalculate d->textHeight, d->textWidth, d->extra->nbLines + // and d->strOutText. + // + int lines = 1; + if ( d->textWidth > (width - 2 * BORDER_SPACE + - format()->leftBorderWidth( _col, _row ) + - format()->rightBorderWidth( _col, _row ) ) + && format()->multiRow( _col, _row ) ) + { + // Copy of d->strOutText but without the newlines. +// TQString o = d->strOutText.replace( TQChar('\n'), " " ); + + // don't remove the existing LF, these are intended line wraps (whishlist #9881) + TQString o = d->strOutText; + + // Break the line at appropriate places, i.e. spaces, if + // necessary. This means to change the spaces where breaks occur + // into newlines. + if ( o.find(' ') != -1 ) + { + d->strOutText = ""; + + // Make sure that we have a space at the end. + o += ' '; + + int start = 0; // Start of the line we are handling now + int breakpos = 0; // The next candidate pos to break the string + int pos1 = 0; + int availableWidth = (int) ( width - 2 * BORDER_SPACE + - format()->leftBorderWidth( _col, _row ) + - format()->rightBorderWidth( _col, _row ) ); + + do { + + breakpos = o.find( ' ', breakpos ); + int linefeed = o.find( '\n', pos1 ); + +// kdDebug() << "start: " << start << "; breakpos: " << breakpos << "; pos1: " << pos1 << "; linefeed: " << linefeed << endl; + + //don't miss LF as a position to calculate current lineWidth + int work_breakpos = breakpos; + if (pos1 < linefeed && linefeed < breakpos) + work_breakpos = linefeed; + + double lineWidth = format()->sheet()->doc() + ->unzoomItX( fm.width( d->strOutText.mid( start, (pos1 - start) ) + + o.mid( pos1, work_breakpos - pos1 ) ) ); + + //linefeed could be -1 when no linefeed is found! + if (breakpos > linefeed && linefeed > 0) + { +// kdDebug() << "applying linefeed to start;" << endl; + start = linefeed; + lines++; + } + + if ( lineWidth <= availableWidth ) { + // We have room for the rest of the line. End it here. + d->strOutText += o.mid( pos1, breakpos - pos1 ); + pos1 = breakpos; + } + else { + // Still not enough room. Try to split further. + if ( o.at( pos1 ) == ' ' ) + pos1++; + + if ( pos1 != 0 && breakpos != -1 ) { + d->strOutText += "\n" + o.mid( pos1, breakpos - pos1 ); + lines++; + } + else + d->strOutText += o.mid( pos1, breakpos - pos1 ); + + start = pos1; + pos1 = breakpos; + } + + breakpos++; + } while( o.find( ' ', breakpos ) != -1 ); + } + else + { + lines = o.contains('\n'); + } + + d->textHeight *= lines; + if (lines > 1) + d->extra()->nbLines = lines; + + d->textX = 0.0; + + // Calculate the maximum width, taking into account linebreaks, + // and put it in d->textWidth. + TQString t; + int i; + int pos = 0; + d->textWidth = 0.0; + do { + i = d->strOutText.find( "\n", pos ); + + if ( i == -1 ) + t = d->strOutText.mid( pos, d->strOutText.length() - pos ); + else { + t = d->strOutText.mid( pos, i - pos ); + pos = i + 1; + } + + double tw = format()->sheet()->doc()->unzoomItX( fm.width( t ) ); + if ( tw > d->textWidth ) + d->textWidth = tw; + } while ( i != -1 ); + } + + // Calculate d->textX and d->textY + offsetAlign( _col, _row ); + + int a = effAlignX(); + + // Get indentation. This is only used for left aligned text. + double indent = 0.0; + if ( a == Format::Left && !isEmpty() ) + indent = format()->getIndent( _col, _row ); + + // Set Flag_CellTooShortX if the text is vertical or angled, and too + // high for the cell. + if ( format()->verticalText( _col, _row ) || format()->getAngle( _col, _row ) != 0 ) { + //RowFormat *rl = format()->sheet()->rowFormat( _row ); + + if ( d->textHeight >= height/*rl->dblHeight()*/ ) + setFlag( Flag_CellTooShortX ); + } + + // Do we have to occupy additional cells to the right? This is only + // done for cells that have no merged cells in the Y direction. + // + // FIXME: Check if all cells along the merged edge to the right are + // empty and use the extra space? No, probably not. + // + if ( d->textWidth + indent > ( width - 2 * BORDER_SPACE + - format()->leftBorderWidth( _col, _row ) + - format()->rightBorderWidth( _col, _row ) ) + && ( !d->hasExtra() || d->extra()->mergedYCells == 0 ) ) + { + int c = d->column; + + // Find free cells to the right of this one. + int end = 0; + while ( !end ) { + ColumnFormat *cl2 = format()->sheet()->columnFormat( c + 1 ); + Cell *cell = format()->sheet()->visibleCellAt( c + 1, d->row ); + + if ( cell->isEmpty() ) { + width += cl2->dblWidth() - 1; + c++; + + // Enough space? + if ( d->textWidth + indent <= ( width - 2 * BORDER_SPACE + - format()->leftBorderWidth( _col, _row ) + - format()->rightBorderWidth( _col, _row ) ) ) + end = 1; + } + else + // Not enough space, but the next cell is not empty + end = -1; + } + + // Try to use additional space from the neighboring cells that + // were calculated in the last step. This is the place that we + // set d->extra()->extraXCells and d->extra()->extraWidth. + // + // Currently this is only done for left aligned cells. We have to + // check to make sure we haven't already force-merged enough cells + // + // FIXME: Why not right/center aligned text? + // + // FIXME: Shouldn't we check to see if end == -1 here before + // setting Flag_CellTooShortX? + // + if ( format()->align( _col, _row ) == Format::Left + || ( format()->align( _col, _row ) == Format::Undefined + && !value().isNumber() ) ) + { + if ( c - d->column > d->extra()->mergedXCells ) { + d->extra()->extraXCells = c - d->column; + d->extra()->extraWidth = width; + for ( int i = d->column + 1; i <= c; ++i ) { + Cell *cell = format()->sheet()->nonDefaultCell( i, d->row ); + cell->obscure( this ); + } + + // Not enough space + if ( end == -1 ) + setFlag( Flag_CellTooShortX ); + } + else + setFlag( Flag_CellTooShortX ); + } + else + setFlag( Flag_CellTooShortX ); + } + + // Do we have to occupy additional cells at the bottom ? + // + // FIXME: Setting to make the current cell grow. + // + if ( format()->multiRow( _col, _row ) + && d->textHeight > ( height - 2 * BORDER_SPACE + - format()->topBorderWidth( _col, _row ) + - format()->bottomBorderWidth( _col, _row ) ) ) + { + int r = d->row; + int end = 0; + + // Find free cells bottom to this one + while ( !end ) { + RowFormat *rl2 = format()->sheet()->rowFormat( r + 1 ); + Cell *cell = format()->sheet()->visibleCellAt( d->column, r + 1 ); + + if ( cell->isEmpty() ) { + height += rl2->dblHeight() - 1.0; + r++; + + // Enough space ? + if ( d->textHeight <= ( height - 2 * BORDER_SPACE + - format()->topBorderWidth( _col, _row ) + - format()->bottomBorderWidth( _col, _row ) ) ) + end = 1; + } + else + // Not enough space, but the next cell is not empty. + end = -1; + } + + // Check to make sure we haven't already force-merged enough cells. + if ( r - d->row > d->extra()->mergedYCells ) + { + d->extra()->extraYCells = r - d->row; + d->extra()->extraHeight = height; + + for ( int i = d->row + 1; i <= r; ++i ) + { + Cell *cell = format()->sheet()->nonDefaultCell( d->column, i ); + cell->obscure( this ); + } + + // Not enough space? + if ( end == -1 ) + setFlag( Flag_CellTooShortY ); + } + else + setFlag( Flag_CellTooShortY ); + } + + clearFlag( Flag_LayoutDirty ); + + return; +} + + +void Cell::valueChanged () +{ + update(); + + format()->sheet()->valueChanged (this); +} + + +// Recalculate d->strOutText. +// + +void Cell::setOutputText() +{ + if ( isDefault() ) { + d->strOutText = TQString(); + + if ( d->hasExtra() && d->extra()->conditions ) + d->extra()->conditions->checkMatches(); + + return; + } + + // If nothing has changed, we don't need to remake the text layout. + if ( !testFlag(Flag_TextFormatDirty) ) + return; + + // We don't want to remake the layout unnecessarily. + clearFlag( Flag_TextFormatDirty ); + + // Display a formula if warranted. If not, display the value instead; + // this is the most common case. + if ( (!hasError()) && isFormula() && format()->sheet()->getShowFormula() + && !( format()->sheet()->isProtected() && format()->isHideFormula( d->column, d->row ) ) + || isEmpty() ) + d->strOutText = d->strText; + else { + d->strOutText = sheet()->doc()->formatter()->formatText (this, + formatType()); + } + + // Check conditions if needed. + if ( d->hasExtra() && d->extra()->conditions ) + d->extra()->conditions->checkMatches(); +} + + +// Recalculate d->textX and d->textY. +// +// Used in makeLayout() and calculateTextParameters(). +// + +void Cell::offsetAlign( int _col, int _row ) +{ + int a; + Format::AlignY ay; + int tmpAngle; + bool tmpVerticalText; + bool tmpMultiRow; + + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + { + Style *style = d->extra()->conditions->matchedStyle(); + + if ( style->hasFeature( Style::SAlignX, true ) ) + a = style->alignX(); + else + a = format()->align( _col, _row ); + + if ( style->hasFeature( Style::SVerticalText, true ) ) + tmpVerticalText = style->hasProperty( Style::PVerticalText ); + else + tmpVerticalText = format()->verticalText( _col, _row ); + + if ( style->hasFeature( Style::SMultiRow, true ) ) + tmpMultiRow = style->hasProperty( Style::PMultiRow ); + else + tmpMultiRow = format()->multiRow( _col, _row ); + + if ( style->hasFeature( Style::SAlignY, true ) ) + ay = style->alignY(); + else + ay = format()->alignY( _col, _row ); + + if ( style->hasFeature( Style::SAngle, true ) ) + tmpAngle = style->rotateAngle(); + else + tmpAngle = format()->getAngle( _col, _row ); + } + else { + a = format()->align( _col, _row ); + ay = format()->alignY( _col, _row ); + tmpAngle = format()->getAngle( _col, _row ); + tmpVerticalText = format()->verticalText( _col, _row ); + tmpMultiRow = format()->multiRow( _col, _row ); + } + + RowFormat *rl = format()->sheet()->rowFormat( _row ); + ColumnFormat *cl = format()->sheet()->columnFormat( _col ); + + double w = cl->dblWidth(); + double h = rl->dblHeight(); + + if ( d->hasExtra() ) { + if ( d->extra()->extraXCells ) w = d->extra()->extraWidth; + if ( d->extra()->extraYCells ) h = d->extra()->extraHeight; + } + + const double effTop = BORDER_SPACE + 0.5 * effTopBorderPen( _col, _row ).width(); + const double effBottom = h - BORDER_SPACE - 0.5 * effBottomBorderPen( _col, _row ).width(); + + // Calculate d->textY based on the vertical alignment and a few + // other inputs. + switch( ay ) + { + case Format::Top: + { + if ( tmpAngle == 0 ) + { + d->textY = effTop + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else if ( tmpAngle < 0 ) + { + d->textY = effTop; + } + else + { + d->textY = effTop + + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY(); + } + break; + } + case Format::Bottom: + { + if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) + { + d->textY = effBottom; + } + else if ( tmpAngle != 0 ) + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + if ( tmpAngle < 0 ) + { + d->textY = effBottom - d->textHeight; + } + else + { + d->textY = effBottom - d->textHeight + + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() ); + } + } + else + { + if ( tmpAngle < 0 ) + { + d->textY = effTop; + } + else + { + d->textY = effTop + + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) + / format()->sheet()->doc()->zoomedResolutionY() ); + } + } + } + else if ( tmpMultiRow && !tmpVerticalText ) + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + d->textY = effBottom - d->textHeight + + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else + { + d->textY = effTop + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + } + else + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + d->textY = effBottom - d->textHeight + + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else + { + d->textY = effTop + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + } + break; + } + case Format::Middle: + case Format::UndefinedY: + { + if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) + { + d->textY = ( h - d->textHeight ) / 2 + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else if ( tmpAngle != 0 ) + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + if ( tmpAngle < 0 ) + { + d->textY = ( h - d->textHeight ) / 2; + } + else + { + d->textY = ( h - d->textHeight ) / 2 + + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY(); + } + } + else + { + if ( tmpAngle < 0 ) + { + d->textY = effTop; + } + else + { + d->textY = effTop + + ( (double)d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() ); + } + } + } + else if ( tmpMultiRow && !tmpVerticalText ) + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + d->textY = ( h - d->textHeight ) / 2 + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else + { + d->textY = effTop + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + } + else + { + // Is enough place available? + if ( effBottom - effTop - d->textHeight > 0 ) + { + d->textY = ( h - d->textHeight ) / 2 + + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + else + d->textY = effTop + + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY(); + } + break; + } + } + + a = effAlignX(); + if ( format()->sheet()->getShowFormula() && + !( format()->sheet()->isProtected() && format()->isHideFormula( _col, _row ) ) ) + { + a = Format::Left; + } + + // Calculate d->textX based on alignment and textwidth. + switch ( a ) { + case Format::Left: + d->textX = 0.5 * effLeftBorderPen( _col, _row ).width() + BORDER_SPACE; + break; + case Format::Right: + d->textX = w - BORDER_SPACE - d->textWidth + - 0.5 * effRightBorderPen( _col, _row ).width(); + break; + case Format::Center: + d->textX = 0.5 * ( w - BORDER_SPACE - d->textWidth - + 0.5 * effRightBorderPen( _col, _row ).width() ); + break; + } +} + + +// Recalculate the current text dimensions, i.e. d->textWidth and +// d->textHeight. +// +// Used in makeLayout() and calculateTextParameters(). +// +void Cell::textSize( TQPainter &_paint ) +{ + TQFontMetrics fm = _paint.fontMetrics(); + // Horizontal text ? + + int tmpAngle; + int _row = row(); + int _col = column(); + bool tmpVerticalText; + bool fontUnderlined; + Format::AlignY ay; + + // Set tmpAngle, tmpeVerticalText, ay and fontUnderlined according + // to if there is a matching condition or not. + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + { + Style *style = d->extra()->conditions->matchedStyle(); + + if ( style->hasFeature( Style::SAngle, true ) ) + tmpAngle = style->rotateAngle(); + else + tmpAngle = format()->getAngle( _col, _row ); + + if ( style->hasFeature( Style::SVerticalText, true ) ) + tmpVerticalText = style->hasProperty( Style::PVerticalText ); + else + tmpVerticalText = format()->verticalText( _col, _row ); + + if ( style->hasFeature( Style::SAlignY, true ) ) + ay = style->alignY(); + else + ay = format()->alignY( _col, _row ); + + if ( style->hasFeature( Style::SFontFlag, true ) ) + fontUnderlined = ( style->fontFlags() & (uint) Style::FUnderline ); + else + fontUnderlined = format()->textFontUnderline( _col, _row ); + } + else { + // The cell has no condition with a maxed style. + tmpAngle = format()->getAngle( _col, _row ); + tmpVerticalText = format()->verticalText( _col, _row ); + ay = format()->alignY( _col, _row ); + fontUnderlined = format()->textFontUnderline( _col, _row ); + } + + // Set d->textWidth and d->textHeight to correct values according to + // if the text is horizontal, vertical or rotated. + if ( !tmpVerticalText && !tmpAngle ) { + // Horizontal text. + + d->textWidth = format()->sheet()->doc()->unzoomItX( fm.width( d->strOutText ) ); + int offsetFont = 0; + if ( ( ay == Format::Bottom ) && fontUnderlined ) { + offsetFont = fm.underlinePos() + 1; + } + + d->textHeight = format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent() + + offsetFont ); + } + else if ( tmpAngle!= 0 ) { + // Rotated text. + + d->textHeight = format()->sheet()->doc() + ->unzoomItY( int( cos( tmpAngle * M_PI / 180 ) + * ( fm.ascent() + fm.descent() ) + + abs( int( ( fm.width( d->strOutText ) + * sin( tmpAngle * M_PI / 180 ) ) ) ) ) ); + + d->textWidth = format()->sheet()->doc() + ->unzoomItX( int( abs( int( ( sin( tmpAngle * M_PI / 180 ) + * ( fm.ascent() + fm.descent() ) ) ) ) + + fm.width( d->strOutText ) + * cos ( tmpAngle * M_PI / 180 ) ) ); + } + else { + // Vertical text. + int width = 0; + for ( unsigned int i = 0; i < d->strOutText.length(); i++ ) + width = TQMAX( width, fm.width( d->strOutText.at( i ) ) ); + + d->textWidth = format()->sheet()->doc()->unzoomItX( width ); + d->textHeight = format()->sheet()->doc()->unzoomItY( ( fm.ascent() + fm.descent() ) + * d->strOutText.length() ); + } +} + + +// Get the effective font to use after the zooming and apply it to `painter'. +// +// Used in makeLayout() and calculateTextParameters(). +// + +void Cell::applyZoomedFont( TQPainter &painter, int _col, int _row ) +{ + TQFont tmpFont( format()->textFont( _col, _row ) ); + + // If there is a matching condition on this cell then set the + // according style parameters. + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) { + + Style * s = d->extra()->conditions->matchedStyle(); + + // Other size? + if ( s->hasFeature( Style::SFontSize, true ) ) + tmpFont.setPointSizeFloat( s->fontSize() ); + + // Other attributes? + if ( s->hasFeature( Style::SFontFlag, true ) ) { + uint flags = s->fontFlags(); + + tmpFont.setBold( flags & (uint) Style::FBold ); + tmpFont.setUnderline( flags & (uint) Style::FUnderline ); + tmpFont.setItalic( flags & (uint) Style::FItalic ); + tmpFont.setStrikeOut( flags & (uint) Style::FStrike ); + } + + // Other family? + if ( s->hasFeature( Style::SFontFamily, true ) ) + tmpFont.setFamily( s->fontFamily() ); + } +#if 0 + else + /* + * could somebody please explaint why we check for isProtected or isHideFormula here + */ + if ( d->extra()->conditions + && d->extra()->conditions->currentCondition( condition ) + && !(format()->sheet()->getShowFormula() + && !( format()->sheet()->isProtected() + && format()->isHideFormula( d->column, d->row ) ) ) ) + { + if ( condition.fontcond ) + tmpFont = *(condition.fontcond); + else + tmpFont = condition.style->font(); + } +#endif + + // Scale the font size according to the current zoom. + tmpFont.setPointSizeFloat( 0.01 * format()->sheet()->doc()->zoom() + * tmpFont.pointSizeFloat() ); + + painter.setFont( tmpFont ); +} + + +//used in Sheet::adjustColumnHelper and Sheet::adjustRow +void Cell::calculateTextParameters( TQPainter &_painter, + int _col, int _row ) +{ + // Apply the correct font to _painter. + applyZoomedFont( _painter, _col, _row ); + + // Recalculate d->textWidth and d->textHeight + textSize( _painter ); + + // Recalculate d->textX and d->textY. + offsetAlign( _col, _row ); +} + + +// ---------------------------------------------------------------- +// Formula handling + + +bool Cell::makeFormula() +{ + clearFormula (); + + d->formula = new KSpread::Formula (sheet(), this); + d->formula->setExpression (d->strText); + + if (!d->formula->isValid ()) { + // Did a syntax error occur ? + clearFormula(); + + if (format()->sheet()->doc()->getShowMessageError()) + { + TQString tmp(i18n("Error in cell %1\n\n")); + tmp = tmp.arg( fullName() ); + KMessageBox::error( (TQWidget*)0L, tmp); + } + setFlag(Flag_ParseError); + Value v; + v.setError ( "####" ); + setValue (v); + return false; + } + + // we must recalc + setCalcDirtyFlag (); + + return true; +} + +void Cell::clearFormula() +{ + delete d->formula; + d->formula = 0L; +} + +bool Cell::calc(bool delay) +{ + if ( !isFormula() ) + return true; + + if (d->formula == 0) + { + if ( testFlag( Flag_ParseError ) ) // there was a parse error + return false; + else + { + /* we were probably at a "isLoading() = true" state when we originally + * parsed + */ + makeFormula (); + + if ( d->formula == 0 ) // there was a parse error + return false; + } + } + + if ( !testFlag( Flag_CalcDirty ) ) + return true; + + if ( delay ) + { + if ( format()->sheet()->doc()->delayCalculation() ) + return true; + } + + setFlag(Flag_LayoutDirty); + setFlag(Flag_TextFormatDirty); + clearFlag(Flag_CalcDirty); + + Value result = d->formula->eval (); + setValue (result); + if (result.isNumber()) + checkNumberFormat(); // auto-chooses number or scientific + + clearFlag(Flag_CalcDirty); + setFlag(Flag_LayoutDirty); + + return true; +} + + +// ================================================================ +// Painting + + +// Paint the cell. This is the main function that calls a lot of +// helper functions. +// +// `rect' is the rectangle that we should paint on. If the cell +// does not overlap this rectangle, we can return immediately. +// `coordinate' is the origin (the upper left) of the cell in document +// coordinates. +// + +void Cell::paintCell( const KoRect &rect, TQPainter & painter, + View *view, + const KoPoint &coordinate, + const TQPoint &cellRef, + int paintBorder, + TQPen & rightPen, TQPen & bottomPen, + TQPen & leftPen, TQPen & topPen, + TQValueList &mergedCellsPainted, + bool drawCursor ) +{ + bool paintBorderRight = paintBorder & Border_Right; + bool paintBorderBottom = paintBorder & Border_Bottom; + bool paintBorderLeft = paintBorder & Border_Left; + bool paintBorderTop = paintBorder & Border_Top; + + // If we are already painting this cell, then return immediately. + // This avoids infinite recursion. + if ( testFlag( Flag_PaintingCell ) ) + return; + + // Indicate that we are painting this cell now. + setFlag( Flag_PaintingCell ); + + // This flag indicates that we are working on drawing the cells that + // another cell is obscuring. The value is the number of levels down we + // are currently working -- i.e. a cell obscured by a cell which is + // obscured by a cell. + static int paintingObscured = 0; + +#if 0 + if (paintingObscured == 0) + kdDebug(36001) << "painting cell " << name() << endl; + else + kdDebug(36001) << " painting obscured cell " << name() << endl; +#endif + + // Sanity check: If we're working on drawing an obscured cell, that + // means this cell should have a cell that obscures it. + Q_ASSERT(!(paintingObscured > 0 && d->extra()->obscuringCells.isEmpty())); + + // The parameter cellref should be *this, unless this is the default cell. + Q_ASSERT(isDefault() + || (((cellRef.x() == d->column) && (cellRef.y() == d->row)))); + + Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); + + double left = coordinate.x(); + + ColumnFormat * colFormat = format()->sheet()->columnFormat( cellRef.x() ); + RowFormat * rowFormat = format()->sheet()->rowFormat( cellRef.y() ); + + // Set width, height to the total width and height that this cell + // covers, including obscured cells, and width0, height0 to the + // width and height of this cell, maybe merged but never implicitly + // extended. + double width0 = colFormat->dblWidth(); + double height0 = rowFormat->dblHeight(); + double width = width0; + double height = height0; + + // Handle right-to-left layout. + // In an RTL sheet the cells have to be painted at their opposite horizontal + // location on the canvas, meaning that column A will be the rightmost column + // on screen, column B will be to the left of it and so on. Here we change + // the horizontal coordinate at which we start painting the cell in case the + // sheet's direction is RTL. We do this only if paintingObscured is 0, + // otherwise the cell's painting location will flip back and forth in + // consecutive calls to paintCell when painting obscured cells. + if ( sheetDir == Sheet::RightToLeft && paintingObscured == 0 + && view && view->canvasWidget() ) + { + double dwidth = view->doc()->unzoomItX(view->canvasWidget()->width()); + left = dwidth - coordinate.x() - width; + } + + // See if this cell is merged or has overflown into neighbor cells. + // In that case, the width/height is greater than just the cell + // itself. + if (d->hasExtra()) { + if (d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0) { + // merged cell extends to the left if sheet is RTL + if ( sheetDir == Sheet::RightToLeft ) { + left -= d->extra()->extraWidth - width; + } + width0 = d->extra()->extraWidth; + height0 = d->extra()->extraHeight; + width = d->extra()->extraWidth; + height = d->extra()->extraHeight; + } + else { +#if 0 + width += d->extra()->extraXCells ? d->extra()->extraWidth : 0; + height += d->extra()->extraYCells ? d->extra()->extraHeight : 0; +#else + // FIXME: Make extraWidth/Height really contain the *extra* width/height. + if ( d->extra()->extraXCells ) + width = d->extra()->extraWidth; + if ( d->extra()->extraYCells ) + height = d->extra()->extraHeight; +#endif + } + } + + // Check if the cell is "selected", i.e. it should be drawn with the + // color that indicates selection (dark blue). If more than one + // square is selected, the last one uses the ordinary colors. In + // that case, "selected" will be set to false even though the cell + // itself really is selected. + bool selected = false; + if ( view != NULL ) { + selected = view->selectionInfo()->contains( cellRef ); + + // But the cell doesn't look selected if this is the marker cell. + Cell *cell = format()->sheet()->cellAt( view->selectionInfo()->marker() ); + TQPoint bottomRight( view->selectionInfo()->marker().x() + cell->extraXCells(), + view->selectionInfo()->marker().y() + cell->extraYCells() ); + TQRect markerArea( view->selectionInfo()->marker(), bottomRight ); + selected = selected && !( markerArea.contains( cellRef ) ); + + // Don't draw any selection at all when printing. + if ( painter.device()->isExtDev() || !drawCursor ) + selected = false; + } + + // Need to make a new layout ? + // + // FIXME: We have already used (at least) extraWidth/Height above, + // and now we are recalculating the layout. This has to be + // moved up above all uses. + // + // FIXME: This needs to be taken out eventually - it is done in + // canvas::paintUpdates(). + if ( testFlag( Flag_LayoutDirty ) ) + makeLayout( painter, cellRef.x(), cellRef.y() ); + + // ---------------- Start the actual painting. ---------------- + + // If the rect of this cell doesn't intersect the rect that should + // be painted, we can skip the rest and return. (Note that we need + // to calculate `left' first before we can do this.) + const KoRect cellRect( left, coordinate.y(), width, height ); + const KoRect cellRect0( left, coordinate.y(), width0, height0 ); + if ( !cellRect.intersects( rect ) ) { + clearFlag( Flag_PaintingCell ); + return; + } + + // Get the background color. + // + // If there is a condition giving the background color for this cell + // (and it matches), use that one, otherwise get the standard + // background. + TQColor backgroundColor; + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundColor, true ) ) + backgroundColor = d->extra()->conditions->matchedStyle()->bgColor(); + else + backgroundColor = bgColor( cellRef.x(), cellRef.y() ); + + // 1. Paint the background. + if ( !isPartOfMerged() ) + paintBackground( painter, cellRect0, cellRef, selected, backgroundColor ); + + // 2. Paint the default borders if we are on screen or if we are printing + // and the checkbox to do this is checked. + if ( painter.device()->devType() != TQInternal::Printer + || format()->sheet()->print()->printGrid()) + paintDefaultBorders( painter, rect, cellRect, cellRef, + paintBorderRight, paintBorderBottom, + paintBorderLeft, paintBorderTop, + rightPen, bottomPen, leftPen, topPen ); + + // 3. Paint all the cells that this one obscures. They may only be + // partially obscured. + // + // The `paintingObscured' variable is used to avoid infinite + // recursion since cells sometimes paint their obscuring cell as + // well. + paintingObscured++; + + if (d->hasExtra() && (d->extra()->extraXCells > 0 + || d->extra()->extraYCells > 0)) { + //kdDebug(36001) << "painting obscured cells for " << name() << endl; + + paintObscuredCells( rect, painter, view, cellRect, cellRef, + paintBorderRight, paintBorderBottom, + paintBorderLeft, paintBorderTop, + rightPen, bottomPen, leftPen, topPen, + mergedCellsPainted); + + // FIXME: Is this the right place for this? + if ( d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0 ) + mergedCellsPainted.prepend( cellRef ); + } + paintingObscured--; + + // 4. Paint the borders of the cell if no other cell is forcing this + // one, i.e. this cell is not part of a merged cell. + // + + // If we print pages, then we disable clipping, otherwise borders are + // cut in the middle at the page borders. + if ( painter.device()->isExtDev() ) + painter.setClipping( false ); + + // Paint the borders if this cell is not part of another merged cell. + if ( !isPartOfMerged() ) { + // if (!testFlag(Flag_Highlight)) + paintCellBorders( painter, rect, cellRect0, + cellRef, + paintBorderRight, paintBorderBottom, + paintBorderLeft, paintBorderTop, + rightPen, bottomPen, leftPen, topPen ); + } + + // Turn clipping back on. + if ( painter.device()->isExtDev() ) + painter.setClipping( true ); + + // 5. Paint diagonal lines and page borders. + paintCellDiagonalLines( painter, cellRect0, cellRef ); + + paintPageBorders( painter, cellRect0, cellRef, + paintBorderRight, paintBorderBottom ); + + + // 6. Now paint the content, if this cell isn't obscured. + if ( !isObscured() ) { + + // 6a. Paint possible comment indicator. + if ( !painter.device()->isExtDev() + || format()->sheet()->print()->printCommentIndicator() ) + paintCommentIndicator( painter, cellRect, cellRef, backgroundColor ); + + // 6b. Paint possible formula indicator. + if ( !painter.device()->isExtDev() + || format()->sheet()->print()->printFormulaIndicator() ) + paintFormulaIndicator( painter, cellRect, backgroundColor ); + + // 6c. Paint possible indicator for clipped text. + paintMoreTextIndicator( painter, cellRect, backgroundColor ); + + //6c. Paint cell highlight +#if 0 + if (highlightBorder != Border_None) + paintCellHighlight ( painter, cellRect, cellRef, highlightBorder, + rightHighlightPen, bottomHighlightPen, + leftHighlightPen, topHighlightPen ); +#endif + + // 6d. Paint the text in the cell unless: + // a) it is empty + // b) something indicates that the text should not be painted + // c) the sheet is protected and the cell is hidden. + if ( !d->strOutText.isEmpty() + && ( !painter.device()->isExtDev() + || !format()->getDontprintText( cellRef.x(), cellRef.y() ) ) + && !( format()->sheet()->isProtected() + && format()->isHideAll( cellRef.x(), cellRef.y() ) ) ) + { + paintText( painter, cellRect, cellRef ); + } + } + + // 7. If this cell is obscured and we are not already painting obscured + // cells, then paint the obscuring cell(s). Otherwise don't do + // anything so that we don't cause an infinite loop. + if ( isObscured() && paintingObscured == 0 && + !( sheetDir == Sheet::RightToLeft && painter.device()->isExtDev() ) ) + { + + //kdDebug(36001) << "painting cells that obscure " << name() << endl; + + // Store the obscuringCells list in a list of TQPoint(column, row) + // This avoids crashes during the iteration through + // obscuringCells, when the cells may get non valid or the list + // itself gets changed during a call of obscuringCell->paintCell + // (this happens e.g. when there is an updateDepend) + if (d->hasExtra()) { + TQValueList listPoints; + TQValueList::iterator it = d->extra()->obscuringCells.begin(); + TQValueList::iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + Cell *obscuringCell = *it; + + listPoints.append( TQPoint( obscuringCell->column(), obscuringCell->row() ) ); + } + + TQValueList::iterator it1 = listPoints.begin(); + TQValueList::iterator end1 = listPoints.end(); + for ( ; it1 != end1; ++it1 ) { + TQPoint obscuringCellRef = *it1; + + // Only paint those obscuring cells that haven't been already + // painted yet. + // + // This optimization removes an O(n^4) behaviour where n is + // the number of cells on one edge in a merged cell. + if ( mergedCellsPainted.contains( obscuringCellRef ) ) + continue; + + Cell *obscuringCell = format()->sheet()->cellAt( obscuringCellRef.x(), + obscuringCellRef.y() ); + + if ( obscuringCell != 0 ) { + double x = format()->sheet()->dblColumnPos( obscuringCellRef.x() ); + double y = format()->sheet()->dblRowPos( obscuringCellRef.y() ); + if ( view != 0 ) { + x -= view->canvasWidget()->xOffset(); + y -= view->canvasWidget()->yOffset(); + } + + KoPoint corner( x, y ); + painter.save(); + + // Get the effective pens for the borders. These are + // determined by possible conditions on the cell with + // associated styles. + TQPen rp( obscuringCell->effRightBorderPen( obscuringCellRef.x(), + obscuringCellRef.y() ) ); + TQPen bp( obscuringCell->effBottomBorderPen( obscuringCellRef.x(), + obscuringCellRef.y() ) ); + TQPen lp( obscuringCell->effLeftBorderPen( obscuringCellRef.x(), + obscuringCellRef.y() ) ); + TQPen tp( obscuringCell->effTopBorderPen( obscuringCellRef.x(), + obscuringCellRef.y() ) ); + + + //kdDebug(36001) << " painting obscuring cell " + // << obscuringCell->name() << endl; + // TQPen highlightPen; + + //Note: Painting of highlight isn't quite right. If several + // cells are merged, then the whole merged cell will be + // painted with the colour of the last cell referenced + // which is inside the merged range. + obscuringCell->paintCell( rect, painter, view, + corner, obscuringCellRef, + Border_Left|Border_Top|Border_Right|Border_Bottom, + rp, bp, lp, tp, + mergedCellsPainted); // new pens + painter.restore(); + } + } + } + } + + // We are done with the painting, so remove the flag on the cell. + clearFlag( Flag_PaintingCell ); +} + + + +// The following code was commented out in the above function. I'll +// leave it here in case this functionality is ever re-implemented and +// someone wants some code to start from. +// +#if 0 + + /** + * Modification for drawing the button + */ + if ( d->style == Cell::ST_Button ) { + TQBrush fill( TQt::lightGray ); + TQApplication::style().drawControl( TQStyle::CE_PushButton, &_painter, this, + TQRect( _tx + 1, _ty + 1, w2 - 1, h2 - 1 ), + defaultColorGroup ); //, selected, &fill ); + } + + /** + * Modification for drawing the combo box + */ + else if ( d->style == Cell::ST_Select ) { + TQApplication::style().drawComboButton( &_painter, _tx + 1, _ty + 1, + w2 - 1, h2 - 1, + defaultColorGroup, selected ); + } +#endif + + +#if 0 + void Cell::paintCellHighlight(TQPainter& painter, + const KoRect& cellRect, + const TQPoint& cellRef, + const int highlightBorder, + const TQPen& rightPen, + const TQPen& bottomPen, + const TQPen& leftPen, + const TQPen& topPen + ) +{ + //painter.drawLine(cellRect.left(),cellRect.top(),cellRect.right(),cellRect.bottom()); + //TQPen pen(d->extra()->highlight); + //painter.setPen(highlightPen); + + TQBrush nullBrush; + painter.setBrush(nullBrush); + + TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect ); + + //The highlight rect is just inside the main cell rect + //This saves the hassle of repainting nearby cells when the highlight is changed as the highlight areas + //do not overlap + zoomedCellRect.setLeft(zoomedCellRect.left()+1); + //zoomedCellRect.setRight(zoomedCellRect.right()-1); + zoomedCellRect.setTop(zoomedCellRect.top()+1); + //zoomedCellRect.setBottom(zoomedCellRect.bottom()-1); + + if ( cellRef.x() != KS_colMax ) + zoomedCellRect.setWidth( zoomedCellRect.width() - 1 ); + if ( cellRef.y() != KS_rowMax ) + zoomedCellRect.setHeight( zoomedCellRect.height() - 1 ); + + if (highlightBorder & Border_Top) + { + painter.setPen(topPen); + painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.top()); + } + if (highlightBorder & Border_Left) + { + painter.setPen(leftPen); + painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.left(),zoomedCellRect.bottom()); + } + if (highlightBorder & Border_Right) + { + painter.setPen(rightPen); + painter.drawLine(zoomedCellRect.right(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.bottom()); + } + if (highlightBorder & Border_Bottom) + { + painter.setPen(bottomPen); + painter.drawLine(zoomedCellRect.left(),zoomedCellRect.bottom(),zoomedCellRect.right(),zoomedCellRect.bottom()); + } + + if (highlightBorder & Border_SizeGrip) + { + TQBrush brush(rightPen.color()); + painter.setBrush(brush); + painter.setPen(rightPen); + painter.drawRect(zoomedCellRect.right()-3,zoomedCellRect.bottom()-3,4,4); + } + + //painter.drawRect(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.width(),zoomedCellRect.height()); +} +#endif + + +// Paint all the cells that this cell obscures (helper function to paintCell). +// +void Cell::paintObscuredCells(const KoRect& rect, TQPainter& painter, + View* view, + const KoRect &cellRect, + const TQPoint &cellRef, + bool paintBorderRight, + bool _paintBorderBottom, + bool paintBorderLeft, + bool _paintBorderTop, + TQPen & rightPen, TQPen & _bottomPen, + TQPen & leftPen, TQPen & _topPen, + TQValueList &mergedCellsPainted) +{ + // If there are no obscured cells, return. + if ( !extraXCells() && !extraYCells() ) + return; + + double ypos = cellRect.y(); + int maxY = extraYCells(); + int maxX = extraXCells(); + + // Loop through the rectangle of squares that we obscure and paint them. + for ( int y = 0; y <= maxY; ++y ) { + double xpos = cellRect.x(); + RowFormat* rl = format()->sheet()->rowFormat( cellRef.y() + y ); + + for( int x = 0; x <= maxX; ++ x ) { + ColumnFormat * cl = format()->sheet()->columnFormat( cellRef.x() + x ); + if ( y != 0 || x != 0 ) { + uint column = cellRef.x() + x; + uint row = cellRef.y() + y; + + TQPen topPen; + TQPen bottomPen; + bool paintBorderTop; + bool paintBorderBottom; + + Cell *cell = format()->sheet()->cellAt( column, row ); + KoPoint corner( xpos, ypos ); + + // Check if the upper and lower borders should be painted, and + // if so which pens we should use. There used to be a nasty + // bug here (#61452). + // Check top pen. Only check if this is not on the top row. + topPen = _topPen; + paintBorderTop = _paintBorderTop; + if ( row > 1 && !cell->isPartOfMerged() ) { + Cell *cellUp = format()->sheet()->cellAt( column, row - 1 ); + + if ( cellUp->isDefault() ) + paintBorderTop = false; + else { + // If the cell towards the top is part of a merged cell, get + // the pointer to the master cell. + cellUp = cellUp->ultimateObscuringCell(); + + topPen = cellUp->effBottomBorderPen( cellUp->column(), + cellUp->row() ); + +#if 0 + int penWidth = TQMAX(1, sheet()->doc()->zoomItY( topPen.width() )); + topPen.setWidth( penWidth ); +#endif + } + } + + // FIXME: I thought we had to check bottom pen as well. + // However, it looks as if we don't need to. It works anyway. + bottomPen = _bottomPen; + paintBorderBottom = _paintBorderBottom; + + int paintBorder = Border_None; + if (paintBorderLeft) paintBorder |= Cell::Border_Left; + if (paintBorderRight) paintBorder |= Cell::Border_Right; + if (paintBorderTop) paintBorder |= Cell::Border_Top; + if (paintBorderBottom) paintBorder |= Cell::Border_Bottom; + + /*Cell::BorderSides highlightBorder = Border_None; + TQPen highlightPen;*/ + + + //kdDebug(36001) << "calling paintcell for obscured cell " + // << cell->name() << endl; + cell->paintCell( rect, painter, view, + corner, + TQPoint( cellRef.x() + x, cellRef.y() + y ), + paintBorder, + rightPen, bottomPen, leftPen, topPen, + mergedCellsPainted); + } + xpos += cl->dblWidth(); + } + + ypos += rl->dblHeight(); + } +} + + +// Paint the background of this cell. +// +void Cell::paintBackground( TQPainter& painter, const KoRect &cellRect, + const TQPoint &cellRef, bool selected, + TQColor &backgroundColor ) +{ + TQColorGroup defaultColorGroup = TQApplication::palette().active(); + TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect ); + + // If this is not the KS_rowMax and/or KS_colMax, then we reduce + // width and/or height by one. This is due to the fact that the + // right/bottom most pixel is shared with the left/top most pixel of + // the following cell. Only in the case of KS_colMax/KS_rowMax we + // need to draw even this pixel, as there isn't a following cell to + // draw the background pixel. + if ( cellRef.x() != KS_colMax ) + zoomedCellRect.setWidth( zoomedCellRect.width() - 1 ); + if ( cellRef.y() != KS_rowMax ) + zoomedCellRect.setHeight( zoomedCellRect.height() - 1 ); + + // Determine the correct background color + if ( selected ) + { + //If the cell's background color is too bright, use the default highlight color + //Otherwise use a lighter version of the cell's background color. + TQColor c; + + int averageColor = (backgroundColor.red() + backgroundColor.green() + backgroundColor.blue()) / 3; + + if (averageColor > 180) + if (averageColor > 225) + c = View::highlightColor(); + else + c = backgroundColor.light( 115 ); //15% lighter + else + c = backgroundColor.light( 125 ); //25% lighter + + painter.setBackgroundColor( c ); + } + else { + TQColor bg( backgroundColor ); + + // Handle printers separately. + if ( !painter.device()->isExtDev() ) { + if ( bg.isValid() ) + painter.setBackgroundColor( bg ); + else + painter.setBackgroundColor( defaultColorGroup.base() ); + } + else { + //bad hack but there is a qt bug + //so I can print backgroundcolor + TQBrush bb( bg ); + if ( !bg.isValid() ) + bb.setColor( TQt::white ); + + painter.fillRect( zoomedCellRect, bb ); + return; + } + } + + // Erase the background of the cell. + if ( !painter.device()->isExtDev() ) + painter.eraseRect( zoomedCellRect ); + + // Get a background brush + TQBrush bb; + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundBrush, true ) ) + bb = d->extra()->conditions->matchedStyle()->backGroundBrush(); + else + bb = backGroundBrush( cellRef.x(), cellRef.y() ); + + // Draw background pattern if necessary. + if ( bb.style() != TQt::NoBrush ) + painter.fillRect( zoomedCellRect, bb ); + + backgroundColor = painter.backgroundColor(); +} + + +// Paint the standard light grey borders that are always visible. +// +void Cell::paintDefaultBorders( TQPainter& painter, const KoRect &rect, + const KoRect &cellRect, + const TQPoint &cellRef, + bool paintBorderRight, bool /*paintBorderBottom*/, + bool paintBorderLeft, bool paintBorderTop, + TQPen const & rightPen, TQPen const & /*bottomPen*/, + TQPen const & leftPen, TQPen const & topPen ) +{ + /* + *** Notes about optimisation *** + + This function was painting the top , left , right & bottom lines in almost all cells previously, contrary to what the comment + below says should happen. There doesn't appear to be a UI option to enable or disable showing of the grid when printing at the moment, + so I have disabled drawing of right and bottom borders for all cells. + + I also couldn't work out under what conditions the variables dt / db would come out as anything other than 0 in the code + for painting the various borders. The effTopBorderPen / effBottomBorderPen calls were taking up a lot of time + according some profiling I did. If that code really is necessary, we need to find a more efficient way of getting the widths + than grabbing the whole TQPen object and asking it. + + + --Robert Knight (robertknight@gmail.com) + */ + Doc* doc = sheet()->doc(); + + Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); + bool paintingToExternalDevice = painter.device()->isExtDev(); + + // Each cell is responsible for drawing it's top and left portions + // of the "default" grid. --Or not drawing it if it shouldn't be + // there. It's also responsible to paint the right and bottom, if + // it is the last cell on a print out. + + bool paintTop; + bool paintLeft; + bool paintBottom=false; + bool paintRight=false; + + paintLeft = ( paintBorderLeft && leftPen.style() == TQt::NoPen + && sheet()->getShowGrid() && sheetDir==Sheet::LeftToRight ); + paintRight = ( paintBorderRight && rightPen.style() == TQt::NoPen + && sheet()->getShowGrid() && sheetDir==Sheet::RightToLeft ); + paintTop = ( paintBorderTop && topPen.style() == TQt::NoPen + && sheet()->getShowGrid() ); +// paintBottom = ( paintBorderBottom && sheet()->getShowGrid() +// && bottomPen.style() == TQt::NoPen ); + + + //Set the single-pixel with pen for drawing the borders with. + painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); + + // If there are extra cells, there might be more conditions. + if (d->hasExtra()) { + TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); + TQValueList::const_iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + Cell *cell = *it; + + paintTop = paintTop && ( cell->row() == cellRef.y() ); + paintBottom = false; + + if ( sheetDir == Sheet::RightToLeft ) { + paintRight = paintRight && ( cell->column() == cellRef.x() ); + paintLeft = false; + } + else { + paintLeft = paintLeft && ( cell->column() == cellRef.x() ); + paintRight = false; + } + } + } + + // The left border. + if ( paintLeft ) { + int dt = 0; + int db = 0; + + #if 0 + if ( cellRef.x() > 1 ) { + Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1, + cellRef.y() ); + TQPen t = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() ); + TQPen b = cell_west->effBottomBorderPen( cellRef.x() - 1, cellRef.y() ); + + if ( t.style() != TQt::NoPen ) + dt = ( t.width() + 1 )/2; + if ( b.style() != TQt::NoPen ) + db = ( t.width() / 2); + } + #endif + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( paintingToExternalDevice ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); + else + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() + dt ), + doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.bottom() - db ) ); + else + painter.drawLine( doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.y() + dt ), + doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.bottom() - db ) ); + } + } + + + // The top border. + if ( paintTop ) { + int dl = 0; + int dr = 0; + + #if 0 + if ( cellRef.y() > 1 ) { + Cell *cell_north = format()->sheet()->cellAt( cellRef.x(), + cellRef.y() - 1 ); + + TQPen l = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 ); + TQPen r = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); + + if ( l.style() != TQt::NoPen ) + dl = ( l.width() - 1 ) / 2 + 1; + if ( r.style() != TQt::NoPen ) + dr = r.width() / 2; + } + #endif + + + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( paintingToExternalDevice ) { + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.y() ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.y() ) ) ); + } + else { + painter.drawLine( doc->zoomItX( cellRect.x() + dl ), + doc->zoomItY( cellRect.y() ), + doc->zoomItX( cellRect.right() - dr ), + doc->zoomItY( cellRect.y() ) ); + } + } + + + // The right border. + if ( paintRight ) { + int dt = 0; + int db = 0; + + #if 0 + if ( cellRef.x() < KS_colMax ) { + Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1, + cellRef.y() ); + + TQPen t = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() ); + TQPen b = cell_east->effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); + + if ( t.style() != TQt::NoPen ) + dt = ( t.width() + 1 ) / 2; + if ( b.style() != TQt::NoPen ) + db = ( t.width() / 2); + } + #endif + + //painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); + else + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.y() + dt ), + doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.bottom() - db ) ); + else + painter.drawLine( doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() + dt ), + doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.bottom() - db ) ); + } + } + + // The bottom border. + /*if ( paintBottom ) { + int dl = 0; + int dr = 0; + if ( cellRef.y() < KS_rowMax ) { + Cell *cell_south = format()->sheet()->cellAt( cellRef.x(), + cellRef.y() + 1 ); + + TQPen l = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); + TQPen r = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); + + if ( l.style() != TQt::NoPen ) + dl = ( l.width() - 1 ) / 2 + 1; + if ( r.style() != TQt::NoPen ) + dr = r.width() / 2; + } + + painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) ); + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ), + doc->zoomItY( TQMAX( rect.top(), cellRect.bottom() ) ), + doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ), + doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() ) ) ); + } + else { + painter.drawLine( doc->zoomItX( cellRect.x() + dl ), + doc->zoomItY( cellRect.bottom() ), + doc->zoomItX( cellRect.right() - dr ), + doc->zoomItY( cellRect.bottom() ) ); + } + }*/ +} + + +// Paint a comment indicator if the cell has a comment. +// +void Cell::paintCommentIndicator( TQPainter& painter, + const KoRect &cellRect, + const TQPoint &/*cellRef*/, + TQColor &backgroundColor ) +{ + Doc * doc = sheet()->doc(); + + // Point the little corner if there is a comment attached + // to this cell. + if ( ( format()->propertiesMask() & (uint) Format::PComment ) + && cellRect.width() > 10.0 + && cellRect.height() > 10.0 + && ( sheet()->print()->printCommentIndicator() + || ( !painter.device()->isExtDev() && sheet()->getShowCommentIndicator() ) ) ) { + TQColor penColor = TQt::red; + + // If background has high red part, switch to blue. + if ( tqRed( backgroundColor.rgb() ) > 127 && + tqGreen( backgroundColor.rgb() ) < 80 && + tqBlue( backgroundColor.rgb() ) < 80 ) + { + penColor = TQt::blue; + } + + // Get the triangle. + TQPointArray point( 3 ); + if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) { + point.setPoint( 0, doc->zoomItX( cellRect.x() + 6.0 ), + doc->zoomItY( cellRect.y() ) ); + point.setPoint( 1, doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.y() ) ); + point.setPoint( 2, doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.y() + 6.0 ) ); + } + else { + point.setPoint( 0, doc->zoomItX( cellRect.right() - 5.0 ), + doc->zoomItY( cellRect.y() ) ); + point.setPoint( 1, doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() ) ); + point.setPoint( 2, doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() + 5.0 ) ); + } + + // And draw it. + painter.setBrush( TQBrush( penColor ) ); + painter.setPen( TQt::NoPen ); + painter.drawPolygon( point ); + } +} + + + +// Paint a small rectangle if this cell holds a formula. +// +void Cell::paintFormulaIndicator( TQPainter& painter, + const KoRect &cellRect, + TQColor &backgroundColor ) +{ + if ( isFormula() && + format()->sheet()->getShowFormulaIndicator() && + cellRect.width() > 10.0 && + cellRect.height() > 10.0 ) + { + Doc* doc = sheet()->doc(); + + TQColor penColor = TQt::blue; + // If background has high blue part, switch to red. + if ( tqRed( backgroundColor.rgb() ) < 80 && + tqGreen( backgroundColor.rgb() ) < 80 && + tqBlue( backgroundColor.rgb() ) > 127 ) + { + penColor = TQt::red; + } + + // Get the triangle... + TQPointArray point( 3 ); + if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) { + point.setPoint( 0, doc->zoomItX( cellRect.right() - 6.0 ), + doc->zoomItY( cellRect.bottom() ) ); + point.setPoint( 1, doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.bottom() ) ); + point.setPoint( 2, doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.bottom() - 6.0 ) ); + } + else { + point.setPoint( 0, doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.bottom() - 6.0 ) ); + point.setPoint( 1, doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.bottom() ) ); + point.setPoint( 2, doc->zoomItX( cellRect.x() + 6.0 ), + doc->zoomItY( cellRect.bottom() ) ); + } + + // ...and draw it. + painter.setBrush( TQBrush( penColor ) ); + painter.setPen( TQt::NoPen ); + painter.drawPolygon( point ); + } +} + + +// Paint an indicator that the text in the cell is cut. +// +void Cell::paintMoreTextIndicator( TQPainter& painter, + const KoRect &cellRect, + TQColor &backgroundColor ) +{ + // Show a red triangle when it's not possible to write all text in cell. + // Don't print the red triangle if we're printing. + if( testFlag( Flag_CellTooShortX ) && + !painter.device()->isExtDev() && + cellRect.height() > 4.0 && + cellRect.width() > 4.0 ) + { + Doc* doc = sheet()->doc(); + + TQColor penColor = TQt::red; + // If background has high red part, switch to blue. + if ( tqRed( backgroundColor.rgb() ) > 127 + && tqGreen( backgroundColor.rgb() ) < 80 + && tqBlue( backgroundColor.rgb() ) < 80 ) + { + penColor = TQt::blue; + } + + // Get the triangle... + TQPointArray point( 3 ); + if ( d->strOutText.isRightToLeft() ) { + point.setPoint( 0, doc->zoomItX( cellRect.left() + 4.0 ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 -4.0 ) ); + point.setPoint( 1, doc->zoomItX( cellRect.left() ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 )); + point.setPoint( 2, doc->zoomItX( cellRect.left() + 4.0 ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 +4.0 ) ); + } + else { + point.setPoint( 0, doc->zoomItX( cellRect.right() - 4.0 ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 - 4.0 ) ); + point.setPoint( 1, doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ) ); + point.setPoint( 2, doc->zoomItX( cellRect.right() - 4.0 ), + doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 + 4.0 ) ); + } + + // ...and paint it. + painter.setBrush( TQBrush( penColor ) ); + painter.setPen( TQt::NoPen ); + painter.drawPolygon( point ); + } +} + + +// Paint the real contents of a cell - the text. +// +void Cell::paintText( TQPainter& painter, + const KoRect &cellRect, + const TQPoint &cellRef ) +{ + Doc *doc = sheet()->doc(); + + ColumnFormat *colFormat = format()->sheet()->columnFormat( cellRef.x() ); + + TQColorGroup defaultColorGroup = TQApplication::palette().active(); + TQColor textColorPrint = effTextColor( cellRef.x(), cellRef.y() ); + + // Resolve the text color if invalid (=default). + if ( !textColorPrint.isValid() ) { + if ( painter.device()->isExtDev() ) + textColorPrint = TQt::black; + else + textColorPrint = TQApplication::palette().active().text(); + } + + TQPen tmpPen( textColorPrint ); + + // Set the font according to the current zoom. + applyZoomedFont( painter, cellRef.x(), cellRef.y() ); + + // Check for red font color for negative values. + if ( !d->hasExtra() + || !d->extra()->conditions + || !d->extra()->conditions->matchedStyle() ) { + if ( value().isNumber() + && !( format()->sheet()->getShowFormula() + && !( format()->sheet()->isProtected() + && format()->isHideFormula( d->column, d->row ) ) ) ) + { + double v = value().asFloat(); + if ( format()->floatColor( cellRef.x(), cellRef.y()) == Format::NegRed + && v < 0.0 ) + tmpPen.setColor( TQt::red ); + } + } + + // Check for blue color, for hyperlink. + if ( !link().isEmpty() ) { + tmpPen.setColor( TQApplication::palette().active().link() ); + TQFont f = painter.font(); + f.setUnderline( true ); + painter.setFont( f ); + } + +#if 0 +/**** + + For now I am commenting this out -- with the default color display you + can read normal text through a highlighted background. Maybe this isn't + always the case, though, and we can put the highlighted text color back in. + In that case, we need to somewhere in here figure out if the text overlaps + another cell outside of the selection, otherwise that portion of the text + will be printed white on white. So just that portion would need to be + painted again in the normal color. + + This should probably be done eventually, anyway, because I like using the + reverse text color for highlighted cells. I just don't like extending the + cell 'highlight' background outside of the selection rectangle because it + looks REALLY ugly. +*/ + + if ( selected && ( cellRef.x() != marker.x() || cellRef.y() != marker.y() ) ) + { + TQPen p( tmpPen ); + p.setColor( defaultColorGroup.highlightedText() ); + painter.setPen( p ); + } + else { + painter.setPen(tmpPen); + } +#endif + painter.setPen( tmpPen ); + + TQString tmpText = d->strOutText; + double tmpHeight = d->textHeight; + double tmpWidth = d->textWidth; + + // If the cell is to narrow to paint the whole contents, then pick + // out a part of the content that we paint. The result of this is + // dependent on the data type of the content. + // + // FIXME: Make this dependent on the height as well. + // + if ( testFlag( Flag_CellTooShortX ) ) { + d->strOutText = textDisplaying( painter ); + + // Recalculate the text width and the offset. + textSize( painter ); + offsetAlign( column(), row() ); + } + + // Hide zero. + if ( format()->sheet()->getHideZero() + && value().isNumber() + && value().asFloat() == 0 ) { + d->strOutText = TQString(); + } + + // Clear extra cell if column or row is hidden + // + // FIXME: I think this should be done before the call to + // textDisplaying() above. + // + if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) { + freeAllObscuredCells(); /* TODO: This looks dangerous...must check when I + have time */ + d->strOutText = ""; + } + + double indent = 0.0; + double offsetCellTooShort = 0.0; + int a = effAlignX(); + + // Apply indent if text is align to left not when text is at right or middle. + if ( a == Format::Left && !isEmpty() ) { + // FIXME: The following condition should be remade into a call to + // a new convenience function: + // if ( hasConditionStyleFeature( Style::SIndent, true )... + // This should be done throughout the entire file. + // + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SIndent, true ) ) + indent = d->extra()->conditions->matchedStyle()->indent(); + else + indent = format()->getIndent( column(), row() ); + } + + // Made an offset, otherwise ### is under red triangle. + if ( a == Format::Right && !isEmpty() && testFlag( Flag_CellTooShortX ) ) + offsetCellTooShort = format()->sheet()->doc()->unzoomItX( 4 ); + + TQFontMetrics fm2 = painter.fontMetrics(); + double offsetFont = 0.0; + + if ( format()->alignY( column(), row() ) == Format::Bottom + && format()->textFontUnderline( column(), row() ) ) + offsetFont = format()->sheet()->doc()->unzoomItX( fm2.underlinePos() + 1 ); + + int tmpAngle; + bool tmpMultiRow; + bool tmpVerticalText; + + // Check for angled or vertical text. + if ( d->hasExtra() + && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + { + Style *matchedStyle = d->extra()->conditions->matchedStyle(); + + if ( matchedStyle->hasFeature( Style::SAngle, true ) ) + tmpAngle = d->extra()->conditions->matchedStyle()->rotateAngle(); + else + tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() ); + + if ( matchedStyle->hasFeature( Style::SVerticalText, true ) ) + tmpVerticalText = matchedStyle->hasProperty( Style::PVerticalText ); + else + tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() ); + + if ( matchedStyle->hasFeature( Style::SMultiRow, true ) ) + tmpMultiRow = matchedStyle->hasProperty( Style::PMultiRow ); + else + tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() ); + } + else { + tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() ); + tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() ); + tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() ); + } + + // Actually paint the text. + // There are 4 possible cases: + // - One line of text , horizontal + // - Angled text + // - Multiple rows of text , horizontal + // - Vertical text + if ( !tmpMultiRow && !tmpVerticalText && !tmpAngle ) { + // Case 1: The simple case, one line, no angle. + + painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX - offsetCellTooShort ), + doc->zoomItY( cellRect.y() + d->textY - offsetFont ), d->strOutText ); + } + else if ( tmpAngle != 0 ) { + // Case 2: an angle. + + int angle = tmpAngle; + TQFontMetrics fm = painter.fontMetrics(); + + painter.rotate( angle ); + double x; + if ( angle > 0 ) + x = indent + cellRect.x() + d->textX; + else + x = indent + cellRect.x() + d->textX + - doc->unzoomItX((int) (( fm.descent() + fm.ascent() ) * sin( angle * M_PI / 180 ))); + double y; + if ( angle > 0 ) + y = cellRect.y() + d->textY; + else + y = cellRect.y() + d->textY + d->textHeight; + painter.drawText( doc->zoomItX( x * cos( angle * M_PI / 180 ) + + y * sin( angle * M_PI / 180 ) ), + doc->zoomItY( -x * sin( angle * M_PI / 180 ) + + y * cos( angle * M_PI / 180 ) ), + d->strOutText ); + painter.rotate( -angle ); + } + else if ( tmpMultiRow && !tmpVerticalText ) { + // Case 3: Multiple rows, but horizontal. + + TQString t; + int i; + int pos = 0; + double dy = 0.0; + TQFontMetrics fm = painter.fontMetrics(); + do { + i = d->strOutText.find( "\n", pos ); + if ( i == -1 ) + t = d->strOutText.mid( pos, d->strOutText.length() - pos ); + else { + t = d->strOutText.mid( pos, i - pos ); + pos = i + 1; + } + + int align = effAlignX(); + if ( format()->sheet()->getShowFormula() + && !( format()->sheet()->isProtected() + && format()->isHideFormula( d->column, d->row ) ) ) + align = Format::Left; + + // #### Torben: This looks duplicated for me + switch ( align ) { + case Format::Left: + d->textX = effLeftBorderPen( cellRef.x(), cellRef.y() ).width() + BORDER_SPACE; + break; + + case Format::Right: + d->textX = cellRect.width() - BORDER_SPACE - doc->unzoomItX( fm.width( t ) ) + - effRightBorderPen( cellRef.x(), cellRef.y() ).width(); + break; + + case Format::Center: + d->textX = ( cellRect.width() - doc->unzoomItX( fm.width( t ) ) ) / 2; + } + + painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ), + doc->zoomItY( cellRect.y() + d->textY + dy ), t ); + dy += doc->unzoomItY( fm.descent() + fm.ascent() ); + } while ( i != -1 ); + } + else if ( tmpVerticalText && !d->strOutText.isEmpty() ) { + // Case 4: Vertical text. + + TQString t; + int i = 0; + int len = 0; + double dy = 0.0; + TQFontMetrics fm = painter.fontMetrics(); + do { + len = d->strOutText.length(); + t = d->strOutText.at( i ); + painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ), + doc->zoomItY( cellRect.y() + d->textY + dy ), t ); + dy += doc->unzoomItY( fm.descent() + fm.ascent() ); + i++; + } while ( i != len ); + } + + // Check for too short cell and set the outText for future reference. + if ( testFlag( Flag_CellTooShortX ) ) { + d->strOutText = tmpText; + d->textHeight = tmpHeight; + d->textWidth = tmpWidth; + } + + if ( format()->sheet()->getHideZero() && value().isNumber() + && value().asFloat() == 0 ) + d->strOutText = tmpText; + + if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) + d->strOutText = tmpText; +} + + +// Paint page borders on the page. Only do this on the screen. +// +void Cell::paintPageBorders( TQPainter& painter, + const KoRect &cellRect, + const TQPoint &cellRef, + bool paintBorderRight, + bool paintBorderBottom ) +{ + // Not screen? Return immediately. + if ( painter.device()->isExtDev() ) + return; + + if ( ! format()->sheet()->isShowPageBorders() ) + return; + + SheetPrint* print = format()->sheet()->print(); + + Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); + + Doc* doc = sheet()->doc(); + int zcellRect_left = doc->zoomItX (cellRect.left()); + int zcellRect_right = doc->zoomItX (cellRect.right()); + int zcellRect_top = doc->zoomItY (cellRect.top()); + int zcellRect_bottom = doc->zoomItY (cellRect.bottom()); + + // Draw page borders + + if ( cellRef.x() >= print->printRange().left() + && cellRef.x() <= print->printRange().right() + 1 + && cellRef.y() >= print->printRange().top() + && cellRef.y() <= print->printRange().bottom() + 1 ) + { + if ( print->isOnNewPageX( cellRef.x() ) + && cellRef.y() <= print->printRange().bottom() ) + { + painter.setPen( sheet()->doc()->pageBorderColor() ); + + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_right, zcellRect_top, + zcellRect_right, zcellRect_bottom ); + else + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_left, zcellRect_bottom ); + } + + if ( print->isOnNewPageY( cellRef.y() ) && + ( cellRef.x() <= print->printRange().right() ) ) + { + painter.setPen( sheet()->doc()->pageBorderColor() ); + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_right, zcellRect_top ); + } + + if ( paintBorderRight ) { + if ( print->isOnNewPageX( cellRef.x() + 1 ) + && cellRef.y() <= print->printRange().bottom() ) { + painter.setPen( sheet()->doc()->pageBorderColor() ); + + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_left, zcellRect_bottom ); + else + painter.drawLine( zcellRect_right, zcellRect_top, + zcellRect_right, zcellRect_bottom ); + } + } + + if ( paintBorderBottom ) { + if ( print->isOnNewPageY( cellRef.y() + 1 ) + && cellRef.x() <= print->printRange().right() ) { + painter.setPen( sheet()->doc()->pageBorderColor() ); + painter.drawLine( zcellRect_left, zcellRect_bottom, + zcellRect_right, zcellRect_bottom ); + } + } + } +} + + +// Paint the cell borders. +// +void Cell::paintCellBorders( TQPainter& painter, const KoRect& rect, + const KoRect &cellRect, + const TQPoint &cellRef, + bool paintRight, bool paintBottom, + bool paintLeft, bool paintTop, + TQPen & _rightPen, TQPen & _bottomPen, + TQPen & _leftPen, TQPen & _topPen ) +{ + + //Sanity check: If we are not painting any of the borders then the function + //really shouldn't be called at all. + if ( (!paintLeft) && (!paintRight) && (!paintTop) && (!paintBottom) ) + return; + + Doc * doc = sheet()->doc(); + + Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection(); + + // compute zoomed rectangles + // I don't use KoRect, because that ends up producing lots of warnings + // about double->int conversions in calls to painter.drawLine + int zrect_left (doc->zoomItX (rect.left())); + int zrect_right (doc->zoomItX (rect.right())); + int zrect_top (doc->zoomItY (rect.top())); + int zrect_bottom (doc->zoomItY (rect.bottom())); + int zcellRect_left (doc->zoomItX (cellRect.left())); + int zcellRect_right (doc->zoomItX (cellRect.right())); + int zcellRect_top (doc->zoomItY (cellRect.top())); + int zcellRect_bottom (doc->zoomItY (cellRect.bottom())); + + /* we might not paint some borders if this cell is merged with another in + that direction + bool paintLeft = paintBorderLeft; + bool paintRight = paintBorderRight; + bool paintTop = paintBorderTop; + bool paintBottom = paintBorderBottom; + */ + + // paintRight = paintRight && ( extraXCells() == 0 ); + // paintBottom = paintBottom && ( d->extra()->extraYCells() == 0 ); + + if (d->hasExtra()) { + TQValueList::const_iterator it = d->extra()->obscuringCells.begin(); + TQValueList::const_iterator end = d->extra()->obscuringCells.end(); + for ( ; it != end; ++it ) { + Cell* cell = *it; + + int xDiff = cellRef.x() - cell->column(); + int yDiff = cellRef.y() - cell->row(); + paintLeft = paintLeft && xDiff == 0; + paintTop = paintTop && yDiff == 0; + + // Paint the border(s) if either this one should or if we have a + // merged cell with this cell as its border. + paintRight = paintRight && cell->mergedXCells() == xDiff; + paintBottom = paintBottom && cell->mergedYCells() == yDiff; + } + } + + // Must create copies of these since otherwise the zoomIt() + // operation will be performed on them repeatedly. + TQPen leftPen( _leftPen ); + TQPen rightPen( _rightPen ); + TQPen topPen( _topPen ); + TQPen bottomPen( _bottomPen ); + + // Determine the pens that should be used for drawing + // the borders. + // + int left_penWidth = TQMAX( 1, doc->zoomItX( leftPen.width() ) ); + int right_penWidth = TQMAX( 1, doc->zoomItX( rightPen.width() ) ); + int top_penWidth = TQMAX( 1, doc->zoomItY( topPen.width() ) ); + int bottom_penWidth = TQMAX( 1, doc->zoomItY( bottomPen.width() ) ); + + leftPen.setWidth( left_penWidth ); + rightPen.setWidth( right_penWidth ); + topPen.setWidth( top_penWidth ); + bottomPen.setWidth( bottom_penWidth ); + + if ( paintLeft && leftPen.style() != TQt::NoPen ) { + int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 + + ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 ); + int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1; + + painter.setPen( leftPen ); + + //kdDebug(36001) << " painting left border of cell " << name() << endl; + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + // FIXME: There is probably Cut&Paste bugs here as well as below. + // The TQMIN/TQMAX and left/right pairs don't really make sense. + // + // UPDATE: In fact, most of these TQMIN/TQMAX combinations + // are TOTALLY BOGUS. For one thing, the idea + // that we always have full cells on paper is wrong + // since we can have embedded sheets in e.g. kword, + // and those can be arbitrarily clipped. WE HAVE TO + // REVISE THIS WHOLE BORDER PAINTING SECTION! + // + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMIN( zrect_right, zcellRect_right ), + TQMAX( zrect_top, zcellRect_top - top ), + TQMIN( zrect_right, zcellRect_right ), + TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); + else + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_top - top ), + TQMAX( zrect_left, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_right, + zcellRect_top - top, + zcellRect_right, + zcellRect_bottom + bottom ); + else + painter.drawLine( zcellRect_left, + zcellRect_top - top, + zcellRect_left, + zcellRect_bottom + bottom ); + } + } + + if ( paintRight && rightPen.style() != TQt::NoPen ) { + int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 + + ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 ); + int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1; + + painter.setPen( rightPen ); + + //kdDebug(36001) << " painting right border of cell " << name() << endl; + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_top - top ), + TQMAX( zrect_left, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); + else { + // FIXME: This is the way all these things should look. + // Make it so. + // + // Only print the right border if it is visible. + if ( zcellRect_right <= zrect_right + right_penWidth / 2) + painter.drawLine( zcellRect_right, + TQMAX( zrect_top, zcellRect_top - top ), + zcellRect_right, + TQMIN( zrect_bottom, zcellRect_bottom + bottom ) ); + } + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_left, + zcellRect_top - top, + zcellRect_left, + zcellRect_bottom + bottom ); + else + painter.drawLine( zcellRect_right, + zcellRect_top - top, + zcellRect_right, + zcellRect_bottom + bottom ); + } + } + + if ( paintTop && topPen.style() != TQt::NoPen ) { + painter.setPen( topPen ); + + //kdDebug(36001) << " painting top border of cell " << name() + // << " [" << zcellRect_left << "," << zcellRect_right + // << ": " << zcellRect_right - zcellRect_left << "]" << endl; + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( zcellRect_top >= zrect_top + top_penWidth / 2) + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + zcellRect_top, + TQMIN( zrect_right, zcellRect_right ), + zcellRect_top ); + } + else { + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_right, zcellRect_top ); + } + } + + if ( paintBottom && bottomPen.style() != TQt::NoPen ) { + painter.setPen( bottomPen ); + + //kdDebug(36001) << " painting bottom border of cell " << name() + // << " [" << zcellRect_left << "," << zcellRect_right + // << ": " << zcellRect_right - zcellRect_left << "]" << endl; + + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( zcellRect_bottom <= zrect_bottom + bottom_penWidth / 2) + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + zcellRect_bottom, + TQMIN( zrect_right, zcellRect_right ), + zcellRect_bottom ); + } + else { + painter.drawLine( zcellRect_left, zcellRect_bottom, + zcellRect_right, zcellRect_bottom ); + } + } + + // FIXME: Look very closely at when the following code is really needed. + // I can't really see any case, but I might be wrong. + // Since the code below is buggy, and incredibly complex, + // I am currently disabling it. If somebody wants to enable + // it again, then please also solve bug 68977: "Embedded KSpread + // document printing problem" at the same time. + return; + +#if 0 + // Look at the cells on our corners. It may happen that we + // just erased parts of their borders corner, so we might need + // to repaint these corners. + // + TQPen vert_pen, horz_pen; + int vert_penWidth, horz_penWidth; + + // Some useful referenses. + Cell *cell_north = format()->sheet()->cellAt( cellRef.x(), + cellRef.y() - 1 ); + Cell *cell_northwest = format()->sheet()->cellAt( cellRef.x() - 1, + cellRef.y() - 1 ); + Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1, + cellRef.y() ); + Cell *cell_northeast = format()->sheet()->cellAt( cellRef.x() + 1, + cellRef.y() - 1 ); + Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1, + cellRef.y() ); + Cell *cell_south = format()->sheet()->cellAt( cellRef.x(), + cellRef.y() + 1 ); + Cell *cell_southwest = format()->sheet()->cellAt( cellRef.x() - 1, + cellRef.y() + 1 ); + Cell *cell_southeast = format()->sheet()->cellAt( cellRef.x() + 1, + cellRef.y() + 1 ); + + // Fix the borders which meet at the top left corner + if ( cell_north->effLeftBorderValue( cellRef.x(), cellRef.y() - 1 ) + >= cell_northwest->effRightBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) ) + vert_pen = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 ); + else + vert_pen = cell_northwest->effRightBorderPen( cellRef.x() - 1, + cellRef.y() - 1 ); + + vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) ); + vert_pen.setWidth( vert_penWidth ); + + if ( vert_pen.style() != TQt::NoPen ) { + if ( cell_west->effTopBorderValue( cellRef.x() - 1, cellRef.y() ) + >= cell_northwest->effBottomBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) ) + horz_pen = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() ); + else + horz_pen = cell_northwest->effBottomBorderPen( cellRef.x() - 1, + cellRef.y() - 1 ); + + horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) ); + int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1; + + painter.setPen( vert_pen ); + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMAX( zrect_left, zcellRect_right ), + TQMAX( zrect_top, zcellRect_top ), + TQMIN( zrect_right, zcellRect_right ), + TQMIN( zrect_bottom, zcellRect_top + bottom ) ); + else + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_top ), + TQMIN( zrect_right, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_top + bottom ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_right, zcellRect_top, + zcellRect_right, zcellRect_top + bottom ); + else + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_left, zcellRect_top + bottom ); + } + } + + // Fix the borders which meet at the top right corner + if ( cell_north->effRightBorderValue( cellRef.x(), cellRef.y() - 1 ) + >= cell_northeast->effLeftBorderValue( cellRef.x() + 1, + cellRef.y() - 1 ) ) + vert_pen = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); + else + vert_pen = cell_northeast->effLeftBorderPen( cellRef.x() + 1, + cellRef.y() - 1 ); + + // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() - 1 ); + vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) ); + vert_pen.setWidth( vert_penWidth ); + if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) { + if ( cell_east->effTopBorderValue( cellRef.x() + 1, cellRef.y() ) + >= cell_northeast->effBottomBorderValue( cellRef.x() + 1, + cellRef.y() - 1 ) ) + horz_pen = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() ); + else + horz_pen = cell_northeast->effBottomBorderPen( cellRef.x() + 1, + cellRef.y() - 1 ); + + // horz_pen = effTopBorderPen( cellRef.x() + 1, cellRef.y() ); + horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) ); + int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1; + + painter.setPen( vert_pen ); + //If we are on paper printout, we limit the length of the lines + //On paper, we always have full cells, on screen not + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_top ), + TQMIN( zrect_right, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_top + bottom ) ); + else + painter.drawLine( TQMAX( zrect_left, zcellRect_right ), + TQMAX( zrect_top, zcellRect_top ), + TQMIN( zrect_right, zcellRect_right ), + TQMIN( zrect_bottom, zcellRect_top + bottom ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_left, zcellRect_top, + zcellRect_left, zcellRect_top + bottom ); + else + painter.drawLine( zcellRect_right, zcellRect_top, + zcellRect_right, zcellRect_top + bottom ); + } + } + + // Bottom + if ( cellRef.y() < KS_rowMax ) { + // Fix the borders which meet at the bottom left corner + if ( cell_south->effLeftBorderValue( cellRef.x(), cellRef.y() + 1 ) + >= cell_southwest->effRightBorderValue( cellRef.x() - 1, + cellRef.y() + 1 ) ) + vert_pen = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); + else + vert_pen = cell_southwest->effRightBorderPen( cellRef.x() - 1, + cellRef.y() + 1 ); + + // vert_pen = effLeftBorderPen( cellRef.x(), cellRef.y() + 1 ); + vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) ); + vert_pen.setWidth( vert_penWidth ); + if ( vert_pen.style() != TQt::NoPen ) { + if ( cell_west->effBottomBorderValue( cellRef.x() - 1, cellRef.y() ) + >= cell_southwest->effTopBorderValue( cellRef.x() - 1, + cellRef.y() + 1 ) ) + horz_pen = cell_west->effBottomBorderPen( cellRef.x() - 1, + cellRef.y() ); + else + horz_pen = cell_southwest->effTopBorderPen( cellRef.x() - 1, + cellRef.y() + 1 ); + + // horz_pen = effBottomBorderPen( cellRef.x() - 1, cellRef.y() ); + horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) ); + int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2; + + painter.setPen( vert_pen ); + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMAX( zrect_left, zcellRect_right ), + TQMAX( zrect_top, zcellRect_bottom - bottom ), + TQMIN( zrect_right, zcellRect_right ), + TQMIN( zrect_bottom, zcellRect_bottom ) ); + else + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_bottom - bottom ), + TQMIN( zrect_right, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_bottom ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_right, zcellRect_bottom - bottom, + zcellRect_right, zcellRect_bottom ); + else + painter.drawLine( zcellRect_left, zcellRect_bottom - bottom, + zcellRect_left, zcellRect_bottom ); + } + } + + // Fix the borders which meet at the bottom right corner + if ( cell_south->effRightBorderValue( cellRef.x(), cellRef.y() + 1 ) + >= cell_southeast->effLeftBorderValue( cellRef.x() + 1, + cellRef.y() + 1 ) ) + vert_pen = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); + else + vert_pen = cell_southeast->effLeftBorderPen( cellRef.x() + 1, + cellRef.y() + 1 ); + + // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() + 1 ); + vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) ); + vert_pen.setWidth( vert_penWidth ); + if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) { + if ( cell_east ->effBottomBorderValue( cellRef.x() + 1, cellRef.y() ) + >= cell_southeast->effTopBorderValue( cellRef.x() + 1, + cellRef.y() + 1 ) ) + + horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() ) + ->effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); + else + horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() + 1 ) + ->effTopBorderPen( cellRef.x() + 1, cellRef.y() + 1 ); + + // horz_pen = effBottomBorderPen( cellRef.x() + 1, cellRef.y() ); + horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) ); + int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2; + + painter.setPen( vert_pen ); + // If we are on paper printout, we limit the length of the lines. + // On paper, we always have full cells, on screen not. + if ( painter.device()->isExtDev() ) { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( TQMAX( zrect_left, zcellRect_left ), + TQMAX( zrect_top, zcellRect_bottom - bottom ), + TQMIN( zrect_right, zcellRect_left ), + TQMIN( zrect_bottom, zcellRect_bottom ) ); + else + painter.drawLine( TQMAX( zrect_left, zcellRect_right ), + TQMAX( zrect_top, zcellRect_bottom - bottom ), + TQMIN( zrect_right, zcellRect_right ), + TQMIN( zrect_bottom, zcellRect_bottom ) ); + } + else { + if ( sheetDir == Sheet::RightToLeft ) + painter.drawLine( zcellRect_left, zcellRect_bottom - bottom, + zcellRect_left, zcellRect_bottom ); + else + painter.drawLine( zcellRect_right, zcellRect_bottom - bottom, + zcellRect_right, zcellRect_bottom ); + } + } + } + #endif +} + + +// Paint diagonal lines through the cell. +// +void Cell::paintCellDiagonalLines( TQPainter& painter, + const KoRect &cellRect, + const TQPoint &cellRef ) +{ + if ( isPartOfMerged() ) + return; + + Doc* doc = sheet()->doc(); + + if ( effFallDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) { + painter.setPen( effFallDiagonalPen( cellRef.x(), cellRef.y() ) ); + painter.drawLine( doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.y() ), + doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.bottom() ) ); + } + + if ( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) { + painter.setPen( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ) ); + painter.drawLine( doc->zoomItX( cellRect.x() ), + doc->zoomItY( cellRect.bottom() ), + doc->zoomItX( cellRect.right() ), + doc->zoomItY( cellRect.y() ) ); + } +} + + +// End of Painting +// ================================================================ + + +int Cell::defineAlignX() +{ + int a = format()->align( column(), row() ); + if ( a == Format::Undefined ) + { + //numbers should be right-aligned by default, as well as BiDi text + if ((formatType() == Text_format) || value().isString()) + a = (d->strOutText.isRightToLeft()) ? + Format::Right : Format::Left; + else { + Value val = value(); + while (val.isArray()) val = val.element (0, 0); + if (val.isBoolean() || val.isNumber()) + a = Format::Right; + else + a = Format::Left; + } + } + return a; +} + +int Cell::effAlignX() +{ + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SAlignX, true ) ) + return d->extra()->conditions->matchedStyle()->alignX(); + + return defineAlignX(); +} + +// Cut strOutText, so that it only holds the part that can be displayed. +// +// Used in paintText(). +// + +TQString Cell::textDisplaying( TQPainter &_painter ) +{ + TQFontMetrics fm = _painter.fontMetrics(); + int a = format()->align( column(), row() ); + + bool isNumeric = value().isNumber(); + + if ( !format()->verticalText( column(),row() ) ) { + // Non-vertical text: the ordinary case. + + // Not enough space but align to left + double len = 0.0; + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + + for ( int i = column(); i <= column() + extraXCells; i++ ) { + ColumnFormat *cl2 = format()->sheet()->columnFormat( i ); + len += cl2->dblWidth() - 1.0; //-1.0 because the pixel in between 2 cells is shared between both cells + } + + TQString tmp; + double tmpIndent = 0.0; + if ( !isEmpty() ) + tmpIndent = format()->getIndent( column(), row() ); + + // Start out with the whole text, cut one character at a time, and + // when the text finally fits, return it. + for ( int i = d->strOutText.length(); i != 0; i-- ) + { + //Note that numbers are always treated as left-aligned since if we have to cut digits off, they should + //always be the least significant ones at the end of the string + if ( a == Format::Left || a == Format::Undefined || isNumeric) + tmp = d->strOutText.left(i); + else if ( a == Format::Right) + tmp = d->strOutText.right(i); + else + tmp = d->strOutText.mid( ( d->strOutText.length() - i ) / 2, i); + + if (isNumeric) + { + //For numeric values, we can cut off digits after the decimal point to make it fit, + //but not the integer part of the number. + //If this number still contains a fraction part then we don't need to do anything, if we have run + //out of space to fit even the integer part of the number then display ######### + //TODO Perhaps try to display integer part in standard form if there is not enough room for it? + + if (!tmp.contains('.')) + d->strOutText=TQString().fill('#',20); + } + + // 4 equal length of red triangle +1 point. + if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) + tmpIndent + < len - 4.0 - 1.0 ) + { + if ( format()->getAngle( column(), row() ) != 0 ) + { + TQString tmp2; + RowFormat *rl = format()->sheet()->rowFormat( row() ); + if ( d->textHeight > rl->dblHeight() ) + { + for ( int j = d->strOutText.length(); j != 0; j-- ) + { + tmp2 = d->strOutText.left( j ); + if ( format()->sheet()->doc()->unzoomItY( fm.width( tmp2 ) ) < rl->dblHeight() - 1.0 ) + { + return d->strOutText.left( TQMIN( tmp.length(), tmp2.length() ) ); + } + } + } + else + return tmp; + + } + else + return tmp; + } + } + return TQString( "" ); + } + else if ( format()->verticalText( column(), row() ) ) { + // Vertical text. + + RowFormat *rl = format()->sheet()->rowFormat( row() ); + double tmpIndent = 0.0; + + // Not enough space but align to left. + double len = 0.0; + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + + for ( int i = column(); i <= column() + extraXCells; i++ ) { + ColumnFormat *cl2 = format()->sheet()->columnFormat( i ); + + // -1.0 because the pixel in between 2 cells is shared between both cells + len += cl2->dblWidth() - 1.0; + } + + if ( !isEmpty() ) + tmpIndent = format()->getIndent( column(), row() ); + + if ( ( d->textWidth + tmpIndent > len ) || d->textWidth == 0.0 ) + return TQString( "" ); + + for ( int i = d->strOutText.length(); i != 0; i-- ) { + if ( format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent() ) * i + < rl->dblHeight() - 1.0 ) + return d->strOutText.left( i ); + } + + return TQString( "" ); + } + + ColumnFormat *cl = format()->sheet()->columnFormat( column() ); + double w = cl->dblWidth(); + + if ( d->hasExtra() && (d->extra()->extraWidth != 0.0) ) + w = d->extra()->extraWidth; + + TQString tmp; + for ( int i = d->strOutText.length(); i != 0; i-- ) { + tmp = d->strOutText.left( i ); + + // 4 equals length of red triangle +1 pixel + if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) < w - 4.0 - 1.0 ) + return tmp; + } + + return TQString(); +} + + +double Cell::dblWidth( int _col, const Canvas *_canvas ) const +{ + if ( _col < 0 ) + _col = d->column; + + if ( _canvas ) + { + if ( testFlag(Flag_Merged) ) + return d->extra()->extraWidth; + + const ColumnFormat *cl = format()->sheet()->columnFormat( _col ); + return cl->dblWidth( _canvas ); + } + + if ( testFlag(Flag_Merged) ) + return d->extra()->extraWidth; + + const ColumnFormat *cl = format()->sheet()->columnFormat( _col ); + return cl->dblWidth(); +} + +int Cell::width( int _col, const Canvas *_canvas ) const +{ + return int( dblWidth( _col, _canvas ) ); +} + +double Cell::dblHeight( int _row, const Canvas *_canvas ) const +{ + if ( _row < 0 ) + _row = d->row; + + if ( _canvas ) + { + if ( testFlag(Flag_Merged) ) + return d->extra()->extraHeight; + + const RowFormat *rl = format()->sheet()->rowFormat( _row ); + return rl->dblHeight( _canvas ); + } + + if ( testFlag(Flag_Merged) ) + return d->extra()->extraHeight; + + const RowFormat *rl = format()->sheet()->rowFormat( _row ); + return rl->dblHeight(); +} + +int Cell::height( int _row, const Canvas *_canvas ) const +{ + return int( dblHeight( _row, _canvas ) ); +} + +/////////////////////////////////////////// +// +// Misc Properties. +// Reimplementation of Format methods. +// +/////////////////////////////////////////// + +const TQBrush& Cell::backGroundBrush( int _col, int _row ) const +{ + if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) ) + { + const Cell* cell = d->extra()->obscuringCells.first(); + return cell->backGroundBrush( cell->column(), cell->row() ); + } + + return format()->backGroundBrush( _col, _row ); +} + +const TQColor& Cell::bgColor( int _col, int _row ) const +{ + if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) ) + { + const Cell* cell = d->extra()->obscuringCells.first(); + return cell->bgColor( cell->column(), cell->row() ); + } + + return format()->bgColor( _col, _row ); +} + +/////////////////////////////////////////// +// +// Borders. +// Reimplementation of Format methods. +// +/////////////////////////////////////////// + +void Cell::setLeftBorderPen( const TQPen& p ) +{ + if ( column() == 1 ) + { + Cell* cell = format()->sheet()->cellAt( column() - 1, row() ); + if ( cell && cell->format()->hasProperty( Format::PRightBorder ) + && format()->sheet()->cellAt( column(), row() ) == this ) + cell->format()->clearProperty( Format::PRightBorder ); + } + + format()->setLeftBorderPen( p ); +} + +void Cell::setTopBorderPen( const TQPen& p ) +{ + if ( row() == 1 ) + { + Cell* cell = format()->sheet()->cellAt( column(), row() - 1 ); + if ( cell && cell->format()->hasProperty( Format::PBottomBorder ) + && format()->sheet()->cellAt( column(), row() ) == this ) + cell->format()->clearProperty( Format::PBottomBorder ); + } + format()->setTopBorderPen( p ); +} + +void Cell::setRightBorderPen( const TQPen& p ) +{ + Cell* cell = 0L; + if ( column() < KS_colMax ) + cell = format()->sheet()->cellAt( column() + 1, row() ); + + if ( cell && cell->format()->hasProperty( Format::PLeftBorder ) + && format()->sheet()->cellAt( column(), row() ) == this ) + cell->format()->clearProperty( Format::PLeftBorder ); + + format()->setRightBorderPen( p ); +} + +void Cell::setBottomBorderPen( const TQPen& p ) +{ + Cell* cell = 0L; + if ( row() < KS_rowMax ) + cell = format()->sheet()->cellAt( column(), row() + 1 ); + + if ( cell && cell->format()->hasProperty( Format::PTopBorder ) + && format()->sheet()->cellAt( column(), row() ) == this ) + cell->format()->clearProperty( Format::PTopBorder ); + + format()->setBottomBorderPen( p ); +} + +const TQPen& Cell::rightBorderPen( int _col, int _row ) const +{ + if ( !format()->hasProperty( Format::PRightBorder ) && ( _col < KS_colMax ) ) + { + Cell * cell = format()->sheet()->cellAt( _col + 1, _row ); + if ( cell && cell->format()->hasProperty( Format::PLeftBorder ) ) + return cell->leftBorderPen( _col + 1, _row ); + } + + return format()->rightBorderPen( _col, _row ); +} + +const TQPen& Cell::leftBorderPen( int _col, int _row ) const +{ + if ( !format()->hasProperty( Format::PLeftBorder ) ) + { + const Cell * cell = format()->sheet()->cellAt( _col - 1, _row ); + if ( cell && cell->format()->hasProperty( Format::PRightBorder ) ) + return cell->rightBorderPen( _col - 1, _row ); + } + + return format()->leftBorderPen( _col, _row ); +} + +const TQPen& Cell::bottomBorderPen( int _col, int _row ) const +{ + if ( !format()->hasProperty( Format::PBottomBorder ) && ( _row < KS_rowMax ) ) + { + const Cell * cell = format()->sheet()->cellAt( _col, _row + 1 ); + if ( cell && cell->format()->hasProperty( Format::PTopBorder ) ) + return cell->topBorderPen( _col, _row + 1 ); + } + + return format()->bottomBorderPen( _col, _row ); +} + +const TQPen& Cell::topBorderPen( int _col, int _row ) const +{ + if ( !format()->hasProperty( Format::PTopBorder ) ) + { + const Cell * cell = format()->sheet()->cellAt( _col, _row - 1 ); + if ( cell->format()->hasProperty( Format::PBottomBorder ) ) + return cell->bottomBorderPen( _col, _row - 1 ); + } + + return format()->topBorderPen( _col, _row ); +} + +const TQColor & Cell::effTextColor( int col, int row ) const +{ + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::STextPen, true ) ) + return d->extra()->conditions->matchedStyle()->pen().color(); + + return format()->textColor( col, row ); +} + +const TQPen& Cell::effLeftBorderPen( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effLeftBorderPen( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SLeftBorder, true ) ) + return d->extra()->conditions->matchedStyle()->leftBorderPen(); + + return leftBorderPen( col, row ); +} + +const TQPen& Cell::effTopBorderPen( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effTopBorderPen( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::STopBorder, true ) ) + return d->extra()->conditions->matchedStyle()->topBorderPen(); + + return topBorderPen( col, row ); +} + +const TQPen& Cell::effRightBorderPen( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effRightBorderPen( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SRightBorder, true ) ) + return d->extra()->conditions->matchedStyle()->rightBorderPen(); + + return rightBorderPen( col, row ); +} + +const TQPen& Cell::effBottomBorderPen( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effBottomBorderPen( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBottomBorder, true ) ) + return d->extra()->conditions->matchedStyle()->bottomBorderPen(); + + return bottomBorderPen( col, row ); +} + +const TQPen & Cell::effGoUpDiagonalPen( int col, int row ) const +{ + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SGoUpDiagonal, true ) ) + return d->extra()->conditions->matchedStyle()->goUpDiagonalPen(); + + return format()->goUpDiagonalPen( col, row ); +} + +const TQPen & Cell::effFallDiagonalPen( int col, int row ) const +{ + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() + && d->extra()->conditions->matchedStyle()->hasFeature( Style::SFallDiagonal, true ) ) + return d->extra()->conditions->matchedStyle()->fallDiagonalPen(); + + return format()->fallDiagonalPen( col, row ); +} + +uint Cell::effBottomBorderValue( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effBottomBorderValue( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + return d->extra()->conditions->matchedStyle()->bottomPenValue(); + + return format()->bottomBorderValue( col, row ); +} + +uint Cell::effRightBorderValue( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effRightBorderValue( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + return d->extra()->conditions->matchedStyle()->rightPenValue(); + + return format()->rightBorderValue( col, row ); +} + +uint Cell::effLeftBorderValue( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effLeftBorderValue( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + return d->extra()->conditions->matchedStyle()->leftPenValue(); + + return format()->leftBorderValue( col, row ); +} + +uint Cell::effTopBorderValue( int col, int row ) const +{ + if ( isPartOfMerged() ) + { + Cell * cell = d->extra()->obscuringCells.first(); + return cell->effTopBorderValue( cell->column(), cell->row() ); + } + + if ( d->hasExtra() && d->extra()->conditions + && d->extra()->conditions->matchedStyle() ) + return d->extra()->conditions->matchedStyle()->topPenValue(); + + return format()->topBorderValue( col, row ); +} + +/////////////////////////////////////////// +// +// Precision +// +/////////////////////////////////////////// + +void Cell::incPrecision() +{ + //TODO: This is ugly. Why not simply regenerate the text to display? Tomas + + if ( !value().isNumber() ) + return; + int tmpPreci = format()->precision( column(), row() ); + + if ( tmpPreci == -1 ) + { + int pos = d->strOutText.find(decimal_point); + if ( pos == -1 ) + pos = d->strOutText.find('.'); + if ( pos == -1 ) + format()->setPrecision(1); + else + { + int start = 0; + if ( d->strOutText.find('%') != -1 ) + start = 2; + else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) ) + start = locale()->currencySymbol().length() + 1; + else if ( (start=d->strOutText.find('E')) != -1 ) + start = d->strOutText.length() - start; + + //kdDebug(36001) << "start=" << start << " pos=" << pos << " length=" << d->strOutText.length() << endl; + format()->setPrecision( TQMAX( 0, (int)d->strOutText.length() - start - pos ) ); + } + } + else if ( tmpPreci < 10 ) + { + format()->setPrecision( ++tmpPreci ); + } + setFlag(Flag_LayoutDirty); +} + +void Cell::decPrecision() +{ + //TODO: This is ugly. Why not simply regenerate the text to display? Tomas + + if ( !value().isNumber() ) + return; + int preciTmp = format()->precision( column(), row() ); +// kdDebug(36001) << "decPrecision: tmpPreci = " << tmpPreci << endl; + if ( format()->precision(column(),row()) == -1 ) + { + int pos = d->strOutText.find( decimal_point ); + int start = 0; + if ( d->strOutText.find('%') != -1 ) + start = 2; + else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) ) + start = locale()->currencySymbol().length() + 1; + else if ( (start = d->strOutText.find('E')) != -1 ) + start = d->strOutText.length() - start; + else + start = 0; + + if ( pos == -1 ) + return; + + format()->setPrecision(d->strOutText.length() - pos - 2 - start); + // if ( preciTmp < 0 ) + // format()->setPrecision( preciTmp ); + } + else if ( preciTmp > 0 ) + { + format()->setPrecision( --preciTmp ); + } + setFlag( Flag_LayoutDirty ); +} + +//set numerical value +//used in Sheet::setSeries (nowhere else yet) +void Cell::setNumber( double number ) +{ + setValue( Value( number ) ); + + d->strText.setNum( number ); + setDisplayText(d->strText); + checkNumberFormat(); +} + +void Cell::setCellText( const TQString& _text, bool asText ) +{ + // TQString ctext = _text; + +// (Tomas) is this trim necessary for anything ? +// if( ctext.length() > 5000 ) +// ctext = ctext.left( 5000 ); + + // empty string ? + if (_text.length() == 0) { + d->strOutText = d->strText = ""; + setValue (Value::empty()); + return; + } + + // as text ? + if (asText) { + d->strOutText = _text; + d->strText = _text; + setValue (Value (_text)); + + return; + } + + TQString oldText = d->strText; + setDisplayText( _text ); + if(!format()->sheet()->isLoading() && !testValidity() ) + { + //reapply old value if action == stop + setDisplayText( oldText ); + } +} + +void Cell::setDisplayText( const TQString& _text ) +{ + bool isLoading = format()->sheet()->isLoading(); + + if (!isLoading) + format()->sheet()->doc()->emitBeginOperation( false ); + + d->strText = _text; + + /** + * A real formula "=A1+A2*3" was entered. + */ + if ( !d->strText.isEmpty() && d->strText[0] == '=' ) + { + setFlag(Flag_LayoutDirty); + setFlag(Flag_TextFormatDirty); + + if ( !makeFormula() ) + kdError(36001) << "ERROR: Syntax ERROR" << endl; + setCalcDirtyFlag (); + } + + /** + * Some numeric value or a string. + */ + else + { + // Find out what data type it is + checkTextInput(); + + setFlag(Flag_LayoutDirty); + setFlag(Flag_TextFormatDirty); + } + + if ( !isLoading ) + format()->sheet()->doc()->emitEndOperation( TQRect( d->column, d->row, 1, 1 ) ); +} + +void Cell::setLink( const TQString& link ) +{ + d->extra()->link = link; + + if( !link.isEmpty() && d->strText.isEmpty() ) + setCellText( link ); +} + +TQString Cell::link() const +{ + return d->hasExtra() ? d->extra()->link : TQString(); +} + +void Cell::update() +{ + /* those obscuring us need to redo their layout cause they can't obscure us + now that we've got text. + This includes cells obscuring cells that we are obscuring + */ + for (int x = d->column; x <= d->column + extraXCells(); x++) + { + for (int y = d->row; y <= d->row + extraYCells(); y++) + { + Cell* cell = format()->sheet()->cellAt(x,y); + cell->setLayoutDirtyFlag(); + } + } + + setCalcDirtyFlag(); + + /* TODO - is this a good place for this? */ + updateChart(true); +} + +bool Cell::testValidity() const +{ + bool valid = false; + if( d->hasExtra() && d->extra()->validity && d->extra()->validity->m_restriction != Restriction::None ) + { + //fixme + if ( d->extra()->validity->allowEmptyCell && d->strText.isEmpty() ) + return true; + + if( value().isNumber() && + (d->extra()->validity->m_restriction == Restriction::Number || + (d->extra()->validity->m_restriction == Restriction::Integer && + value().asFloat() == ceil(value().asFloat())))) + { + switch( d->extra()->validity->m_cond) + { + case Conditional::Equal: + valid = ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON + && value().asFloat() - d->extra()->validity->valMin > + (0.0 - DBL_EPSILON)); + break; + case Conditional::DifferentTo: + valid = !( ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON + && value().asFloat() - d->extra()->validity->valMin > + (0.0 - DBL_EPSILON)) ); + break; + case Conditional::Superior: + valid = ( value().asFloat() > d->extra()->validity->valMin); + break; + case Conditional::Inferior: + valid = ( value().asFloat() extra()->validity->valMin); + break; + case Conditional::SuperiorEqual: + valid = ( value().asFloat() >= d->extra()->validity->valMin); + break; + case Conditional::InferiorEqual: + valid = (value().asFloat() <= d->extra()->validity->valMin); + break; + case Conditional::Between: + valid = ( value().asFloat() >= d->extra()->validity->valMin && + value().asFloat() <= d->extra()->validity->valMax); + break; + case Conditional::Different: + valid = (value().asFloat() < d->extra()->validity->valMin || + value().asFloat() > d->extra()->validity->valMax); + break; + default : + break; + } + } + else if(d->extra()->validity->m_restriction==Restriction::Text) + { + valid = value().isString(); + } + else if ( d->extra()->validity->m_restriction == Restriction::List ) + { + //test int value + if ( value().isString() && d->extra()->validity->listValidity.contains( value().asString() ) ) + valid = true; + } + else if(d->extra()->validity->m_restriction==Restriction::TextLength) + { + if( value().isString() ) + { + int len = d->strOutText.length(); + switch( d->extra()->validity->m_cond) + { + case Conditional::Equal: + if (len == d->extra()->validity->valMin) + valid = true; + break; + case Conditional::DifferentTo: + if (len != d->extra()->validity->valMin) + valid = true; + break; + case Conditional::Superior: + if(len > d->extra()->validity->valMin) + valid = true; + break; + case Conditional::Inferior: + if(len < d->extra()->validity->valMin) + valid = true; + break; + case Conditional::SuperiorEqual: + if(len >= d->extra()->validity->valMin) + valid = true; + break; + case Conditional::InferiorEqual: + if(len <= d->extra()->validity->valMin) + valid = true; + break; + case Conditional::Between: + if(len >= d->extra()->validity->valMin && len <= d->extra()->validity->valMax) + valid = true; + break; + case Conditional::Different: + if(len extra()->validity->valMin || len >d->extra()->validity->valMax) + valid = true; + break; + default : + break; + } + } + } + else if(d->extra()->validity->m_restriction == Restriction::Time && isTime()) + { + switch( d->extra()->validity->m_cond) + { + case Conditional::Equal: + valid = (value().asTime() == d->extra()->validity->timeMin); + break; + case Conditional::DifferentTo: + valid = (value().asTime() != d->extra()->validity->timeMin); + break; + case Conditional::Superior: + valid = (value().asTime() > d->extra()->validity->timeMin); + break; + case Conditional::Inferior: + valid = (value().asTime() < d->extra()->validity->timeMin); + break; + case Conditional::SuperiorEqual: + valid = (value().asTime() >= d->extra()->validity->timeMin); + break; + case Conditional::InferiorEqual: + valid = (value().asTime() <= d->extra()->validity->timeMin); + break; + case Conditional::Between: + valid = (value().asTime() >= d->extra()->validity->timeMin && + value().asTime() <= d->extra()->validity->timeMax); + break; + case Conditional::Different: + valid = (value().asTime() < d->extra()->validity->timeMin || + value().asTime() > d->extra()->validity->timeMax); + break; + default : + break; + + } + } + else if(d->extra()->validity->m_restriction == Restriction::Date && isDate()) + { + switch( d->extra()->validity->m_cond) + { + case Conditional::Equal: + valid = (value().asDate() == d->extra()->validity->dateMin); + break; + case Conditional::DifferentTo: + valid = (value().asDate() != d->extra()->validity->dateMin); + break; + case Conditional::Superior: + valid = (value().asDate() > d->extra()->validity->dateMin); + break; + case Conditional::Inferior: + valid = (value().asDate() < d->extra()->validity->dateMin); + break; + case Conditional::SuperiorEqual: + valid = (value().asDate() >= d->extra()->validity->dateMin); + break; + case Conditional::InferiorEqual: + valid = (value().asDate() <= d->extra()->validity->dateMin); + break; + case Conditional::Between: + valid = (value().asDate() >= d->extra()->validity->dateMin && + value().asDate() <= d->extra()->validity->dateMax); + break; + case Conditional::Different: + valid = (value().asDate() < d->extra()->validity->dateMin || + value().asDate() > d->extra()->validity->dateMax); + break; + default : + break; + + } + } + } + else + { + valid= true; + } + + if(!valid &&d->extra()->validity != NULL && d->extra()->validity->displayMessage) + { + switch (d->extra()->validity->m_action ) + { + case Action::Stop: + KMessageBox::error((TQWidget*)0L, d->extra()->validity->message, + d->extra()->validity->title); + break; + case Action::Warning: + KMessageBox::warningYesNo((TQWidget*)0L, d->extra()->validity->message, + d->extra()->validity->title); + break; + case Action::Information: + KMessageBox::information((TQWidget*)0L, d->extra()->validity->message, + d->extra()->validity->title); + break; + } + } + if (!d->hasExtra()) + return true; //okay if there's no validity + return (valid || d->extra()->validity == NULL || d->extra()->validity->m_action != Action::Stop); +} + +FormatType Cell::formatType() const +{ + return format()->getFormatType( d->column, d->row ); +} + +double Cell::textWidth() const +{ + return d->textWidth; +} + +double Cell::textHeight() const +{ + return d->textHeight; +} + +int Cell::mergedXCells() const +{ + return d->hasExtra() ? d->extra()->mergedXCells : 0; +} + +int Cell::mergedYCells() const +{ + return d->hasExtra() ? d->extra()->mergedYCells : 0; +} + +int Cell::extraXCells() const +{ + return d->hasExtra() ? d->extra()->extraXCells : 0; +} + +int Cell::extraYCells() const +{ + return d->hasExtra() ? d->extra()->extraYCells : 0; +} + +double Cell::extraWidth() const +{ + return d->hasExtra() ? d->extra()->extraWidth : 0; +} + +double Cell::extraHeight() const +{ + return d->hasExtra() ? d->extra()->extraHeight : 0; +} + + +bool Cell::isDate() const +{ + FormatType ft = formatType(); + + return (formatIsDate (ft) || ((ft == Generic_format) && + (value().format() == Value::fmt_Date))); +} + +bool Cell::isTime() const +{ + FormatType ft = formatType(); + + return (formatIsTime (ft) || ((ft == Generic_format) && + (value().format() == Value::fmt_Time))); +} + +void Cell::setCalcDirtyFlag() +{ + if ( !isFormula() ) + { + //don't set the flag if we don't hold a formula + clearFlag(Flag_CalcDirty); + return; + } + setFlag(Flag_CalcDirty); + format()->sheet()->setRegionPaintDirty(cellRect()); +} + + +bool Cell::updateChart(bool refresh) +{ + // Update a chart for example if it depends on this cell. + if ( d->row != 0 && d->column != 0 ) + { + CellBinding *bind; + for ( bind = format()->sheet()->firstCellBinding(); bind != 0L; bind = format()->sheet()->nextCellBinding() ) + { + if ( bind->contains( d->column, d->row ) ) + { + if (!refresh) + return true; + + bind->cellChanged( this ); + } + } + return true; + } + return false; + +} + +double Cell::getDouble () +{ + if (isDefault()) + return 0.0; + //(Tomas) umm can't we simply call value().asFloat() ? + if (isDate()) + { + TQDate date = value().asDate(); + TQDate dummy (1900, 1, 1); + return (dummy.daysTo (date) + 1); + } + if (isTime()) + { + TQTime time = value().asTime(); + TQTime dummy; + return dummy.secsTo( time ); + } + if (value().isNumber()) + return value().asFloat(); + + return 0.0; +} + +void Cell::convertToDouble () +{ + if (isDefault()) + return; + + setValue (getDouble ()); +} + +void Cell::convertToPercent () +{ + if (isDefault()) + return; + + setValue (getDouble ()); + d->value.setFormat (Value::fmt_Percent); +} + +void Cell::convertToMoney () +{ + if (isDefault()) + return; + + setValue (getDouble ()); + d->value.setFormat (Value::fmt_Money); + format()->setPrecision (locale()->fracDigits()); +} + +void Cell::convertToTime () +{ + //(Tomas) This is weird. And I mean *REALLY* weird. First, we + //generate a time (TQTime), then we convert it to text, then + //we give the text to the cell and ask it to parse it. Weird... + + if (isDefault() || isEmpty()) + return; + + setValue (getDouble ()); + TQTime time = value().asDateTime().time(); + int msec = (int) ( (value().asFloat() - (int) value().asFloat()) * 1000 ); + time = time.addMSecs( msec ); + setCellText( time.toString() ); +} + +void Cell::convertToDate () +{ + //(Tomas) This is weird. And I mean *REALLY* weird. First, we + //generate a date (TQDate), then we convert it to text, then + //we give the text to the cell and ask it to parse it. Weird... + + if (isDefault() || isEmpty()) + return; + + setValue (getDouble ()); + + //TODO: why did we call setValue(), when we override it here? + TQDate date(1900, 1, 1); + date = date.addDays( (int) value().asFloat() - 1 ); + date = value().asDateTime().date(); + setCellText (locale()->formatDate (date, true)); +} + +void Cell::checkTextInput() +{ + // Goal of this method: determine the value of the cell + clearAllErrors(); + + d->value = Value::empty(); + + // Get the text from that cell + TQString str = d->strText; + + sheet()->doc()->parser()->parse (str, this); + + // Parsing as time acts like an autoformat: we even change d->strText + // [h]:mm:ss -> might get set by ValueParser + if (isTime() && (formatType() != Time_format7)) + d->strText = locale()->formatTime( value().asDateTime().time(), true); + + // convert first letter to uppercase ? + if (format()->sheet()->getFirstLetterUpper() && value().isString() && + (!d->strText.isEmpty())) + { + TQString str = value().asString(); + setValue( Value( str[0].upper() + str.right( str.length()-1 ) ) ); + } +} + +//used in calc, setNumber, ValueParser +void Cell::checkNumberFormat() +{ + if ( formatType() == Number_format && value().isNumber() ) + { + if ( value().asFloat() > 1e+10 ) + format()->setFormatType( Scientific_format ); + } +} + + +// ================================================================ +// Saving and loading + + +TQDomElement Cell::save( TQDomDocument& doc, + int _x_offset, int _y_offset, + bool force, bool copy, bool era ) +{ + // Save the position of this cell + TQDomElement cell = doc.createElement( "cell" ); + cell.setAttribute( "row", d->row - _y_offset ); + cell.setAttribute( "column", d->column - _x_offset ); + // + // Save the formatting information + // + TQDomElement formatElement = format()->save( doc, d->column, d->row, force, copy ); + if ( formatElement.hasChildNodes() || formatElement.attributes().length() ) // don't save empty tags + cell.appendChild( formatElement ); + + if ( doesMergeCells() ) + { + if ( extraXCells() ) + formatElement.setAttribute( "colspan", extraXCells() ); + if ( extraYCells() ) + formatElement.setAttribute( "rowspan", extraYCells() ); + } + + if ( d->hasExtra() && d->extra()->conditions ) + { + TQDomElement conditionElement = d->extra()->conditions->saveConditions( doc ); + + if ( !conditionElement.isNull() ) + cell.appendChild( conditionElement ); + } + + if ( d->hasExtra() && (d->extra()->validity != 0) ) + { + TQDomElement validity = doc.createElement("validity"); + + TQDomElement param=doc.createElement("param"); + param.setAttribute("cond",(int)d->extra()->validity->m_cond); + param.setAttribute("action",(int)d->extra()->validity->m_action); + param.setAttribute("allow",(int)d->extra()->validity->m_restriction); + param.setAttribute("valmin",d->extra()->validity->valMin); + param.setAttribute("valmax",d->extra()->validity->valMax); + param.setAttribute("displaymessage",d->extra()->validity->displayMessage); + param.setAttribute("displayvalidationinformation",d->extra()->validity->displayValidationInformation); + param.setAttribute("allowemptycell",d->extra()->validity->allowEmptyCell); + if ( !d->extra()->validity->listValidity.isEmpty() ) + param.setAttribute( "listvalidity", d->extra()->validity->listValidity.join( ";" ) ); + validity.appendChild(param); + TQDomElement title = doc.createElement( "title" ); + title.appendChild( doc.createTextNode( d->extra()->validity->title ) ); + validity.appendChild( title ); + TQDomElement message = doc.createElement( "message" ); + message.appendChild( doc.createCDATASection( d->extra()->validity->message ) ); + validity.appendChild( message ); + + TQDomElement inputTitle = doc.createElement( "inputtitle" ); + inputTitle.appendChild( doc.createTextNode( d->extra()->validity->titleInfo ) ); + validity.appendChild( inputTitle ); + + TQDomElement inputMessage = doc.createElement( "inputmessage" ); + inputMessage.appendChild( doc.createTextNode( d->extra()->validity->messageInfo ) ); + validity.appendChild( inputMessage ); + + + + TQString tmp; + if ( d->extra()->validity->timeMin.isValid() ) + { + TQDomElement timeMin = doc.createElement( "timemin" ); + tmp=d->extra()->validity->timeMin.toString(); + timeMin.appendChild( doc.createTextNode( tmp ) ); + validity.appendChild( timeMin ); + } + if ( d->extra()->validity->timeMax.isValid() ) + { + TQDomElement timeMax = doc.createElement( "timemax" ); + tmp=d->extra()->validity->timeMax.toString(); + timeMax.appendChild( doc.createTextNode( tmp ) ); + validity.appendChild( timeMax ); + } + + if ( d->extra()->validity->dateMin.isValid() ) + { + TQDomElement dateMin = doc.createElement( "datemin" ); + TQString tmp("%1/%2/%3"); + tmp = tmp.arg(d->extra()->validity->dateMin.year()).arg(d->extra()->validity->dateMin.month()).arg(d->extra()->validity->dateMin.day()); + dateMin.appendChild( doc.createTextNode( tmp ) ); + validity.appendChild( dateMin ); + } + if ( d->extra()->validity->dateMax.isValid() ) + { + TQDomElement dateMax = doc.createElement( "datemax" ); + TQString tmp("%1/%2/%3"); + tmp = tmp.arg(d->extra()->validity->dateMax.year()).arg(d->extra()->validity->dateMax.month()).arg(d->extra()->validity->dateMax.day()); + dateMax.appendChild( doc.createTextNode( tmp ) ); + validity.appendChild( dateMax ); + } + + cell.appendChild( validity ); + } + + if ( format()->comment() ) + { + TQDomElement comment = doc.createElement( "comment" ); + comment.appendChild( doc.createCDATASection( *format()->comment() ) ); + cell.appendChild( comment ); + } + + // + // Save the text + // + if ( !d->strText.isEmpty() ) + { + // Formulas need to be encoded to ensure that they + // are position independent. + if ( isFormula() ) + { + TQDomElement text = doc.createElement( "text" ); + // if we are cutting to the clipboard, relative references need to be encoded absolutely + text.appendChild( doc.createTextNode( encodeFormula( era ) ) ); + cell.appendChild( text ); + + /* we still want to save the results of the formula */ + TQDomElement formulaResult = doc.createElement( "result" ); + saveCellResult( doc, formulaResult, d->strOutText ); + cell.appendChild( formulaResult ); + + } + else if ( !link().isEmpty() ) + { + // KSpread pre 1.4 saves link as rich text, marked with first char ' + // Have to be saved in some CDATA section because of too many special charatcers. + TQDomElement text = doc.createElement( "text" ); + TQString qml = "!" + d->strText + ""; + text.appendChild( doc.createCDATASection( qml ) ); + cell.appendChild( text ); + } + else + { + // Save the cell contents (in a locale-independent way) + TQDomElement text = doc.createElement( "text" ); + saveCellResult( doc, text, d->strText ); + cell.appendChild( text ); + } + } + if ( cell.hasChildNodes() || cell.attributes().length() > 2 ) // don't save empty tags + // (the >2 is due to "row" and "column" attributes) + return cell; + else + return TQDomElement(); +} + +bool Cell::saveCellResult( TQDomDocument& doc, TQDomElement& result, + TQString str ) +{ + TQString dataType = "Other"; // fallback + + if ( value().isNumber() ) + { + if ( isDate() ) + { + // serial number of date + TQDate dd = value().asDateTime().date(); + dataType = "Date"; + str = "%1/%2/%3"; + str = str.arg(dd.year()).arg(dd.month()).arg(dd.day()); + } + else if( isTime() ) + { + // serial number of time + dataType = "Time"; + str = value().asDateTime().time().toString(); + } + else + { + // real number + dataType = "Num"; + if (value().isInteger()) + str = TQString::number(value().asInteger()); + else + str = TQString::number(value().asFloat(), 'g', DBL_DIG); + } + } + + if ( value().isBoolean() ) + { + dataType = "Bool"; + str = value().asBoolean() ? "true" : "false"; + } + + if ( value().isString() ) + { + dataType = "Str"; + str = value().asString(); + } + + result.setAttribute( "dataType", dataType ); + if ( !d->strOutText.isEmpty() ) + result.setAttribute( "outStr", d->strOutText ); + result.appendChild( doc.createTextNode( str ) ); + + return true; /* really isn't much of a way for this function to fail */ +} + +void Cell::saveOasisAnnotation( KoXmlWriter &xmlwriter ) +{ + if ( format()->comment() ) + { + // + xmlwriter.startElement( "office:annotation" ); + TQStringList text = TQStringList::split( "\n", *format()->comment() ); + for ( TQStringList::Iterator it = text.begin(); it != text.end(); ++it ) { + xmlwriter.startElement( "text:p" ); + xmlwriter.addTextNode( *it ); + xmlwriter.endElement(); + } + xmlwriter.endElement(); + } +} + + + +TQString Cell::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles ) +{ + if ( d->hasExtra() && d->extra()->conditions ) + { + // this has to be an automatic style + currentCellStyle = KoGenStyle( Doc::STYLE_CELL_AUTO, "table-cell" ); + d->extra()->conditions->saveOasisConditions( currentCellStyle ); + } + return format()->saveOasisCellStyle( currentCellStyle, mainStyles ); +} + + +bool Cell::saveOasis( KoXmlWriter& xmlwriter, KoGenStyles &mainStyles, + int row, int column, int &repeated, + GenValidationStyles &valStyle ) +{ + if ( !isPartOfMerged() ) + xmlwriter.startElement( "table:table-cell" ); + else + xmlwriter.startElement( "table:covered-table-cell" ); +#if 0 + //add font style + TQFont font; + Value const value( cell->value() ); + if ( !cell->isDefault() ) + { + font = cell->format()->textFont( i, row ); + m_styles.addFont( font ); + + if ( cell->format()->hasProperty( Format::PComment ) ) + hasComment = true; + } +#endif + // NOTE save the value before the style as long as the Formatter does not work correctly + if ( link().isEmpty() ) + saveOasisValue (xmlwriter); + + KoGenStyle currentCellStyle; // the type determined in saveOasisCellStyle + saveOasisCellStyle( currentCellStyle,mainStyles ); + // skip 'table:style-name' attribute for the default style + if ( !currentCellStyle.isDefaultStyle() ) + xmlwriter.addAttribute( "table:style-name", mainStyles.styles()[currentCellStyle] ); + + // group empty cells with the same style + if ( isEmpty() && !format()->hasProperty( Format::PComment ) && + !isPartOfMerged() && !doesMergeCells() ) + { + bool refCellIsDefault = isDefault(); + int j = column + 1; + Cell *nextCell = format()->sheet()->getNextCellRight( column, row ); + while ( nextCell ) + { + // if + // the next cell is not the adjacent one + // or + // the next cell is not empty + if ( nextCell->column() != j || !nextCell->isEmpty() ) + { + if ( refCellIsDefault ) + { + // if the origin cell was a default cell, + // we count the default cells + repeated = nextCell->column() - j + 1; + } + // otherwise we just stop here to process the adjacent + // cell in the next iteration of the outer loop + // (in Sheet::saveOasisCells) + break; + } + + KoGenStyle nextCellStyle; // the type is determined in saveOasisCellStyle + nextCell->saveOasisCellStyle( nextCellStyle,mainStyles ); + + if ( nextCell->isPartOfMerged() || nextCell->doesMergeCells() || + nextCell->format()->hasProperty( Format::PComment ) || + !(nextCellStyle == currentCellStyle) ) + { + break; + } + ++repeated; + // get the next cell and set the index to the adjacent cell + nextCell = format()->sheet()->getNextCellRight( j++, row ); + } + kdDebug() << "Cell::saveOasis: empty cell in column " << column << " " + << "repeated " << repeated << " time(s)" << endl; + + if ( repeated > 1 ) + xmlwriter.addAttribute( "table:number-columns-repeated", TQString::number( repeated ) ); + } + + + if (d->hasExtra() && d->extra()->validity) + { + GenValidationStyle styleVal(d->extra()->validity); + xmlwriter.addAttribute( "table:validation-name", valStyle.lookup( styleVal ) ); + } + if ( isFormula() ) + { + //kdDebug() << "Formula found" << endl; + TQString formula( convertFormulaToOasisFormat( text() ) ); + xmlwriter.addAttribute( "table:formula", formula ); + } + else if ( !link().isEmpty() ) + { + //kdDebug()<<"Link found \n"; + xmlwriter.startElement( "text:p" ); + xmlwriter.startElement( "text:a" ); + //Reference cell is started by "#" + if ( localReferenceAnchor( link() ) ) + xmlwriter.addAttribute( " xlink:href", ( "#"+link() ) ); + else + xmlwriter.addAttribute( " xlink:href", link() ); + xmlwriter.addTextNode( text() ); + xmlwriter.endElement(); + xmlwriter.endElement(); + } + + if ( doesMergeCells() ) + { + int colSpan = mergedXCells() + 1; + int rowSpan = mergedYCells() + 1; + + if ( colSpan > 1 ) + xmlwriter.addAttribute( "table:number-columns-spanned", TQString::number( colSpan ) ); + + if ( rowSpan > 1 ) + xmlwriter.addAttribute( "table:number-rows-spanned", TQString::number( rowSpan ) ); + } + + if ( !isEmpty() && link().isEmpty() ) + { + xmlwriter.startElement( "text:p" ); + xmlwriter.addTextNode( strOutText().utf8() ); + xmlwriter.endElement(); + } + + saveOasisAnnotation( xmlwriter ); + + xmlwriter.endElement(); + return true; +} + +void Cell::saveOasisValue (KoXmlWriter &xmlWriter) +{ + switch (value().format()) + { + case Value::fmt_None: break; //NOTHING HERE + case Value::fmt_Boolean: + { + xmlWriter.addAttribute( "office:value-type", "boolean" ); + xmlWriter.addAttribute( "office:boolean-value", ( value().asBoolean() ? + "true" : "false" ) ); + break; + } + case Value::fmt_Number: + { + xmlWriter.addAttribute( "office:value-type", "float" ); + if (value().isInteger()) + xmlWriter.addAttribute( "office:value", TQString::number( value().asInteger() ) ); + else + xmlWriter.addAttribute( "office:value", TQString::number( value().asFloat(), 'g', DBL_DIG ) ); + break; + } + case Value::fmt_Percent: + { + xmlWriter.addAttribute( "office:value-type", "percentage" ); + xmlWriter.addAttribute( "office:value", + TQString::number( value().asFloat() ) ); + break; + } + case Value::fmt_Money: + { + xmlWriter.addAttribute( "office:value-type", "currency" ); + Format::Currency currency; + if (format()->currencyInfo(currency)) + xmlWriter.addAttribute( "office:currency", Currency::getCurrencyCode(currency.type) ); + xmlWriter.addAttribute( "office:value", + TQString::number( value().asFloat() ) ); + break; + } + case Value::fmt_DateTime: break; //NOTHING HERE + case Value::fmt_Date: + { + xmlWriter.addAttribute( "office:value-type", "date" ); + xmlWriter.addAttribute( "office:date-value", + value().asDate().toString( Qt::ISODate ) ); + break; + } + case Value::fmt_Time: + { + xmlWriter.addAttribute( "office:value-type", "time" ); + xmlWriter.addAttribute( "office:time-value", + value().asTime().toString( "PThhHmmMssS" ) ); + break; + } + case Value::fmt_String: + { + xmlWriter.addAttribute( "office:value-type", "string" ); + xmlWriter.addAttribute( "office:string-value", value().asString() ); + break; + } + }; +} + +TQString Cell::convertFormulaToOasisFormat( const TQString & formula ) const +{ + TQString s; + TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)"); + int n = exp.search( formula, 0 ); + kdDebug() << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length() + << ", Matched length: " << exp.matchedLength() << endl; + + bool inQuote1 = false; + bool inQuote2 = false; + int i = 0; + int l = (int) formula.length(); + if ( l <= 0 ) + return formula; + while ( i < l ) + { + if ( ( n != -1 ) && ( n < i ) ) + { + n = exp.search( formula, i ); + kdDebug() << "Exp: " << formula.right( l - i ) << ", n: " << n << endl; + } + if ( formula[i] == '"' ) + { + inQuote1 = !inQuote1; + s += formula[i]; + ++i; + continue; + } + if ( formula[i] == '\'' ) + { + // named area + inQuote2 = !inQuote2; + ++i; + continue; + } + if ( inQuote1 || inQuote2 ) + { + s += formula[i]; + ++i; + continue; + } + if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) ) + { + s += '='; + ++i;++i; + continue; + } + if ( formula[i] == '!' ) + { + insertBracket( s ); + s += '.'; + ++i; + continue; + } + if ( formula[i] == ',' ) + { + s += '.'; + ++i; + continue; + } + if ( n == i ) + { + int ml = exp.matchedLength(); + if ( formula[ i + ml ] == '!' ) + { + kdDebug() << "No cell ref but sheet name" << endl; + s += formula[i]; + ++i; + continue; + } + if ( ( i > 0 ) && ( formula[i - 1] != '!' ) ) + s += "[."; + for ( int j = 0; j < ml; ++j ) + { + s += formula[i]; + ++i; + } + s += ']'; + continue; + } + + s += formula[i]; + ++i; + } + + return s; +} + +void Cell::loadOasisConditional( TQDomElement * style ) +{ + if ( style )//safe + { + TQDomElement e; + forEachElement( e, style->toElement() ) + { + if ( e.localName() == "map" && e.namespaceURI() == KoXmlNS::style ) + { + if (d->hasExtra()) + delete d->extra()->conditions; + d->extra()->conditions = new Conditions( this ); + d->extra()->conditions->loadOasisConditions( e ); + d->extra()->conditions->checkMatches(); + // break here + // Conditions::loadOasisConditions finishes the iteration + break; + } + } + } +} + +bool Cell::loadOasis( const TQDomElement& element , KoOasisLoadingContext& oasisContext , Style* style ) +{ + kdDebug() << "*** Loading cell properties ***** at " << column() << "," << row () << endl; + + if ( element.hasAttributeNS( KoXmlNS::table, "style-name" ) ) + { + kdDebug()<<" table:style-name: "<( cellStyle ) ); + } + + if (style) + { + format()->setStyle( style ); + } + + //Search and load each paragraph of text. Each paragraph is separated by a line break. + loadOasisCellText( element ); + + // + // formula + // + bool isFormula = false; + if ( element.hasAttributeNS( KoXmlNS::table, "formula" ) ) + { + kdDebug()<<" formula :"<strText.at(0) == '=' ) //prepend ' to the text to avoid = to be painted + d->strText.prepend('\''); + + // + // validation + // + if ( element.hasAttributeNS( KoXmlNS::table, "validation-name" ) ) + { + kdDebug()<<" validation-name: "<strText.isEmpty()) + { + TQString str = locale()->formatNumber( value, 15 ); + setCellText( str ); + } + } + + // currency value + else if( valuetype == "currency" ) + { + bool ok = false; + double value = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok ); + if( ok ) + { + setCellValue( value, Money_format ); + + if (element.hasAttributeNS( KoXmlNS::office, "currency" ) ) + { + Currency currency(element.attributeNS( KoXmlNS::office, "currency", TQString() ) ); + format()->setCurrency( currency.getIndex(), currency.getDisplayCode() ); + } + } + } + else if( valuetype == "percentage" ) + { + bool ok = false; + double v = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok ); + if( ok ) + { + Value value; + value.setValue (v); + value.setFormat (Value::fmt_Percent); + setCellValue( value ); + + if ( !isFormula && d->strText.isEmpty()) + { + TQString str = locale()->formatNumber( v, 15 ); + setCellText( str ); + } + + format()->setFormatType (Percentage_format); + } + } + else if ( valuetype == "date" ) + { + TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); + if ( value.isEmpty() ) + value = element.attributeNS( KoXmlNS::office, "date-value", TQString() ); + kdDebug() << "Type: date, value: " << value << endl; + + // "1980-10-15" + int year = 0, month = 0, day = 0; + bool ok = false; + + int p1 = value.find( '-' ); + if ( p1 > 0 ) + year = value.left( p1 ).toInt( &ok ); + + kdDebug() << "year: " << value.left( p1 ) << endl; + + int p2 = value.find( '-', ++p1 ); + + if ( ok ) + month = value.mid( p1, p2 - p1 ).toInt( &ok ); + + kdDebug() << "month: " << value.mid( p1, p2 - p1 ) << endl; + + if ( ok ) + day = value.right( value.length() - p2 - 1 ).toInt( &ok ); + + kdDebug() << "day: " << value.right( value.length() - p2 ) << endl; + + if ( ok ) + { + setCellValue( TQDate( year, month, day ) ); + if ( style ) + format()->setFormatType (style->formatType()); + kdDebug() << "Set TQDate: " << year << " - " << month << " - " << day << endl; + } + + } + else if ( valuetype == "time" ) + { + TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); + if ( value.isEmpty() ) + value = element.attributeNS( KoXmlNS::office, "time-value", TQString() ); + kdDebug() << "Type: time: " << value << endl; + // "PT15H10M12S" + int hours = 0, minutes = 0, seconds = 0; + int l = value.length(); + TQString num; + bool ok = false; + for ( int i = 0; i < l; ++i ) + { + if ( value[i].isNumber() ) + { + num += value[i]; + continue; + } + else if ( value[i] == 'H' ) + hours = num.toInt( &ok ); + else if ( value[i] == 'M' ) + minutes = num.toInt( &ok ); + else if ( value[i] == 'S' ) + seconds = num.toInt( &ok ); + else + continue; + + kdDebug() << "Num: " << num << endl; + + num = ""; + if ( !ok ) + break; + } + kdDebug() << "Hours: " << hours << ", " << minutes << ", " << seconds << endl; + + if ( ok ) + { + // Value kval( timeToNum( hours, minutes, seconds ) ); + // cell->setValue( kval ); + setCellValue( TQTime( hours % 24, minutes, seconds ) ); + if ( style ) + format()->setFormatType (style->formatType()); + } + } + else if( valuetype == "string" ) + { + TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() ); + if ( value.isEmpty() && element.hasAttributeNS( KoXmlNS::office, "string-value" )) + { + //if there is not string-value entry don't overwrite value stored into + value = element.attributeNS( KoXmlNS::office, "string-value", TQString() ); + setCellValue( value ); + } + format()->setFormatType (Text_format); + } + else + kdDebug()<<" type of value found : "< 1 || rowSpan > 1 ) + mergeCells( d->column, d->row, colSpan - 1, rowSpan - 1 ); + + // + // cell comment/annotation + // + TQDomElement annotationElement = KoDom::namedItemNS( element, KoXmlNS::office, "annotation" ); + if ( !annotationElement.isNull() ) + { + TQString comment; + TQDomNode node = annotationElement.firstChild(); + while( !node.isNull() ) + { + TQDomElement commentElement = node.toElement(); + if( !commentElement.isNull() ) + if( commentElement.localName() == "p" && commentElement.namespaceURI() == KoXmlNS::text ) + { + if( !comment.isEmpty() ) comment.append( '\n' ); + comment.append( commentElement.text() ); + } + + node = node.nextSibling(); + } + + if( !comment.isEmpty() ) + format()->setComment( comment ); + } + + TQDomElement frame = KoDom::namedItemNS( element, KoXmlNS::draw, "frame" ); + if ( !frame.isNull() ) + loadOasisObjects( frame, oasisContext ); + + if (isFormula) + setCalcDirtyFlag (); // formulas must be recalculated + + return true; +} + +void Cell::loadOasisCellText( const TQDomElement& parent ) +{ + //Search and load each paragraph of text. Each paragraph is separated by a line break + TQDomElement textParagraphElement; + TQString cellText; + + bool multipleTextParagraphsFound=false; + + forEachElement( textParagraphElement , parent ) + { + if ( textParagraphElement.localName()=="p" && + textParagraphElement.namespaceURI()== KoXmlNS::text ) + { + // our text, could contain formating for value or result of formul + if (cellText.isEmpty()) + cellText = textParagraphElement.text(); + else + { + cellText += "\n"+textParagraphElement.text(); + multipleTextParagraphsFound=true; + } + + TQDomElement textA = KoDom::namedItemNS( textParagraphElement, KoXmlNS::text, "a" ); + if( !textA.isNull() ) + { + if ( textA.hasAttributeNS( KoXmlNS::xlink, "href" ) ) + { + TQString link = textA.attributeNS( KoXmlNS::xlink, "href", TQString() ); + cellText = textA.text(); + setCellText( cellText ); + setValue( cellText ); + if ( link[0]=='#' ) + link=link.remove( 0, 1 ); + setLink( link ); + } + } + } + } + + if (!cellText.isNull()) + { + setCellText( cellText ); + setValue( cellText ); + } + + //Enable word wrapping if multiple lines of text have been found. + if ( multipleTextParagraphsFound ) + { + format()->setMultiRow(true); + } +} + +void Cell::loadOasisObjects( const TQDomElement &parent, KoOasisLoadingContext& oasisContext ) +{ + for( TQDomElement e = parent; !e.isNull(); e = e.nextSibling().toElement() ) + { + if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw ) + { + EmbeddedObject *obj = 0; + TQDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" ); + if ( !object.isNull() ) + { + if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", TQString()).isNull() ) + obj = new EmbeddedChart( sheet()->doc(), sheet() ); + else + obj = new EmbeddedKOfficeObject( sheet()->doc(), sheet() ); + } + else + { + TQDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" ); + if ( !image.isNull() ) + obj = new EmbeddedPictureObject( sheet(), sheet()->doc()->pictureCollection() ); + else + kdDebug() << "Object type wasn't loaded!" << endl; + } + + if ( obj ) + { + obj->loadOasis( e, oasisContext ); + sheet()->doc()->insertObject( obj ); + + TQString ref = e.attributeNS( KoXmlNS::table, "end-cell-address", TQString() ); + if ( ref.isNull() ) + continue; + + ref = Oasis::decodeFormula( ref ); + Point point( ref ); + if ( !point.isValid() ) + continue; + + KoRect geometry = obj->geometry(); + geometry.setLeft( geometry.left() + sheet()->columnPos( d->column, 0 ) ); + geometry.setTop( geometry.top() + sheet()->rowPos( d->row, 0 ) ); + + TQString str = e.attributeNS( KoXmlNS::table, "end-x", TQString() ); + if ( !str.isNull() ) + { + uint end_x = (uint) KoUnit::parseValue( str ); + geometry.setRight( sheet()->columnPos( point.column(), 0) + end_x ); + } + + str = e.attributeNS( KoXmlNS::table, "end-y", TQString() ); + if ( !str.isNull() ) + { + uint end_y = (uint) KoUnit::parseValue( str ); + geometry.setBottom( sheet()->rowPos( point.row(), 0) + end_y ); + } + + obj->setGeometry( geometry ); + } + } + } +} + +void Cell::loadOasisValidation( const TQString& validationName ) +{ + TQDomElement element = sheet()->doc()->loadingInfo()->validation( validationName); + if (d->hasExtra()) + delete d->extra()->validity; + d->extra()->validity = new Validity; + if ( element.hasAttributeNS( KoXmlNS::table, "condition" ) ) + { + TQString valExpression = element.attributeNS( KoXmlNS::table, "condition", TQString() ); + kdDebug()<<" element.attribute( table:condition ) "<' | '<=' | '>=' | '=' | '!=' + //Value ::= NumberValue | String | Formula + //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information. + //A String comprises one or more characters surrounded by quotation marks. + //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater. + + //ExtendedTrueCondition + if ( valExpression.contains( "cell-content-text-length()" ) ) + { + //"cell-content-text-length()>45" + valExpression = valExpression.remove("oooc:cell-content-text-length()" ); + kdDebug()<<" valExpression = :"<extra()->validity->m_restriction = Restriction::TextLength; + + loadOasisValidationCondition( valExpression ); + } + else if ( valExpression.contains( "cell-content-is-text()" ) ) + { + d->extra()->validity->m_restriction = Restriction::Text; + } + //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value) | cell-content-is-in-list( StringList ) + else if ( valExpression.contains( "cell-content-text-length-is-between" ) ) + { + d->extra()->validity->m_restriction = Restriction::TextLength; + d->extra()->validity->m_cond = Conditional::Between; + valExpression = valExpression.remove( "oooc:cell-content-text-length-is-between(" ); + kdDebug()<<" valExpression :"<extra()->validity->m_restriction = Restriction::TextLength; + d->extra()->validity->m_cond = Conditional::Different; + valExpression = valExpression.remove( "oooc:cell-content-text-length-is-not-between(" ); + kdDebug()<<" valExpression :"<extra()->validity->m_restriction = Restriction::List; + valExpression = valExpression.remove( "oooc:cell-content-is-in-list(" ); + kdDebug()<<" valExpression :"<extra()->validity->listValidity = TQStringList::split( ";", valExpression ); + + } + //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time() + else + { + if (valExpression.contains( "cell-content-is-whole-number()" ) ) + { + d->extra()->validity->m_restriction = Restriction::Number; + valExpression = valExpression.remove( "oooc:cell-content-is-whole-number() and " ); + } + else if (valExpression.contains( "cell-content-is-decimal-number()" ) ) + { + d->extra()->validity->m_restriction = Restriction::Integer; + valExpression = valExpression.remove( "oooc:cell-content-is-decimal-number() and " ); + } + else if (valExpression.contains( "cell-content-is-date()" ) ) + { + d->extra()->validity->m_restriction = Restriction::Date; + valExpression = valExpression.remove( "oooc:cell-content-is-date() and " ); + } + else if (valExpression.contains( "cell-content-is-time()" ) ) + { + d->extra()->validity->m_restriction = Restriction::Time; + valExpression = valExpression.remove( "oooc:cell-content-is-time() and " ); + } + kdDebug()<<"valExpression :"<extra()->validity->m_cond = Conditional::Between; + } + if ( valExpression.contains( "cell-content-is-not-between(" ) ) + { + valExpression = valExpression.remove( "cell-content-is-not-between(" ); + valExpression = valExpression.remove( ")" ); + TQStringList listVal = TQStringList::split( ",", valExpression ); + loadOasisValidationValue( listVal ); + d->extra()->validity->m_cond = Conditional::Different; + } + } + } + if ( element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" ) ) + { + kdDebug()<<" element.hasAttribute( table:allow-empty-cell ) :"<extra()->validity->allowEmptyCell = ( ( element.attributeNS( KoXmlNS::table, "allow-empty-cell", TQString() )=="true" ) ? true : false ); + } + if ( element.hasAttributeNS( KoXmlNS::table, "base-cell-address" ) ) + { + //todo what is it ? + } + + TQDomElement help = KoDom::namedItemNS( element, KoXmlNS::table, "help-message" ); + if ( !help.isNull() ) + { + if ( help.hasAttributeNS( KoXmlNS::table, "title" ) ) + { + kdDebug()<<"help.attribute( table:title ) :"<extra()->validity->titleInfo = help.attributeNS( KoXmlNS::table, "title", TQString() ); + } + if ( help.hasAttributeNS( KoXmlNS::table, "display" ) ) + { + kdDebug()<<"help.attribute( table:display ) :"<extra()->validity->displayValidationInformation = ( ( help.attributeNS( KoXmlNS::table, "display", TQString() )=="true" ) ? true : false ); + } + TQDomElement attrText = KoDom::namedItemNS( help, KoXmlNS::text, "p" ); + if ( !attrText.isNull() ) + { + kdDebug()<<"help text :"<extra()->validity->messageInfo = attrText.text(); + } + } + + TQDomElement error = KoDom::namedItemNS( element, KoXmlNS::table, "error-message" ); + if ( !error.isNull() ) + { + if ( error.hasAttributeNS( KoXmlNS::table, "title" ) ) + d->extra()->validity->title = error.attributeNS( KoXmlNS::table, "title", TQString() ); + if ( error.hasAttributeNS( KoXmlNS::table, "message-type" ) ) + { + TQString str = error.attributeNS( KoXmlNS::table, "message-type", TQString() ); + if ( str == "warning" ) + d->extra()->validity->m_action = Action::Warning; + else if ( str == "information" ) + d->extra()->validity->m_action = Action::Information; + else if ( str == "stop" ) + d->extra()->validity->m_action = Action::Stop; + else + kdDebug()<<"validation : message type unknown :"<extra()->validity->displayMessage = (error.attributeNS( KoXmlNS::table, "display", TQString() )=="true"); + } + TQDomElement attrText = KoDom::namedItemNS( error, KoXmlNS::text, "p" ); + if ( !attrText.isNull() ) + d->extra()->validity->message = attrText.text(); + } +} + + +void Cell::loadOasisValidationValue( const TQStringList &listVal ) +{ + bool ok = false; + kdDebug()<<" listVal[0] :"<extra()->validity->m_restriction == Restriction::Date ) + { + d->extra()->validity->dateMin = TQDate::fromString( listVal[0] ); + d->extra()->validity->dateMax = TQDate::fromString( listVal[1] ); + } + else if ( d->extra()->validity->m_restriction == Restriction::Time ) + { + d->extra()->validity->timeMin = TQTime::fromString( listVal[0] ); + d->extra()->validity->timeMax = TQTime::fromString( listVal[1] ); + } + else + { + d->extra()->validity->valMin = listVal[0].toDouble(&ok); + if ( !ok ) + { + d->extra()->validity->valMin = listVal[0].toInt(&ok); + if ( !ok ) + kdDebug()<<" Try to parse this value :"<extra()->validity->valMin = listVal[0]; +#endif + } + ok=false; + d->extra()->validity->valMax = listVal[1].toDouble(&ok); + if ( !ok ) + { + d->extra()->validity->valMax = listVal[1].toInt(&ok); + if ( !ok ) + kdDebug()<<" Try to parse this value :"<extra()->validity->valMax = listVal[1]; +#endif + } + } +} + +void Cell::loadOasisValidationCondition( TQString &valExpression ) +{ + TQString value; + if (valExpression.find( "<=" )==0 ) + { + value = valExpression.remove( 0,2 ); + d->extra()->validity->m_cond = Conditional::InferiorEqual; + } + else if (valExpression.find( ">=" )==0 ) + { + value = valExpression.remove( 0,2 ); + d->extra()->validity->m_cond = Conditional::SuperiorEqual; + } + else if (valExpression.find( "!=" )==0 ) + { + //add Differentto attribute + value = valExpression.remove( 0,2 ); + d->extra()->validity->m_cond = Conditional::DifferentTo; + } + else if ( valExpression.find( "<" )==0 ) + { + value = valExpression.remove( 0,1 ); + d->extra()->validity->m_cond = Conditional::Inferior; + } + else if(valExpression.find( ">" )==0 ) + { + value = valExpression.remove( 0,1 ); + d->extra()->validity->m_cond = Conditional::Superior; + } + else if (valExpression.find( "=" )==0 ) + { + value = valExpression.remove( 0,1 ); + d->extra()->validity->m_cond = Conditional::Equal; + } + else + kdDebug()<<" I don't know how to parse it :"<extra()->validity->m_restriction == Restriction::Date ) + { + d->extra()->validity->dateMin = TQDate::fromString( value ); + } + else if (d->extra()->validity->m_restriction == Restriction::Date ) + { + d->extra()->validity->timeMin = TQTime::fromString( value ); + } + else + { + bool ok = false; + d->extra()->validity->valMin = value.toDouble(&ok); + if ( !ok ) + { + d->extra()->validity->valMin = value.toInt(&ok); + if ( !ok ) + kdDebug()<<" Try to parse this value :"<extra()->validity->valMin = value; +#endif + } + } +} + + +bool Cell::load( const TQDomElement & cell, int _xshift, int _yshift, + Paste::Mode pm, Paste::Operation op, bool paste ) +{ + bool ok; + + // + // First of all determine in which row and column this + // cell belongs. + // + d->row = cell.attribute( "row" ).toInt( &ok ) + _yshift; + if ( !ok ) return false; + d->column = cell.attribute( "column" ).toInt( &ok ) + _xshift; + if ( !ok ) return false; + + // Validation + if ( d->row < 1 || d->row > KS_rowMax ) + { + kdDebug(36001) << "Cell::load: Value out of Range Cell:row=" << d->row << endl; + return false; + } + if ( d->column < 1 || d->column > KS_colMax ) + { + kdDebug(36001) << "Cell::load: Value out of Range Cell:column=" << d->column << endl; + return false; + } + + // + // Load formatting information. + // + TQDomElement f = cell.namedItem( "format" ).toElement(); + if ( !f.isNull() + && ( (pm == Paste::Normal) || (pm == Paste::Format) || (pm == Paste::NoBorder) ) ) + { + // send pm parameter. Didn't load Borders if pm==NoBorder + + if ( !format()->load( f, pm, paste ) ) + return false; + + if ( f.hasAttribute( "colspan" ) ) + { + int i = f.attribute("colspan").toInt( &ok ); + if ( !ok ) return false; + // Validation + if ( i < 0 || i > KS_spanMax ) + { + kdDebug(36001) << "Value out of range Cell::colspan=" << i << endl; + return false; + } + if (i || d->hasExtra()) + d->extra()->extraXCells = i; + if ( i > 0 ) + { + setFlag(Flag_Merged); + } + } + + if ( f.hasAttribute( "rowspan" ) ) + { + int i = f.attribute("rowspan").toInt( &ok ); + if ( !ok ) return false; + // Validation + if ( i < 0 || i > KS_spanMax ) + { + kdDebug(36001) << "Value out of range Cell::rowspan=" << i << endl; + return false; + } + if (i || d->hasExtra()) + d->extra()->extraYCells = i; + if ( i > 0 ) + { + setFlag(Flag_Merged); + } + } + + if ( testFlag( Flag_Merged ) ) + { + if (d->hasExtra()) + mergeCells( d->column, d->row, d->extra()->extraXCells, d->extra()->extraYCells ); + } + + } + + // + // Load the condition section of a cell. + // + TQDomElement conditionsElement = cell.namedItem( "condition" ).toElement(); + if ( !conditionsElement.isNull()) + { + if (d->hasExtra()) + delete d->extra()->conditions; + d->extra()->conditions = new Conditions( this ); + d->extra()->conditions->loadConditions( conditionsElement ); + d->extra()->conditions->checkMatches(); + } + else if ((pm == Paste::Normal) || (pm == Paste::NoBorder)) + { + //clear the conditional formatting + if (d->hasExtra()) + { + delete d->extra()->conditions; + d->extra()->conditions = 0; + } + } + + TQDomElement validity = cell.namedItem( "validity" ).toElement(); + if ( !validity.isNull()) + { + TQDomElement param = validity.namedItem( "param" ).toElement(); + if(!param.isNull()) + { + d->extra()->validity = new Validity; + if ( param.hasAttribute( "cond" ) ) + { + d->extra()->validity->m_cond = (Conditional::Type) param.attribute("cond").toInt( &ok ); + if ( !ok ) + return false; + } + if ( param.hasAttribute( "action" ) ) + { + d->extra()->validity->m_action = (Action::Type) param.attribute("action").toInt( &ok ); + if ( !ok ) + return false; + } + if ( param.hasAttribute( "allow" ) ) + { + d->extra()->validity->m_restriction = (Restriction::Type) param.attribute("allow").toInt( &ok ); + if ( !ok ) + return false; + } + if ( param.hasAttribute( "valmin" ) ) + { + d->extra()->validity->valMin = param.attribute("valmin").toDouble( &ok ); + if ( !ok ) + return false; + } + if ( param.hasAttribute( "valmax" ) ) + { + d->extra()->validity->valMax = param.attribute("valmax").toDouble( &ok ); + if ( !ok ) + return false; + } + if ( param.hasAttribute( "displaymessage" ) ) + { + d->extra()->validity->displayMessage = ( bool )param.attribute("displaymessage").toInt(); + } + if ( param.hasAttribute( "displayvalidationinformation" ) ) + { + d->extra()->validity->displayValidationInformation = ( bool )param.attribute("displayvalidationinformation").toInt(); + } + if ( param.hasAttribute( "allowemptycell" ) ) + { + d->extra()->validity->allowEmptyCell = ( bool )param.attribute("allowemptycell").toInt(); + } + if ( param.hasAttribute("listvalidity") ) + { + d->extra()->validity->listValidity=TQStringList::split(";", param.attribute("listvalidity") ); + } + } + TQDomElement inputTitle = validity.namedItem( "inputtitle" ).toElement(); + if (!inputTitle.isNull()) + { + d->extra()->validity->titleInfo = inputTitle.text(); + } + TQDomElement inputMessage = validity.namedItem( "inputmessage" ).toElement(); + if (!inputMessage.isNull()) + { + d->extra()->validity->messageInfo = inputMessage.text(); + } + + TQDomElement title = validity.namedItem( "title" ).toElement(); + if (!title.isNull()) + { + d->extra()->validity->title = title.text(); + } + TQDomElement message = validity.namedItem( "message" ).toElement(); + if (!message.isNull()) + { + d->extra()->validity->message = message.text(); + } + TQDomElement timeMin = validity.namedItem( "timemin" ).toElement(); + if ( !timeMin.isNull() ) + { + d->extra()->validity->timeMin = toTime(timeMin); + } + TQDomElement timeMax = validity.namedItem( "timemax" ).toElement(); + if ( !timeMax.isNull() ) + { + d->extra()->validity->timeMax = toTime(timeMax); + } + TQDomElement dateMin = validity.namedItem( "datemin" ).toElement(); + if ( !dateMin.isNull() ) + { + d->extra()->validity->dateMin = toDate(dateMin); + } + TQDomElement dateMax = validity.namedItem( "datemax" ).toElement(); + if ( !dateMax.isNull() ) + { + d->extra()->validity->dateMax = toDate(dateMax); + } + } + else if ((pm == Paste::Normal) || (pm == Paste::NoBorder)) + { + // clear the validity + removeValidity(); + } + + // + // Load the comment + // + TQDomElement comment = cell.namedItem( "comment" ).toElement(); + if ( !comment.isNull() && ( pm == Paste::Normal || pm == Paste::Comment || pm == Paste::NoBorder )) + { + TQString t = comment.text(); + //t = t.stripWhiteSpace(); + format()->setComment( t ); + } + + // + // The real content of the cell is loaded here. It is stored in + // the "text" tag, which contains either a text or a CDATA section. + // + // TODO: make this suck less. We set data twice, in loadCellData, and + // also here. Not good. + TQDomElement text = cell.namedItem( "text" ).toElement(); + + if ( !text.isNull() && + ( pm == Paste::Normal || pm == Paste::Text || pm == Paste::NoBorder || pm == Paste::Result ) ) + { + /* older versions mistakenly put the datatype attribute on the cell + instead of the text. Just move it over in case we're parsing + an old document */ + if ( cell.hasAttribute( "dataType" ) ) // new docs + text.setAttribute( "dataType", cell.attribute( "dataType" ) ); + + TQDomElement result = cell.namedItem( "result" ).toElement(); + TQString txt = text.text(); + if ((pm == Paste::Result) && (txt[0] == '=')) + // paste text of the element, if we want to paste result + // and the source cell contains a formula + // note that we mustn't use setCellValue after this, or else we lose + // all the formulas ... + d->strText = result.text(); + else + //otherwise copy everything + loadCellData(text, op); + + if ( !result.isNull() ) + { + TQString dataType; + TQString t = result.text(); + + if ( result.hasAttribute( "dataType" ) ) + dataType = result.attribute( "dataType" ); + if ( result.hasAttribute( "outStr" ) ) + { + d->strOutText = result.attribute( "outStr" ); + if ( !d->strOutText.isEmpty() ) + clearFlag( Flag_TextFormatDirty ); + } + + bool clear = true; + // boolean ? + if( dataType == "Bool" ) + { + if ( t == "false" ) + setValue( false ); + else if ( t == "true" ) + setValue( true ); + else + clear = false; + } + else if( dataType == "Num" ) + { + bool ok = false; + double dd = t.toDouble( &ok ); + if ( ok ) + setValue ( dd ); + else + clear = false; + } + else if( dataType == "Date" ) + { + bool ok = false; + double dd = t.toDouble( &ok ); + if ( ok ) + setValue ( dd ); + else + { + int pos = t.find( '/' ); + int year = t.mid( 0, pos ).toInt(); + int pos1 = t.find( '/', pos + 1 ); + int month = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt(); + int day = t.right( t.length() - pos1 - 1 ).toInt(); + TQDate date( year, month, day ); + if ( date.isValid() ) + setValue( date ); + else + clear = false; + } + } + else if( dataType == "Time" ) + { + bool ok = false; + double dd = t.toDouble( &ok ); + if ( ok ) + setCellValue( dd ); + else + { + int hours = -1; + int minutes = -1; + int second = -1; + int pos, pos1; + pos = t.find( ':' ); + hours = t.mid( 0, pos ).toInt(); + pos1 = t.find( ':', pos + 1 ); + minutes = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt(); + second = t.right( t.length() - pos1 - 1 ).toInt(); + TQTime time( hours, minutes, second ); + if ( time.isValid() ) + setValue( time ); + else + clear = false; + } + } + else + { + setValue( t ); + } + + // if ( clear ) + // clearFlag( Flag_CalcDirty ); + } + } + + return true; +} + +bool Cell::loadCellData(const TQDomElement & text, Paste::Operation op ) +{ + //TODO: use converter()->asString() to generate strText + + TQString t = text.text(); + t = t.stripWhiteSpace(); + + setFlag(Flag_LayoutDirty); + setFlag(Flag_TextFormatDirty); + + // A formula like =A1+A2 ? + if( t[0] == '=' ) + { + t = decodeFormula( t, d->column, d->row ); + setCellText (pasteOperation( t, d->strText, op )); + + setFlag(Flag_CalcDirty); + clearAllErrors(); + + if ( !makeFormula() ) + kdError(36001) << "ERROR: Syntax ERROR" << endl; + } + // rich text ? + else if (t[0] == '!' ) + { + // KSpread pre 1.4 stores hyperlink as rich text (first char is '!') + // extract the link and the correspoding text + // This is a rather dirty hack, but enough for KSpread generated XML + bool inside_tag = false; + TQString qml_text; + TQString tag; + TQString qml_link; + + for( unsigned i = 1; i < t.length(); i++ ) + { + TQChar ch = t[i]; + if( ch == '<' ) + { + if( !inside_tag ) + { + inside_tag = true; + tag = TQString(); + } + } + else if( ch == '>' ) + { + if( inside_tag ) + { + inside_tag = false; + if( tag.startsWith( "a href=\"", true ) ) + if( tag.endsWith( "\"" ) ) + qml_link = tag.mid( 8, tag.length()-9 ); + tag = TQString(); + } + } + else + { + if( !inside_tag ) + qml_text += ch; + else + tag += ch; + } + } + + if( !qml_link.isEmpty() ) + d->extra()->link = qml_link; + d->strText = qml_text; + setValue( d->strText ); + } + else + { + bool newStyleLoading = true; + TQString dataType; + + if ( text.hasAttribute( "dataType" ) ) // new docs + { + dataType = text.attribute( "dataType" ); + } + else // old docs: do the ugly solution of calling checkTextInput to parse the text + { + // ...except for date/time + if (isDate() && ( t.contains('/') == 2 )) + dataType = "Date"; + else if (isTime() && ( t.contains(':') == 2 ) ) + dataType = "Time"; + else + { + d->strText = pasteOperation( t, d->strText, op ); + checkTextInput(); + //kdDebug(36001) << "Cell::load called checkTextInput, got dataType=" << dataType << " t=" << t << endl; + newStyleLoading = false; + } + } + + if ( newStyleLoading ) + { + d->value = Value::empty(); + clearAllErrors(); + + // boolean ? + if( dataType == "Bool" ) + { + bool val = (t.lower() == "true"); + setCellValue (val); + } + + // number ? + else if( dataType == "Num" ) + { + bool ok = false; + if (t.contains('.')) + setValue ( Value( t.toDouble(&ok) ) ); // We save in non-localized format + else + setValue ( Value( t.toLong(&ok) ) ); + if ( !ok ) + { + kdWarning(36001) << "Couldn't parse '" << t << "' as number." << endl; + } + /* We will need to localize the text version of the number */ + TDELocale* locale = format()->sheet()->doc()->locale(); + + /* TDELocale::formatNumber requires the precision we want to return. + */ + int precision = t.length() - t.find('.') - 1; + + if ( formatType() == Percentage_format ) + { + if (value().isInteger()) + t = locale->formatNumber( value().asInteger() * 100 ); + else + t = locale->formatNumber( value().asFloat() * 100.0, precision ); + d->strText = pasteOperation( t, d->strText, op ); + d->strText += '%'; + } + else + { + if (value().isInteger()) + t = locale->formatLong(value().asInteger()); + else + t = locale->formatNumber(value().asFloat(), precision); + d->strText = pasteOperation( t, d->strText, op ); + } + } + + // date ? + else if( dataType == "Date" ) + { + int pos = t.find('/'); + int year = t.mid(0,pos).toInt(); + int pos1 = t.find('/',pos+1); + int month = t.mid(pos+1,((pos1-1)-pos)).toInt(); + int day = t.right(t.length()-pos1-1).toInt(); + setValue( TQDate(year,month,day) ); + if ( value().asDate().isValid() ) // Should always be the case for new docs + d->strText = locale()->formatDate( value().asDate(), true ); + else // This happens with old docs, when format is set wrongly to date + { + d->strText = pasteOperation( t, d->strText, op ); + checkTextInput(); + } + } + + // time ? + else if( dataType == "Time" ) + { + int hours = -1; + int minutes = -1; + int second = -1; + int pos, pos1; + pos = t.find(':'); + hours = t.mid(0,pos).toInt(); + pos1 = t.find(':',pos+1); + minutes = t.mid(pos+1,((pos1-1)-pos)).toInt(); + second = t.right(t.length()-pos1-1).toInt(); + setValue( TQTime(hours,minutes,second) ); + if ( value().asTime().isValid() ) // Should always be the case for new docs + d->strText = locale()->formatTime( value().asTime(), true ); + else // This happens with old docs, when format is set wrongly to time + { + d->strText = pasteOperation( t, d->strText, op ); + checkTextInput(); + } + } + + else + { + // Set the cell's text + d->strText = pasteOperation( t, d->strText, op ); + setValue( d->strText ); + } + } + } + + if ( text.hasAttribute( "outStr" ) ) // very new docs + { + d->strOutText = text.attribute( "outStr" ); + if ( !d->strOutText.isEmpty() ) + clearFlag( Flag_TextFormatDirty ); + } + + if ( !format()->sheet()->isLoading() ) + setCellText( d->strText ); + + if ( d->hasExtra() && d->extra()->conditions ) + d->extra()->conditions->checkMatches(); + + return true; +} + +TQTime Cell::toTime(const TQDomElement &element) +{ + //TODO: can't we use tryParseTime (after modification) instead? + TQString t = element.text(); + t = t.stripWhiteSpace(); + int hours = -1; + int minutes = -1; + int second = -1; + int pos, pos1; + pos = t.find(':'); + hours = t.mid(0,pos).toInt(); + pos1 = t.find(':',pos+1); + minutes = t.mid(pos+1,((pos1-1)-pos)).toInt(); + second = t.right(t.length()-pos1-1).toInt(); + setValue( Value( TQTime(hours,minutes,second)) ); + return value().asTime(); +} + +TQDate Cell::toDate(const TQDomElement &element) +{ + TQString t = element.text(); + int pos; + int pos1; + int year = -1; + int month = -1; + int day = -1; + pos = t.find('/'); + year = t.mid(0,pos).toInt(); + pos1 = t.find('/',pos+1); + month = t.mid(pos+1,((pos1-1)-pos)).toInt(); + day = t.right(t.length()-pos1-1).toInt(); + setValue( Value( TQDate(year,month,day) ) ); + return value().asDate(); +} + +TQString Cell::pasteOperation( const TQString &new_text, const TQString &old_text, Paste::Operation op ) +{ + if ( op == Paste::OverWrite ) + return new_text; + + TQString tmp_op; + TQString tmp; + TQString old; + + if( !new_text.isEmpty() && new_text[0] == '=' ) + { + tmp = new_text.right( new_text.length() - 1 ); + } + else + { + tmp = new_text; + } + + if ( old_text.isEmpty() && + ( op == Paste::Add || op == Paste::Mul || op == Paste::Sub || op == Paste::Div ) ) + { + old = "=0"; + } + + if( !old_text.isEmpty() && old_text[0] == '=' ) + { + old = old_text.right( old_text.length() - 1 ); + } + else + { + old = old_text; + } + + bool b1, b2; + tmp.toDouble( &b1 ); + old.toDouble( &b2 ); + if (b1 && !b2 && old.length() == 0) + { + old = "0"; + b2 = true; + } + + if( b1 && b2 ) + { + switch( op ) + { + case Paste::Add: + tmp_op = TQString::number(old.toDouble()+tmp.toDouble()); + break; + case Paste::Mul : + tmp_op = TQString::number(old.toDouble()*tmp.toDouble()); + break; + case Paste::Sub: + tmp_op = TQString::number(old.toDouble()-tmp.toDouble()); + break; + case Paste::Div: + tmp_op = TQString::number(old.toDouble()/tmp.toDouble()); + break; + default: + Q_ASSERT( 0 ); + } + + setFlag(Flag_LayoutDirty); + clearAllErrors(); + + return tmp_op; + } + else if ( ( new_text[0] == '=' && old_text[0] == '=' ) || + ( b1 && old_text[0] == '=' ) || ( new_text[0] == '=' && b2 ) ) + { + switch( op ) + { + case Paste::Add : + tmp_op="=("+old+")+"+"("+tmp+")"; + break; + case Paste::Mul : + tmp_op="=("+old+")*"+"("+tmp+")"; + break; + case Paste::Sub: + tmp_op="=("+old+")-"+"("+tmp+")"; + break; + case Paste::Div: + tmp_op="=("+old+")/"+"("+tmp+")"; + break; + default : + Q_ASSERT( 0 ); + } + + tmp_op = decodeFormula( tmp_op, d->column, d->row ); + setFlag(Flag_LayoutDirty); + clearAllErrors(); + + return tmp_op; + } + + tmp = decodeFormula( new_text, d->column, d->row ); + setFlag(Flag_LayoutDirty); + clearAllErrors(); + + return tmp; +} + +TQString Cell::testAnchor( int x, int y ) const +{ + if( link().isEmpty() ) + return TQString(); + + const Doc* doc = format()->sheet()->doc(); + int x1 = doc->zoomItX( d->textX ); + int y1 = doc->zoomItX( d->textY - d->textHeight ); + int x2 = doc->zoomItX( d->textX + d->textWidth ); + int y2 = doc->zoomItX( d->textY ); + + if( x > x1 ) if( x < x2 ) + if( y > y1 ) if( y < y2 ) + return link(); + + return TQString(); +} + +void Cell::sheetDies() +{ + // Avoid unobscuring the cells in the destructor. + if (d->hasExtra()) + { + d->extra()->extraXCells = 0; + d->extra()->extraYCells = 0; + d->extra()->mergedXCells = 0; + d->extra()->mergedYCells = 0; + } + + //d->nextCell = 0; + //d->previousCell = 0; +} + +Cell::~Cell() +{ + if ( d->nextCell ) + d->nextCell->setPreviousCell( d->previousCell ); + if ( d->previousCell ) + d->previousCell->setNextCell( d->nextCell ); + + if (d->hasExtra()) + { + delete d->extra()->validity; + } + + // Unobscure cells. + int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0; + int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0; + for( int x = 0; x <= extraXCells; ++x ) + for( int y = (x == 0) ? 1 : 0; // avoid looking at (+0,+0) + y <= extraYCells; ++y ) + { + Cell* cell = format()->sheet()->cellAt( d->column + x, d->row + y ); + if ( cell ) + cell->unobscure(this); + } + + d->value = Value::empty(); + + if (!isDefault()) + valueChanged (); //our value has been changed (is now null), but only if we aren't default + + delete d->format; + delete d; +} + +bool Cell::operator > ( const Cell & cell ) const +{ + if ( value().isNumber() ) // ### what about bools ? + { + if ( cell.value().isNumber() ) + return value().asFloat() > cell.value().asFloat(); + else + return false; // numbers are always < than texts + } + else if(isDate()) + { + if( cell.isDate() ) + return value().asDate() > cell.value().asDate(); + else if (cell.value().isNumber()) + return true; + else + return false; //date are always < than texts and time + } + else if(isTime()) + { + if( cell.isTime() ) + return value().asTime() > cell.value().asTime(); + else if( cell.isDate()) + return true; //time are always > than date + else if( cell.value().isNumber()) + return true; + else + return false; //time are always < than texts + } + else + { + if ( Map::respectCase ) + return value().asString().compare(cell.value().asString()) > 0; + else + return ( value().asString() ).lower().compare(cell.value().asString().lower()) > 0; + } +} + +bool Cell::operator < ( const Cell & cell ) const +{ + if ( value().isNumber() ) + { + if ( cell.value().isNumber() ) + return value().asFloat() < cell.value().asFloat(); + else + return true; // numbers are always < than texts + } + else if(isDate()) + { + if( cell.isDate() ) + return value().asDateTime().date() < cell.value().asDateTime().date(); + else if( cell.value().isNumber()) + return false; + else + return true; //date are always < than texts and time + } + else if(isTime()) + { + if( cell.isTime() ) + return value().asDateTime().time() < cell.value().asDateTime().time(); + else if(cell.isDate()) + return false; //time are always > than date + else if( cell.value().isNumber()) + return false; + else + return true; //time are always < than texts + } + else + { + if ( Map::respectCase ) + return value().asString().compare(cell.value().asString()) < 0; + else + return ( value().asString() ).lower().compare(cell.value().asString().lower()) < 0; + } +} + +bool Cell::operator==( const Cell& other ) const +{ + if ( d->strText != other.d->strText ) + return false; + if ( d->value != other.d->value ) + return false; + if ( *d->format != *other.d->format ) + return false; + if ( d->hasExtra() ) + { + if ( !other.d->hasExtra() ) + return false; + if ( d->extra()->link != other.d->extra()->link ) + return false; + if ( d->extra()->mergedXCells != other.d->extra()->mergedXCells ) + return false; + if ( d->extra()->mergedYCells != other.d->extra()->mergedYCells ) + return false; + if ( d->extra()->conditions ) + { + if ( !other.d->extra()->conditions ) + return false; + if ( *d->extra()->conditions != *other.d->extra()->conditions ) + return false; + } + if ( d->extra()->validity ) + { + if ( !other.d->extra()->validity ) + return false; + if ( *d->extra()->validity != *other.d->extra()->validity ) + return false; + } + } + return true; +} + +TQRect Cell::cellRect() +{ + Q_ASSERT(!isDefault()); + return TQRect(TQPoint(d->column, d->row), TQPoint(d->column, d->row)); +} + +TQValueList Cell::conditionList() const +{ + if ( !d->hasExtra() || !d->extra()->conditions ) + { + TQValueList emptyList; + return emptyList; + } + + return d->extra()->conditions->conditionList(); +} + +void Cell::setConditionList( const TQValueList & newList ) +{ + if (d->hasExtra()) + delete d->extra()->conditions; + d->extra()->conditions = new Conditions( this ); + d->extra()->conditions->setConditionList( newList ); + d->extra()->conditions->checkMatches(); +} + +bool Cell::hasError() const +{ + return ( testFlag(Flag_ParseError) || + testFlag(Flag_CircularCalculation) || + testFlag(Flag_DependancyError)); +} + +void Cell::clearAllErrors() +{ + clearFlag( Flag_ParseError ); + clearFlag( Flag_CircularCalculation ); + clearFlag( Flag_DependancyError ); +} + +bool Cell::calcDirtyFlag() +{ + return isFormula() ? testFlag( Flag_CalcDirty ) : false; +} + +bool Cell::layoutDirtyFlag() const +{ + return testFlag( Flag_LayoutDirty ); +} + +void Cell::clearDisplayDirtyFlag() +{ + clearFlag( Flag_DisplayDirty ); +} + +void Cell::setDisplayDirtyFlag() +{ + setFlag( Flag_DisplayDirty ); +} + +bool Cell::doesMergeCells() const +{ + return testFlag( Flag_Merged ); +} + +void Cell::clearFlag( CellFlags flag ) +{ + d->flags &= ~(TQ_UINT32)flag; +} + +void Cell::setFlag( CellFlags flag ) +{ + d->flags |= (TQ_UINT32)flag; +} + +bool Cell::testFlag( CellFlags flag ) const +{ + return ( d->flags & (TQ_UINT32)flag ); +} + + +void Cell::checkForNamedAreas( TQString & formula ) const +{ + KSPLoadingInfo* loadinginfo = sheet()->doc()->loadingInfo(); + if(! loadinginfo) { + kdDebug() << "Cell::checkForNamedAreas loadinginfo is NULL" << endl; + return; + } + + int l = formula.length(); + int i = 0; + TQString word; + int start = 0; + while ( i < l ) + { + if ( formula[i].isLetterOrNumber() ) + { + word += formula[i]; + ++i; + continue; + } + if ( !word.isEmpty() ) + { + if ( loadinginfo->findWordInAreaList(word) ) + { + formula = formula.replace( start, word.length(), "'" + word + "'" ); + l = formula.length(); + ++i; + kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <findWordInAreaList(word) ) + { + formula = formula.replace( start, word.length(), "'" + word + "'" ); + l = formula.length(); + ++i; + kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 < - Copyright (C) 2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include - -#include "kspread_cell.h" -#include "kspread_format.h" - -#include "kspread_cluster.h" - -using namespace KSpread; - -/**************************************************** - * - * Cluster - * - ****************************************************/ - -/* Generate a matrix LEVEL1 with the size LEVEL1*LEVEL1 */ -Cluster::Cluster() - : m_first( 0 ), m_autoDelete( false ), m_biggestX(0), m_biggestY(0) -{ - m_cluster = (Cell***)malloc( KSPREAD_CLUSTER_LEVEL1 * KSPREAD_CLUSTER_LEVEL1 * sizeof( Cell** ) ); - - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) - m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; -} - -/* Delete the matrix LEVEL1 and all existing LEVEL2 matrizes */ -Cluster::~Cluster() -{ -// Can't we use clear(), to remove double code - Philipp? - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) - { - Cell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ]; - if ( cl ) - { - free( cl ); - m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; - } - } - - if ( m_autoDelete ) - { - Cell* cell = m_first; - while( cell ) - { - Cell* n = cell->nextCell(); - delete cell; - cell = n; - } - } - - free( m_cluster ); -} - -void Cluster::clear() -{ - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) - { - Cell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ]; - if ( cl ) - { - free( cl ); - m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; - } - } - - if ( m_autoDelete ) - { - Cell* cell = m_first; - while( cell ) - { - Cell* n = cell->nextCell(); - delete cell; - cell = n; - } - } - - m_first = 0; - m_biggestX = m_biggestY = 0; -} - -Cell* Cluster::lookup( int x, int y ) const -{ - if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) - { - kdDebug(36001) << "Cluster::lookup: invalid column or row value (col: " - << x << " | row: " << y << ")" << endl; - return 0; - } - int cx = x / KSPREAD_CLUSTER_LEVEL2; - int cy = y / KSPREAD_CLUSTER_LEVEL2; - int dx = x % KSPREAD_CLUSTER_LEVEL2; - int dy = y % KSPREAD_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( !cl ) - return 0; - - return cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ]; -} - -/* Paste a cell in LEVEL2 (it's more paste than insert) */ -void Cluster::insert( Cell* cell, int x, int y ) -{ - if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) - { - kdDebug(36001) << "Cluster::insert: invalid column or row value (col: " - << x << " | row: " << y << ")" << endl; - return; - } - - int cx = x / KSPREAD_CLUSTER_LEVEL2; - int cy = y / KSPREAD_CLUSTER_LEVEL2; - int dx = x % KSPREAD_CLUSTER_LEVEL2; - int dy = y % KSPREAD_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( !cl ) - { - cl = (Cell**)malloc( KSPREAD_CLUSTER_LEVEL2 * KSPREAD_CLUSTER_LEVEL2 * sizeof( Cell* ) ); - m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] = cl; - - for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) - for( int b = 0; b < KSPREAD_CLUSTER_LEVEL2; ++b ) - cl[ b * KSPREAD_CLUSTER_LEVEL2 + a ] = 0; - } - - if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) - remove( x, y ); - - cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = cell; - - if ( m_first ) - { - cell->setNextCell( m_first ); - m_first->setPreviousCell( cell ); - } - m_first = cell; - - if (x > m_biggestX) m_biggestX = x; - if (y > m_biggestY) m_biggestY = y; -} - -/* Removes the cell of a matrix, the matrix itself keeps unchanged */ -void Cluster::remove( int x, int y ) -{ - if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) - { - kdDebug(36001) << "Cluster::remove: invalid column or row value (col: " - << x << " | row: " << y << ")" << endl; - return; - } - - int cx = x / KSPREAD_CLUSTER_LEVEL2; - int cy = y / KSPREAD_CLUSTER_LEVEL2; - int dx = x % KSPREAD_CLUSTER_LEVEL2; - int dy = y % KSPREAD_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( !cl ) - return; - - Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ]; - if ( !c ) - return; - - cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = 0; - - if ( m_autoDelete ) - { - if ( m_first == c ) - m_first = c->nextCell(); - if(c->doesMergeCells()) - { - c->mergeCells(c->column(),c->row(),0,0); - } - delete c; - } - else - { - if ( m_first == c ) - m_first = c->nextCell(); - if ( c->previousCell() ) - c->previousCell()->setNextCell( c->nextCell() ); - if ( c->nextCell() ) - c->nextCell()->setPreviousCell( c->previousCell() ); - c->setNextCell( 0 ); - c->setPreviousCell( 0 ); - } -} - -bool Cluster::shiftRow( const TQPoint& marker ) -{ - bool dummy; - return shiftRow( marker, dummy ); -} - -bool Cluster::shiftColumn( const TQPoint& marker ) -{ - bool dummy; - return shiftColumn( marker, dummy ); -} - -void Cluster::unshiftColumn( const TQPoint& marker ) -{ - bool dummy; - unshiftColumn( marker, dummy ); -} - -void Cluster::unshiftRow( const TQPoint& marker ) -{ - bool dummy; - unshiftRow( marker, dummy ); -} - -void Cluster::setAutoDelete( bool b ) -{ - m_autoDelete = b; -} - -bool Cluster::autoDelete() const -{ - return m_autoDelete; -} - -Cell* Cluster::firstCell() const -{ - return m_first; -} - -bool Cluster::shiftRow( const TQPoint& marker, bool& work ) -{ - work = false; - - if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) - { - kdDebug(36001) << "Cluster::shiftRow: invalid column or row value (col: " - << marker.x() << " | row: " << marker.y() << ")" << endl; - return false; - } - - int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; - int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; - int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; - int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; - - // Is there a cell at the bottom most position ? - // In this case the shift is impossible. - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ]; - if ( cl && cl[ dy * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] ) - return false; - - bool a = autoDelete(); - setAutoDelete( false ); - - // Move cells in this row one down. - for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) - { - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ]; - if ( cl ) - { - work = true; - int left = 0; - if ( i == cx ) - left = dx; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) - right = KSPREAD_CLUSTER_LEVEL2 - 2; - for( int k = right; k >= left; --k ) - { - Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ]; - if ( c ) - { - remove( c->column(), c->row() ); - c->move( c->column() + 1, c->row() ); - insert( c, c->column(), c->row() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -bool Cluster::shiftColumn( const TQPoint& marker, bool& work ) -{ - work = false; - - if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) - { - kdDebug(36001) << "Cluster::shiftColumn: invalid column or row value (col: " - << marker.x() << " | row: " << marker.y() << ")" << endl; - return false; - } - - int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; - int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; - int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; - int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; - - // Is there a cell at the right most position ? - // In this case the shift is impossible. - Cell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + cx ]; - if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + dx ] ) - return false; - - bool a = autoDelete(); - setAutoDelete( false ); - - // Move cells in this column one right. - for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cy ; --i ) - { - Cell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( cl ) - { - work = true; - - int top = 0; - if ( i == cy ) - top = dy; - int bottom = KSPREAD_CLUSTER_LEVEL2 - 1; - if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) - bottom = KSPREAD_CLUSTER_LEVEL2 - 2; - for( int k = bottom; k >= top; --k ) - { - Cell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ]; - if ( c ) - { - remove( c->column(), c->row() ); - c->move( c->column(), c->row() + 1 ); - insert( c, c->column(), c->row() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -bool Cluster::insertColumn( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "Cluster::insertColumn: invalid column value (col: " - << col << ")" << endl; - return false; - } - - // Is there a cell at the right most position ? - // In this case the shift is impossible. - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - Cell** cl = m_cluster[ t1 * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ]; - if ( cl ) - for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - if ( cl[ t2 * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] ) - return false; - } - - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - bool work = true; - for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - shiftRow( TQPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work ); - } - - return true; -} - -bool Cluster::insertRow( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "Cluster::insertRow: invalid row value (row: " - << row << ")" << endl; - return false; - } - - // Is there a cell at the bottom most position ? - // In this case the shift is impossible. - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - Cell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + t1 ]; - if ( cl ) - for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - if ( cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + t2 ] ) - return false; - } - - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - bool work = true; - for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - shiftColumn( TQPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work ); - } - - return true; -} - -void Cluster::unshiftColumn( const TQPoint& marker, bool& work ) -{ - work = false; - - if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) - { - kdDebug(36001) << "Cluster::unshiftColumn: invalid column or row value (col: " - << marker.x() << " | row: " << marker.y() << ")" << endl; - return; - } - - int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; - int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; - int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; - int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; - - bool a = autoDelete(); - setAutoDelete( false ); - - // Move cells in this column one column to the left. - for( int i = cy; i < KSPREAD_CLUSTER_LEVEL1; ++i ) - { - Cell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( cl ) - { - work = true; - - int top = 0; - if ( i == cy ) - top = dy + 1; - int bottom = KSPREAD_CLUSTER_LEVEL2 - 1; - for( int k = top; k <= bottom; ++k ) - { - Cell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ]; - if ( c ) - { - remove( c->column(), c->row() ); - c->move( c->column(), c->row() - 1 ); - insert( c, c->column(), c->row() ); - } - } - } - } - - setAutoDelete( a ); -} - -void Cluster::unshiftRow( const TQPoint& marker, bool& work ) -{ - work = false; - - if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) - { - kdDebug(36001) << "Cluster::unshiftRow: invalid column or row value (col: " - << marker.x() << " | row: " << marker.y() << ")" << endl; - return; - } - - int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; - int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; - int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; - int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; - - bool a = autoDelete(); - setAutoDelete( false ); - - // Move cells in this row one row up. - for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) - { - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ]; - if ( cl ) - { - work = true; - - int left = 0; - if ( i == cx ) - left = dx + 1; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - for( int k = left; k <= right; ++k ) - { - Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ]; - if ( c ) - { - remove( c->column(), c->row() ); - c->move( c->column() - 1, c->row() ); - insert( c, c->column(), c->row() ); - } - } - } - } - - setAutoDelete( a ); -} - -void Cluster::removeColumn( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "Cluster::removeColumn: invalid column value (col: " - << col << ")" << endl; - return; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - for( int y1 = 0; y1 < KSPREAD_CLUSTER_LEVEL1; ++y1 ) - { - Cell** cl = m_cluster[ y1 * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( cl ) - for( int y2 = 0; y2 < KSPREAD_CLUSTER_LEVEL2; ++y2 ) - if ( cl[ y2 * KSPREAD_CLUSTER_LEVEL2 + dx ] ) - remove( col, y1 * KSPREAD_CLUSTER_LEVEL1 + y2 ); - } - - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - bool work = true; - for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - unshiftRow( TQPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work ); - } -} - -void Cluster::removeRow( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "Cluster::removeRow: invalid row value (row: " - << row << ")" << endl; - return; - } - - int cy = row / KSPREAD_CLUSTER_LEVEL2; - int dy = row % KSPREAD_CLUSTER_LEVEL2; - - for( int x1 = 0; x1 < KSPREAD_CLUSTER_LEVEL1; ++x1 ) - { - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + x1 ]; - if ( cl ) - for( int x2 = 0; x2 < KSPREAD_CLUSTER_LEVEL2; ++x2 ) - if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + x2 ] ) - remove( x1 * KSPREAD_CLUSTER_LEVEL2 + x2, row ); - } - - for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) - { - bool work = true; - for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) - unshiftColumn( TQPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work ); - } -} - -void Cluster::clearColumn( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "Cluster::clearColumn: invalid column value (col: " - << col << ")" << endl; - return; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - for( int cy = 0; cy < KSPREAD_CLUSTER_LEVEL1; ++cy ) - { - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; - if ( cl ) - for( int dy = 0; dy < KSPREAD_CLUSTER_LEVEL2; ++dy ) - if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) - { - int row = cy * KSPREAD_CLUSTER_LEVEL2 + dy ; - remove( col, row ); - } - } -} - -void Cluster::clearRow( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "Cluster::clearRow: invalid row value (row: " - << row << ")" << endl; - return; - } - - int cy = row / KSPREAD_CLUSTER_LEVEL2; - int dy = row % KSPREAD_CLUSTER_LEVEL2; - - for( int cx = 0; cx < KSPREAD_CLUSTER_LEVEL1; ++cx ) - { - Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL2 + cx ]; - if ( cl ) - for( int dx = 0; dx < KSPREAD_CLUSTER_LEVEL2; ++dx ) - if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) - { - int column = cx * KSPREAD_CLUSTER_LEVEL2 + dx ; - remove( column, row ); - } - } -} - -Value Cluster::valueRange (int col1, int row1, - int col2, int row2) const -{ - Value empty; - - //swap first/second values if needed - if (col1 > col2) - { - int p = col1; col1 = col2; col2 = p; - } - if (row1 > row2) - { - int p = row1; row1 = col2; row2 = p; - } - if ((row1 < 0) || (col1 < 0) || (row2 > KSPREAD_CLUSTER_MAX) || - (col2 > KSPREAD_CLUSTER_MAX)) - return empty; - - // if we are out of range occupied by cells, we return an empty - // array of the requested size - if ((row1 > m_biggestY) || (col1 > m_biggestX)) - { - int cols = col2 - col1 + 1; - int rows = row2 - row1 + 1; - Value array (cols, rows); - return array; - } - - return makeArray (col1, row1, col2, row2); -} - -Value Cluster::makeArray (int col1, int row1, - int col2, int row2) const -{ - // this generates an array of values - // TODO: make this thing faster by skipping empty regions - int cols = col2 - col1 + 1; - int rows = row2 - row1 + 1; - Value array (cols, rows); - for (int row = row1; row <= row2; ++row) - for (int col = col1; col <= col2; ++col) - { - Cell *cell = lookup (col, row); - if (cell) - { - Value val = cell->value(); - array.setElement (col-col1, row-row1, val); - } - } - - //return the result - return array; -} - -Cell* Cluster::getFirstCellColumn(int col) const -{ - Cell* cell = lookup(col, 1); - - if (cell == NULL) - { - cell = getNextCellDown(col, 1); - } - return cell; -} - -Cell* Cluster::getLastCellColumn(int col) const -{ - Cell* cell = lookup(col, KS_rowMax); - - if (cell == NULL) - { - cell = getNextCellUp(col, KS_rowMax); - } - return cell; -} - -Cell* Cluster::getFirstCellRow(int row) const -{ - Cell* cell = lookup(1, row); - - if (cell == NULL) - { - cell = getNextCellRight(1, row); - } - return cell; -} - -Cell* Cluster::getLastCellRow(int row) const -{ - Cell* cell = lookup(KS_colMax, row); - - if (cell == NULL) - { - cell = getNextCellLeft(KS_colMax, row); - } - return cell; -} - -Cell* Cluster::getNextCellUp(int col, int row) const -{ - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int cy = (row - 1) / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - int dy = (row - 1) % KSPREAD_CLUSTER_LEVEL2; - - while (cy >= 0) - { - if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) - { - while (dy >= 0) - { - - if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) - { - return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; - } - dy--; - } - } - cy--; - dy = KSPREAD_CLUSTER_LEVEL2 - 1; - } - return NULL; -} - -Cell* Cluster::getNextCellDown(int col, int row) const -{ - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int cy = (row + 1) / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - int dy = (row + 1) % KSPREAD_CLUSTER_LEVEL2; - - while (cy < KSPREAD_CLUSTER_LEVEL1) - { - if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) - { - while (dy < KSPREAD_CLUSTER_LEVEL2) - { - - if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) - { - return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; - } - dy++; - } - } - cy++; - dy = 0; - } - return NULL; -} - -Cell* Cluster::getNextCellLeft(int col, int row) const -{ - int cx = (col - 1) / KSPREAD_CLUSTER_LEVEL2; - int cy = row / KSPREAD_CLUSTER_LEVEL2; - int dx = (col - 1) % KSPREAD_CLUSTER_LEVEL2; - int dy = row % KSPREAD_CLUSTER_LEVEL2; - - while (cx >= 0) - { - if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) - { - while (dx >= 0) - { - - if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) - { - return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; - } - dx--; - } - } - cx--; - dx = KSPREAD_CLUSTER_LEVEL2 - 1; - } - return NULL; -} - -Cell* Cluster::getNextCellRight(int col, int row) const -{ - int cx = (col + 1) / KSPREAD_CLUSTER_LEVEL2; - int cy = row / KSPREAD_CLUSTER_LEVEL2; - int dx = (col + 1) % KSPREAD_CLUSTER_LEVEL2; - int dy = row % KSPREAD_CLUSTER_LEVEL2; - - while (cx < KSPREAD_CLUSTER_LEVEL1) - { - if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) - { - while (dx < KSPREAD_CLUSTER_LEVEL2) - { - - if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) - { - return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] - [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; - } - dx++; - } - } - cx++; - dx = 0; - } - return NULL; -} - -/**************************************************** - * - * ColumnCluster - * - ****************************************************/ - -ColumnCluster::ColumnCluster() - : m_first( 0 ), m_autoDelete( false ) -{ - m_cluster = (ColumnFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( ColumnFormat** ) ); - - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - m_cluster[ x ] = 0; -} - -ColumnCluster::~ColumnCluster() -{ - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - { - ColumnFormat** cl = m_cluster[ x ]; - if ( cl ) - { - free( cl ); - m_cluster[ x ] = 0; - } - } - - if ( m_autoDelete ) - { - ColumnFormat* cell = m_first; - while( cell ) - { - ColumnFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - - free( m_cluster ); -} - -ColumnFormat* ColumnCluster::lookup( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::lookup: invalid column value (col: " - << col << ")" << endl; - return 0; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - ColumnFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return 0; - - return cl[ dx ]; -} - -const ColumnFormat* ColumnCluster::lookup( int col ) const -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::lookup: invalid column value (col: " - << col << ")" << endl; - return 0; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - ColumnFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return 0; - - return cl[ dx ]; -} - -void ColumnCluster::clear() -{ - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - { - ColumnFormat** cl = m_cluster[ x ]; - if ( cl ) - { - free( cl ); - m_cluster[ x ] = 0; - } - } - - if ( m_autoDelete ) - { - ColumnFormat* cell = m_first; - while( cell ) - { - ColumnFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - m_first = 0; -} - -void ColumnCluster::insertElement( ColumnFormat* lay, int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::insertElement: invalid column value (col: " - << col << ")" << endl; - return; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - ColumnFormat** cl = m_cluster[ cx ]; - if ( !cl ) - { - cl = (ColumnFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( ColumnFormat* ) ); - m_cluster[ cx ] = cl; - - for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) - cl[ a ] = 0; - } - - if ( cl[ dx ] ) - removeElement( col ); - - cl[ dx ] = lay; - - if ( m_first ) - { - lay->setNext( m_first ); - m_first->setPrevious( lay ); - } - m_first = lay; -} - -void ColumnCluster::removeElement( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::removeElement: invalid column value (col: " - << col << ")" << endl; - return; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - ColumnFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return; - - ColumnFormat* c = cl[ dx ]; - if ( !c ) - return; - - cl[ dx ] = 0; - - if ( m_autoDelete ) - { - if ( m_first == c ) - m_first = c->next(); - delete c; - } - else - { - if ( m_first == c ) - m_first = c->next(); - if ( c->previous() ) - c->previous()->setNext( c->next() ); - if ( c->next() ) - c->next()->setPrevious( c->previous() ); - c->setNext( 0 ); - c->setPrevious( 0 ); - } -} - -bool ColumnCluster::insertColumn( int col ) -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::insertColumn: invalid column value (col: " - << col << ")" << endl; - return false; - } - - int cx = col / KSPREAD_CLUSTER_LEVEL2; - int dx = col % KSPREAD_CLUSTER_LEVEL2; - - // Is there a column layout at the right most position ? - // In this case the shift is impossible. - ColumnFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ]; - if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] ) - return false; - - bool a = autoDelete(); - setAutoDelete( false ); - - for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) - { - ColumnFormat** cl = m_cluster[ i ]; - if ( cl ) - { - int left = 0; - if ( i == cx ) - left = dx; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) - right = KSPREAD_CLUSTER_LEVEL2 - 2; - for( int k = right; k >= left; --k ) - { - ColumnFormat* c = cl[ k ]; - if ( c ) - { - removeElement( c->column() ); - c->setColumn( c->column() + 1 ); - insertElement( c, c->column() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -bool ColumnCluster::removeColumn( int column ) -{ - if ( column >= KSPREAD_CLUSTER_MAX || column < 0 ) - { - kdDebug(36001) << "ColumnCluster::removeColumn: invalid column value (col: " - << column << ")" << endl; - return false; - } - - int cx = column / KSPREAD_CLUSTER_LEVEL2; - int dx = column % KSPREAD_CLUSTER_LEVEL2; - - removeElement( column ); - - bool a = autoDelete(); - setAutoDelete( false ); - - for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) - { - ColumnFormat** cl = m_cluster[ i ]; - if ( cl ) - { - int left = 0; - if ( i == cx ) - left = dx + 1; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - for( int k = left; k <= right; ++k ) - { - ColumnFormat* c = cl[ k ]; - if ( c ) - { - removeElement( c->column() ); - c->setColumn( c->column() - 1 ); - insertElement( c, c->column() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -void ColumnCluster::setAutoDelete( bool a ) -{ - m_autoDelete = a; -} - -bool ColumnCluster::autoDelete() const -{ - return m_autoDelete; -} - -ColumnFormat* ColumnCluster::next( int col ) const -{ - if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) - { - kdDebug(36001) << "ColumnCluster::next: invalid column value (col: " - << col << ")" << endl; - return 0; - } - - int cx = (col + 1) / KSPREAD_CLUSTER_LEVEL2; - int dx = (col + 1) % KSPREAD_CLUSTER_LEVEL2; - - while ( cx < KSPREAD_CLUSTER_LEVEL1 ) - { - if ( m_cluster[ cx ] ) - { - while ( dx < KSPREAD_CLUSTER_LEVEL2 ) - { - - if ( m_cluster[ cx ][ dx ] ) - { - return m_cluster[ cx ][ dx ]; - } - ++dx; - } - } - ++cx; - dx = 0; - } - return 0; -} - -/**************************************************** - * - * RowCluster - * - ****************************************************/ - -RowCluster::RowCluster() - : m_first( 0 ), m_autoDelete( false ) -{ - m_cluster = (RowFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( RowFormat** ) ); - - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - m_cluster[ x ] = 0; -} - -RowCluster::~RowCluster() -{ - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - { - RowFormat** cl = m_cluster[ x ]; - if ( cl ) - { - free( cl ); - m_cluster[ x ] = 0; - } - } - - if ( m_autoDelete ) - { - RowFormat* cell = m_first; - while( cell ) - { - RowFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - free( m_cluster ); -} - -const RowFormat* RowCluster::lookup( int row ) const -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::lookup: invalid row value (row: " - << row << ")" << endl; - return 0; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return 0; - - return cl[ dx ]; -} - -RowFormat* RowCluster::lookup( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::lookup: invalid row value (row: " - << row << ")" << endl; - return 0; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return 0; - - return cl[ dx ]; -} - -void RowCluster::clear() -{ - for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) - { - RowFormat** cl = m_cluster[ x ]; - if ( cl ) - { - free( cl ); - m_cluster[ x ] = 0; - } - } - - if ( m_autoDelete ) - { - RowFormat* cell = m_first; - while( cell ) - { - RowFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - m_first = 0; -} - -void RowCluster::insertElement( RowFormat* lay, int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::insertElement: invalid row value (row: " - << row << ")" << endl; - return; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if ( !cl ) - { - cl = (RowFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( RowFormat* ) ); - m_cluster[ cx ] = cl; - - for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) - cl[ a ] = 0; - } - - if ( cl[ dx ] ) - removeElement( row ); - - cl[ dx ] = lay; - - if ( m_first ) - { - lay->setNext( m_first ); - m_first->setPrevious( lay ); - } - m_first = lay; -} - -void RowCluster::removeElement( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::removeElement: invalid row value (row: " - << row << ")" << endl; - return; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if ( !cl ) - return; - - RowFormat* c = cl[ dx ]; - if ( !c ) - return; - - cl[ dx ] = 0; - - if ( m_autoDelete ) - { - if ( m_first == c ) - m_first = c->next(); - delete c; - } - else - { - if ( m_first == c ) - m_first = c->next(); - if ( c->previous() ) - c->previous()->setNext( c->next() ); - if ( c->next() ) - c->next()->setPrevious( c->previous() ); - c->setNext( 0 ); - c->setPrevious( 0 ); - } -} - -bool RowCluster::insertRow( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::insertRow: invalid row value (row: " - << row << ")" << endl; - return false; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - // Is there a row layout at the bottom most position ? - // In this case the shift is impossible. - RowFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ]; - if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] ) - return false; - - bool a = autoDelete(); - setAutoDelete( false ); - - for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) - { - RowFormat** cl = m_cluster[ i ]; - if ( cl ) - { - int left = 0; - if ( i == cx ) - left = dx; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) - right = KSPREAD_CLUSTER_LEVEL2 - 2; - for( int k = right; k >= left; --k ) - { - RowFormat* c = cl[ k ]; - if ( c ) - { - removeElement( c->row() ); - c->setRow( c->row() + 1 ); - insertElement( c, c->row() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -bool RowCluster::removeRow( int row ) -{ - if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) - { - kdDebug(36001) << "RowCluster::removeRow: invalid row value (row: " - << row << ")" << endl; - return false; - } - - int cx = row / KSPREAD_CLUSTER_LEVEL2; - int dx = row % KSPREAD_CLUSTER_LEVEL2; - - removeElement( row ); - - bool a = autoDelete(); - setAutoDelete( false ); - - for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) - { - RowFormat** cl = m_cluster[ i ]; - if ( cl ) - { - int left = 0; - if ( i == cx ) - left = dx + 1; - int right = KSPREAD_CLUSTER_LEVEL2 - 1; - for( int k = left; k <= right; ++k ) - { - RowFormat* c = cl[ k ]; - if ( c ) - { - removeElement( c->row() ); - c->setRow( c->row() - 1 ); - insertElement( c, c->row() ); - } - } - } - } - - setAutoDelete( a ); - - return true; -} - -void RowCluster::setAutoDelete( bool a ) -{ - m_autoDelete = a; -} - -bool RowCluster::autoDelete() const -{ - return m_autoDelete; -} diff --git a/kspread/kspread_cluster.cpp b/kspread/kspread_cluster.cpp new file mode 100644 index 00000000..318ee758 --- /dev/null +++ b/kspread/kspread_cluster.cpp @@ -0,0 +1,1449 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Tomas Mecir + Copyright (C) 2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include + +#include "kspread_cell.h" +#include "kspread_format.h" + +#include "kspread_cluster.h" + +using namespace KSpread; + +/**************************************************** + * + * Cluster + * + ****************************************************/ + +/* Generate a matrix LEVEL1 with the size LEVEL1*LEVEL1 */ +Cluster::Cluster() + : m_first( 0 ), m_autoDelete( false ), m_biggestX(0), m_biggestY(0) +{ + m_cluster = (Cell***)malloc( KSPREAD_CLUSTER_LEVEL1 * KSPREAD_CLUSTER_LEVEL1 * sizeof( Cell** ) ); + + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) + m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; +} + +/* Delete the matrix LEVEL1 and all existing LEVEL2 matrizes */ +Cluster::~Cluster() +{ +// Can't we use clear(), to remove double code - Philipp? + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) + { + Cell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ]; + if ( cl ) + { + free( cl ); + m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; + } + } + + if ( m_autoDelete ) + { + Cell* cell = m_first; + while( cell ) + { + Cell* n = cell->nextCell(); + delete cell; + cell = n; + } + } + + free( m_cluster ); +} + +void Cluster::clear() +{ + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y ) + { + Cell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ]; + if ( cl ) + { + free( cl ); + m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0; + } + } + + if ( m_autoDelete ) + { + Cell* cell = m_first; + while( cell ) + { + Cell* n = cell->nextCell(); + delete cell; + cell = n; + } + } + + m_first = 0; + m_biggestX = m_biggestY = 0; +} + +Cell* Cluster::lookup( int x, int y ) const +{ + if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) + { + kdDebug(36001) << "Cluster::lookup: invalid column or row value (col: " + << x << " | row: " << y << ")" << endl; + return 0; + } + int cx = x / KSPREAD_CLUSTER_LEVEL2; + int cy = y / KSPREAD_CLUSTER_LEVEL2; + int dx = x % KSPREAD_CLUSTER_LEVEL2; + int dy = y % KSPREAD_CLUSTER_LEVEL2; + + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( !cl ) + return 0; + + return cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ]; +} + +/* Paste a cell in LEVEL2 (it's more paste than insert) */ +void Cluster::insert( Cell* cell, int x, int y ) +{ + if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) + { + kdDebug(36001) << "Cluster::insert: invalid column or row value (col: " + << x << " | row: " << y << ")" << endl; + return; + } + + int cx = x / KSPREAD_CLUSTER_LEVEL2; + int cy = y / KSPREAD_CLUSTER_LEVEL2; + int dx = x % KSPREAD_CLUSTER_LEVEL2; + int dy = y % KSPREAD_CLUSTER_LEVEL2; + + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( !cl ) + { + cl = (Cell**)malloc( KSPREAD_CLUSTER_LEVEL2 * KSPREAD_CLUSTER_LEVEL2 * sizeof( Cell* ) ); + m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] = cl; + + for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) + for( int b = 0; b < KSPREAD_CLUSTER_LEVEL2; ++b ) + cl[ b * KSPREAD_CLUSTER_LEVEL2 + a ] = 0; + } + + if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) + remove( x, y ); + + cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = cell; + + if ( m_first ) + { + cell->setNextCell( m_first ); + m_first->setPreviousCell( cell ); + } + m_first = cell; + + if (x > m_biggestX) m_biggestX = x; + if (y > m_biggestY) m_biggestY = y; +} + +/* Removes the cell of a matrix, the matrix itself keeps unchanged */ +void Cluster::remove( int x, int y ) +{ + if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 ) + { + kdDebug(36001) << "Cluster::remove: invalid column or row value (col: " + << x << " | row: " << y << ")" << endl; + return; + } + + int cx = x / KSPREAD_CLUSTER_LEVEL2; + int cy = y / KSPREAD_CLUSTER_LEVEL2; + int dx = x % KSPREAD_CLUSTER_LEVEL2; + int dy = y % KSPREAD_CLUSTER_LEVEL2; + + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( !cl ) + return; + + Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ]; + if ( !c ) + return; + + cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = 0; + + if ( m_autoDelete ) + { + if ( m_first == c ) + m_first = c->nextCell(); + if(c->doesMergeCells()) + { + c->mergeCells(c->column(),c->row(),0,0); + } + delete c; + } + else + { + if ( m_first == c ) + m_first = c->nextCell(); + if ( c->previousCell() ) + c->previousCell()->setNextCell( c->nextCell() ); + if ( c->nextCell() ) + c->nextCell()->setPreviousCell( c->previousCell() ); + c->setNextCell( 0 ); + c->setPreviousCell( 0 ); + } +} + +bool Cluster::shiftRow( const TQPoint& marker ) +{ + bool dummy; + return shiftRow( marker, dummy ); +} + +bool Cluster::shiftColumn( const TQPoint& marker ) +{ + bool dummy; + return shiftColumn( marker, dummy ); +} + +void Cluster::unshiftColumn( const TQPoint& marker ) +{ + bool dummy; + unshiftColumn( marker, dummy ); +} + +void Cluster::unshiftRow( const TQPoint& marker ) +{ + bool dummy; + unshiftRow( marker, dummy ); +} + +void Cluster::setAutoDelete( bool b ) +{ + m_autoDelete = b; +} + +bool Cluster::autoDelete() const +{ + return m_autoDelete; +} + +Cell* Cluster::firstCell() const +{ + return m_first; +} + +bool Cluster::shiftRow( const TQPoint& marker, bool& work ) +{ + work = false; + + if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || + marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) + { + kdDebug(36001) << "Cluster::shiftRow: invalid column or row value (col: " + << marker.x() << " | row: " << marker.y() << ")" << endl; + return false; + } + + int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; + int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; + int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; + int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; + + // Is there a cell at the bottom most position ? + // In this case the shift is impossible. + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ]; + if ( cl && cl[ dy * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] ) + return false; + + bool a = autoDelete(); + setAutoDelete( false ); + + // Move cells in this row one down. + for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) + { + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ]; + if ( cl ) + { + work = true; + int left = 0; + if ( i == cx ) + left = dx; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) + right = KSPREAD_CLUSTER_LEVEL2 - 2; + for( int k = right; k >= left; --k ) + { + Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ]; + if ( c ) + { + remove( c->column(), c->row() ); + c->move( c->column() + 1, c->row() ); + insert( c, c->column(), c->row() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +bool Cluster::shiftColumn( const TQPoint& marker, bool& work ) +{ + work = false; + + if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || + marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) + { + kdDebug(36001) << "Cluster::shiftColumn: invalid column or row value (col: " + << marker.x() << " | row: " << marker.y() << ")" << endl; + return false; + } + + int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; + int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; + int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; + int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; + + // Is there a cell at the right most position ? + // In this case the shift is impossible. + Cell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + cx ]; + if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + dx ] ) + return false; + + bool a = autoDelete(); + setAutoDelete( false ); + + // Move cells in this column one right. + for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cy ; --i ) + { + Cell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( cl ) + { + work = true; + + int top = 0; + if ( i == cy ) + top = dy; + int bottom = KSPREAD_CLUSTER_LEVEL2 - 1; + if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) + bottom = KSPREAD_CLUSTER_LEVEL2 - 2; + for( int k = bottom; k >= top; --k ) + { + Cell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ]; + if ( c ) + { + remove( c->column(), c->row() ); + c->move( c->column(), c->row() + 1 ); + insert( c, c->column(), c->row() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +bool Cluster::insertColumn( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "Cluster::insertColumn: invalid column value (col: " + << col << ")" << endl; + return false; + } + + // Is there a cell at the right most position ? + // In this case the shift is impossible. + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + Cell** cl = m_cluster[ t1 * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ]; + if ( cl ) + for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + if ( cl[ t2 * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] ) + return false; + } + + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + bool work = true; + for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + shiftRow( TQPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work ); + } + + return true; +} + +bool Cluster::insertRow( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "Cluster::insertRow: invalid row value (row: " + << row << ")" << endl; + return false; + } + + // Is there a cell at the bottom most position ? + // In this case the shift is impossible. + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + Cell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + t1 ]; + if ( cl ) + for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + if ( cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + t2 ] ) + return false; + } + + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + bool work = true; + for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + shiftColumn( TQPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work ); + } + + return true; +} + +void Cluster::unshiftColumn( const TQPoint& marker, bool& work ) +{ + work = false; + + if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || + marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) + { + kdDebug(36001) << "Cluster::unshiftColumn: invalid column or row value (col: " + << marker.x() << " | row: " << marker.y() << ")" << endl; + return; + } + + int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; + int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; + int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; + int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; + + bool a = autoDelete(); + setAutoDelete( false ); + + // Move cells in this column one column to the left. + for( int i = cy; i < KSPREAD_CLUSTER_LEVEL1; ++i ) + { + Cell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( cl ) + { + work = true; + + int top = 0; + if ( i == cy ) + top = dy + 1; + int bottom = KSPREAD_CLUSTER_LEVEL2 - 1; + for( int k = top; k <= bottom; ++k ) + { + Cell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ]; + if ( c ) + { + remove( c->column(), c->row() ); + c->move( c->column(), c->row() - 1 ); + insert( c, c->column(), c->row() ); + } + } + } + } + + setAutoDelete( a ); +} + +void Cluster::unshiftRow( const TQPoint& marker, bool& work ) +{ + work = false; + + if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 || + marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 ) + { + kdDebug(36001) << "Cluster::unshiftRow: invalid column or row value (col: " + << marker.x() << " | row: " << marker.y() << ")" << endl; + return; + } + + int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2; + int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2; + int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2; + int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2; + + bool a = autoDelete(); + setAutoDelete( false ); + + // Move cells in this row one row up. + for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) + { + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ]; + if ( cl ) + { + work = true; + + int left = 0; + if ( i == cx ) + left = dx + 1; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + for( int k = left; k <= right; ++k ) + { + Cell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ]; + if ( c ) + { + remove( c->column(), c->row() ); + c->move( c->column() - 1, c->row() ); + insert( c, c->column(), c->row() ); + } + } + } + } + + setAutoDelete( a ); +} + +void Cluster::removeColumn( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "Cluster::removeColumn: invalid column value (col: " + << col << ")" << endl; + return; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + for( int y1 = 0; y1 < KSPREAD_CLUSTER_LEVEL1; ++y1 ) + { + Cell** cl = m_cluster[ y1 * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( cl ) + for( int y2 = 0; y2 < KSPREAD_CLUSTER_LEVEL2; ++y2 ) + if ( cl[ y2 * KSPREAD_CLUSTER_LEVEL2 + dx ] ) + remove( col, y1 * KSPREAD_CLUSTER_LEVEL1 + y2 ); + } + + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + bool work = true; + for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + unshiftRow( TQPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work ); + } +} + +void Cluster::removeRow( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "Cluster::removeRow: invalid row value (row: " + << row << ")" << endl; + return; + } + + int cy = row / KSPREAD_CLUSTER_LEVEL2; + int dy = row % KSPREAD_CLUSTER_LEVEL2; + + for( int x1 = 0; x1 < KSPREAD_CLUSTER_LEVEL1; ++x1 ) + { + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + x1 ]; + if ( cl ) + for( int x2 = 0; x2 < KSPREAD_CLUSTER_LEVEL2; ++x2 ) + if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + x2 ] ) + remove( x1 * KSPREAD_CLUSTER_LEVEL2 + x2, row ); + } + + for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 ) + { + bool work = true; + for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 ) + unshiftColumn( TQPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work ); + } +} + +void Cluster::clearColumn( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "Cluster::clearColumn: invalid column value (col: " + << col << ")" << endl; + return; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + for( int cy = 0; cy < KSPREAD_CLUSTER_LEVEL1; ++cy ) + { + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ]; + if ( cl ) + for( int dy = 0; dy < KSPREAD_CLUSTER_LEVEL2; ++dy ) + if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) + { + int row = cy * KSPREAD_CLUSTER_LEVEL2 + dy ; + remove( col, row ); + } + } +} + +void Cluster::clearRow( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "Cluster::clearRow: invalid row value (row: " + << row << ")" << endl; + return; + } + + int cy = row / KSPREAD_CLUSTER_LEVEL2; + int dy = row % KSPREAD_CLUSTER_LEVEL2; + + for( int cx = 0; cx < KSPREAD_CLUSTER_LEVEL1; ++cx ) + { + Cell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL2 + cx ]; + if ( cl ) + for( int dx = 0; dx < KSPREAD_CLUSTER_LEVEL2; ++dx ) + if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] ) + { + int column = cx * KSPREAD_CLUSTER_LEVEL2 + dx ; + remove( column, row ); + } + } +} + +Value Cluster::valueRange (int col1, int row1, + int col2, int row2) const +{ + Value empty; + + //swap first/second values if needed + if (col1 > col2) + { + int p = col1; col1 = col2; col2 = p; + } + if (row1 > row2) + { + int p = row1; row1 = col2; row2 = p; + } + if ((row1 < 0) || (col1 < 0) || (row2 > KSPREAD_CLUSTER_MAX) || + (col2 > KSPREAD_CLUSTER_MAX)) + return empty; + + // if we are out of range occupied by cells, we return an empty + // array of the requested size + if ((row1 > m_biggestY) || (col1 > m_biggestX)) + { + int cols = col2 - col1 + 1; + int rows = row2 - row1 + 1; + Value array (cols, rows); + return array; + } + + return makeArray (col1, row1, col2, row2); +} + +Value Cluster::makeArray (int col1, int row1, + int col2, int row2) const +{ + // this generates an array of values + // TODO: make this thing faster by skipping empty regions + int cols = col2 - col1 + 1; + int rows = row2 - row1 + 1; + Value array (cols, rows); + for (int row = row1; row <= row2; ++row) + for (int col = col1; col <= col2; ++col) + { + Cell *cell = lookup (col, row); + if (cell) + { + Value val = cell->value(); + array.setElement (col-col1, row-row1, val); + } + } + + //return the result + return array; +} + +Cell* Cluster::getFirstCellColumn(int col) const +{ + Cell* cell = lookup(col, 1); + + if (cell == NULL) + { + cell = getNextCellDown(col, 1); + } + return cell; +} + +Cell* Cluster::getLastCellColumn(int col) const +{ + Cell* cell = lookup(col, KS_rowMax); + + if (cell == NULL) + { + cell = getNextCellUp(col, KS_rowMax); + } + return cell; +} + +Cell* Cluster::getFirstCellRow(int row) const +{ + Cell* cell = lookup(1, row); + + if (cell == NULL) + { + cell = getNextCellRight(1, row); + } + return cell; +} + +Cell* Cluster::getLastCellRow(int row) const +{ + Cell* cell = lookup(KS_colMax, row); + + if (cell == NULL) + { + cell = getNextCellLeft(KS_colMax, row); + } + return cell; +} + +Cell* Cluster::getNextCellUp(int col, int row) const +{ + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int cy = (row - 1) / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + int dy = (row - 1) % KSPREAD_CLUSTER_LEVEL2; + + while (cy >= 0) + { + if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) + { + while (dy >= 0) + { + + if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) + { + return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; + } + dy--; + } + } + cy--; + dy = KSPREAD_CLUSTER_LEVEL2 - 1; + } + return NULL; +} + +Cell* Cluster::getNextCellDown(int col, int row) const +{ + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int cy = (row + 1) / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + int dy = (row + 1) % KSPREAD_CLUSTER_LEVEL2; + + while (cy < KSPREAD_CLUSTER_LEVEL1) + { + if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) + { + while (dy < KSPREAD_CLUSTER_LEVEL2) + { + + if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) + { + return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; + } + dy++; + } + } + cy++; + dy = 0; + } + return NULL; +} + +Cell* Cluster::getNextCellLeft(int col, int row) const +{ + int cx = (col - 1) / KSPREAD_CLUSTER_LEVEL2; + int cy = row / KSPREAD_CLUSTER_LEVEL2; + int dx = (col - 1) % KSPREAD_CLUSTER_LEVEL2; + int dy = row % KSPREAD_CLUSTER_LEVEL2; + + while (cx >= 0) + { + if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) + { + while (dx >= 0) + { + + if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) + { + return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; + } + dx--; + } + } + cx--; + dx = KSPREAD_CLUSTER_LEVEL2 - 1; + } + return NULL; +} + +Cell* Cluster::getNextCellRight(int col, int row) const +{ + int cx = (col + 1) / KSPREAD_CLUSTER_LEVEL2; + int cy = row / KSPREAD_CLUSTER_LEVEL2; + int dx = (col + 1) % KSPREAD_CLUSTER_LEVEL2; + int dy = row % KSPREAD_CLUSTER_LEVEL2; + + while (cx < KSPREAD_CLUSTER_LEVEL1) + { + if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL ) + { + while (dx < KSPREAD_CLUSTER_LEVEL2) + { + + if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL ) + { + return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ] + [ dy*KSPREAD_CLUSTER_LEVEL2 + dx]; + } + dx++; + } + } + cx++; + dx = 0; + } + return NULL; +} + +/**************************************************** + * + * ColumnCluster + * + ****************************************************/ + +ColumnCluster::ColumnCluster() + : m_first( 0 ), m_autoDelete( false ) +{ + m_cluster = (ColumnFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( ColumnFormat** ) ); + + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + m_cluster[ x ] = 0; +} + +ColumnCluster::~ColumnCluster() +{ + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + { + ColumnFormat** cl = m_cluster[ x ]; + if ( cl ) + { + free( cl ); + m_cluster[ x ] = 0; + } + } + + if ( m_autoDelete ) + { + ColumnFormat* cell = m_first; + while( cell ) + { + ColumnFormat* n = cell->next(); + delete cell; + cell = n; + } + } + + + free( m_cluster ); +} + +ColumnFormat* ColumnCluster::lookup( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::lookup: invalid column value (col: " + << col << ")" << endl; + return 0; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + ColumnFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return 0; + + return cl[ dx ]; +} + +const ColumnFormat* ColumnCluster::lookup( int col ) const +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::lookup: invalid column value (col: " + << col << ")" << endl; + return 0; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + ColumnFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return 0; + + return cl[ dx ]; +} + +void ColumnCluster::clear() +{ + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + { + ColumnFormat** cl = m_cluster[ x ]; + if ( cl ) + { + free( cl ); + m_cluster[ x ] = 0; + } + } + + if ( m_autoDelete ) + { + ColumnFormat* cell = m_first; + while( cell ) + { + ColumnFormat* n = cell->next(); + delete cell; + cell = n; + } + } + + m_first = 0; +} + +void ColumnCluster::insertElement( ColumnFormat* lay, int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::insertElement: invalid column value (col: " + << col << ")" << endl; + return; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + ColumnFormat** cl = m_cluster[ cx ]; + if ( !cl ) + { + cl = (ColumnFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( ColumnFormat* ) ); + m_cluster[ cx ] = cl; + + for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) + cl[ a ] = 0; + } + + if ( cl[ dx ] ) + removeElement( col ); + + cl[ dx ] = lay; + + if ( m_first ) + { + lay->setNext( m_first ); + m_first->setPrevious( lay ); + } + m_first = lay; +} + +void ColumnCluster::removeElement( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::removeElement: invalid column value (col: " + << col << ")" << endl; + return; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + ColumnFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return; + + ColumnFormat* c = cl[ dx ]; + if ( !c ) + return; + + cl[ dx ] = 0; + + if ( m_autoDelete ) + { + if ( m_first == c ) + m_first = c->next(); + delete c; + } + else + { + if ( m_first == c ) + m_first = c->next(); + if ( c->previous() ) + c->previous()->setNext( c->next() ); + if ( c->next() ) + c->next()->setPrevious( c->previous() ); + c->setNext( 0 ); + c->setPrevious( 0 ); + } +} + +bool ColumnCluster::insertColumn( int col ) +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::insertColumn: invalid column value (col: " + << col << ")" << endl; + return false; + } + + int cx = col / KSPREAD_CLUSTER_LEVEL2; + int dx = col % KSPREAD_CLUSTER_LEVEL2; + + // Is there a column layout at the right most position ? + // In this case the shift is impossible. + ColumnFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ]; + if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] ) + return false; + + bool a = autoDelete(); + setAutoDelete( false ); + + for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) + { + ColumnFormat** cl = m_cluster[ i ]; + if ( cl ) + { + int left = 0; + if ( i == cx ) + left = dx; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) + right = KSPREAD_CLUSTER_LEVEL2 - 2; + for( int k = right; k >= left; --k ) + { + ColumnFormat* c = cl[ k ]; + if ( c ) + { + removeElement( c->column() ); + c->setColumn( c->column() + 1 ); + insertElement( c, c->column() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +bool ColumnCluster::removeColumn( int column ) +{ + if ( column >= KSPREAD_CLUSTER_MAX || column < 0 ) + { + kdDebug(36001) << "ColumnCluster::removeColumn: invalid column value (col: " + << column << ")" << endl; + return false; + } + + int cx = column / KSPREAD_CLUSTER_LEVEL2; + int dx = column % KSPREAD_CLUSTER_LEVEL2; + + removeElement( column ); + + bool a = autoDelete(); + setAutoDelete( false ); + + for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) + { + ColumnFormat** cl = m_cluster[ i ]; + if ( cl ) + { + int left = 0; + if ( i == cx ) + left = dx + 1; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + for( int k = left; k <= right; ++k ) + { + ColumnFormat* c = cl[ k ]; + if ( c ) + { + removeElement( c->column() ); + c->setColumn( c->column() - 1 ); + insertElement( c, c->column() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +void ColumnCluster::setAutoDelete( bool a ) +{ + m_autoDelete = a; +} + +bool ColumnCluster::autoDelete() const +{ + return m_autoDelete; +} + +ColumnFormat* ColumnCluster::next( int col ) const +{ + if ( col >= KSPREAD_CLUSTER_MAX || col < 0 ) + { + kdDebug(36001) << "ColumnCluster::next: invalid column value (col: " + << col << ")" << endl; + return 0; + } + + int cx = (col + 1) / KSPREAD_CLUSTER_LEVEL2; + int dx = (col + 1) % KSPREAD_CLUSTER_LEVEL2; + + while ( cx < KSPREAD_CLUSTER_LEVEL1 ) + { + if ( m_cluster[ cx ] ) + { + while ( dx < KSPREAD_CLUSTER_LEVEL2 ) + { + + if ( m_cluster[ cx ][ dx ] ) + { + return m_cluster[ cx ][ dx ]; + } + ++dx; + } + } + ++cx; + dx = 0; + } + return 0; +} + +/**************************************************** + * + * RowCluster + * + ****************************************************/ + +RowCluster::RowCluster() + : m_first( 0 ), m_autoDelete( false ) +{ + m_cluster = (RowFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( RowFormat** ) ); + + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + m_cluster[ x ] = 0; +} + +RowCluster::~RowCluster() +{ + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + { + RowFormat** cl = m_cluster[ x ]; + if ( cl ) + { + free( cl ); + m_cluster[ x ] = 0; + } + } + + if ( m_autoDelete ) + { + RowFormat* cell = m_first; + while( cell ) + { + RowFormat* n = cell->next(); + delete cell; + cell = n; + } + } + + free( m_cluster ); +} + +const RowFormat* RowCluster::lookup( int row ) const +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::lookup: invalid row value (row: " + << row << ")" << endl; + return 0; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + RowFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return 0; + + return cl[ dx ]; +} + +RowFormat* RowCluster::lookup( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::lookup: invalid row value (row: " + << row << ")" << endl; + return 0; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + RowFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return 0; + + return cl[ dx ]; +} + +void RowCluster::clear() +{ + for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x ) + { + RowFormat** cl = m_cluster[ x ]; + if ( cl ) + { + free( cl ); + m_cluster[ x ] = 0; + } + } + + if ( m_autoDelete ) + { + RowFormat* cell = m_first; + while( cell ) + { + RowFormat* n = cell->next(); + delete cell; + cell = n; + } + } + + m_first = 0; +} + +void RowCluster::insertElement( RowFormat* lay, int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::insertElement: invalid row value (row: " + << row << ")" << endl; + return; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + RowFormat** cl = m_cluster[ cx ]; + if ( !cl ) + { + cl = (RowFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( RowFormat* ) ); + m_cluster[ cx ] = cl; + + for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a ) + cl[ a ] = 0; + } + + if ( cl[ dx ] ) + removeElement( row ); + + cl[ dx ] = lay; + + if ( m_first ) + { + lay->setNext( m_first ); + m_first->setPrevious( lay ); + } + m_first = lay; +} + +void RowCluster::removeElement( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::removeElement: invalid row value (row: " + << row << ")" << endl; + return; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + RowFormat** cl = m_cluster[ cx ]; + if ( !cl ) + return; + + RowFormat* c = cl[ dx ]; + if ( !c ) + return; + + cl[ dx ] = 0; + + if ( m_autoDelete ) + { + if ( m_first == c ) + m_first = c->next(); + delete c; + } + else + { + if ( m_first == c ) + m_first = c->next(); + if ( c->previous() ) + c->previous()->setNext( c->next() ); + if ( c->next() ) + c->next()->setPrevious( c->previous() ); + c->setNext( 0 ); + c->setPrevious( 0 ); + } +} + +bool RowCluster::insertRow( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::insertRow: invalid row value (row: " + << row << ")" << endl; + return false; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + // Is there a row layout at the bottom most position ? + // In this case the shift is impossible. + RowFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ]; + if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] ) + return false; + + bool a = autoDelete(); + setAutoDelete( false ); + + for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i ) + { + RowFormat** cl = m_cluster[ i ]; + if ( cl ) + { + int left = 0; + if ( i == cx ) + left = dx; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 ) + right = KSPREAD_CLUSTER_LEVEL2 - 2; + for( int k = right; k >= left; --k ) + { + RowFormat* c = cl[ k ]; + if ( c ) + { + removeElement( c->row() ); + c->setRow( c->row() + 1 ); + insertElement( c, c->row() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +bool RowCluster::removeRow( int row ) +{ + if ( row >= KSPREAD_CLUSTER_MAX || row < 0 ) + { + kdDebug(36001) << "RowCluster::removeRow: invalid row value (row: " + << row << ")" << endl; + return false; + } + + int cx = row / KSPREAD_CLUSTER_LEVEL2; + int dx = row % KSPREAD_CLUSTER_LEVEL2; + + removeElement( row ); + + bool a = autoDelete(); + setAutoDelete( false ); + + for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i ) + { + RowFormat** cl = m_cluster[ i ]; + if ( cl ) + { + int left = 0; + if ( i == cx ) + left = dx + 1; + int right = KSPREAD_CLUSTER_LEVEL2 - 1; + for( int k = left; k <= right; ++k ) + { + RowFormat* c = cl[ k ]; + if ( c ) + { + removeElement( c->row() ); + c->setRow( c->row() - 1 ); + insertElement( c, c->row() ); + } + } + } + } + + setAutoDelete( a ); + + return true; +} + +void RowCluster::setAutoDelete( bool a ) +{ + m_autoDelete = a; +} + +bool RowCluster::autoDelete() const +{ + return m_autoDelete; +} diff --git a/kspread/kspread_condition.cc b/kspread/kspread_condition.cc deleted file mode 100644 index 876dfbf0..00000000 --- a/kspread/kspread_condition.cc +++ /dev/null @@ -1,670 +0,0 @@ -/* This file is part of the KDE project - Copyright 1998, 1999 Torben Weis - Copyright 1999- 2003 The KSpread Team - www.koffice.org/kspread - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include "kspread_cell.h" -#include "kspread_sheet.h" -#include "kspread_doc.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_util.h" - -#include - -#include -#include -#include -#include -#include - -#include "kspread_condition.h" - -using namespace KSpread; - -Conditional::Conditional(): - val1( 0.0 ), val2( 0.0 ), strVal1( 0 ), strVal2( 0 ), - colorcond( 0 ), fontcond( 0 ), styleName( 0 ), - style( 0 ), cond( None ) -{ -} - -Conditional::~Conditional() -{ - delete strVal1; - delete strVal2; - delete colorcond; - delete fontcond; - delete styleName; -} - -Conditional::Conditional( const Conditional& c ) -{ - operator=( c ); -} - -Conditional& Conditional::operator=( const Conditional& d ) -{ - strVal1 = d.strVal1 ? new TQString( *d.strVal1 ) : 0; - strVal2 = d.strVal2 ? new TQString( *d.strVal2 ) : 0; - styleName = d.styleName ? new TQString( *d.styleName ) : 0; - fontcond = d.fontcond ? new TQFont( *d.fontcond ) : 0; - colorcond = d.colorcond ? new TQColor( *d.colorcond ) : 0; - val1 = d.val1; - val2 = d.val2; - style = d.style; - cond = d.cond; - - return *this; -} - -bool Conditional::operator==(const Conditional& other) const -{ - if ( cond == other.cond && - val1 == other.val1 && - val2 == other.val2 && - *strVal1 == *other.strVal1 && - *strVal2 == *other.strVal2 && - *colorcond == *other.colorcond && - *fontcond == *other.fontcond && - *styleName == *other.styleName && - *style == *other.style ) - { - return true; - } - return false; -} - -Conditions::Conditions( const Cell * ownerCell ) - : m_cell( ownerCell ), m_matchedStyle( 0 ) -{ - Q_ASSERT( ownerCell != NULL ); -} - -Conditions::~Conditions() -{ - m_condList.clear(); -} - -void Conditions::checkMatches() -{ - Conditional condition; - - if ( currentCondition( condition ) ) - m_matchedStyle = condition.style; - else - m_matchedStyle = 0; -} - -bool Conditions::currentCondition( Conditional & condition ) -{ - /* for now, the first condition that is true is the one that will be used */ - - TQValueList::const_iterator it; - double value = m_cell->value().asFloat(); - TQString strVal = m_cell->value().asString(); - - - for ( it = m_condList.begin(); it != m_condList.end(); ++it ) - { - condition = *it; - -// if ( (*it).styleName ) -// kdDebug()<<"*it :"<< *( ( *it ).styleName ) <value().isNumber() ) - continue; - - switch ( condition.cond ) - { - case Conditional::Equal: - if ( condition.strVal1 ) - { - if ( strVal == *condition.strVal1 ) - return true; - } - else - if ( value - condition.val1 < DBL_EPSILON && - value - condition.val1 > (0.0 - DBL_EPSILON) ) - { - return true; - } - break; - - case Conditional::Superior: - if ( condition.strVal1 ) - { - if ( strVal > *condition.strVal1 ) - return true; - } - else - if ( value > condition.val1 ) - { - return true; - } - break; - - case Conditional::Inferior: - if ( condition.strVal1 ) - { - if ( strVal < *condition.strVal1 ) - return true; - } - else - if ( value < condition.val1 ) - { - return true; - } - break; - - case Conditional::SuperiorEqual : - if ( condition.strVal1 ) - { - if ( strVal >= *condition.strVal1 ) - return true; - } - else - if ( value >= condition.val1 ) - { - return true; - } - break; - - case Conditional::InferiorEqual : - if ( condition.strVal1 ) - { - if ( strVal <= *condition.strVal1 ) - return true; - } - else - if ( value <= condition.val1 ) - { - return true; - } - break; - - case Conditional::Between : - if ( condition.strVal1 && condition.strVal2 ) - { - if ( strVal > *condition.strVal1 && strVal < *condition.strVal2 ) - return true; - } - else - if ( ( value > TQMIN(condition.val1, condition.val2 ) ) - && ( value < TQMAX(condition.val1, condition.val2 ) ) ) - { - return true; - } - break; - - case Conditional::Different : - if ( condition.strVal1 && condition.strVal2 ) - { - if ( strVal < *condition.strVal1 || strVal > *condition.strVal2 ) - return true; - } - else - if ( ( value < TQMIN(condition.val1, condition.val2 ) ) - || ( value > TQMAX(condition.val1, condition.val2) ) ) - { - return true; - } - break; - case Conditional::DifferentTo : - if ( condition.strVal1 ) - { - if ( strVal != *condition.strVal1 ) - return true; - } - else - if ( value != condition.val1 ) - { - return true; - } - break; - - default: - break; - } - } - return false; -} - -TQValueList Conditions::conditionList() const -{ - return m_condList; -} - -void Conditions::setConditionList( const TQValueList & list ) -{ - m_condList.clear(); - - TQValueList::const_iterator it; - for ( it = list.begin(); it != list.end(); ++it ) - { - Conditional d = *it; - m_condList.append( Conditional( d ) ); - } -} - -void Conditions::saveOasisConditions( KoGenStyle ¤tCellStyle ) -{ - //todo fix me with kspread old format!!! - if ( m_condList.isEmpty() ) - return; - TQValueList::const_iterator it; - int i = 0; - for ( it = m_condList.begin(); it != m_condList.end(); ++it, ++i ) - { - Conditional condition = *it; - // - TQMap map; - map.insert( "style:condition", saveOasisConditionValue( condition ) ); - map.insert( "style:apply-style-name", *( condition.styleName ) ); - //map.insert( ""style:base-cell-address", "..." );//todo - currentCellStyle.addStyleMap( map ); - } -} - -TQString Conditions::saveOasisConditionValue( Conditional &condition) -{ - //we can also compare text value. - //todo adapt it. - TQString value; - switch( condition.cond ) - { - case Conditional::None: - break; - case Conditional::Equal: - value="cell-content()="; - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::Superior: - value="cell-content()>"; - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::Inferior: - value="cell-content()<"; - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::SuperiorEqual: - value="cell-content()>="; - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::InferiorEqual: - value="cell-content()<="; - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::Between: - value="cell-content-is-between("; - if ( condition.strVal1 ) - { - value+=*condition.strVal1; - value+=","; - if ( condition.strVal2 ) - value+=*condition.strVal2; - } - else - { - value+=TQString::number( condition.val1 ); - value+=","; - value+=TQString::number( condition.val2 ); - } - value+=")"; - break; - case Conditional::DifferentTo: - value="cell-content()!="; //FIXME not good here ! - if ( condition.strVal1 ) - value+=*condition.strVal1; - else - value+=TQString::number( condition.val1 ); - break; - case Conditional::Different: - value="cell-content-is-not-between("; - if ( condition.strVal1 ) - { - value+=*condition.strVal1; - value+=","; - if ( condition.strVal2 ) - value+=*condition.strVal2; - } - else - { - value+=TQString::number( condition.val1 ); - value+=","; - value+=TQString::number( condition.val2 ); - } - value+=")"; - break; - } - return value; -} - - -TQDomElement Conditions::saveConditions( TQDomDocument & doc ) const -{ - TQDomElement conditions = doc.createElement("condition"); - TQValueList::const_iterator it; - TQDomElement child; - int num = 0; - TQString name; - - for ( it = m_condList.begin(); it != m_condList.end(); ++it ) - { - Conditional condition = *it; - - /* the name of the element will be "condition" - * This is unimportant now but in older versions three conditions were - * hardcoded with names "first" "second" and "third" - */ - name.setNum( num ); - name.prepend( "condition" ); - - child = doc.createElement( name ); - child.setAttribute( "cond", (int) condition.cond ); - - // TODO: saving in KSpread 1.1 | KSpread 1.2 format - if ( condition.strVal1 ) - { - child.setAttribute( "strval1", *condition.strVal1 ); - if ( condition.strVal2 ) - child.setAttribute( "strval2", *condition.strVal2 ); - } - else - { - child.setAttribute( "val1", condition.val1 ); - child.setAttribute( "val2", condition.val2 ); - } - if ( condition.styleName ) - { - child.setAttribute( "style", *condition.styleName ); - } - else - { - child.setAttribute( "color", condition.colorcond->name() ); - child.appendChild( util_createElement( "font", *condition.fontcond, doc ) ); - } - - conditions.appendChild( child ); - - ++num; - } - - if ( num == 0 ) - { - /* there weren't any real conditions -- return a null dom element */ - return TQDomElement(); - } - else - { - return conditions; - } -} - -void Conditions::loadOasisConditions( const TQDomElement & element ) -{ - kdDebug(36003) << "Loading conditional styles" << endl; - TQDomNode node( element ); - StyleManager * manager = m_cell->sheet()->doc()->styleManager(); - - while ( !node.isNull() ) - { - TQDomElement elementItem = node.toElement(); - if ( elementItem.tagName()== "map" && elementItem.namespaceURI() == KoXmlNS::style ) - { - bool ok = true; - kdDebug(36003) << "\tcondition: "<< elementItem.attributeNS( KoXmlNS::style, "condition", TQString() )<style( *newCondition.styleName ); - if ( !newCondition.style ) - ok = false; - else - ok = true; - } - - if ( ok ) - m_condList.append( newCondition ); - else - kdDebug(36003) << "Error loading condition " << elementItem.nodeName()<< endl; - } - node = node.nextSibling(); - } -} - -void Conditions::loadOasisConditionValue( const TQString &styleCondition, Conditional &newCondition ) -{ - TQString val( styleCondition ); - if ( val.contains( "cell-content()" ) ) - { - val = val.remove( "cell-content()" ); - loadOasisCondition( val,newCondition ); - } - //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) - //for the moment we support just int/double value, not text/date/time :( - if ( val.contains( "cell-content-is-between(" ) ) - { - val = val.remove( "cell-content-is-between(" ); - val = val.remove( ")" ); - TQStringList listVal = TQStringList::split( "," , val ); - loadOasisValidationValue( listVal, newCondition ); - newCondition.cond = Conditional::Between; - } - if ( val.contains( "cell-content-is-not-between(" ) ) - { - val = val.remove( "cell-content-is-not-between(" ); - val = val.remove( ")" ); - TQStringList listVal = TQStringList::split( ",", val ); - loadOasisValidationValue( listVal,newCondition ); - newCondition.cond = Conditional::Different; - } - -} - - -void Conditions::loadOasisCondition( TQString &valExpression, Conditional &newCondition ) -{ - TQString value; - if (valExpression.find( "<=" )==0 ) - { - value = valExpression.remove( 0,2 ); - newCondition.cond = Conditional::InferiorEqual; - } - else if (valExpression.find( ">=" )==0 ) - { - value = valExpression.remove( 0,2 ); - newCondition.cond = Conditional::SuperiorEqual; - } - else if (valExpression.find( "!=" )==0 ) - { - //add Differentto attribute - value = valExpression.remove( 0,2 ); - newCondition.cond = Conditional::DifferentTo; - } - else if ( valExpression.find( "<" )==0 ) - { - value = valExpression.remove( 0,1 ); - newCondition.cond = Conditional::Inferior; - } - else if(valExpression.find( ">" )==0 ) - { - value = valExpression.remove( 0,1 ); - newCondition.cond = Conditional::Superior; - } - else if (valExpression.find( "=" )==0 ) - { - value = valExpression.remove( 0,1 ); - newCondition.cond = Conditional::Equal; - } - else - kdDebug()<<" I don't know how to parse it :"<sheet()->doc()->styleManager(); - - for ( int i = 0; i < (int)(nodeList.length()); ++i ) - { - newCondition.strVal1 = 0; - newCondition.strVal2 = 0; - newCondition.styleName = 0; - newCondition.fontcond = 0; - newCondition.colorcond = 0; - - TQDomElement conditionElement = nodeList.item( i ).toElement(); - - ok = conditionElement.hasAttribute( "cond" ); - - if ( ok ) - newCondition.cond = (Conditional::Type) conditionElement.attribute( "cond" ).toInt( &ok ); - else continue; - - if ( conditionElement.hasAttribute( "val1" ) ) - { - newCondition.val1 = conditionElement.attribute( "val1" ).toDouble( &ok ); - - if ( conditionElement.hasAttribute( "val2" ) ) - newCondition.val2 = conditionElement.attribute("val2").toDouble( &ok ); - } - - if ( conditionElement.hasAttribute( "strval1" ) ) - { - newCondition.strVal1 = new TQString( conditionElement.attribute( "strval1" ) ); - - if ( conditionElement.hasAttribute( "strval2" ) ) - newCondition.strVal2 = new TQString( conditionElement.attribute( "strval2" ) ); - } - - if ( conditionElement.hasAttribute( "color" ) ) - newCondition.colorcond = new TQColor( conditionElement.attribute( "color" ) ); - - TQDomElement font = conditionElement.namedItem( "font" ).toElement(); - if ( !font.isNull() ) - newCondition.fontcond = new TQFont( util_toFont( font ) ); - - if ( conditionElement.hasAttribute( "style" ) ) - { - newCondition.styleName = new TQString( conditionElement.attribute( "style" ) ); - newCondition.style = manager->style( *newCondition.styleName ); - if ( !newCondition.style ) - ok = false; - } - - if ( ok ) - { - m_condList.append( newCondition ); - } - else - { - kdDebug(36001) << "Error loading condition " << conditionElement.nodeName()<< endl; - } - } -} - -bool Conditions::operator==( const Conditions& other ) const -{ - if ( !( *m_matchedStyle == *other.m_matchedStyle ) ) - return false; - if ( m_condList.count() != other.m_condList.count() ) - return false; - TQValueList::ConstIterator end( m_condList.end() ); - for ( TQValueList::ConstIterator it( m_condList.begin() ); it != end; ++it ) - { - bool found = false; - TQValueList::ConstIterator otherEnd( other.m_condList.end() ); - for ( TQValueList::ConstIterator otherIt( other.m_condList.begin() ); otherIt != otherEnd; ++otherIt ) - { - if ( (*it) == (*otherIt) ) - found = true; - } - if ( !found ) - return false; - } - return true; -} diff --git a/kspread/kspread_condition.cpp b/kspread/kspread_condition.cpp new file mode 100644 index 00000000..876dfbf0 --- /dev/null +++ b/kspread/kspread_condition.cpp @@ -0,0 +1,670 @@ +/* This file is part of the KDE project + Copyright 1998, 1999 Torben Weis + Copyright 1999- 2003 The KSpread Team + www.koffice.org/kspread + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include "kspread_cell.h" +#include "kspread_sheet.h" +#include "kspread_doc.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_util.h" + +#include + +#include +#include +#include +#include +#include + +#include "kspread_condition.h" + +using namespace KSpread; + +Conditional::Conditional(): + val1( 0.0 ), val2( 0.0 ), strVal1( 0 ), strVal2( 0 ), + colorcond( 0 ), fontcond( 0 ), styleName( 0 ), + style( 0 ), cond( None ) +{ +} + +Conditional::~Conditional() +{ + delete strVal1; + delete strVal2; + delete colorcond; + delete fontcond; + delete styleName; +} + +Conditional::Conditional( const Conditional& c ) +{ + operator=( c ); +} + +Conditional& Conditional::operator=( const Conditional& d ) +{ + strVal1 = d.strVal1 ? new TQString( *d.strVal1 ) : 0; + strVal2 = d.strVal2 ? new TQString( *d.strVal2 ) : 0; + styleName = d.styleName ? new TQString( *d.styleName ) : 0; + fontcond = d.fontcond ? new TQFont( *d.fontcond ) : 0; + colorcond = d.colorcond ? new TQColor( *d.colorcond ) : 0; + val1 = d.val1; + val2 = d.val2; + style = d.style; + cond = d.cond; + + return *this; +} + +bool Conditional::operator==(const Conditional& other) const +{ + if ( cond == other.cond && + val1 == other.val1 && + val2 == other.val2 && + *strVal1 == *other.strVal1 && + *strVal2 == *other.strVal2 && + *colorcond == *other.colorcond && + *fontcond == *other.fontcond && + *styleName == *other.styleName && + *style == *other.style ) + { + return true; + } + return false; +} + +Conditions::Conditions( const Cell * ownerCell ) + : m_cell( ownerCell ), m_matchedStyle( 0 ) +{ + Q_ASSERT( ownerCell != NULL ); +} + +Conditions::~Conditions() +{ + m_condList.clear(); +} + +void Conditions::checkMatches() +{ + Conditional condition; + + if ( currentCondition( condition ) ) + m_matchedStyle = condition.style; + else + m_matchedStyle = 0; +} + +bool Conditions::currentCondition( Conditional & condition ) +{ + /* for now, the first condition that is true is the one that will be used */ + + TQValueList::const_iterator it; + double value = m_cell->value().asFloat(); + TQString strVal = m_cell->value().asString(); + + + for ( it = m_condList.begin(); it != m_condList.end(); ++it ) + { + condition = *it; + +// if ( (*it).styleName ) +// kdDebug()<<"*it :"<< *( ( *it ).styleName ) <value().isNumber() ) + continue; + + switch ( condition.cond ) + { + case Conditional::Equal: + if ( condition.strVal1 ) + { + if ( strVal == *condition.strVal1 ) + return true; + } + else + if ( value - condition.val1 < DBL_EPSILON && + value - condition.val1 > (0.0 - DBL_EPSILON) ) + { + return true; + } + break; + + case Conditional::Superior: + if ( condition.strVal1 ) + { + if ( strVal > *condition.strVal1 ) + return true; + } + else + if ( value > condition.val1 ) + { + return true; + } + break; + + case Conditional::Inferior: + if ( condition.strVal1 ) + { + if ( strVal < *condition.strVal1 ) + return true; + } + else + if ( value < condition.val1 ) + { + return true; + } + break; + + case Conditional::SuperiorEqual : + if ( condition.strVal1 ) + { + if ( strVal >= *condition.strVal1 ) + return true; + } + else + if ( value >= condition.val1 ) + { + return true; + } + break; + + case Conditional::InferiorEqual : + if ( condition.strVal1 ) + { + if ( strVal <= *condition.strVal1 ) + return true; + } + else + if ( value <= condition.val1 ) + { + return true; + } + break; + + case Conditional::Between : + if ( condition.strVal1 && condition.strVal2 ) + { + if ( strVal > *condition.strVal1 && strVal < *condition.strVal2 ) + return true; + } + else + if ( ( value > TQMIN(condition.val1, condition.val2 ) ) + && ( value < TQMAX(condition.val1, condition.val2 ) ) ) + { + return true; + } + break; + + case Conditional::Different : + if ( condition.strVal1 && condition.strVal2 ) + { + if ( strVal < *condition.strVal1 || strVal > *condition.strVal2 ) + return true; + } + else + if ( ( value < TQMIN(condition.val1, condition.val2 ) ) + || ( value > TQMAX(condition.val1, condition.val2) ) ) + { + return true; + } + break; + case Conditional::DifferentTo : + if ( condition.strVal1 ) + { + if ( strVal != *condition.strVal1 ) + return true; + } + else + if ( value != condition.val1 ) + { + return true; + } + break; + + default: + break; + } + } + return false; +} + +TQValueList Conditions::conditionList() const +{ + return m_condList; +} + +void Conditions::setConditionList( const TQValueList & list ) +{ + m_condList.clear(); + + TQValueList::const_iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + { + Conditional d = *it; + m_condList.append( Conditional( d ) ); + } +} + +void Conditions::saveOasisConditions( KoGenStyle ¤tCellStyle ) +{ + //todo fix me with kspread old format!!! + if ( m_condList.isEmpty() ) + return; + TQValueList::const_iterator it; + int i = 0; + for ( it = m_condList.begin(); it != m_condList.end(); ++it, ++i ) + { + Conditional condition = *it; + // + TQMap map; + map.insert( "style:condition", saveOasisConditionValue( condition ) ); + map.insert( "style:apply-style-name", *( condition.styleName ) ); + //map.insert( ""style:base-cell-address", "..." );//todo + currentCellStyle.addStyleMap( map ); + } +} + +TQString Conditions::saveOasisConditionValue( Conditional &condition) +{ + //we can also compare text value. + //todo adapt it. + TQString value; + switch( condition.cond ) + { + case Conditional::None: + break; + case Conditional::Equal: + value="cell-content()="; + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::Superior: + value="cell-content()>"; + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::Inferior: + value="cell-content()<"; + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::SuperiorEqual: + value="cell-content()>="; + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::InferiorEqual: + value="cell-content()<="; + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::Between: + value="cell-content-is-between("; + if ( condition.strVal1 ) + { + value+=*condition.strVal1; + value+=","; + if ( condition.strVal2 ) + value+=*condition.strVal2; + } + else + { + value+=TQString::number( condition.val1 ); + value+=","; + value+=TQString::number( condition.val2 ); + } + value+=")"; + break; + case Conditional::DifferentTo: + value="cell-content()!="; //FIXME not good here ! + if ( condition.strVal1 ) + value+=*condition.strVal1; + else + value+=TQString::number( condition.val1 ); + break; + case Conditional::Different: + value="cell-content-is-not-between("; + if ( condition.strVal1 ) + { + value+=*condition.strVal1; + value+=","; + if ( condition.strVal2 ) + value+=*condition.strVal2; + } + else + { + value+=TQString::number( condition.val1 ); + value+=","; + value+=TQString::number( condition.val2 ); + } + value+=")"; + break; + } + return value; +} + + +TQDomElement Conditions::saveConditions( TQDomDocument & doc ) const +{ + TQDomElement conditions = doc.createElement("condition"); + TQValueList::const_iterator it; + TQDomElement child; + int num = 0; + TQString name; + + for ( it = m_condList.begin(); it != m_condList.end(); ++it ) + { + Conditional condition = *it; + + /* the name of the element will be "condition" + * This is unimportant now but in older versions three conditions were + * hardcoded with names "first" "second" and "third" + */ + name.setNum( num ); + name.prepend( "condition" ); + + child = doc.createElement( name ); + child.setAttribute( "cond", (int) condition.cond ); + + // TODO: saving in KSpread 1.1 | KSpread 1.2 format + if ( condition.strVal1 ) + { + child.setAttribute( "strval1", *condition.strVal1 ); + if ( condition.strVal2 ) + child.setAttribute( "strval2", *condition.strVal2 ); + } + else + { + child.setAttribute( "val1", condition.val1 ); + child.setAttribute( "val2", condition.val2 ); + } + if ( condition.styleName ) + { + child.setAttribute( "style", *condition.styleName ); + } + else + { + child.setAttribute( "color", condition.colorcond->name() ); + child.appendChild( util_createElement( "font", *condition.fontcond, doc ) ); + } + + conditions.appendChild( child ); + + ++num; + } + + if ( num == 0 ) + { + /* there weren't any real conditions -- return a null dom element */ + return TQDomElement(); + } + else + { + return conditions; + } +} + +void Conditions::loadOasisConditions( const TQDomElement & element ) +{ + kdDebug(36003) << "Loading conditional styles" << endl; + TQDomNode node( element ); + StyleManager * manager = m_cell->sheet()->doc()->styleManager(); + + while ( !node.isNull() ) + { + TQDomElement elementItem = node.toElement(); + if ( elementItem.tagName()== "map" && elementItem.namespaceURI() == KoXmlNS::style ) + { + bool ok = true; + kdDebug(36003) << "\tcondition: "<< elementItem.attributeNS( KoXmlNS::style, "condition", TQString() )<style( *newCondition.styleName ); + if ( !newCondition.style ) + ok = false; + else + ok = true; + } + + if ( ok ) + m_condList.append( newCondition ); + else + kdDebug(36003) << "Error loading condition " << elementItem.nodeName()<< endl; + } + node = node.nextSibling(); + } +} + +void Conditions::loadOasisConditionValue( const TQString &styleCondition, Conditional &newCondition ) +{ + TQString val( styleCondition ); + if ( val.contains( "cell-content()" ) ) + { + val = val.remove( "cell-content()" ); + loadOasisCondition( val,newCondition ); + } + //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) + //for the moment we support just int/double value, not text/date/time :( + if ( val.contains( "cell-content-is-between(" ) ) + { + val = val.remove( "cell-content-is-between(" ); + val = val.remove( ")" ); + TQStringList listVal = TQStringList::split( "," , val ); + loadOasisValidationValue( listVal, newCondition ); + newCondition.cond = Conditional::Between; + } + if ( val.contains( "cell-content-is-not-between(" ) ) + { + val = val.remove( "cell-content-is-not-between(" ); + val = val.remove( ")" ); + TQStringList listVal = TQStringList::split( ",", val ); + loadOasisValidationValue( listVal,newCondition ); + newCondition.cond = Conditional::Different; + } + +} + + +void Conditions::loadOasisCondition( TQString &valExpression, Conditional &newCondition ) +{ + TQString value; + if (valExpression.find( "<=" )==0 ) + { + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::InferiorEqual; + } + else if (valExpression.find( ">=" )==0 ) + { + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::SuperiorEqual; + } + else if (valExpression.find( "!=" )==0 ) + { + //add Differentto attribute + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::DifferentTo; + } + else if ( valExpression.find( "<" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Inferior; + } + else if(valExpression.find( ">" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Superior; + } + else if (valExpression.find( "=" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Equal; + } + else + kdDebug()<<" I don't know how to parse it :"<sheet()->doc()->styleManager(); + + for ( int i = 0; i < (int)(nodeList.length()); ++i ) + { + newCondition.strVal1 = 0; + newCondition.strVal2 = 0; + newCondition.styleName = 0; + newCondition.fontcond = 0; + newCondition.colorcond = 0; + + TQDomElement conditionElement = nodeList.item( i ).toElement(); + + ok = conditionElement.hasAttribute( "cond" ); + + if ( ok ) + newCondition.cond = (Conditional::Type) conditionElement.attribute( "cond" ).toInt( &ok ); + else continue; + + if ( conditionElement.hasAttribute( "val1" ) ) + { + newCondition.val1 = conditionElement.attribute( "val1" ).toDouble( &ok ); + + if ( conditionElement.hasAttribute( "val2" ) ) + newCondition.val2 = conditionElement.attribute("val2").toDouble( &ok ); + } + + if ( conditionElement.hasAttribute( "strval1" ) ) + { + newCondition.strVal1 = new TQString( conditionElement.attribute( "strval1" ) ); + + if ( conditionElement.hasAttribute( "strval2" ) ) + newCondition.strVal2 = new TQString( conditionElement.attribute( "strval2" ) ); + } + + if ( conditionElement.hasAttribute( "color" ) ) + newCondition.colorcond = new TQColor( conditionElement.attribute( "color" ) ); + + TQDomElement font = conditionElement.namedItem( "font" ).toElement(); + if ( !font.isNull() ) + newCondition.fontcond = new TQFont( util_toFont( font ) ); + + if ( conditionElement.hasAttribute( "style" ) ) + { + newCondition.styleName = new TQString( conditionElement.attribute( "style" ) ); + newCondition.style = manager->style( *newCondition.styleName ); + if ( !newCondition.style ) + ok = false; + } + + if ( ok ) + { + m_condList.append( newCondition ); + } + else + { + kdDebug(36001) << "Error loading condition " << conditionElement.nodeName()<< endl; + } + } +} + +bool Conditions::operator==( const Conditions& other ) const +{ + if ( !( *m_matchedStyle == *other.m_matchedStyle ) ) + return false; + if ( m_condList.count() != other.m_condList.count() ) + return false; + TQValueList::ConstIterator end( m_condList.end() ); + for ( TQValueList::ConstIterator it( m_condList.begin() ); it != end; ++it ) + { + bool found = false; + TQValueList::ConstIterator otherEnd( other.m_condList.end() ); + for ( TQValueList::ConstIterator otherIt( other.m_condList.begin() ); otherIt != otherEnd; ++otherIt ) + { + if ( (*it) == (*otherIt) ) + found = true; + } + if ( !found ) + return false; + } + return true; +} diff --git a/kspread/kspread_doc.cc b/kspread/kspread_doc.cc deleted file mode 100644 index 7643b31d..00000000 --- a/kspread/kspread_doc.cc +++ /dev/null @@ -1,2462 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005-2006 Inge Wallin - (C) 2004 Ariya Hidayat - (C) 2002-2003 Norbert Andres - (C) 2000-2002 Laurent Montel - (C) 2002 John Dailey - (C) 2002 Phillip Mueller - (C) 2000 Werner Trobin - (C) 1999-2000 Simon Hausmann - (C) 1999 David Faure - (C) 1998-2000 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kspread_canvas.h" -#include "kspread_locale.h" -#include "kspread_map.h" -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include "kspread_style_manager.h" -#include "kspread_undo.h" -#include "kspread_util.h" -#include "kspread_view.h" - -#include "commands.h" -#include "damages.h" -#include "formula.h" -#include "functions.h" -#include "ksploadinginfo.h" -#include "selection.h" -#include "valuecalc.h" -#include "valueconverter.h" -#include "valueformatter.h" -#include "valueparser.h" - -#include "KSpreadDocIface.h" - -#include "kspread_doc.h" - -using namespace std; -using namespace KSpread; - -static const int CURRENT_SYNTAX_VERSION = 1; -// Make sure an appropriate DTD is available in www/koffice/DTD if changing this value -static const char * CURRENT_DTD_VERSION = "1.2"; - -class Doc::Private -{ -public: - - Map *map; - TDELocale *locale; - StyleManager *styleManager; - ValueParser *parser; - ValueFormatter *formatter; - ValueConverter *converter; - ValueCalc *calc; - - Sheet *activeSheet; - KSPLoadingInfo *m_loadingInfo; - static TQValueList s_docs; - static int s_docId; - - DCOPObject* dcop; - - // URL of the this part. This variable is only set if the load() function - // had been called with an URL as argument. - TQString fileURL; - - // for undo/redo - int undoLocked; - KoCommandHistory* commandHistory; - - // true if loading is in process, otherwise false. - // This flag is used to avoid updates etc. during loading. - bool isLoading; - - TQColor pageBorderColor; - - TQPtrList plugins; - - TQValueList refs; - TDECompletion listCompletion; - - int numOperations; - - TQValueList damages; - - // document properties - int syntaxVersion; - bool verticalScrollBar:1; - bool horizontalScrollBar:1; - bool columnHeader:1; - bool rowHeader:1; - TQColor gridColor; - double indentValue; - bool showStatusBar:1; - bool showTabBar:1; - bool showFormulaBar:1; - bool showError:1; - TDEGlobalSettings::Completion completionMode; - KSpread::MoveTo moveTo; - MethodOfCalc calcMethod; - bool delayCalculation:1; - KSpellConfig *spellConfig; - bool dontCheckUpperWord:1; - bool dontCheckTitleCase:1; - bool configLoadFromFile:1; - TQStringList spellListIgnoreAll; - /// list of all objects - TQPtrList m_embeddedObjects; - KoPictureCollection m_pictureCollection; - TQValueList usedPictures; - bool m_savingWholeDocument; -}; - -/***************************************************************************** - * - * Doc - * - *****************************************************************************/ - -TQValueList Doc::Private::s_docs; -int Doc::Private::s_docId = 0; - -Doc::Doc( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, bool singleViewMode ) - : KoDocument( parentWidget, widgetName, parent, name, singleViewMode ) -{ - d = new Private; - d->m_loadingInfo = 0L; - - d->map = new Map( this, "Map" ); - d->locale = new Locale; - d->styleManager = new StyleManager(); - - d->parser = new ValueParser( d->locale ); - d->converter = new ValueConverter ( d->parser ); - d->calc = new ValueCalc( d->converter ); - d->calc->setDoc (this); - d->formatter = new ValueFormatter( d->converter ); - - d->activeSheet = 0; - - d->pageBorderColor = TQt::red; - d->configLoadFromFile = false; - - TQFont f( KoGlobal::defaultFont() ); - Format::setGlobalRowHeight( f.pointSizeFloat() + 3 ); - Format::setGlobalColWidth( ( f.pointSizeFloat() + 3 ) * 5 ); - - d->plugins.setAutoDelete( false ); - - d->delayCalculation = false; - - documents().append( this ); - - setInstance( Factory::global(), false ); - setTemplateType( "kspread_template" ); - - d->dcop = 0; - d->isLoading = false; - d->numOperations = 1; // don't start repainting before the GUI is done... - - d->undoLocked = 0; - d->commandHistory = new KoCommandHistory( actionCollection() ); - connect( d->commandHistory, TQT_SIGNAL( commandExecuted() ), TQT_SLOT( commandExecuted() ) ); - connect( d->commandHistory, TQT_SIGNAL( documentRestored() ), TQT_SLOT( documentRestored() ) ); - - - // Make us scripsheet if the document has a name - // Set a name if there is no name specified - if ( !name ) - { - TQString tmp( "Document%1" ); - tmp = tmp.arg( d->s_docId++ ); - setName( tmp.local8Bit());//tmp.latin1() ); - dcopObject(); - } - else - dcopObject(); - - // default document properties - d->syntaxVersion = CURRENT_SYNTAX_VERSION; - d->verticalScrollBar = true; - d->horizontalScrollBar = true; - d->columnHeader = true; - d->rowHeader = true; - d->gridColor = TQt::lightGray; - d->indentValue = 10.0; - d->showStatusBar = true; - d->showFormulaBar = true; - d->showTabBar = true; - d->showError = false; - d->calcMethod = SumOfNumber; - d->moveTo = KSpread::Bottom; - d->completionMode = TDEGlobalSettings::CompletionAuto; - d->spellConfig = 0; - d->dontCheckUpperWord = false; - d->dontCheckTitleCase = false; -} - -Doc::~Doc() -{ - //don't save config when kword is embedded into konqueror - if(isReadWrite()) - saveConfig(); - - delete d->dcop; - d->s_docs.remove( this ); - - kdDebug(36001) << "alive 1" << endl; - - delete d->commandHistory; - - delete d->spellConfig; - - delete d->locale; - delete d->map; - delete d->styleManager; - delete d->parser; - delete d->formatter; - delete d->converter; - delete d->calc; - - delete d; -} - -TQValueList Doc::documents() -{ - return Private::s_docs; -} - -bool Doc::initDoc(InitDocFlags flags, TQWidget* parentWidget) -{ - // ElapsedTime et( " initDoc " ); - - TQString f; - - if (flags==KoDocument::InitDocEmpty) - { - TDEConfig *config = Factory::global()->config(); - int _page=1; - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - _page=config->readNumEntry( "NbPage",1 ) ; - } - - for( int i=0; i<_page; i++ ) - map()->addNewSheet(); - - resetURL(); - setEmpty(); - initConfig(); - styleManager()->createBuiltinStyles(); - - return true; - } - - KoTemplateChooseDia::ReturnType ret; - KoTemplateChooseDia::DialogType dlgtype; - if (flags != KoDocument::InitDocFileNew ) - dlgtype = KoTemplateChooseDia::Everything; - else - dlgtype = KoTemplateChooseDia::OnlyTemplates; - - ret = KoTemplateChooseDia::choose( Factory::global(), f, - dlgtype, "kspread_template", parentWidget ); - - if ( ret == KoTemplateChooseDia::File ) - { - KURL url( f ); - - bool ok=openURL(url); - - while (KoDocument::isLoading()) - kapp->processEvents(); - - return ok; - - - } - - if ( ret == KoTemplateChooseDia::Empty ) - { - TDEConfig *config = Factory::global()->config(); - int _page=1; - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - _page=config->readNumEntry( "NbPage",1 ) ; - } - - for( int i=0; i<_page; i++ ) - map()->addNewSheet (); - - resetURL(); - setEmpty(); - initConfig(); - styleManager()->createBuiltinStyles(); - return true; - } - - if ( ret == KoTemplateChooseDia::Template ) - { - resetURL(); - d->m_loadingInfo = new KSPLoadingInfo; - d->m_loadingInfo->setLoadTemplate( true ); - bool ok = loadNativeFormat( f ); - if ( !ok ) - { - showLoadingErrorDialog(); - deleteLoadingInfo(); - } - setEmpty(); - initConfig(); - return ok; - } - - return false; -} - -void Doc::openTemplate (const TQString& file) -{ - d->m_loadingInfo = new KSPLoadingInfo; - d->m_loadingInfo->setLoadTemplate( true ); - KoDocument::openTemplate( file ); - deleteLoadingInfo(); - initConfig(); -} - -void Doc::initEmpty() -{ - TDEConfig *config = Factory::global()->config(); - int _page=1; - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - _page=config->readNumEntry( "NbPage",1 ) ; - } - - for( int i=0; i<_page; i++ ) - map()->addNewSheet(); - - resetURL(); - initConfig(); - styleManager()->createBuiltinStyles(); - - KoDocument::initEmpty(); -} - -TDELocale *Doc::locale () const -{ - return d->locale; -} - -Map *Doc::map () const -{ - return d->map; -} - -StyleManager *Doc::styleManager () const -{ - return d->styleManager; -} - -ValueParser *Doc::parser () const -{ - return d->parser; -} - -ValueFormatter *Doc::formatter () const -{ - return d->formatter; -} - -ValueConverter *Doc::converter () const -{ - return d->converter; -} - -ValueCalc *Doc::calc () const -{ - return d->calc; -} - -void Doc::saveConfig() -{ - if ( isEmbedded() ||!isReadWrite()) - return; - TDEConfig *config = Factory::global()->config(); - config->setGroup( "Parameters" ); - config->writeEntry( "Zoom", m_zoom ); - -} - -void Doc::initConfig() -{ - TDEConfig *config = Factory::global()->config(); - - if( config->hasGroup("KSpread Page Layout" )) - { - config->setGroup( "KSpread Page Layout" ); - setUnit( (KoUnit::Unit)config->readNumEntry( "Default unit page" ,0)); - } - if( config->hasGroup("Parameters" )) - { - config->setGroup( "Parameters" ); - m_zoom = config->readNumEntry( "Zoom", 100 ); - } - else - m_zoom = 100; - - int undo=30; - if(config->hasGroup("Misc" ) ) - { - config->setGroup( "Misc" ); - undo=config->readNumEntry("UndoRedo",-1); - } - if(undo!=-1) - setUndoRedoLimit(undo); - - setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); -} - -int Doc::syntaxVersion() const -{ - return d->syntaxVersion; -} - -bool Doc::isLoading() const -{ - return d->isLoading || KoDocument::isLoading(); -} - -void Doc::doNotPaint(bool status) -{ - d->isLoading = status; -} - - -TQColor Doc::pageBorderColor() const -{ - return d->pageBorderColor; -} - -void Doc::changePageBorderColor( const TQColor & _color) -{ - d->pageBorderColor = _color; -} - -const TQValueList &Doc::listArea() -{ - return d->refs; -} - -TDECompletion& Doc::completion() -{ - return d->listCompletion; -} - -KoView* Doc::createViewInstance( TQWidget* parent, const char* name ) -{ - if ( name == 0 ) - name = "View"; - return new View( parent, name, this ); -} - -bool Doc::saveChildren( KoStore* _store ) -{ - return map()->saveChildren( _store ); -} - -int Doc::supportedSpecialFormats() const -{ - return KoDocument::supportedSpecialFormats(); -} - -bool Doc::completeSaving( KoStore* _store ) -{ - d->m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, d->usedPictures ); - - return true; -} - - -TQDomDocument Doc::saveXML() -{ - //Terminate current cell edition, if any - TQPtrListIterator it( views() ); - - /* don't pull focus away from the editor if this is just a background - autosave */ - if (!isAutosaving()) - { - for (; it.current(); ++it ) - static_cast( it.current() )->deleteEditor( true ); - } - - TQDomDocument doc = createDomDocument( "spreadsheet", CURRENT_DTD_VERSION ); - TQDomElement spread = doc.documentElement(); - spread.setAttribute( "editor", "KSpread" ); - spread.setAttribute( "mime", "application/x-kspread" ); - spread.setAttribute( "syntaxVersion", CURRENT_SYNTAX_VERSION ); - - TQDomElement dlocale = ((Locale *)locale())->save( doc ); - spread.appendChild( dlocale ); - - if (d->refs.count() != 0 ) - { - TQDomElement areaname = saveAreaName( doc ); - spread.appendChild( areaname ); - } - - if( !d->spellListIgnoreAll.isEmpty() ) - { - TQDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" ); - spread.appendChild( spellCheckIgnore ); - for ( TQStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it ) - { - TQDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" ); - spellCheckIgnore.appendChild( spellElem ); - spellElem.setAttribute( "word", *it ); - } - } - - SavedDocParts::const_iterator iter = m_savedDocParts.begin(); - SavedDocParts::const_iterator end = m_savedDocParts.end(); - while ( iter != end ) - { - // save data we loaded in the beginning and which has no owner back to file - spread.appendChild( iter.data() ); - ++iter; - } - - TQDomElement defaults = doc.createElement( "defaults" ); - defaults.setAttribute( "row-height", Format::globalRowHeight() ); - defaults.setAttribute( "col-width", Format::globalColWidth() ); - spread.appendChild( defaults ); - - Plugin * plugin = d->plugins.first(); - for ( ; plugin != 0; plugin = d->plugins.next() ) - { - TQDomElement data( plugin->saveXML( doc ) ); - if ( !data.isNull() ) - spread.appendChild( data ); - } - - TQDomElement s = styleManager()->save( doc ); - spread.appendChild( s ); - TQDomElement e = map()->save( doc ); - spread.appendChild( e ); - - setModified( false ); - - return doc; -} - -bool Doc::loadChildren( KoStore* _store ) -{ - return map()->loadChildren( _store ); -} - -bool Doc::saveOasis( KoStore* store, KoXmlWriter* manifestWriter ) -{ - emitBeginOperation(true); - bool result=saveOasisHelper( store, manifestWriter, SaveAll ); - emitEndOperation(); - - return result; -} - -bool Doc::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag, - TQString* /*plainText*/, KoPicture* /*picture*/ ) -{ - d->m_pictureCollection.assignUniqueIds(); - //Terminate current cell edition, if any - TQPtrListIterator it2( views() ); - d->m_savingWholeDocument = saveFlag == SaveAll ? true : false; - - /* don't pull focus away from the editor if this is just a background - autosave */ - if (!isAutosaving()) - { - for (; it2.current(); ++it2 ) - static_cast( it2.current() )->deleteEditor( true ); - } - if ( !store->open( "content.xml" ) ) - return false; - - KoStoreDevice dev( store ); - KoXmlWriter* contentWriter = createOasisXmlWriter( &dev, "office:document-content" ); - KoGenStyles mainStyles;//for compile - - KTempFile contentTmpFile; - //Check that temp file was successfully created - if (contentTmpFile.status() != 0) - { - tqWarning("Creation of temporary file to store document content failed."); - return false; - } - - contentTmpFile.setAutoDelete( true ); - TQFile* tmpFile = contentTmpFile.file(); - KoXmlWriter contentTmpWriter( TQT_TQIODEVICE(tmpFile), 1 ); - - - - //todo fixme just add a element for testing saving content.xml - contentTmpWriter.startElement( "office:body" ); - contentTmpWriter.startElement( "office:spreadsheet" ); - - int indexObj = 1; - int partIndexObj = 0; - - // Saving the custom cell styles including the default cell style. - styleManager()->saveOasis( mainStyles ); - - // Saving the default column style - KoGenStyle defaultColumnStyle( Doc::STYLE_COLUMN_USER, "table-column" ); - defaultColumnStyle.addPropertyPt( "style:column-width", Format::globalColWidth() ); - defaultColumnStyle.setDefaultStyle( true ); - mainStyles.lookup( defaultColumnStyle, "Default", KoGenStyles::DontForceNumbering ); - - // Saving the default row style - KoGenStyle defaultRowStyle( Doc::STYLE_ROW_USER, "table-row" ); - defaultRowStyle.addPropertyPt( "style:row-height", Format::globalRowHeight() ); - defaultRowStyle.setDefaultStyle( true ); - mainStyles.lookup( defaultRowStyle, "Default", KoGenStyles::DontForceNumbering ); - - // Saving the map. - map()->saveOasis( contentTmpWriter, mainStyles, store, manifestWriter, indexObj, partIndexObj ); - - saveOasisAreaName( contentTmpWriter ); - contentTmpWriter.endElement(); ////office:spreadsheet - contentTmpWriter.endElement(); ////office:body - - // Done with writing out the contents to the tempfile, we can now write out the automatic styles - contentWriter->startElement( "office:automatic-styles" ); - - TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_AUTO ); - TQValueList::const_iterator it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); - } - - styles = mainStyles.styles( STYLE_PAGE ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-properties" ); - } - - styles = mainStyles.styles( STYLE_COLUMN_AUTO ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); - } - - styles = mainStyles.styles( STYLE_ROW_AUTO ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); - } - - styles = mainStyles.styles( STYLE_CELL_AUTO ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); - } - - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_NUMBER ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); - } - - //TODO FIXME !!!! - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/ ); - } - - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/ ); - } - - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_FRACTION ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); - } - - //TODO FIME !!!!! - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_PERCENTAGE ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:percentage-style", (*it).name, 0 /*TODO ????*/ ); - } - - //TODO FIME !!!!! - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_CURRENCY ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:currency-style", (*it).name, 0 /*TODO ????*/ ); - } - - styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); - } - - - contentWriter->endElement(); // office:automatic-styles - - - // And now we can copy over the contents from the tempfile to the real one - tmpFile->close(); - contentWriter->addCompleteElement( TQT_TQIODEVICE(tmpFile) ); - contentTmpFile.close(); - - - contentWriter->endElement(); // root element - contentWriter->endDocument(); - delete contentWriter; - if ( !store->close() ) - return false; - //add manifest line for content.xml - manifestWriter->addManifestEntry( "content.xml", "text/xml" ); - - //todo add manifest line for style.xml - if ( !store->open( "styles.xml" ) ) - return false; - - manifestWriter->addManifestEntry( "styles.xml", "text/xml" ); - saveOasisDocumentStyles( store, mainStyles ); - - if ( !store->close() ) // done with styles.xml - return false; - - makeUsedPixmapList(); - d->m_pictureCollection.saveOasisToStore( store, d->usedPictures, manifestWriter); - - if(!store->open("settings.xml")) - return false; - - KoXmlWriter* settingsWriter = createOasisXmlWriter(&dev, "office:document-settings"); - settingsWriter->startElement("office:settings"); - settingsWriter->startElement("config:config-item-set"); - settingsWriter->addAttribute("config:name", "view-settings"); - - KoUnit::saveOasis(settingsWriter, unit()); - - saveOasisSettings( *settingsWriter ); - - settingsWriter->endElement(); // config:config-item-set - - settingsWriter->startElement("config:config-item-set"); - settingsWriter->addAttribute("config:name", "configuration-settings"); - settingsWriter->addConfigItem("SpellCheckerIgnoreList", d->spellListIgnoreAll.join( "," ) ); - settingsWriter->endElement(); // config:config-item-set - settingsWriter->endElement(); // office:settings - settingsWriter->endElement(); // Root:element - settingsWriter->endDocument(); - delete settingsWriter; - - if(!store->close()) - return false; - - manifestWriter->addManifestEntry("settings.xml", "text/xml"); - - - if ( saveFlag == SaveSelected ) - { - TQPtrListIterator it(embeddedObjects() ); - for( ; it.current(); ++it ) - { - if ( it.current()->getType() != OBJECT_CHART && it.current()->getType() != OBJECT_KOFFICE_PART ) - continue; - KoDocumentChild *embedded = dynamic_cast(it.current() )->embeddedObject(); - //NOTE: If an application's .desktop file lies about opendocument support (ie. it indicates that it has - //a native OASIS mime type, when it doesn't, this causes a crash when trying to reload and paint - //the object, since it won't have an associated document. - if ( !embedded->saveOasis( store, manifestWriter ) ) - continue; - } - } - - - setModified( false ); - - return true; -} - -void Doc::loadOasisSettings( const TQDomDocument&settingsDoc ) -{ - KoOasisSettings settings( settingsDoc ); - KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); - if ( !viewSettings.isNull() ) - { - setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit"))); - } - map()->loadOasisSettings( settings ); - loadOasisIgnoreList( settings ); -} - -void Doc::saveOasisSettings( KoXmlWriter &settingsWriter ) -{ - settingsWriter.startElement("config:config-item-map-indexed"); - settingsWriter.addAttribute("config:name", "Views"); - settingsWriter.startElement( "config:config-item-map-entry" ); - map()->saveOasisSettings( settingsWriter ); - settingsWriter.endElement(); - settingsWriter.endElement(); -} - - -void Doc::loadOasisIgnoreList( const KoOasisSettings& settings ) -{ - KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" ); - if ( !configurationSettings.isNull() ) - { - const TQString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" ); - //kdDebug()<<" ignorelist :"<spellListIgnoreAll = TQStringList::split( ',', ignorelist ); - } -} - - -void Doc::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles ) const -{ - KoStoreDevice stylesDev( store ); - KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" ); - - stylesWriter->startElement( "office:styles" ); - TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_USER ); - TQValueList::const_iterator it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); - } - - // Writing out the common column styles. - styles = mainStyles.styles( Doc::STYLE_COLUMN_USER ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - if ( (*it).style->isDefaultStyle() ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-column-properties" ); - } - else { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); - } - } - - // Writing out the row column styles. - styles = mainStyles.styles( Doc::STYLE_ROW_USER ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - if ( (*it).style->isDefaultStyle() ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-row-properties" ); - } - else { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); - } - } - - // Writing out the common cell styles. - styles = mainStyles.styles( Doc::STYLE_CELL_USER ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - if ( (*it).style->isDefaultStyle() ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-cell-properties" ); - } - else { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); - } - } - - styles = mainStyles.styles( KoGenStyle::STYLE_HATCH ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "draw:hatch", (*it).name, "style:graphic-properties" , true, true /*add draw:name*/); - } - styles = mainStyles.styles( KoGenStyle::STYLE_GRAPHICAUTO ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" ); - } - - stylesWriter->endElement(); // office:styles - - stylesWriter->startElement( "office:automatic-styles" ); - styles = mainStyles.styles( KoGenStyle::STYLE_PAGELAYOUT ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false /*don't close*/ ); - stylesWriter->endElement(); - } - - stylesWriter->endElement(); // office:automatic-styles - //code from kword - stylesWriter->startElement( "office:master-styles" ); - - styles = mainStyles.styles( Doc::STYLE_PAGEMASTER ); - it = styles.begin(); - for ( ; it != styles.end() ; ++it ) { - (*it).style->writeStyle( stylesWriter, mainStyles, "style:master-page", (*it).name, "" ); - } - - stylesWriter->endElement(); // office:master-style - - - stylesWriter->endElement(); // root element (office:document-styles) - stylesWriter->endDocument(); - delete stylesWriter;; -} - -bool Doc::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store) -{ - if ( !d->m_loadingInfo ) - d->m_loadingInfo = new KSPLoadingInfo; - - TQTime dt; - dt.start(); - - emit sigProgress( 0 ); - d->isLoading = true; - d->spellListIgnoreAll.clear(); - - d->refs.clear(); - - TQDomElement content = doc.documentElement(); - TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) ); - if ( realBody.isNull() ) - { - setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." )); - deleteLoadingInfo(); - return false; - } - TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "spreadsheet" ); - - if ( body.isNull() ) - { - kdError(32001) << "No office:spreadsheet found!" << endl; - TQDomElement childElem; - TQString localName; - forEachElement( childElem, realBody ) { - localName = childElem.localName(); - } - if ( localName.isEmpty() ) - setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) ); - else - setErrorMessage( i18n( "This document is not a spreadsheet, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) ); - deleteLoadingInfo(); - return false; - } - - KoOasisLoadingContext context( this, oasisStyles, store ); - - //load in first - styleManager()->loadOasisStyleTemplate( oasisStyles ); - - // load default column style - const TQDomElement* defaultColumnStyle = oasisStyles.defaultStyle( "table-column" ); - if ( defaultColumnStyle ) - { -// kDebug() << "style:default-style style:family=\"table-column\"" << endl; - KoStyleStack styleStack; - styleStack.push( *defaultColumnStyle ); - styleStack.setTypeProperties( "table-column" ); - if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) ) - { - const double width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ), -1.0 ); - if ( width != -1.0 ) - { -// kDebug() << "\tstyle:column-width: " << width << endl; - Format::setGlobalColWidth( width ); - } - } - } - - // load default row style - const TQDomElement* defaultRowStyle = oasisStyles.defaultStyle( "table-row" ); - if ( defaultRowStyle ) - { -// kDebug() << "style:default-style style:family=\"table-row\"" << endl; - KoStyleStack styleStack; - styleStack.push( *defaultRowStyle ); - styleStack.setTypeProperties( "table-row" ); - if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) ) - { - const double height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ), -1.0 ); - if ( height != -1.0 ) - { -// kDebug() << "\tstyle:row-height: " << height << endl; - Format::setGlobalRowHeight( height ); - } - } - } - - // TODO check versions and mimetypes etc. - loadOasisAreaName( body ); - loadOasisCellValidation( body ); - - // all goes to workbook - if ( !map()->loadOasis( body, context ) ) - { - d->isLoading = false; - deleteLoadingInfo(); - return false; - } - - - if ( !settings.isNull() ) - { - loadOasisSettings( settings ); - } - emit sigProgress( 90 ); - initConfig(); - emit sigProgress(-1); - - //display loading time - kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; - return true; -} - -bool Doc::loadXML( TQIODevice *, const TQDomDocument& doc ) -{ - TQTime dt; - dt.start(); - - emit sigProgress( 0 ); - d->isLoading = true; - d->spellListIgnoreAll.clear(); - // - TQDomElement spread = doc.documentElement(); - - if ( spread.attribute( "mime" ) != "application/x-kspread" && spread.attribute( "mime" ) != "application/vnd.kde.kspread" ) - { - d->isLoading = false; - setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" ).arg( spread.attribute("mime") ) ); - return false; - } - - d->syntaxVersion = Doc::getAttribute( spread, "syntaxVersion", 0 ); - if ( d->syntaxVersion > CURRENT_SYNTAX_VERSION ) - { - int ret = KMessageBox::warningContinueCancel( - 0, i18n("This document was created with a newer version of KSpread (syntax version: %1)\n" - "When you open it with this version of KSpread, some information may be lost.").arg(d->syntaxVersion), - i18n("File Format Mismatch"), KStdGuiItem::cont() ); - if ( ret == KMessageBox::Cancel ) - { - setErrorMessage( "USER_CANCELED" ); - return false; - } - } - - // - TQDomElement loc = spread.namedItem( "locale" ).toElement(); - if ( !loc.isNull() ) - ((Locale *) locale())->load( loc ); - - emit sigProgress( 5 ); - - TQDomElement defaults = spread.namedItem( "defaults" ).toElement(); - if ( !defaults.isNull() ) - { - bool ok = false; - double d = defaults.attribute( "row-height" ).toDouble( &ok ); - if ( !ok ) - return false; - Format::setGlobalRowHeight( d ); - - d = defaults.attribute( "col-width" ).toDouble( &ok ); - - if ( !ok ) - return false; - - Format::setGlobalColWidth( d ); - } - - d->refs.clear(); - // - TQDomElement areaname = spread.namedItem( "areaname" ).toElement(); - if ( !areaname.isNull()) - loadAreaName(areaname); - - TQDomElement ignoreAll = spread.namedItem( "SPELLCHECKIGNORELIST").toElement(); - if ( !ignoreAll.isNull()) - { - TQDomElement spellWord=spread.namedItem("SPELLCHECKIGNORELIST").toElement(); - - spellWord=spellWord.firstChild().toElement(); - while ( !spellWord.isNull() ) - { - if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" ) - { - d->spellListIgnoreAll.append(spellWord.attribute("word")); - } - spellWord=spellWord.nextSibling().toElement(); - } - } - - emit sigProgress( 40 ); - // In case of reload (e.g. from konqueror) - map()->sheetList().clear(); // it's set to autoDelete - - TQDomElement styles = spread.namedItem( "styles" ).toElement(); - if ( !styles.isNull() ) - { - if ( !styleManager()->loadXML( styles ) ) - { - setErrorMessage( i18n( "Styles cannot be loaded." ) ); - d->isLoading = false; - return false; - } - } - - // - TQDomElement mymap = spread.namedItem( "map" ).toElement(); - if ( mymap.isNull() ) - { - setErrorMessage( i18n("Invalid document. No map tag.") ); - d->isLoading = false; - return false; - } - if ( !map()->loadXML( mymap ) ) - { - d->isLoading = false; - return false; - } - - //Backwards compatibility with older versions for paper layout - if ( d->syntaxVersion < 1 ) - { - TQDomElement paper = spread.namedItem( "paper" ).toElement(); - if ( !paper.isNull() ) - { - loadPaper( paper ); - } - } - - emit sigProgress( 85 ); - - TQDomElement element( spread.firstChild().toElement() ); - while ( !element.isNull() ) - { - TQString tagName( element.tagName() ); - - if ( tagName != "locale" && tagName != "map" && tagName != "styles" - && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname" - && tagName != "paper" ) - { - // belongs to a plugin, load it and save it for later use - m_savedDocParts[ tagName ] = element; - } - - element = element.nextSibling().toElement(); - } - - emit sigProgress( 90 ); - initConfig(); - emit sigProgress(-1); - - kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; - - emit sig_refreshView(); - - return true; -} - -void Doc::loadPaper( TQDomElement const & paper ) -{ - // - TQString format = paper.attribute( "format" ); - TQString orientation = paper.attribute( "orientation" ); - - // - TQDomElement borders = paper.namedItem( "borders" ).toElement(); - if ( !borders.isNull() ) - { - float left = borders.attribute( "left" ).toFloat(); - float right = borders.attribute( "right" ).toFloat(); - float top = borders.attribute( "top" ).toFloat(); - float bottom = borders.attribute( "bottom" ).toFloat(); - - //apply to all sheet - TQPtrListIterator it ( map()->sheetList() ); - for( ; it.current(); ++it ) - { - it.current()->print()->setPaperLayout( left, top, right, bottom, - format, orientation ); - } - } - - TQString hleft, hright, hcenter; - TQString fleft, fright, fcenter; - // - TQDomElement head = paper.namedItem( "head" ).toElement(); - if ( !head.isNull() ) - { - TQDomElement left = head.namedItem( "left" ).toElement(); - if ( !left.isNull() ) - hleft = left.text(); - TQDomElement center = head.namedItem( "center" ).toElement(); - if ( !center.isNull() ) - hcenter = center.text(); - TQDomElement right = head.namedItem( "right" ).toElement(); - if ( !right.isNull() ) - hright = right.text(); - } - // - TQDomElement foot = paper.namedItem( "foot" ).toElement(); - if ( !foot.isNull() ) - { - TQDomElement left = foot.namedItem( "left" ).toElement(); - if ( !left.isNull() ) - fleft = left.text(); - TQDomElement center = foot.namedItem( "center" ).toElement(); - if ( !center.isNull() ) - fcenter = center.text(); - TQDomElement right = foot.namedItem( "right" ).toElement(); - if ( !right.isNull() ) - fright = right.text(); - } - //The macro "" formerly was typed as "" - hleft = hleft.replace( "
", "" ); - hcenter = hcenter.replace( "
", "" ); - hright = hright.replace( "
", "" ); - fleft = fleft.replace( "
", "" ); - fcenter = fcenter.replace( "
", "" ); - fright = fright.replace( "
", "" ); - - TQPtrListIterator it ( map()->sheetList() ); - for( ; it.current(); ++it ) - { - it.current()->print()->setHeadFootLine( hleft, hcenter, hright, - fleft, fcenter, fright); - } -} - -bool Doc::completeLoading( KoStore* /* _store */ ) -{ - kdDebug(36001) << "------------------------ COMPLETING --------------------" << endl; - - d->isLoading = false; - - // map()->update(); - - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - ((View*)it.current())->initialPosition(); - - kdDebug(36001) << "------------------------ COMPLETION DONE --------------------" << endl; - - setModified( false ); - return true; -} - - -void Doc::registerPlugin( Plugin * plugin ) -{ - d->plugins.append( plugin ); -} - -void Doc::deregisterPlugin( Plugin * plugin ) -{ - d->plugins.remove( plugin ); -} - -bool Doc::docData( TQString const & xmlTag, TQDomElement & data ) -{ - SavedDocParts::iterator iter = m_savedDocParts.find( xmlTag ); - if ( iter == m_savedDocParts.end() ) - return false; - - data = iter.data(); - m_savedDocParts.erase( iter ); - - return true; -} - -void Doc::setShowVerticalScrollBar(bool _show) -{ - d->verticalScrollBar=_show; -} - -bool Doc::showVerticalScrollBar()const -{ - return d->verticalScrollBar; -} - -void Doc::setShowHorizontalScrollBar(bool _show) -{ - d->horizontalScrollBar=_show; -} - -bool Doc::showHorizontalScrollBar()const -{ - return d->horizontalScrollBar; -} - -TDEGlobalSettings::Completion Doc::completionMode( ) const -{ - return d->completionMode; -} - -void Doc::setShowColumnHeader(bool _show) -{ - d->columnHeader=_show; -} - -bool Doc::showColumnHeader() const -{ - return d->columnHeader; -} - -void Doc::setShowRowHeader(bool _show) -{ - d->rowHeader=_show; -} - -bool Doc::showRowHeader() const -{ - return d->rowHeader; -} - -void Doc::setGridColor( const TQColor& color ) -{ - d->gridColor = color; -} - -TQColor Doc::gridColor() const -{ - return d->gridColor; -} - -void Doc::setCompletionMode( TDEGlobalSettings::Completion complMode) -{ - d->completionMode= complMode; -} - -double Doc::indentValue() const -{ - return d->indentValue; -} - -void Doc::setIndentValue( double val ) -{ - d->indentValue = val; -} - -void Doc::setShowStatusBar(bool _statusBar) -{ - d->showStatusBar=_statusBar; -} - -bool Doc::showStatusBar() const -{ - return d->showStatusBar; -} - -void Doc::setShowTabBar(bool _tabbar) -{ - d->showTabBar=_tabbar; -} - -bool Doc::showTabBar()const -{ - return d->showTabBar; -} - -void Doc::setShowFormulaBar(bool _formulaBar) -{ - d->showFormulaBar=_formulaBar; -} - -bool Doc::showFormulaBar() const -{ - return d->showFormulaBar; -} - -void Doc::setShowMessageError(bool _show) -{ - d->showError=_show; -} - -bool Doc::showMessageError() const -{ - return d->showError; -} - -KSpread::MoveTo Doc::getMoveToValue() const -{ - return d->moveTo; -} - -void Doc::setMoveToValue(KSpread::MoveTo _moveTo) -{ - d->moveTo = _moveTo; -} - -void Doc::setTypeOfCalc( MethodOfCalc _calc) -{ - d->calcMethod=_calc; -} - -MethodOfCalc Doc::getTypeOfCalc() const -{ - return d->calcMethod; -} - -void Doc::setKSpellConfig(KSpellConfig _tdespell) -{ - if (d->spellConfig == 0 ) - d->spellConfig = new KSpellConfig(); - - d->spellConfig->setNoRootAffix(_tdespell.noRootAffix ()); - d->spellConfig->setRunTogether(_tdespell.runTogether ()); - d->spellConfig->setDictionary(_tdespell.dictionary ()); - d->spellConfig->setDictFromList(_tdespell.dictFromList()); - d->spellConfig->setEncoding(_tdespell.encoding()); - d->spellConfig->setClient(_tdespell.client()); -} - -KSpellConfig * Doc::getKSpellConfig() -{ - if (!d->spellConfig) - { - KSpellConfig ksconfig; - - TDEConfig *config = Factory::global()->config(); - if( config->hasGroup("KSpell kspread" ) ) - { - config->setGroup( "KSpell kspread" ); - ksconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0)); - ksconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0)); - ksconfig.setDictionary(config->readEntry ("KSpell_Dictionary", "")); - ksconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", false)); - ksconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KS_E_ASCII)); - ksconfig.setClient(config->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL)); - setKSpellConfig(ksconfig); - - setDontCheckUpperWord(config->readBoolEntry("KSpell_IgnoreUppercaseWords", false)); - setDontCheckTitleCase(config->readBoolEntry("KSpell_IgnoreTitleCaseWords", false)); - } - } - return d->spellConfig; -} - -bool Doc::dontCheckUpperWord() const -{ - return d->dontCheckUpperWord; -} - -void Doc::setDontCheckUpperWord( bool b ) -{ - d->dontCheckUpperWord = b; -} - -bool Doc::dontCheckTitleCase() const -{ - return d->dontCheckTitleCase; -} - -void Doc::setDontCheckTitleCase( bool b ) -{ - d->dontCheckTitleCase = b; -} - -TQString Doc::unitName() const -{ - return KoUnit::unitName( unit() ); -} - -void Doc::increaseNumOperation() -{ - ++d->numOperations; -} - -void Doc::decreaseNumOperation() -{ - --d->numOperations; -} - -void Doc::addIgnoreWordAllList( const TQStringList & _lst) -{ - d->spellListIgnoreAll = _lst; -} - -TQStringList Doc::spellListIgnoreAll() const -{ - return d->spellListIgnoreAll; -} - -void Doc::setZoomAndResolution( int zoom, int dpiX, int dpiY ) -{ - KoZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY ); -} - -void Doc::newZoomAndResolution( bool updateViews, bool /*forPrint*/ ) -{ -/* layout(); - updateAllFrames();*/ - if ( updateViews ) - { - emit sig_refreshView(); - } -} - -void Doc::addCommand( KCommand* command ) -{ - if (undoLocked()) return; - d->commandHistory->addCommand( command, false ); - setModified( true ); -} - -void Doc::addCommand( UndoAction* undo ) -{ - if (undoLocked()) return; - UndoWrapperCommand* command = new UndoWrapperCommand( undo ); - addCommand( command ); - setModified( true ); -} - -void Doc::undo() -{ - undoLock (); - d->commandHistory->undo(); - undoUnlock (); -} - -void Doc::redo() -{ - undoLock (); - d->commandHistory->redo(); - undoUnlock (); -} - -void Doc::commandExecuted() -{ - setModified( true ); -} - -void Doc::documentRestored() -{ - setModified( false ); -} - -void Doc::undoLock() -{ - d->undoLocked++; -} - -void Doc::undoUnlock() -{ - d->undoLocked--; -} - -bool Doc::undoLocked() const -{ - return (d->undoLocked > 0); -} - -KoCommandHistory* Doc::commandHistory() -{ - return d->commandHistory; -} - -void Doc::enableUndo( bool _b ) -{ - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - static_cast( it.current() )->enableUndo( _b ); -} - -void Doc::enableRedo( bool _b ) -{ - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - static_cast( it.current() )->enableRedo( _b ); -} - -void Doc::paintContent( TQPainter& painter, const TQRect& rect, - bool transparent, double zoomX, double /*zoomY*/ ) -{ - kdDebug(36001) << "paintContent() called on " << rect << endl; - - // ElapsedTime et( "Doc::paintContent1" ); - //kdDebug(36001) << "Doc::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl; - - // save current zoom - int oldZoom = m_zoom; - - // choose sheet: the first or the active - Sheet* sheet = 0L; - if ( !d->activeSheet ) - sheet = map()->firstSheet(); - else - sheet = d->activeSheet; - if ( !sheet ) - return; - - // only one zoom is supported - double d_zoom = 1.0; - setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() ); - if ( m_zoomedResolutionX != zoomX ) - d_zoom *= ( zoomX / m_zoomedResolutionX ); - - // KSpread support zoom, therefore no need to scale with worldMatrix - TQWMatrix matrix = painter.worldMatrix(); - matrix.setMatrix( 1, 0, 0, 1, matrix.dx(), matrix.dy() ); - TQRect prect = rect; - prect.setWidth( (int) (prect.width() * painter.worldMatrix().m11()) ); - prect.setHeight( (int) (prect.height() * painter.worldMatrix().m22()) ); - setZoomAndResolution( (int) ( d_zoom * 100 ), KoGlobal::dpiX(), KoGlobal::dpiY() ); - // paint the content, now zoom is correctly set - kdDebug(36001)<<"paintContent-------------------------------------\n"; - painter.save(); - painter.setWorldMatrix( matrix ); - paintContent( painter, prect, transparent, sheet, false ); - painter.restore(); - - // restore zoom - m_zoom = oldZoom; - setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); -} - -void Doc::paintContent( TQPainter& painter, const TQRect& rect, bool /*transparent*/, Sheet* sheet, bool drawCursor ) -{ - if ( isLoading() ) - return; - // ElapsedTime et( "Doc::paintContent2" ); - - // if ( !transparent ) - // painter.eraseRect( rect ); - - double xpos; - double ypos; - int left_col = sheet->leftColumn( unzoomItX( rect.x() ), xpos ); - int right_col = sheet->rightColumn( unzoomItX( rect.right() ) ); - int top_row = sheet->topRow( unzoomItY( rect.y() ), ypos ); - int bottom_row = sheet->bottomRow( unzoomItY( rect.bottom() ) ); - TQPen pen; - pen.setWidth( 1 ); - painter.setPen( pen ); - - /* Update the entire visible area. */ - TQValueList cellAreaList; - cellAreaList.append( TQRect( left_col, - top_row, - right_col - left_col + 1, - bottom_row - top_row + 1) ); - - paintCellRegions(painter, rect, NULL, cellAreaList, sheet, drawCursor); -} - -void Doc::paintUpdates() -{ - // ElapsedTime et( "Doc::paintUpdates" ); - - TQPtrListIterator it( views() ); - View * view = NULL; - Sheet * sheet = NULL; - - for (; it.current(); ++it ) - { - view = static_cast( it.current() ); - view->paintUpdates(); - } - - for (sheet = map()->firstSheet(); sheet != NULL; - sheet = map()->nextSheet()) - { - sheet->clearPaintDirtyData(); - } -} - -void Doc::paintCellRegions(TQPainter& painter, const TQRect &viewRect, - View* view, - TQValueList cellRegions, - const Sheet* sheet, bool /*drawCursor*/) -{ - // - // Clip away children - // - - TQRegion rgn = painter.clipRegion(); - if ( rgn.isEmpty() ) - rgn = TQRegion( TQRect( 0, 0, viewRect.width(), viewRect.height() ) ); - - TQWMatrix matrix; - if ( view ) { - matrix.scale( zoomedResolutionX(), - zoomedResolutionY() ); - matrix.translate( - view->canvasWidget()->xOffset(), - - view->canvasWidget()->yOffset() ); - } - else { - matrix = painter.worldMatrix(); - } - -// TQPtrListIterator it( children() ); -// for( ; it.current(); ++it ) { -// // if ( ((Child*)it.current())->sheet() == sheet && -// // !m_pView->hasDocumentInWindow( it.current()->document() ) ) -// if ( ((Child*)it.current())->sheet() == sheet) -// rgn -= it.current()->region( matrix ); -// } - painter.setClipRegion( rgn ); - - TQPen pen; - pen.setWidth( 1 ); - painter.setPen( pen ); - - TQRect cellRegion; - KoRect unzoomedViewRect = unzoomRect( viewRect ); - - for (unsigned int i=0; i < cellRegions.size(); i++) { - cellRegion = cellRegions[i]; - - PaintRegion(painter, unzoomedViewRect, view, cellRegion, sheet); - } -} - - -void Doc::PaintRegion(TQPainter &painter, const KoRect &viewRegion, - View* view, const TQRect &paintRegion, - const Sheet* sheet) -{ - // Paint region has cell coordinates (col,row) while viewRegion has - // world coordinates. paintRegion is the cells to update and - // viewRegion is the area actually onscreen. - - if ( paintRegion.left() <= 0 || paintRegion.top() <= 0 ) - return; - - // Get the world coordinates of the upper left corner of the - // paintRegion The view is NULL, when paintRegion is called from - // paintContent, which itself is only called, when we should paint - // the output for INACTIVE embedded view. If inactive embedded, - // then there is no view and we alwas start at top/left, so the - // offset is 0. - // - KoPoint dblCorner; - if ( view == 0L ) //Most propably we are embedded and inactive, so no offset - dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ), - sheet->dblRowPos( paintRegion.top() ) ); - else - dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ) - - view->canvasWidget()->xOffset(), - sheet->dblRowPos( paintRegion.top() ) - - view->canvasWidget()->yOffset() ); - KoPoint dblCurrentCellPos( dblCorner ); - - int regionBottom = paintRegion.bottom(); - int regionRight = paintRegion.right(); - int regionLeft = paintRegion.left(); - int regionTop = paintRegion.top(); - - TQValueList mergedCellsPainted; - for ( int y = regionTop; - y <= regionBottom && dblCurrentCellPos.y() <= viewRegion.bottom(); - ++y ) - { - const RowFormat * row_lay = sheet->rowFormat( y ); - dblCurrentCellPos.setX( dblCorner.x() ); - - for ( int x = regionLeft; - x <= regionRight && dblCurrentCellPos.x() <= viewRegion.right(); - ++x ) - { - const ColumnFormat *col_lay = sheet->columnFormat( x ); - Cell* cell = sheet->cellAt( x, y ); - - TQPoint cellRef( x, y ); - -#if 0 - bool paintBordersBottom = false; - bool paintBordersRight = false; - bool paintBordersLeft = false; - bool paintBordersTop = false; -#endif - int paintBorder = Cell::Border_None; - - TQPen rightPen( cell->effRightBorderPen( x, y ) ); - TQPen leftPen( cell->effLeftBorderPen( x, y ) ); - TQPen topPen( cell->effTopBorderPen( x, y ) ); - TQPen bottomPen( cell->effBottomBorderPen( x, y ) ); - - // Paint border if outermost cell or if the pen is more "worth" - // than the border pen of the cell on the other side of the - // border or if the cell on the other side is not painted. In - // the latter case get the pen that is of more "worth" - - // right border: - if ( x >= KS_colMax ) - //paintBordersRight = true; - paintBorder |= Cell::Border_Right; - else if ( x == regionRight ) { - paintBorder |= Cell::Border_Right; - if ( cell->effRightBorderValue( x, y ) - < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) - rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); - } - else { - paintBorder |= Cell::Border_Right; - if ( cell->effRightBorderValue( x, y ) - < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) - rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); - } - - // Similiar for other borders... - // bottom border: - if ( y >= KS_rowMax ) - paintBorder |= Cell::Border_Bottom; - else if ( y == regionBottom ) { - paintBorder |= Cell::Border_Bottom; - if ( cell->effBottomBorderValue( x, y ) - < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) - bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); - } - else { - paintBorder |= Cell::Border_Bottom; - if ( cell->effBottomBorderValue( x, y ) - < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) - bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); - } - - // left border: - if ( x == 1 ) - paintBorder |= Cell::Border_Left; - else if ( x == regionLeft ) { - paintBorder |= Cell::Border_Left; - if ( cell->effLeftBorderValue( x, y ) - < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) - leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); - } - else { - paintBorder |= Cell::Border_Left; - if ( cell->effLeftBorderValue( x, y ) - < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) - leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); - } - - // top border: - if ( y == 1 ) - paintBorder |= Cell::Border_Top; - else if ( y == regionTop ) { - paintBorder |= Cell::Border_Top; - if ( cell->effTopBorderValue( x, y ) - < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) - topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); - } - else { - paintBorder |= Cell::Border_Top; - if ( cell->effTopBorderValue( x, y ) - < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) - topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); - } - -#if 0 - cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, - paintBordersRight, paintBordersBottom, - paintBordersLeft, paintBordersTop, - rightPen, bottomPen, leftPen, topPen, - mergedCellsPainted, false ); - - Cell::BorderSides highlightBorder=Cell::Border_None; - TQPen highlightPen; -#endif - - cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, - paintBorder, - rightPen, bottomPen, leftPen, topPen, - mergedCellsPainted, false ); - - - dblCurrentCellPos.setX( dblCurrentCellPos.x() + col_lay->dblWidth() ); - } - dblCurrentCellPos.setY( dblCurrentCellPos.y() + row_lay->dblHeight() ); - } -} - - -DCOPObject* Doc::dcopObject() -{ - if ( !d->dcop ) - d->dcop = new DocIface( this ); - - return d->dcop; -} - -void Doc::addAreaName(const TQRect &_rect,const TQString & name,const TQString & sheetName) -{ - setModified( true ); - Reference tmp; - tmp.rect = _rect; - tmp.sheet_name = sheetName; - tmp.ref_name = name; - d->refs.append( tmp); - emit sig_addAreaName( name ); -} - -void Doc::removeArea( const TQString & name) -{ - TQValueList::Iterator it2; - for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) - { - if((*it2).ref_name==name) - { - d->refs.remove(it2); - emit sig_removeAreaName( name ); - return; - } - } -} - -void Doc::changeAreaSheetName(const TQString & oldName,const TQString & sheetName) -{ - TQValueList::Iterator it2; - for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) - { - if((*it2).sheet_name==oldName) - (*it2).sheet_name=sheetName; - } -} - -TQRect Doc::getRectArea(const TQString &_sheetName) -{ - TQValueList::Iterator it2; - for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) - { - if((*it2).ref_name==_sheetName) - { - return (*it2).rect; - } - } - return TQRect(-1,-1,-1,-1); -} - -TQDomElement Doc::saveAreaName( TQDomDocument& doc ) -{ - TQDomElement element = doc.createElement( "areaname" ); - TQValueList::Iterator it2; - for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) - { - TQDomElement e = doc.createElement("reference"); - TQDomElement tabname = doc.createElement( "tabname" ); - tabname.appendChild( doc.createTextNode( (*it2).sheet_name ) ); - e.appendChild( tabname ); - - TQDomElement refname = doc.createElement( "refname" ); - refname.appendChild( doc.createTextNode( (*it2).ref_name ) ); - e.appendChild( refname ); - - TQDomElement rect = doc.createElement( "rect" ); - rect.setAttribute( "left-rect", ((*it2).rect).left() ); - rect.setAttribute( "right-rect",((*it2).rect).right() ); - rect.setAttribute( "top-rect", ((*it2).rect).top() ); - rect.setAttribute( "bottom-rect", ((*it2).rect).bottom() ); - e.appendChild( rect ); - element.appendChild(e); - } - return element; -} - -void Doc::loadOasisCellValidation( const TQDomElement&body ) -{ - TQDomNode validation = KoDom::namedItemNS( body, KoXmlNS::table, "content-validations" ); - kdDebug()<<"void Doc::loadOasisCellValidation( const TQDomElement&body ) \n"; - kdDebug()<<"validation.isNull ? "<m_loadingInfo->appendValidation(element.attributeNS( KoXmlNS::table, "name", TQString() ), element ); - kdDebug()<<" validation found :"<0 ) - { - xmlWriter.startElement( "table:named-expressions" ); - TQValueList::Iterator it; - for ( it = d->refs.begin(); it != d->refs.end(); ++it ) - { - xmlWriter.startElement( "table:named-range" ); - - xmlWriter.addAttribute( "table:name", ( *it ).ref_name ); - xmlWriter.addAttribute( "table:base-cell-address", convertRefToBase( ( *it ).sheet_name, ( *it ).rect ) ); - xmlWriter.addAttribute( "table:cell-range-address", convertRefToRange( ( *it ).sheet_name, ( *it ).rect ) ); - - xmlWriter.endElement(); - } - xmlWriter.endElement(); - } -} - -void Doc::loadOasisAreaName( const TQDomElement& body ) -{ - kdDebug()<<"void Doc::loadOasisAreaName( const TQDomElement& body ) \n"; - TQDomNode namedAreas = KoDom::namedItemNS( body, KoXmlNS::table, "named-expressions" ); - if ( !namedAreas.isNull() ) - { - kdDebug()<<" area name exist \n"; - TQDomNode area = namedAreas.firstChild(); - while ( !area.isNull() ) - { - TQDomElement e = area.toElement(); - - if ( e.localName() == "named-range" ) - { - if ( !e.hasAttributeNS( KoXmlNS::table, "name" ) || !e.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) ) - { - kdDebug() << "Reading in named area failed" << endl; - area = area.nextSibling(); - continue; - } - - // TODO: what is: sheet:base-cell-address - TQString name = e.attributeNS( KoXmlNS::table, "name", TQString() ); - TQString range = e.attributeNS( KoXmlNS::table, "cell-range-address", TQString() ); - kdDebug()<<"area name : "<m_loadingInfo->addWordInAreaList( name ); - kdDebug() << "Reading in named area, name: " << name << ", area: " << range << endl; - - range = Oasis::decodeFormula( range ); - - if ( range.find( ':' ) == -1 ) - { - Point p( range ); - - int n = range.find( '!' ); - if ( n > 0 ) - range = range + ":" + range.right( range.length() - n - 1); - - kdDebug() << "=> Area: " << range << endl; - } - - if ( range.contains( '!' ) && range[0] == '$' ) - { - // cut absolute sheet indicator - range.remove( 0, 1 ); - } - - Range p( range ); - - addAreaName( p.range(), name, p.sheetName() ); - kdDebug() << "Area range: " << p.toString() << endl; - } - else if ( e.localName() == "named-expression" ) - { - kdDebug() << "Named expression found." << endl; - // TODO - } - - area = area.nextSibling(); - } - } -} - -void Doc::loadAreaName( const TQDomElement& element ) -{ - TQDomElement tmp=element.firstChild().toElement(); - for( ; !tmp.isNull(); tmp=tmp.nextSibling().toElement() ) - { - if ( tmp.tagName() == "reference" ) - { - TQString tabname; - TQString refname; - int left=0; - int right=0; - int top=0; - int bottom=0; - TQDomElement sheetName = tmp.namedItem( "tabname" ).toElement(); - if ( !sheetName.isNull() ) - { - tabname=sheetName.text(); - } - TQDomElement referenceName = tmp.namedItem( "refname" ).toElement(); - if ( !referenceName.isNull() ) - { - refname=referenceName.text(); - } - TQDomElement rect =tmp.namedItem( "rect" ).toElement(); - if (!rect.isNull()) - { - bool ok; - if ( rect.hasAttribute( "left-rect" ) ) - left=rect.attribute("left-rect").toInt( &ok ); - if ( rect.hasAttribute( "right-rect" ) ) - right=rect.attribute("right-rect").toInt( &ok ); - if ( rect.hasAttribute( "top-rect" ) ) - top=rect.attribute("top-rect").toInt( &ok ); - if ( rect.hasAttribute( "bottom-rect" ) ) - bottom=rect.attribute("bottom-rect").toInt( &ok ); - } - TQRect _rect; - _rect.setCoords(left,top,right,bottom); - addAreaName(_rect,refname,tabname); - } - } -} - -void Doc::addStringCompletion(const TQString &stringCompletion) -{ - if ( d->listCompletion.items().contains(stringCompletion) == 0 ) - d->listCompletion.addItem( stringCompletion ); -} - -void Doc::refreshInterface() -{ - emit sig_refreshView(); -} - -void Doc::refreshLocale() -{ - emit sig_refreshLocale(); -} - - -void Doc::emitBeginOperation(bool waitCursor) -{ - //If an emitBeginOperation occurs with waitCursor enabled, then the waiting cursor is set - //until all operations have been completed. - // - //The reason being that any operations started before the first one with waitCursor set - //are expected to be completed in a short time anyway. - TQCursor* activeOverride = static_cast(TQApplication::overrideCursor()); - - if (waitCursor && ( (!activeOverride) || (activeOverride->shape() != TQt::waitCursor.shape()) ) ) - { - TQApplication::setOverrideCursor(TQt::waitCursor); - } - -// /* just duplicate the current cursor on the stack, then */ -// else if (TQApplication::overrideCursor() != NULL) -// { -// TQApplication::setOverrideCursor(TQApplication::overrideCursor()->shape()); -// } - - KoDocument::emitBeginOperation(); - d->delayCalculation = true; - d->numOperations++; -} - -void Doc::emitBeginOperation(void) -{ - emitBeginOperation(true); -} - - -void Doc::emitEndOperation() -{ - d->numOperations--; - - if (d->numOperations <= 0) - { - d->numOperations = 0; - d->delayCalculation = false; - } - - KoDocument::emitEndOperation(); - - if (d->numOperations == 0) - { - TQApplication::restoreOverrideCursor(); - - /* do this after the parent class emitEndOperation because that allows updates - on the view again - */ - paintUpdates(); - } -} - -void Doc::emitEndOperation( const Region& /*region*/ ) -{ - d->numOperations--; - - if ( d->numOperations > 0 || !d->activeSheet ) - { - KoDocument::emitEndOperation(); - return; - } - - d->numOperations = 0; - d->delayCalculation = false; - - KoDocument::emitEndOperation(); - - TQApplication::restoreOverrideCursor(); - - /* do this after the parent class emitEndOperation because that allows updates - on the view again - */ - paintUpdates(); -} - -bool Doc::delayCalculation() const -{ - return d->delayCalculation; -} - -void Doc::updateBorderButton() -{ - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - static_cast( it.current() )->updateBorderButton(); -} - -void Doc::insertSheet( Sheet * sheet ) -{ - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - ((View*)it.current())->insertSheet( sheet ); -} - -void Doc::takeSheet( Sheet * sheet ) -{ - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - ((View*)it.current())->removeSheet( sheet ); -} - -void Doc::addIgnoreWordAll( const TQString & word) -{ - if( d->spellListIgnoreAll.findIndex( word )==-1) - d->spellListIgnoreAll.append( word ); -} - -void Doc::clearIgnoreWordAll( ) -{ - d->spellListIgnoreAll.clear(); -} - -void Doc::setDisplaySheet(Sheet *_sheet ) -{ - d->activeSheet = _sheet; -} - -KSPLoadingInfo * Doc::loadingInfo() const -{ - return d->m_loadingInfo; -} - -void Doc::deleteLoadingInfo() -{ - delete d->m_loadingInfo; - d->m_loadingInfo = 0; -} - -Sheet * Doc::displaySheet() const -{ - return d->activeSheet; -} - -void Doc::addView( KoView *_view ) -{ - KoDocument::addView( _view ); - TQPtrListIterator it( views() ); - for (; it.current(); ++it ) - ((View*)it.current())->closeEditor(); -} - -void Doc::addDamage( Damage* damage ) -{ - d->damages.append( damage ); - - if( d->damages.count() == 1 ) - TQTimer::singleShot( 0, this, TQT_SLOT( flushDamages() ) ); -} - -void Doc::flushDamages() -{ - emit damagesFlushed( d->damages ); - TQValueList::Iterator it; - for( it = d->damages.begin(); it != d->damages.end(); ++it ) - delete *it; - d->damages.clear(); -} - -void Doc::loadConfigFromFile() -{ - d->configLoadFromFile = true; -} - -bool Doc::configLoadFromFile() const -{ - return d->configLoadFromFile; -} - - -void Doc::insertObject( EmbeddedObject * obj ) -{ - switch ( obj->getType() ) - { - case OBJECT_KOFFICE_PART: case OBJECT_CHART: - { - KoDocument::insertChild( dynamic_cast(obj)->embeddedObject() ); - break; - } - default: - ; - } - d->m_embeddedObjects.append( obj ); -} - -TQPtrList& Doc::embeddedObjects() -{ - return d->m_embeddedObjects; -} - -KoPictureCollection *Doc::pictureCollection() -{ - return &d->m_pictureCollection; -} - -void Doc::repaint( const TQRect& rect ) -{ - TQRect r; - TQPtrListIterator it( views() ); - for( ; it.current(); ++it ) - { - r = rect; - Canvas* canvas = ((View*)it.current())->canvasWidget(); - r.moveTopLeft( TQPoint( r.x() - (int) canvas->xOffset(), - r.y() - (int) canvas->yOffset() ) ); - canvas->update( r ); - } -} - -void Doc::repaint( EmbeddedObject *obj ) -{ - TQPtrListIterator it( views() ); - for( ; it.current(); ++it ) - { - Canvas* canvas = ((View*)it.current())->canvasWidget(); - if ( obj->sheet() == canvas->activeSheet() ) - canvas->repaintObject( obj ); - } -} - -void Doc::repaint( const KoRect& rect ) -{ - TQRect r; - TQPtrListIterator it( views() ); - for( ; it.current(); ++it ) - { - Canvas* canvas = ((View*)it.current())->canvasWidget(); - - r = zoomRect( rect ); - r.moveBy( (int)( -canvas->xOffset()*zoomedResolutionX() ) , - (int)( -canvas->yOffset() *zoomedResolutionY()) ); - canvas->update( r ); - } -} - -void Doc::addShell( KoMainWindow *shell ) -{ - connect( shell, TQT_SIGNAL( documentSaved() ), d->commandHistory, TQT_SLOT( documentSaved() ) ); - KoDocument::addShell( shell ); -} - -int Doc::undoRedoLimit() const -{ - return d->commandHistory->undoLimit(); -} - -void Doc::setUndoRedoLimit(int val) -{ - d->commandHistory->setUndoLimit(val); - d->commandHistory->setRedoLimit(val); -} - -void Doc::insertPixmapKey( KoPictureKey key ) -{ - if ( !d->usedPictures.contains( key ) ) - d->usedPictures.append( key ); -} - -void Doc::makeUsedPixmapList() -{ - d->usedPictures.clear(); - TQPtrListIterator it( d->m_embeddedObjects ); - for ( ; it.current() ; ++it ) - { - if( it.current()->getType() == OBJECT_PICTURE && ( d->m_savingWholeDocument || it.current()->isSelected() ) ) - insertPixmapKey( static_cast( it.current() )->getKey() ); - } -} - -bool Doc::savingWholeDocument() -{ - return d->m_savingWholeDocument; -} - -#include "kspread_doc.moc" - diff --git a/kspread/kspread_doc.cpp b/kspread/kspread_doc.cpp new file mode 100644 index 00000000..7643b31d --- /dev/null +++ b/kspread/kspread_doc.cpp @@ -0,0 +1,2462 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Inge Wallin + (C) 2004 Ariya Hidayat + (C) 2002-2003 Norbert Andres + (C) 2000-2002 Laurent Montel + (C) 2002 John Dailey + (C) 2002 Phillip Mueller + (C) 2000 Werner Trobin + (C) 1999-2000 Simon Hausmann + (C) 1999 David Faure + (C) 1998-2000 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kspread_canvas.h" +#include "kspread_locale.h" +#include "kspread_map.h" +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include "kspread_style_manager.h" +#include "kspread_undo.h" +#include "kspread_util.h" +#include "kspread_view.h" + +#include "commands.h" +#include "damages.h" +#include "formula.h" +#include "functions.h" +#include "ksploadinginfo.h" +#include "selection.h" +#include "valuecalc.h" +#include "valueconverter.h" +#include "valueformatter.h" +#include "valueparser.h" + +#include "KSpreadDocIface.h" + +#include "kspread_doc.h" + +using namespace std; +using namespace KSpread; + +static const int CURRENT_SYNTAX_VERSION = 1; +// Make sure an appropriate DTD is available in www/koffice/DTD if changing this value +static const char * CURRENT_DTD_VERSION = "1.2"; + +class Doc::Private +{ +public: + + Map *map; + TDELocale *locale; + StyleManager *styleManager; + ValueParser *parser; + ValueFormatter *formatter; + ValueConverter *converter; + ValueCalc *calc; + + Sheet *activeSheet; + KSPLoadingInfo *m_loadingInfo; + static TQValueList s_docs; + static int s_docId; + + DCOPObject* dcop; + + // URL of the this part. This variable is only set if the load() function + // had been called with an URL as argument. + TQString fileURL; + + // for undo/redo + int undoLocked; + KoCommandHistory* commandHistory; + + // true if loading is in process, otherwise false. + // This flag is used to avoid updates etc. during loading. + bool isLoading; + + TQColor pageBorderColor; + + TQPtrList plugins; + + TQValueList refs; + TDECompletion listCompletion; + + int numOperations; + + TQValueList damages; + + // document properties + int syntaxVersion; + bool verticalScrollBar:1; + bool horizontalScrollBar:1; + bool columnHeader:1; + bool rowHeader:1; + TQColor gridColor; + double indentValue; + bool showStatusBar:1; + bool showTabBar:1; + bool showFormulaBar:1; + bool showError:1; + TDEGlobalSettings::Completion completionMode; + KSpread::MoveTo moveTo; + MethodOfCalc calcMethod; + bool delayCalculation:1; + KSpellConfig *spellConfig; + bool dontCheckUpperWord:1; + bool dontCheckTitleCase:1; + bool configLoadFromFile:1; + TQStringList spellListIgnoreAll; + /// list of all objects + TQPtrList m_embeddedObjects; + KoPictureCollection m_pictureCollection; + TQValueList usedPictures; + bool m_savingWholeDocument; +}; + +/***************************************************************************** + * + * Doc + * + *****************************************************************************/ + +TQValueList Doc::Private::s_docs; +int Doc::Private::s_docId = 0; + +Doc::Doc( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, bool singleViewMode ) + : KoDocument( parentWidget, widgetName, parent, name, singleViewMode ) +{ + d = new Private; + d->m_loadingInfo = 0L; + + d->map = new Map( this, "Map" ); + d->locale = new Locale; + d->styleManager = new StyleManager(); + + d->parser = new ValueParser( d->locale ); + d->converter = new ValueConverter ( d->parser ); + d->calc = new ValueCalc( d->converter ); + d->calc->setDoc (this); + d->formatter = new ValueFormatter( d->converter ); + + d->activeSheet = 0; + + d->pageBorderColor = TQt::red; + d->configLoadFromFile = false; + + TQFont f( KoGlobal::defaultFont() ); + Format::setGlobalRowHeight( f.pointSizeFloat() + 3 ); + Format::setGlobalColWidth( ( f.pointSizeFloat() + 3 ) * 5 ); + + d->plugins.setAutoDelete( false ); + + d->delayCalculation = false; + + documents().append( this ); + + setInstance( Factory::global(), false ); + setTemplateType( "kspread_template" ); + + d->dcop = 0; + d->isLoading = false; + d->numOperations = 1; // don't start repainting before the GUI is done... + + d->undoLocked = 0; + d->commandHistory = new KoCommandHistory( actionCollection() ); + connect( d->commandHistory, TQT_SIGNAL( commandExecuted() ), TQT_SLOT( commandExecuted() ) ); + connect( d->commandHistory, TQT_SIGNAL( documentRestored() ), TQT_SLOT( documentRestored() ) ); + + + // Make us scripsheet if the document has a name + // Set a name if there is no name specified + if ( !name ) + { + TQString tmp( "Document%1" ); + tmp = tmp.arg( d->s_docId++ ); + setName( tmp.local8Bit());//tmp.latin1() ); + dcopObject(); + } + else + dcopObject(); + + // default document properties + d->syntaxVersion = CURRENT_SYNTAX_VERSION; + d->verticalScrollBar = true; + d->horizontalScrollBar = true; + d->columnHeader = true; + d->rowHeader = true; + d->gridColor = TQt::lightGray; + d->indentValue = 10.0; + d->showStatusBar = true; + d->showFormulaBar = true; + d->showTabBar = true; + d->showError = false; + d->calcMethod = SumOfNumber; + d->moveTo = KSpread::Bottom; + d->completionMode = TDEGlobalSettings::CompletionAuto; + d->spellConfig = 0; + d->dontCheckUpperWord = false; + d->dontCheckTitleCase = false; +} + +Doc::~Doc() +{ + //don't save config when kword is embedded into konqueror + if(isReadWrite()) + saveConfig(); + + delete d->dcop; + d->s_docs.remove( this ); + + kdDebug(36001) << "alive 1" << endl; + + delete d->commandHistory; + + delete d->spellConfig; + + delete d->locale; + delete d->map; + delete d->styleManager; + delete d->parser; + delete d->formatter; + delete d->converter; + delete d->calc; + + delete d; +} + +TQValueList Doc::documents() +{ + return Private::s_docs; +} + +bool Doc::initDoc(InitDocFlags flags, TQWidget* parentWidget) +{ + // ElapsedTime et( " initDoc " ); + + TQString f; + + if (flags==KoDocument::InitDocEmpty) + { + TDEConfig *config = Factory::global()->config(); + int _page=1; + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + _page=config->readNumEntry( "NbPage",1 ) ; + } + + for( int i=0; i<_page; i++ ) + map()->addNewSheet(); + + resetURL(); + setEmpty(); + initConfig(); + styleManager()->createBuiltinStyles(); + + return true; + } + + KoTemplateChooseDia::ReturnType ret; + KoTemplateChooseDia::DialogType dlgtype; + if (flags != KoDocument::InitDocFileNew ) + dlgtype = KoTemplateChooseDia::Everything; + else + dlgtype = KoTemplateChooseDia::OnlyTemplates; + + ret = KoTemplateChooseDia::choose( Factory::global(), f, + dlgtype, "kspread_template", parentWidget ); + + if ( ret == KoTemplateChooseDia::File ) + { + KURL url( f ); + + bool ok=openURL(url); + + while (KoDocument::isLoading()) + kapp->processEvents(); + + return ok; + + + } + + if ( ret == KoTemplateChooseDia::Empty ) + { + TDEConfig *config = Factory::global()->config(); + int _page=1; + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + _page=config->readNumEntry( "NbPage",1 ) ; + } + + for( int i=0; i<_page; i++ ) + map()->addNewSheet (); + + resetURL(); + setEmpty(); + initConfig(); + styleManager()->createBuiltinStyles(); + return true; + } + + if ( ret == KoTemplateChooseDia::Template ) + { + resetURL(); + d->m_loadingInfo = new KSPLoadingInfo; + d->m_loadingInfo->setLoadTemplate( true ); + bool ok = loadNativeFormat( f ); + if ( !ok ) + { + showLoadingErrorDialog(); + deleteLoadingInfo(); + } + setEmpty(); + initConfig(); + return ok; + } + + return false; +} + +void Doc::openTemplate (const TQString& file) +{ + d->m_loadingInfo = new KSPLoadingInfo; + d->m_loadingInfo->setLoadTemplate( true ); + KoDocument::openTemplate( file ); + deleteLoadingInfo(); + initConfig(); +} + +void Doc::initEmpty() +{ + TDEConfig *config = Factory::global()->config(); + int _page=1; + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + _page=config->readNumEntry( "NbPage",1 ) ; + } + + for( int i=0; i<_page; i++ ) + map()->addNewSheet(); + + resetURL(); + initConfig(); + styleManager()->createBuiltinStyles(); + + KoDocument::initEmpty(); +} + +TDELocale *Doc::locale () const +{ + return d->locale; +} + +Map *Doc::map () const +{ + return d->map; +} + +StyleManager *Doc::styleManager () const +{ + return d->styleManager; +} + +ValueParser *Doc::parser () const +{ + return d->parser; +} + +ValueFormatter *Doc::formatter () const +{ + return d->formatter; +} + +ValueConverter *Doc::converter () const +{ + return d->converter; +} + +ValueCalc *Doc::calc () const +{ + return d->calc; +} + +void Doc::saveConfig() +{ + if ( isEmbedded() ||!isReadWrite()) + return; + TDEConfig *config = Factory::global()->config(); + config->setGroup( "Parameters" ); + config->writeEntry( "Zoom", m_zoom ); + +} + +void Doc::initConfig() +{ + TDEConfig *config = Factory::global()->config(); + + if( config->hasGroup("KSpread Page Layout" )) + { + config->setGroup( "KSpread Page Layout" ); + setUnit( (KoUnit::Unit)config->readNumEntry( "Default unit page" ,0)); + } + if( config->hasGroup("Parameters" )) + { + config->setGroup( "Parameters" ); + m_zoom = config->readNumEntry( "Zoom", 100 ); + } + else + m_zoom = 100; + + int undo=30; + if(config->hasGroup("Misc" ) ) + { + config->setGroup( "Misc" ); + undo=config->readNumEntry("UndoRedo",-1); + } + if(undo!=-1) + setUndoRedoLimit(undo); + + setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); +} + +int Doc::syntaxVersion() const +{ + return d->syntaxVersion; +} + +bool Doc::isLoading() const +{ + return d->isLoading || KoDocument::isLoading(); +} + +void Doc::doNotPaint(bool status) +{ + d->isLoading = status; +} + + +TQColor Doc::pageBorderColor() const +{ + return d->pageBorderColor; +} + +void Doc::changePageBorderColor( const TQColor & _color) +{ + d->pageBorderColor = _color; +} + +const TQValueList &Doc::listArea() +{ + return d->refs; +} + +TDECompletion& Doc::completion() +{ + return d->listCompletion; +} + +KoView* Doc::createViewInstance( TQWidget* parent, const char* name ) +{ + if ( name == 0 ) + name = "View"; + return new View( parent, name, this ); +} + +bool Doc::saveChildren( KoStore* _store ) +{ + return map()->saveChildren( _store ); +} + +int Doc::supportedSpecialFormats() const +{ + return KoDocument::supportedSpecialFormats(); +} + +bool Doc::completeSaving( KoStore* _store ) +{ + d->m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, d->usedPictures ); + + return true; +} + + +TQDomDocument Doc::saveXML() +{ + //Terminate current cell edition, if any + TQPtrListIterator it( views() ); + + /* don't pull focus away from the editor if this is just a background + autosave */ + if (!isAutosaving()) + { + for (; it.current(); ++it ) + static_cast( it.current() )->deleteEditor( true ); + } + + TQDomDocument doc = createDomDocument( "spreadsheet", CURRENT_DTD_VERSION ); + TQDomElement spread = doc.documentElement(); + spread.setAttribute( "editor", "KSpread" ); + spread.setAttribute( "mime", "application/x-kspread" ); + spread.setAttribute( "syntaxVersion", CURRENT_SYNTAX_VERSION ); + + TQDomElement dlocale = ((Locale *)locale())->save( doc ); + spread.appendChild( dlocale ); + + if (d->refs.count() != 0 ) + { + TQDomElement areaname = saveAreaName( doc ); + spread.appendChild( areaname ); + } + + if( !d->spellListIgnoreAll.isEmpty() ) + { + TQDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" ); + spread.appendChild( spellCheckIgnore ); + for ( TQStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it ) + { + TQDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" ); + spellCheckIgnore.appendChild( spellElem ); + spellElem.setAttribute( "word", *it ); + } + } + + SavedDocParts::const_iterator iter = m_savedDocParts.begin(); + SavedDocParts::const_iterator end = m_savedDocParts.end(); + while ( iter != end ) + { + // save data we loaded in the beginning and which has no owner back to file + spread.appendChild( iter.data() ); + ++iter; + } + + TQDomElement defaults = doc.createElement( "defaults" ); + defaults.setAttribute( "row-height", Format::globalRowHeight() ); + defaults.setAttribute( "col-width", Format::globalColWidth() ); + spread.appendChild( defaults ); + + Plugin * plugin = d->plugins.first(); + for ( ; plugin != 0; plugin = d->plugins.next() ) + { + TQDomElement data( plugin->saveXML( doc ) ); + if ( !data.isNull() ) + spread.appendChild( data ); + } + + TQDomElement s = styleManager()->save( doc ); + spread.appendChild( s ); + TQDomElement e = map()->save( doc ); + spread.appendChild( e ); + + setModified( false ); + + return doc; +} + +bool Doc::loadChildren( KoStore* _store ) +{ + return map()->loadChildren( _store ); +} + +bool Doc::saveOasis( KoStore* store, KoXmlWriter* manifestWriter ) +{ + emitBeginOperation(true); + bool result=saveOasisHelper( store, manifestWriter, SaveAll ); + emitEndOperation(); + + return result; +} + +bool Doc::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag, + TQString* /*plainText*/, KoPicture* /*picture*/ ) +{ + d->m_pictureCollection.assignUniqueIds(); + //Terminate current cell edition, if any + TQPtrListIterator it2( views() ); + d->m_savingWholeDocument = saveFlag == SaveAll ? true : false; + + /* don't pull focus away from the editor if this is just a background + autosave */ + if (!isAutosaving()) + { + for (; it2.current(); ++it2 ) + static_cast( it2.current() )->deleteEditor( true ); + } + if ( !store->open( "content.xml" ) ) + return false; + + KoStoreDevice dev( store ); + KoXmlWriter* contentWriter = createOasisXmlWriter( &dev, "office:document-content" ); + KoGenStyles mainStyles;//for compile + + KTempFile contentTmpFile; + //Check that temp file was successfully created + if (contentTmpFile.status() != 0) + { + tqWarning("Creation of temporary file to store document content failed."); + return false; + } + + contentTmpFile.setAutoDelete( true ); + TQFile* tmpFile = contentTmpFile.file(); + KoXmlWriter contentTmpWriter( TQT_TQIODEVICE(tmpFile), 1 ); + + + + //todo fixme just add a element for testing saving content.xml + contentTmpWriter.startElement( "office:body" ); + contentTmpWriter.startElement( "office:spreadsheet" ); + + int indexObj = 1; + int partIndexObj = 0; + + // Saving the custom cell styles including the default cell style. + styleManager()->saveOasis( mainStyles ); + + // Saving the default column style + KoGenStyle defaultColumnStyle( Doc::STYLE_COLUMN_USER, "table-column" ); + defaultColumnStyle.addPropertyPt( "style:column-width", Format::globalColWidth() ); + defaultColumnStyle.setDefaultStyle( true ); + mainStyles.lookup( defaultColumnStyle, "Default", KoGenStyles::DontForceNumbering ); + + // Saving the default row style + KoGenStyle defaultRowStyle( Doc::STYLE_ROW_USER, "table-row" ); + defaultRowStyle.addPropertyPt( "style:row-height", Format::globalRowHeight() ); + defaultRowStyle.setDefaultStyle( true ); + mainStyles.lookup( defaultRowStyle, "Default", KoGenStyles::DontForceNumbering ); + + // Saving the map. + map()->saveOasis( contentTmpWriter, mainStyles, store, manifestWriter, indexObj, partIndexObj ); + + saveOasisAreaName( contentTmpWriter ); + contentTmpWriter.endElement(); ////office:spreadsheet + contentTmpWriter.endElement(); ////office:body + + // Done with writing out the contents to the tempfile, we can now write out the automatic styles + contentWriter->startElement( "office:automatic-styles" ); + + TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_AUTO ); + TQValueList::const_iterator it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); + } + + styles = mainStyles.styles( STYLE_PAGE ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-properties" ); + } + + styles = mainStyles.styles( STYLE_COLUMN_AUTO ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); + } + + styles = mainStyles.styles( STYLE_ROW_AUTO ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); + } + + styles = mainStyles.styles( STYLE_CELL_AUTO ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); + } + + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_NUMBER ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); + } + + //TODO FIXME !!!! + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/ ); + } + + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/ ); + } + + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_FRACTION ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); + } + + //TODO FIME !!!!! + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_PERCENTAGE ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:percentage-style", (*it).name, 0 /*TODO ????*/ ); + } + + //TODO FIME !!!!! + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_CURRENCY ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:currency-style", (*it).name, 0 /*TODO ????*/ ); + } + + styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); + } + + + contentWriter->endElement(); // office:automatic-styles + + + // And now we can copy over the contents from the tempfile to the real one + tmpFile->close(); + contentWriter->addCompleteElement( TQT_TQIODEVICE(tmpFile) ); + contentTmpFile.close(); + + + contentWriter->endElement(); // root element + contentWriter->endDocument(); + delete contentWriter; + if ( !store->close() ) + return false; + //add manifest line for content.xml + manifestWriter->addManifestEntry( "content.xml", "text/xml" ); + + //todo add manifest line for style.xml + if ( !store->open( "styles.xml" ) ) + return false; + + manifestWriter->addManifestEntry( "styles.xml", "text/xml" ); + saveOasisDocumentStyles( store, mainStyles ); + + if ( !store->close() ) // done with styles.xml + return false; + + makeUsedPixmapList(); + d->m_pictureCollection.saveOasisToStore( store, d->usedPictures, manifestWriter); + + if(!store->open("settings.xml")) + return false; + + KoXmlWriter* settingsWriter = createOasisXmlWriter(&dev, "office:document-settings"); + settingsWriter->startElement("office:settings"); + settingsWriter->startElement("config:config-item-set"); + settingsWriter->addAttribute("config:name", "view-settings"); + + KoUnit::saveOasis(settingsWriter, unit()); + + saveOasisSettings( *settingsWriter ); + + settingsWriter->endElement(); // config:config-item-set + + settingsWriter->startElement("config:config-item-set"); + settingsWriter->addAttribute("config:name", "configuration-settings"); + settingsWriter->addConfigItem("SpellCheckerIgnoreList", d->spellListIgnoreAll.join( "," ) ); + settingsWriter->endElement(); // config:config-item-set + settingsWriter->endElement(); // office:settings + settingsWriter->endElement(); // Root:element + settingsWriter->endDocument(); + delete settingsWriter; + + if(!store->close()) + return false; + + manifestWriter->addManifestEntry("settings.xml", "text/xml"); + + + if ( saveFlag == SaveSelected ) + { + TQPtrListIterator it(embeddedObjects() ); + for( ; it.current(); ++it ) + { + if ( it.current()->getType() != OBJECT_CHART && it.current()->getType() != OBJECT_KOFFICE_PART ) + continue; + KoDocumentChild *embedded = dynamic_cast(it.current() )->embeddedObject(); + //NOTE: If an application's .desktop file lies about opendocument support (ie. it indicates that it has + //a native OASIS mime type, when it doesn't, this causes a crash when trying to reload and paint + //the object, since it won't have an associated document. + if ( !embedded->saveOasis( store, manifestWriter ) ) + continue; + } + } + + + setModified( false ); + + return true; +} + +void Doc::loadOasisSettings( const TQDomDocument&settingsDoc ) +{ + KoOasisSettings settings( settingsDoc ); + KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); + if ( !viewSettings.isNull() ) + { + setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit"))); + } + map()->loadOasisSettings( settings ); + loadOasisIgnoreList( settings ); +} + +void Doc::saveOasisSettings( KoXmlWriter &settingsWriter ) +{ + settingsWriter.startElement("config:config-item-map-indexed"); + settingsWriter.addAttribute("config:name", "Views"); + settingsWriter.startElement( "config:config-item-map-entry" ); + map()->saveOasisSettings( settingsWriter ); + settingsWriter.endElement(); + settingsWriter.endElement(); +} + + +void Doc::loadOasisIgnoreList( const KoOasisSettings& settings ) +{ + KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" ); + if ( !configurationSettings.isNull() ) + { + const TQString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" ); + //kdDebug()<<" ignorelist :"<spellListIgnoreAll = TQStringList::split( ',', ignorelist ); + } +} + + +void Doc::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles ) const +{ + KoStoreDevice stylesDev( store ); + KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" ); + + stylesWriter->startElement( "office:styles" ); + TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_USER ); + TQValueList::const_iterator it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); + } + + // Writing out the common column styles. + styles = mainStyles.styles( Doc::STYLE_COLUMN_USER ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + if ( (*it).style->isDefaultStyle() ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-column-properties" ); + } + else { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); + } + } + + // Writing out the row column styles. + styles = mainStyles.styles( Doc::STYLE_ROW_USER ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + if ( (*it).style->isDefaultStyle() ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-row-properties" ); + } + else { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); + } + } + + // Writing out the common cell styles. + styles = mainStyles.styles( Doc::STYLE_CELL_USER ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + if ( (*it).style->isDefaultStyle() ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-cell-properties" ); + } + else { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); + } + } + + styles = mainStyles.styles( KoGenStyle::STYLE_HATCH ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "draw:hatch", (*it).name, "style:graphic-properties" , true, true /*add draw:name*/); + } + styles = mainStyles.styles( KoGenStyle::STYLE_GRAPHICAUTO ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" ); + } + + stylesWriter->endElement(); // office:styles + + stylesWriter->startElement( "office:automatic-styles" ); + styles = mainStyles.styles( KoGenStyle::STYLE_PAGELAYOUT ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false /*don't close*/ ); + stylesWriter->endElement(); + } + + stylesWriter->endElement(); // office:automatic-styles + //code from kword + stylesWriter->startElement( "office:master-styles" ); + + styles = mainStyles.styles( Doc::STYLE_PAGEMASTER ); + it = styles.begin(); + for ( ; it != styles.end() ; ++it ) { + (*it).style->writeStyle( stylesWriter, mainStyles, "style:master-page", (*it).name, "" ); + } + + stylesWriter->endElement(); // office:master-style + + + stylesWriter->endElement(); // root element (office:document-styles) + stylesWriter->endDocument(); + delete stylesWriter;; +} + +bool Doc::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store) +{ + if ( !d->m_loadingInfo ) + d->m_loadingInfo = new KSPLoadingInfo; + + TQTime dt; + dt.start(); + + emit sigProgress( 0 ); + d->isLoading = true; + d->spellListIgnoreAll.clear(); + + d->refs.clear(); + + TQDomElement content = doc.documentElement(); + TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) ); + if ( realBody.isNull() ) + { + setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." )); + deleteLoadingInfo(); + return false; + } + TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "spreadsheet" ); + + if ( body.isNull() ) + { + kdError(32001) << "No office:spreadsheet found!" << endl; + TQDomElement childElem; + TQString localName; + forEachElement( childElem, realBody ) { + localName = childElem.localName(); + } + if ( localName.isEmpty() ) + setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) ); + else + setErrorMessage( i18n( "This document is not a spreadsheet, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) ); + deleteLoadingInfo(); + return false; + } + + KoOasisLoadingContext context( this, oasisStyles, store ); + + //load in first + styleManager()->loadOasisStyleTemplate( oasisStyles ); + + // load default column style + const TQDomElement* defaultColumnStyle = oasisStyles.defaultStyle( "table-column" ); + if ( defaultColumnStyle ) + { +// kDebug() << "style:default-style style:family=\"table-column\"" << endl; + KoStyleStack styleStack; + styleStack.push( *defaultColumnStyle ); + styleStack.setTypeProperties( "table-column" ); + if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) ) + { + const double width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ), -1.0 ); + if ( width != -1.0 ) + { +// kDebug() << "\tstyle:column-width: " << width << endl; + Format::setGlobalColWidth( width ); + } + } + } + + // load default row style + const TQDomElement* defaultRowStyle = oasisStyles.defaultStyle( "table-row" ); + if ( defaultRowStyle ) + { +// kDebug() << "style:default-style style:family=\"table-row\"" << endl; + KoStyleStack styleStack; + styleStack.push( *defaultRowStyle ); + styleStack.setTypeProperties( "table-row" ); + if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) ) + { + const double height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ), -1.0 ); + if ( height != -1.0 ) + { +// kDebug() << "\tstyle:row-height: " << height << endl; + Format::setGlobalRowHeight( height ); + } + } + } + + // TODO check versions and mimetypes etc. + loadOasisAreaName( body ); + loadOasisCellValidation( body ); + + // all goes to workbook + if ( !map()->loadOasis( body, context ) ) + { + d->isLoading = false; + deleteLoadingInfo(); + return false; + } + + + if ( !settings.isNull() ) + { + loadOasisSettings( settings ); + } + emit sigProgress( 90 ); + initConfig(); + emit sigProgress(-1); + + //display loading time + kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; + return true; +} + +bool Doc::loadXML( TQIODevice *, const TQDomDocument& doc ) +{ + TQTime dt; + dt.start(); + + emit sigProgress( 0 ); + d->isLoading = true; + d->spellListIgnoreAll.clear(); + // + TQDomElement spread = doc.documentElement(); + + if ( spread.attribute( "mime" ) != "application/x-kspread" && spread.attribute( "mime" ) != "application/vnd.kde.kspread" ) + { + d->isLoading = false; + setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" ).arg( spread.attribute("mime") ) ); + return false; + } + + d->syntaxVersion = Doc::getAttribute( spread, "syntaxVersion", 0 ); + if ( d->syntaxVersion > CURRENT_SYNTAX_VERSION ) + { + int ret = KMessageBox::warningContinueCancel( + 0, i18n("This document was created with a newer version of KSpread (syntax version: %1)\n" + "When you open it with this version of KSpread, some information may be lost.").arg(d->syntaxVersion), + i18n("File Format Mismatch"), KStdGuiItem::cont() ); + if ( ret == KMessageBox::Cancel ) + { + setErrorMessage( "USER_CANCELED" ); + return false; + } + } + + // + TQDomElement loc = spread.namedItem( "locale" ).toElement(); + if ( !loc.isNull() ) + ((Locale *) locale())->load( loc ); + + emit sigProgress( 5 ); + + TQDomElement defaults = spread.namedItem( "defaults" ).toElement(); + if ( !defaults.isNull() ) + { + bool ok = false; + double d = defaults.attribute( "row-height" ).toDouble( &ok ); + if ( !ok ) + return false; + Format::setGlobalRowHeight( d ); + + d = defaults.attribute( "col-width" ).toDouble( &ok ); + + if ( !ok ) + return false; + + Format::setGlobalColWidth( d ); + } + + d->refs.clear(); + // + TQDomElement areaname = spread.namedItem( "areaname" ).toElement(); + if ( !areaname.isNull()) + loadAreaName(areaname); + + TQDomElement ignoreAll = spread.namedItem( "SPELLCHECKIGNORELIST").toElement(); + if ( !ignoreAll.isNull()) + { + TQDomElement spellWord=spread.namedItem("SPELLCHECKIGNORELIST").toElement(); + + spellWord=spellWord.firstChild().toElement(); + while ( !spellWord.isNull() ) + { + if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" ) + { + d->spellListIgnoreAll.append(spellWord.attribute("word")); + } + spellWord=spellWord.nextSibling().toElement(); + } + } + + emit sigProgress( 40 ); + // In case of reload (e.g. from konqueror) + map()->sheetList().clear(); // it's set to autoDelete + + TQDomElement styles = spread.namedItem( "styles" ).toElement(); + if ( !styles.isNull() ) + { + if ( !styleManager()->loadXML( styles ) ) + { + setErrorMessage( i18n( "Styles cannot be loaded." ) ); + d->isLoading = false; + return false; + } + } + + // + TQDomElement mymap = spread.namedItem( "map" ).toElement(); + if ( mymap.isNull() ) + { + setErrorMessage( i18n("Invalid document. No map tag.") ); + d->isLoading = false; + return false; + } + if ( !map()->loadXML( mymap ) ) + { + d->isLoading = false; + return false; + } + + //Backwards compatibility with older versions for paper layout + if ( d->syntaxVersion < 1 ) + { + TQDomElement paper = spread.namedItem( "paper" ).toElement(); + if ( !paper.isNull() ) + { + loadPaper( paper ); + } + } + + emit sigProgress( 85 ); + + TQDomElement element( spread.firstChild().toElement() ); + while ( !element.isNull() ) + { + TQString tagName( element.tagName() ); + + if ( tagName != "locale" && tagName != "map" && tagName != "styles" + && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname" + && tagName != "paper" ) + { + // belongs to a plugin, load it and save it for later use + m_savedDocParts[ tagName ] = element; + } + + element = element.nextSibling().toElement(); + } + + emit sigProgress( 90 ); + initConfig(); + emit sigProgress(-1); + + kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; + + emit sig_refreshView(); + + return true; +} + +void Doc::loadPaper( TQDomElement const & paper ) +{ + // + TQString format = paper.attribute( "format" ); + TQString orientation = paper.attribute( "orientation" ); + + // + TQDomElement borders = paper.namedItem( "borders" ).toElement(); + if ( !borders.isNull() ) + { + float left = borders.attribute( "left" ).toFloat(); + float right = borders.attribute( "right" ).toFloat(); + float top = borders.attribute( "top" ).toFloat(); + float bottom = borders.attribute( "bottom" ).toFloat(); + + //apply to all sheet + TQPtrListIterator it ( map()->sheetList() ); + for( ; it.current(); ++it ) + { + it.current()->print()->setPaperLayout( left, top, right, bottom, + format, orientation ); + } + } + + TQString hleft, hright, hcenter; + TQString fleft, fright, fcenter; + // + TQDomElement head = paper.namedItem( "head" ).toElement(); + if ( !head.isNull() ) + { + TQDomElement left = head.namedItem( "left" ).toElement(); + if ( !left.isNull() ) + hleft = left.text(); + TQDomElement center = head.namedItem( "center" ).toElement(); + if ( !center.isNull() ) + hcenter = center.text(); + TQDomElement right = head.namedItem( "right" ).toElement(); + if ( !right.isNull() ) + hright = right.text(); + } + // + TQDomElement foot = paper.namedItem( "foot" ).toElement(); + if ( !foot.isNull() ) + { + TQDomElement left = foot.namedItem( "left" ).toElement(); + if ( !left.isNull() ) + fleft = left.text(); + TQDomElement center = foot.namedItem( "center" ).toElement(); + if ( !center.isNull() ) + fcenter = center.text(); + TQDomElement right = foot.namedItem( "right" ).toElement(); + if ( !right.isNull() ) + fright = right.text(); + } + //The macro "" formerly was typed as "
" + hleft = hleft.replace( "
", "" ); + hcenter = hcenter.replace( "
", "" ); + hright = hright.replace( "
", "" ); + fleft = fleft.replace( "
", "" ); + fcenter = fcenter.replace( "
", "" ); + fright = fright.replace( "
", "" ); + + TQPtrListIterator it ( map()->sheetList() ); + for( ; it.current(); ++it ) + { + it.current()->print()->setHeadFootLine( hleft, hcenter, hright, + fleft, fcenter, fright); + } +} + +bool Doc::completeLoading( KoStore* /* _store */ ) +{ + kdDebug(36001) << "------------------------ COMPLETING --------------------" << endl; + + d->isLoading = false; + + // map()->update(); + + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + ((View*)it.current())->initialPosition(); + + kdDebug(36001) << "------------------------ COMPLETION DONE --------------------" << endl; + + setModified( false ); + return true; +} + + +void Doc::registerPlugin( Plugin * plugin ) +{ + d->plugins.append( plugin ); +} + +void Doc::deregisterPlugin( Plugin * plugin ) +{ + d->plugins.remove( plugin ); +} + +bool Doc::docData( TQString const & xmlTag, TQDomElement & data ) +{ + SavedDocParts::iterator iter = m_savedDocParts.find( xmlTag ); + if ( iter == m_savedDocParts.end() ) + return false; + + data = iter.data(); + m_savedDocParts.erase( iter ); + + return true; +} + +void Doc::setShowVerticalScrollBar(bool _show) +{ + d->verticalScrollBar=_show; +} + +bool Doc::showVerticalScrollBar()const +{ + return d->verticalScrollBar; +} + +void Doc::setShowHorizontalScrollBar(bool _show) +{ + d->horizontalScrollBar=_show; +} + +bool Doc::showHorizontalScrollBar()const +{ + return d->horizontalScrollBar; +} + +TDEGlobalSettings::Completion Doc::completionMode( ) const +{ + return d->completionMode; +} + +void Doc::setShowColumnHeader(bool _show) +{ + d->columnHeader=_show; +} + +bool Doc::showColumnHeader() const +{ + return d->columnHeader; +} + +void Doc::setShowRowHeader(bool _show) +{ + d->rowHeader=_show; +} + +bool Doc::showRowHeader() const +{ + return d->rowHeader; +} + +void Doc::setGridColor( const TQColor& color ) +{ + d->gridColor = color; +} + +TQColor Doc::gridColor() const +{ + return d->gridColor; +} + +void Doc::setCompletionMode( TDEGlobalSettings::Completion complMode) +{ + d->completionMode= complMode; +} + +double Doc::indentValue() const +{ + return d->indentValue; +} + +void Doc::setIndentValue( double val ) +{ + d->indentValue = val; +} + +void Doc::setShowStatusBar(bool _statusBar) +{ + d->showStatusBar=_statusBar; +} + +bool Doc::showStatusBar() const +{ + return d->showStatusBar; +} + +void Doc::setShowTabBar(bool _tabbar) +{ + d->showTabBar=_tabbar; +} + +bool Doc::showTabBar()const +{ + return d->showTabBar; +} + +void Doc::setShowFormulaBar(bool _formulaBar) +{ + d->showFormulaBar=_formulaBar; +} + +bool Doc::showFormulaBar() const +{ + return d->showFormulaBar; +} + +void Doc::setShowMessageError(bool _show) +{ + d->showError=_show; +} + +bool Doc::showMessageError() const +{ + return d->showError; +} + +KSpread::MoveTo Doc::getMoveToValue() const +{ + return d->moveTo; +} + +void Doc::setMoveToValue(KSpread::MoveTo _moveTo) +{ + d->moveTo = _moveTo; +} + +void Doc::setTypeOfCalc( MethodOfCalc _calc) +{ + d->calcMethod=_calc; +} + +MethodOfCalc Doc::getTypeOfCalc() const +{ + return d->calcMethod; +} + +void Doc::setKSpellConfig(KSpellConfig _tdespell) +{ + if (d->spellConfig == 0 ) + d->spellConfig = new KSpellConfig(); + + d->spellConfig->setNoRootAffix(_tdespell.noRootAffix ()); + d->spellConfig->setRunTogether(_tdespell.runTogether ()); + d->spellConfig->setDictionary(_tdespell.dictionary ()); + d->spellConfig->setDictFromList(_tdespell.dictFromList()); + d->spellConfig->setEncoding(_tdespell.encoding()); + d->spellConfig->setClient(_tdespell.client()); +} + +KSpellConfig * Doc::getKSpellConfig() +{ + if (!d->spellConfig) + { + KSpellConfig ksconfig; + + TDEConfig *config = Factory::global()->config(); + if( config->hasGroup("KSpell kspread" ) ) + { + config->setGroup( "KSpell kspread" ); + ksconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0)); + ksconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0)); + ksconfig.setDictionary(config->readEntry ("KSpell_Dictionary", "")); + ksconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", false)); + ksconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KS_E_ASCII)); + ksconfig.setClient(config->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL)); + setKSpellConfig(ksconfig); + + setDontCheckUpperWord(config->readBoolEntry("KSpell_IgnoreUppercaseWords", false)); + setDontCheckTitleCase(config->readBoolEntry("KSpell_IgnoreTitleCaseWords", false)); + } + } + return d->spellConfig; +} + +bool Doc::dontCheckUpperWord() const +{ + return d->dontCheckUpperWord; +} + +void Doc::setDontCheckUpperWord( bool b ) +{ + d->dontCheckUpperWord = b; +} + +bool Doc::dontCheckTitleCase() const +{ + return d->dontCheckTitleCase; +} + +void Doc::setDontCheckTitleCase( bool b ) +{ + d->dontCheckTitleCase = b; +} + +TQString Doc::unitName() const +{ + return KoUnit::unitName( unit() ); +} + +void Doc::increaseNumOperation() +{ + ++d->numOperations; +} + +void Doc::decreaseNumOperation() +{ + --d->numOperations; +} + +void Doc::addIgnoreWordAllList( const TQStringList & _lst) +{ + d->spellListIgnoreAll = _lst; +} + +TQStringList Doc::spellListIgnoreAll() const +{ + return d->spellListIgnoreAll; +} + +void Doc::setZoomAndResolution( int zoom, int dpiX, int dpiY ) +{ + KoZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY ); +} + +void Doc::newZoomAndResolution( bool updateViews, bool /*forPrint*/ ) +{ +/* layout(); + updateAllFrames();*/ + if ( updateViews ) + { + emit sig_refreshView(); + } +} + +void Doc::addCommand( KCommand* command ) +{ + if (undoLocked()) return; + d->commandHistory->addCommand( command, false ); + setModified( true ); +} + +void Doc::addCommand( UndoAction* undo ) +{ + if (undoLocked()) return; + UndoWrapperCommand* command = new UndoWrapperCommand( undo ); + addCommand( command ); + setModified( true ); +} + +void Doc::undo() +{ + undoLock (); + d->commandHistory->undo(); + undoUnlock (); +} + +void Doc::redo() +{ + undoLock (); + d->commandHistory->redo(); + undoUnlock (); +} + +void Doc::commandExecuted() +{ + setModified( true ); +} + +void Doc::documentRestored() +{ + setModified( false ); +} + +void Doc::undoLock() +{ + d->undoLocked++; +} + +void Doc::undoUnlock() +{ + d->undoLocked--; +} + +bool Doc::undoLocked() const +{ + return (d->undoLocked > 0); +} + +KoCommandHistory* Doc::commandHistory() +{ + return d->commandHistory; +} + +void Doc::enableUndo( bool _b ) +{ + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + static_cast( it.current() )->enableUndo( _b ); +} + +void Doc::enableRedo( bool _b ) +{ + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + static_cast( it.current() )->enableRedo( _b ); +} + +void Doc::paintContent( TQPainter& painter, const TQRect& rect, + bool transparent, double zoomX, double /*zoomY*/ ) +{ + kdDebug(36001) << "paintContent() called on " << rect << endl; + + // ElapsedTime et( "Doc::paintContent1" ); + //kdDebug(36001) << "Doc::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl; + + // save current zoom + int oldZoom = m_zoom; + + // choose sheet: the first or the active + Sheet* sheet = 0L; + if ( !d->activeSheet ) + sheet = map()->firstSheet(); + else + sheet = d->activeSheet; + if ( !sheet ) + return; + + // only one zoom is supported + double d_zoom = 1.0; + setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() ); + if ( m_zoomedResolutionX != zoomX ) + d_zoom *= ( zoomX / m_zoomedResolutionX ); + + // KSpread support zoom, therefore no need to scale with worldMatrix + TQWMatrix matrix = painter.worldMatrix(); + matrix.setMatrix( 1, 0, 0, 1, matrix.dx(), matrix.dy() ); + TQRect prect = rect; + prect.setWidth( (int) (prect.width() * painter.worldMatrix().m11()) ); + prect.setHeight( (int) (prect.height() * painter.worldMatrix().m22()) ); + setZoomAndResolution( (int) ( d_zoom * 100 ), KoGlobal::dpiX(), KoGlobal::dpiY() ); + // paint the content, now zoom is correctly set + kdDebug(36001)<<"paintContent-------------------------------------\n"; + painter.save(); + painter.setWorldMatrix( matrix ); + paintContent( painter, prect, transparent, sheet, false ); + painter.restore(); + + // restore zoom + m_zoom = oldZoom; + setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); +} + +void Doc::paintContent( TQPainter& painter, const TQRect& rect, bool /*transparent*/, Sheet* sheet, bool drawCursor ) +{ + if ( isLoading() ) + return; + // ElapsedTime et( "Doc::paintContent2" ); + + // if ( !transparent ) + // painter.eraseRect( rect ); + + double xpos; + double ypos; + int left_col = sheet->leftColumn( unzoomItX( rect.x() ), xpos ); + int right_col = sheet->rightColumn( unzoomItX( rect.right() ) ); + int top_row = sheet->topRow( unzoomItY( rect.y() ), ypos ); + int bottom_row = sheet->bottomRow( unzoomItY( rect.bottom() ) ); + TQPen pen; + pen.setWidth( 1 ); + painter.setPen( pen ); + + /* Update the entire visible area. */ + TQValueList cellAreaList; + cellAreaList.append( TQRect( left_col, + top_row, + right_col - left_col + 1, + bottom_row - top_row + 1) ); + + paintCellRegions(painter, rect, NULL, cellAreaList, sheet, drawCursor); +} + +void Doc::paintUpdates() +{ + // ElapsedTime et( "Doc::paintUpdates" ); + + TQPtrListIterator it( views() ); + View * view = NULL; + Sheet * sheet = NULL; + + for (; it.current(); ++it ) + { + view = static_cast( it.current() ); + view->paintUpdates(); + } + + for (sheet = map()->firstSheet(); sheet != NULL; + sheet = map()->nextSheet()) + { + sheet->clearPaintDirtyData(); + } +} + +void Doc::paintCellRegions(TQPainter& painter, const TQRect &viewRect, + View* view, + TQValueList cellRegions, + const Sheet* sheet, bool /*drawCursor*/) +{ + // + // Clip away children + // + + TQRegion rgn = painter.clipRegion(); + if ( rgn.isEmpty() ) + rgn = TQRegion( TQRect( 0, 0, viewRect.width(), viewRect.height() ) ); + + TQWMatrix matrix; + if ( view ) { + matrix.scale( zoomedResolutionX(), + zoomedResolutionY() ); + matrix.translate( - view->canvasWidget()->xOffset(), + - view->canvasWidget()->yOffset() ); + } + else { + matrix = painter.worldMatrix(); + } + +// TQPtrListIterator it( children() ); +// for( ; it.current(); ++it ) { +// // if ( ((Child*)it.current())->sheet() == sheet && +// // !m_pView->hasDocumentInWindow( it.current()->document() ) ) +// if ( ((Child*)it.current())->sheet() == sheet) +// rgn -= it.current()->region( matrix ); +// } + painter.setClipRegion( rgn ); + + TQPen pen; + pen.setWidth( 1 ); + painter.setPen( pen ); + + TQRect cellRegion; + KoRect unzoomedViewRect = unzoomRect( viewRect ); + + for (unsigned int i=0; i < cellRegions.size(); i++) { + cellRegion = cellRegions[i]; + + PaintRegion(painter, unzoomedViewRect, view, cellRegion, sheet); + } +} + + +void Doc::PaintRegion(TQPainter &painter, const KoRect &viewRegion, + View* view, const TQRect &paintRegion, + const Sheet* sheet) +{ + // Paint region has cell coordinates (col,row) while viewRegion has + // world coordinates. paintRegion is the cells to update and + // viewRegion is the area actually onscreen. + + if ( paintRegion.left() <= 0 || paintRegion.top() <= 0 ) + return; + + // Get the world coordinates of the upper left corner of the + // paintRegion The view is NULL, when paintRegion is called from + // paintContent, which itself is only called, when we should paint + // the output for INACTIVE embedded view. If inactive embedded, + // then there is no view and we alwas start at top/left, so the + // offset is 0. + // + KoPoint dblCorner; + if ( view == 0L ) //Most propably we are embedded and inactive, so no offset + dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ), + sheet->dblRowPos( paintRegion.top() ) ); + else + dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ) + - view->canvasWidget()->xOffset(), + sheet->dblRowPos( paintRegion.top() ) + - view->canvasWidget()->yOffset() ); + KoPoint dblCurrentCellPos( dblCorner ); + + int regionBottom = paintRegion.bottom(); + int regionRight = paintRegion.right(); + int regionLeft = paintRegion.left(); + int regionTop = paintRegion.top(); + + TQValueList mergedCellsPainted; + for ( int y = regionTop; + y <= regionBottom && dblCurrentCellPos.y() <= viewRegion.bottom(); + ++y ) + { + const RowFormat * row_lay = sheet->rowFormat( y ); + dblCurrentCellPos.setX( dblCorner.x() ); + + for ( int x = regionLeft; + x <= regionRight && dblCurrentCellPos.x() <= viewRegion.right(); + ++x ) + { + const ColumnFormat *col_lay = sheet->columnFormat( x ); + Cell* cell = sheet->cellAt( x, y ); + + TQPoint cellRef( x, y ); + +#if 0 + bool paintBordersBottom = false; + bool paintBordersRight = false; + bool paintBordersLeft = false; + bool paintBordersTop = false; +#endif + int paintBorder = Cell::Border_None; + + TQPen rightPen( cell->effRightBorderPen( x, y ) ); + TQPen leftPen( cell->effLeftBorderPen( x, y ) ); + TQPen topPen( cell->effTopBorderPen( x, y ) ); + TQPen bottomPen( cell->effBottomBorderPen( x, y ) ); + + // Paint border if outermost cell or if the pen is more "worth" + // than the border pen of the cell on the other side of the + // border or if the cell on the other side is not painted. In + // the latter case get the pen that is of more "worth" + + // right border: + if ( x >= KS_colMax ) + //paintBordersRight = true; + paintBorder |= Cell::Border_Right; + else if ( x == regionRight ) { + paintBorder |= Cell::Border_Right; + if ( cell->effRightBorderValue( x, y ) + < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) + rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); + } + else { + paintBorder |= Cell::Border_Right; + if ( cell->effRightBorderValue( x, y ) + < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) + rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); + } + + // Similiar for other borders... + // bottom border: + if ( y >= KS_rowMax ) + paintBorder |= Cell::Border_Bottom; + else if ( y == regionBottom ) { + paintBorder |= Cell::Border_Bottom; + if ( cell->effBottomBorderValue( x, y ) + < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) + bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); + } + else { + paintBorder |= Cell::Border_Bottom; + if ( cell->effBottomBorderValue( x, y ) + < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) + bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); + } + + // left border: + if ( x == 1 ) + paintBorder |= Cell::Border_Left; + else if ( x == regionLeft ) { + paintBorder |= Cell::Border_Left; + if ( cell->effLeftBorderValue( x, y ) + < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) + leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); + } + else { + paintBorder |= Cell::Border_Left; + if ( cell->effLeftBorderValue( x, y ) + < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) + leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); + } + + // top border: + if ( y == 1 ) + paintBorder |= Cell::Border_Top; + else if ( y == regionTop ) { + paintBorder |= Cell::Border_Top; + if ( cell->effTopBorderValue( x, y ) + < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) + topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); + } + else { + paintBorder |= Cell::Border_Top; + if ( cell->effTopBorderValue( x, y ) + < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) + topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); + } + +#if 0 + cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, + paintBordersRight, paintBordersBottom, + paintBordersLeft, paintBordersTop, + rightPen, bottomPen, leftPen, topPen, + mergedCellsPainted, false ); + + Cell::BorderSides highlightBorder=Cell::Border_None; + TQPen highlightPen; +#endif + + cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, + paintBorder, + rightPen, bottomPen, leftPen, topPen, + mergedCellsPainted, false ); + + + dblCurrentCellPos.setX( dblCurrentCellPos.x() + col_lay->dblWidth() ); + } + dblCurrentCellPos.setY( dblCurrentCellPos.y() + row_lay->dblHeight() ); + } +} + + +DCOPObject* Doc::dcopObject() +{ + if ( !d->dcop ) + d->dcop = new DocIface( this ); + + return d->dcop; +} + +void Doc::addAreaName(const TQRect &_rect,const TQString & name,const TQString & sheetName) +{ + setModified( true ); + Reference tmp; + tmp.rect = _rect; + tmp.sheet_name = sheetName; + tmp.ref_name = name; + d->refs.append( tmp); + emit sig_addAreaName( name ); +} + +void Doc::removeArea( const TQString & name) +{ + TQValueList::Iterator it2; + for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) + { + if((*it2).ref_name==name) + { + d->refs.remove(it2); + emit sig_removeAreaName( name ); + return; + } + } +} + +void Doc::changeAreaSheetName(const TQString & oldName,const TQString & sheetName) +{ + TQValueList::Iterator it2; + for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) + { + if((*it2).sheet_name==oldName) + (*it2).sheet_name=sheetName; + } +} + +TQRect Doc::getRectArea(const TQString &_sheetName) +{ + TQValueList::Iterator it2; + for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) + { + if((*it2).ref_name==_sheetName) + { + return (*it2).rect; + } + } + return TQRect(-1,-1,-1,-1); +} + +TQDomElement Doc::saveAreaName( TQDomDocument& doc ) +{ + TQDomElement element = doc.createElement( "areaname" ); + TQValueList::Iterator it2; + for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) + { + TQDomElement e = doc.createElement("reference"); + TQDomElement tabname = doc.createElement( "tabname" ); + tabname.appendChild( doc.createTextNode( (*it2).sheet_name ) ); + e.appendChild( tabname ); + + TQDomElement refname = doc.createElement( "refname" ); + refname.appendChild( doc.createTextNode( (*it2).ref_name ) ); + e.appendChild( refname ); + + TQDomElement rect = doc.createElement( "rect" ); + rect.setAttribute( "left-rect", ((*it2).rect).left() ); + rect.setAttribute( "right-rect",((*it2).rect).right() ); + rect.setAttribute( "top-rect", ((*it2).rect).top() ); + rect.setAttribute( "bottom-rect", ((*it2).rect).bottom() ); + e.appendChild( rect ); + element.appendChild(e); + } + return element; +} + +void Doc::loadOasisCellValidation( const TQDomElement&body ) +{ + TQDomNode validation = KoDom::namedItemNS( body, KoXmlNS::table, "content-validations" ); + kdDebug()<<"void Doc::loadOasisCellValidation( const TQDomElement&body ) \n"; + kdDebug()<<"validation.isNull ? "<m_loadingInfo->appendValidation(element.attributeNS( KoXmlNS::table, "name", TQString() ), element ); + kdDebug()<<" validation found :"<0 ) + { + xmlWriter.startElement( "table:named-expressions" ); + TQValueList::Iterator it; + for ( it = d->refs.begin(); it != d->refs.end(); ++it ) + { + xmlWriter.startElement( "table:named-range" ); + + xmlWriter.addAttribute( "table:name", ( *it ).ref_name ); + xmlWriter.addAttribute( "table:base-cell-address", convertRefToBase( ( *it ).sheet_name, ( *it ).rect ) ); + xmlWriter.addAttribute( "table:cell-range-address", convertRefToRange( ( *it ).sheet_name, ( *it ).rect ) ); + + xmlWriter.endElement(); + } + xmlWriter.endElement(); + } +} + +void Doc::loadOasisAreaName( const TQDomElement& body ) +{ + kdDebug()<<"void Doc::loadOasisAreaName( const TQDomElement& body ) \n"; + TQDomNode namedAreas = KoDom::namedItemNS( body, KoXmlNS::table, "named-expressions" ); + if ( !namedAreas.isNull() ) + { + kdDebug()<<" area name exist \n"; + TQDomNode area = namedAreas.firstChild(); + while ( !area.isNull() ) + { + TQDomElement e = area.toElement(); + + if ( e.localName() == "named-range" ) + { + if ( !e.hasAttributeNS( KoXmlNS::table, "name" ) || !e.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) ) + { + kdDebug() << "Reading in named area failed" << endl; + area = area.nextSibling(); + continue; + } + + // TODO: what is: sheet:base-cell-address + TQString name = e.attributeNS( KoXmlNS::table, "name", TQString() ); + TQString range = e.attributeNS( KoXmlNS::table, "cell-range-address", TQString() ); + kdDebug()<<"area name : "<m_loadingInfo->addWordInAreaList( name ); + kdDebug() << "Reading in named area, name: " << name << ", area: " << range << endl; + + range = Oasis::decodeFormula( range ); + + if ( range.find( ':' ) == -1 ) + { + Point p( range ); + + int n = range.find( '!' ); + if ( n > 0 ) + range = range + ":" + range.right( range.length() - n - 1); + + kdDebug() << "=> Area: " << range << endl; + } + + if ( range.contains( '!' ) && range[0] == '$' ) + { + // cut absolute sheet indicator + range.remove( 0, 1 ); + } + + Range p( range ); + + addAreaName( p.range(), name, p.sheetName() ); + kdDebug() << "Area range: " << p.toString() << endl; + } + else if ( e.localName() == "named-expression" ) + { + kdDebug() << "Named expression found." << endl; + // TODO + } + + area = area.nextSibling(); + } + } +} + +void Doc::loadAreaName( const TQDomElement& element ) +{ + TQDomElement tmp=element.firstChild().toElement(); + for( ; !tmp.isNull(); tmp=tmp.nextSibling().toElement() ) + { + if ( tmp.tagName() == "reference" ) + { + TQString tabname; + TQString refname; + int left=0; + int right=0; + int top=0; + int bottom=0; + TQDomElement sheetName = tmp.namedItem( "tabname" ).toElement(); + if ( !sheetName.isNull() ) + { + tabname=sheetName.text(); + } + TQDomElement referenceName = tmp.namedItem( "refname" ).toElement(); + if ( !referenceName.isNull() ) + { + refname=referenceName.text(); + } + TQDomElement rect =tmp.namedItem( "rect" ).toElement(); + if (!rect.isNull()) + { + bool ok; + if ( rect.hasAttribute( "left-rect" ) ) + left=rect.attribute("left-rect").toInt( &ok ); + if ( rect.hasAttribute( "right-rect" ) ) + right=rect.attribute("right-rect").toInt( &ok ); + if ( rect.hasAttribute( "top-rect" ) ) + top=rect.attribute("top-rect").toInt( &ok ); + if ( rect.hasAttribute( "bottom-rect" ) ) + bottom=rect.attribute("bottom-rect").toInt( &ok ); + } + TQRect _rect; + _rect.setCoords(left,top,right,bottom); + addAreaName(_rect,refname,tabname); + } + } +} + +void Doc::addStringCompletion(const TQString &stringCompletion) +{ + if ( d->listCompletion.items().contains(stringCompletion) == 0 ) + d->listCompletion.addItem( stringCompletion ); +} + +void Doc::refreshInterface() +{ + emit sig_refreshView(); +} + +void Doc::refreshLocale() +{ + emit sig_refreshLocale(); +} + + +void Doc::emitBeginOperation(bool waitCursor) +{ + //If an emitBeginOperation occurs with waitCursor enabled, then the waiting cursor is set + //until all operations have been completed. + // + //The reason being that any operations started before the first one with waitCursor set + //are expected to be completed in a short time anyway. + TQCursor* activeOverride = static_cast(TQApplication::overrideCursor()); + + if (waitCursor && ( (!activeOverride) || (activeOverride->shape() != TQt::waitCursor.shape()) ) ) + { + TQApplication::setOverrideCursor(TQt::waitCursor); + } + +// /* just duplicate the current cursor on the stack, then */ +// else if (TQApplication::overrideCursor() != NULL) +// { +// TQApplication::setOverrideCursor(TQApplication::overrideCursor()->shape()); +// } + + KoDocument::emitBeginOperation(); + d->delayCalculation = true; + d->numOperations++; +} + +void Doc::emitBeginOperation(void) +{ + emitBeginOperation(true); +} + + +void Doc::emitEndOperation() +{ + d->numOperations--; + + if (d->numOperations <= 0) + { + d->numOperations = 0; + d->delayCalculation = false; + } + + KoDocument::emitEndOperation(); + + if (d->numOperations == 0) + { + TQApplication::restoreOverrideCursor(); + + /* do this after the parent class emitEndOperation because that allows updates + on the view again + */ + paintUpdates(); + } +} + +void Doc::emitEndOperation( const Region& /*region*/ ) +{ + d->numOperations--; + + if ( d->numOperations > 0 || !d->activeSheet ) + { + KoDocument::emitEndOperation(); + return; + } + + d->numOperations = 0; + d->delayCalculation = false; + + KoDocument::emitEndOperation(); + + TQApplication::restoreOverrideCursor(); + + /* do this after the parent class emitEndOperation because that allows updates + on the view again + */ + paintUpdates(); +} + +bool Doc::delayCalculation() const +{ + return d->delayCalculation; +} + +void Doc::updateBorderButton() +{ + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + static_cast( it.current() )->updateBorderButton(); +} + +void Doc::insertSheet( Sheet * sheet ) +{ + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + ((View*)it.current())->insertSheet( sheet ); +} + +void Doc::takeSheet( Sheet * sheet ) +{ + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + ((View*)it.current())->removeSheet( sheet ); +} + +void Doc::addIgnoreWordAll( const TQString & word) +{ + if( d->spellListIgnoreAll.findIndex( word )==-1) + d->spellListIgnoreAll.append( word ); +} + +void Doc::clearIgnoreWordAll( ) +{ + d->spellListIgnoreAll.clear(); +} + +void Doc::setDisplaySheet(Sheet *_sheet ) +{ + d->activeSheet = _sheet; +} + +KSPLoadingInfo * Doc::loadingInfo() const +{ + return d->m_loadingInfo; +} + +void Doc::deleteLoadingInfo() +{ + delete d->m_loadingInfo; + d->m_loadingInfo = 0; +} + +Sheet * Doc::displaySheet() const +{ + return d->activeSheet; +} + +void Doc::addView( KoView *_view ) +{ + KoDocument::addView( _view ); + TQPtrListIterator it( views() ); + for (; it.current(); ++it ) + ((View*)it.current())->closeEditor(); +} + +void Doc::addDamage( Damage* damage ) +{ + d->damages.append( damage ); + + if( d->damages.count() == 1 ) + TQTimer::singleShot( 0, this, TQT_SLOT( flushDamages() ) ); +} + +void Doc::flushDamages() +{ + emit damagesFlushed( d->damages ); + TQValueList::Iterator it; + for( it = d->damages.begin(); it != d->damages.end(); ++it ) + delete *it; + d->damages.clear(); +} + +void Doc::loadConfigFromFile() +{ + d->configLoadFromFile = true; +} + +bool Doc::configLoadFromFile() const +{ + return d->configLoadFromFile; +} + + +void Doc::insertObject( EmbeddedObject * obj ) +{ + switch ( obj->getType() ) + { + case OBJECT_KOFFICE_PART: case OBJECT_CHART: + { + KoDocument::insertChild( dynamic_cast(obj)->embeddedObject() ); + break; + } + default: + ; + } + d->m_embeddedObjects.append( obj ); +} + +TQPtrList& Doc::embeddedObjects() +{ + return d->m_embeddedObjects; +} + +KoPictureCollection *Doc::pictureCollection() +{ + return &d->m_pictureCollection; +} + +void Doc::repaint( const TQRect& rect ) +{ + TQRect r; + TQPtrListIterator it( views() ); + for( ; it.current(); ++it ) + { + r = rect; + Canvas* canvas = ((View*)it.current())->canvasWidget(); + r.moveTopLeft( TQPoint( r.x() - (int) canvas->xOffset(), + r.y() - (int) canvas->yOffset() ) ); + canvas->update( r ); + } +} + +void Doc::repaint( EmbeddedObject *obj ) +{ + TQPtrListIterator it( views() ); + for( ; it.current(); ++it ) + { + Canvas* canvas = ((View*)it.current())->canvasWidget(); + if ( obj->sheet() == canvas->activeSheet() ) + canvas->repaintObject( obj ); + } +} + +void Doc::repaint( const KoRect& rect ) +{ + TQRect r; + TQPtrListIterator it( views() ); + for( ; it.current(); ++it ) + { + Canvas* canvas = ((View*)it.current())->canvasWidget(); + + r = zoomRect( rect ); + r.moveBy( (int)( -canvas->xOffset()*zoomedResolutionX() ) , + (int)( -canvas->yOffset() *zoomedResolutionY()) ); + canvas->update( r ); + } +} + +void Doc::addShell( KoMainWindow *shell ) +{ + connect( shell, TQT_SIGNAL( documentSaved() ), d->commandHistory, TQT_SLOT( documentSaved() ) ); + KoDocument::addShell( shell ); +} + +int Doc::undoRedoLimit() const +{ + return d->commandHistory->undoLimit(); +} + +void Doc::setUndoRedoLimit(int val) +{ + d->commandHistory->setUndoLimit(val); + d->commandHistory->setRedoLimit(val); +} + +void Doc::insertPixmapKey( KoPictureKey key ) +{ + if ( !d->usedPictures.contains( key ) ) + d->usedPictures.append( key ); +} + +void Doc::makeUsedPixmapList() +{ + d->usedPictures.clear(); + TQPtrListIterator it( d->m_embeddedObjects ); + for ( ; it.current() ; ++it ) + { + if( it.current()->getType() == OBJECT_PICTURE && ( d->m_savingWholeDocument || it.current()->isSelected() ) ) + insertPixmapKey( static_cast( it.current() )->getKey() ); + } +} + +bool Doc::savingWholeDocument() +{ + return d->m_savingWholeDocument; +} + +#include "kspread_doc.moc" + diff --git a/kspread/kspread_editors.cc b/kspread/kspread_editors.cc deleted file mode 100644 index 4af76159..00000000 --- a/kspread/kspread_editors.cc +++ /dev/null @@ -1,1589 +0,0 @@ -/* This file is part of the KDE project - - Copyright 1999-2006 The KSpread Team - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_editors.h" -#include "kspread_canvas.h" -#include "kspread_cell.h" -#include "kspread_doc.h" -#include "selection.h" -#include "kspread_sheet.h" -#include "kspread_view.h" -#include "kspread_util.h" -#include "formula.h" -#include "functions.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -//#include -#include -#include -#include -#include -#include -#include -#include - -using namespace KSpread; - - - -/***************************************************************************** - * - * FormulaEditorHighlighter - * - ****************************************************************************/ - -namespace KSpread -{ - -class FormulaEditorHighlighter::Private -{ -public: - Private() - { - canvas = 0; - tokens = Tokens(); - rangeCount = 0; - rangeChanged = false; - } - - // source for cell reference checking - Canvas* canvas; - Tokens tokens; - uint rangeCount; - bool rangeChanged; -}; - - -FormulaEditorHighlighter::FormulaEditorHighlighter(TQTextEdit* textEdit, Canvas* canvas) - : TQSyntaxHighlighter(textEdit) -{ - d = new Private(); - d->canvas = canvas; -} - -FormulaEditorHighlighter::~FormulaEditorHighlighter() -{ - delete d; -} - -const Tokens& FormulaEditorHighlighter::formulaTokens() const -{ - return d->tokens; -} - -int FormulaEditorHighlighter::highlightParagraph(const TQString& text, int /* endStateOfLastPara */) -{ - // reset syntax highlighting - setFormat(0, text.length(), TQt::black); - - // save the old ones to identify range changes - Tokens oldTokens = d->tokens; - - // interpret the text as formula - // we accept invalid/incomplete formulas - Formula f; - d->tokens = f.scan(text); - - TQFont editorFont = textEdit()->currentFont(); - TQFont font; - - uint oldRangeCount = d->rangeCount; - - d->rangeCount = 0; - TQValueList colors = d->canvas->choice()->colors(); - TQValueList alreadyFoundRanges; - - for (uint i = 0; i < d->tokens.count(); ++i) - { - Token token = d->tokens[i]; - Token::Type type = token.type(); - - switch (type) - { - case Token::Cell: - case Token::Range: - { - // don't compare, if we have already found a change - if (!d->rangeChanged && i < oldTokens.count() && token.text() != oldTokens[i].text()) - { - d->rangeChanged = true; - } - - Range newRange( token.text() ); - - if (!alreadyFoundRanges.contains(newRange)) - { - alreadyFoundRanges.append(newRange); - d->rangeCount++; - } - setFormat(token.pos() + 1, token.text().length(), colors[ alreadyFoundRanges.findIndex(newRange) % colors.size()] ); - } - break; - case Token::Boolean: // True, False (also i18n-ized) -/* font = TQFont(editorFont); - font.setBold(true); - setFormat(token.pos() + 1, token.text().length(), font);*/ - break; - case Token::Identifier: // function name or named area*/ -/* font = TQFont(editorFont); - font.setBold(true); - setFormat(token.pos() + 1, token.text().length(), font);*/ - break; - - case Token::Unknown: - case Token::Integer: // 14, 3, 1977 - case Token::Float: // 3.141592, 1e10, 5.9e-7 - case Token::String: // "KOffice", "The quick brown fox..." - case Token::Operator: // +, *, /, - - { - switch (token.asOperator()) - { - case Token::LeftPar: - case Token::RightPar: - //Check where this brace is in relation to the cursor and highlight it if necessary. - handleBrace( i ); - break; - default: - break; - } - } - break; - } - } - - if (oldRangeCount != d->rangeCount) - d->rangeChanged = true; - - return 0; -} - -void FormulaEditorHighlighter::handleBrace( uint index ) -{ - int cursorParagraph; - int cursorPos; - const Token& token = d->tokens.at( index ); - - textEdit()->getCursorPosition( &cursorParagraph , &cursorPos ); - - int distance = cursorPos-token.pos(); - int opType = token.asOperator(); - bool highlightBrace=false; - - //Check where the cursor is in relation to this left or right parenthesis token. - //Only one pair of braces should be highlighted at a time, and if the cursor - //is between two braces, the inner-most pair should be highlighted. - - if ( opType == Token::LeftPar ) - { - //If cursor is directly to the left of this left brace, highlight it - if ( distance == 1 ) - highlightBrace=true; - else - //Cursor is directly to the right of this left brace, highlight it unless - //there is another left brace to the right (in which case that should be highlighted instead as it - //is the inner-most brace) - if (distance==2) - if ( (index == d->tokens.count()-1) || ( d->tokens.at(index+1).asOperator() != Token::LeftPar) ) - highlightBrace=true; - - } - else - { - //If cursor is directly to the right of this right brace, highlight it - if ( distance == 2 ) - highlightBrace=true; - else - //Cursor is directly to the left of this right brace, so highlight it unless - //there is another right brace to the left (in which case that should be highlighted instead as it - //is the inner-most brace) - if ( distance == 1 ) - if ( (index == 0) || (d->tokens.at(index-1).asOperator() != Token::RightPar) ) - highlightBrace=true; - } - - if (highlightBrace) - { - TQFont font = TQFont( textEdit()->currentFont() ); - font.setBold(true); - setFormat(token.pos() + 1, token.text().length(), font); - - int matching = findMatchingBrace( index ); - - if (matching != -1) - { - Token matchingBrace = d->tokens.at(matching); - setFormat( matchingBrace.pos() + 1 , matchingBrace.text().length() , font); - } - } -} - -int FormulaEditorHighlighter::findMatchingBrace(int pos) -{ - int depth=0; - int step=0; - - Tokens tokens = d->tokens; - - //If this is a left brace we need to step forwards through the text to find the matching right brace, - //otherwise, it is a right brace so we need to step backwards through the text to find the matching left - //brace. - if (tokens.at(pos).asOperator() == Token::LeftPar) - step = 1; - else - step = -1; - - for (int index=pos ; (index >= 0) && (index < (int) tokens.count() ) ; index += step ) - { - if (tokens.at(index).asOperator() == Token::LeftPar) - depth++; - if (tokens.at(index).asOperator() == Token::RightPar) - depth--; - - if (depth == 0) - { - return index; - } - } - - return -1; -} - -uint FormulaEditorHighlighter::rangeCount() const -{ - return d->rangeCount; -} - -bool FormulaEditorHighlighter::rangeChanged() const -{ - return d->rangeChanged; -} - -void FormulaEditorHighlighter::resetRangeChanged() -{ - d->rangeChanged=false; -} - -} // namespace KSpread - - - -/***************************************************************************** - * - * FunctionCompletion - * - ****************************************************************************/ - -class FunctionCompletion::Private -{ -public: - CellEditor* editor; - TQVBox *completionPopup; - TDEListBox *completionListBox; - TQLabel* hintLabel; -}; - -FunctionCompletion::FunctionCompletion( CellEditor* editor ): -TQObject( editor ) -{ - d = new Private; - d->editor = editor; - d->hintLabel = 0; - - d->completionPopup = new TQVBox( editor->topLevelWidget(), 0, WType_Popup ); - d->completionPopup->setFrameStyle( TQFrame::Box | TQFrame::Plain ); - d->completionPopup->setLineWidth( 1 ); - d->completionPopup->installEventFilter( this ); - d->completionPopup->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Minimum); - - d->completionListBox = new TDEListBox( d->completionPopup ); - d->completionPopup->setFocusProxy( d->completionListBox ); - d->completionListBox->setFrameStyle( TQFrame::NoFrame ); - d->completionListBox->setVariableWidth( true ); - d->completionListBox->installEventFilter( this ); - connect( d->completionListBox, TQT_SIGNAL(selected(const TQString&)), this, - TQT_SLOT(itemSelected(const TQString&)) ); - connect( d->completionListBox, TQT_SIGNAL(highlighted(const TQString&)), this, - TQT_SLOT(itemSelected(const TQString&)) ); - - d->hintLabel = new TQLabel( 0, "autocalc", TQt::WStyle_StaysOnTop | - TQt::WStyle_Customize | TQt::WStyle_NoBorder | TQt::WStyle_Tool | TQt::WX11BypassWM ); - d->hintLabel->setFrameStyle( TQFrame::Plain | TQFrame::Box ); - d->hintLabel->setPalette( TQToolTip::palette() ); - d->hintLabel->hide(); -} - -FunctionCompletion::~FunctionCompletion() -{ - delete d->hintLabel; - delete d; -} - -void FunctionCompletion::itemSelected( const TQString& item ) -{ - KSpread::FunctionDescription* desc; - desc = KSpread::FunctionRepository::self()->functionInfo(item); - if(!desc) - { - d->hintLabel->hide(); - return; - } - - TQString helpText = desc->helpText()[0]; - if( helpText.isEmpty() ) - { - d->hintLabel->hide(); - return; - } - - helpText.append("").prepend(""); - d->hintLabel->setText( helpText ); - d->hintLabel->adjustSize(); - - // reposition nicely - TQPoint pos = d->editor->mapToGlobal( TQPoint( d->editor->width(), 0 ) ); - pos.setY( pos.y() - d->hintLabel->height() - 1 ); - d->hintLabel->move( pos ); - d->hintLabel->show(); - d->hintLabel->raise(); - - // do not show it forever - //TQTimer::singleShot( 5000, d->hintLabel, TQT_SLOT( hide()) ); -} - -bool FunctionCompletion::eventFilter( TQObject *obj, TQEvent *ev ) -{ - if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(d->completionPopup) || TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(d->completionListBox) ) - { - if ( ev->type() == TQEvent::KeyPress ) - { - TQKeyEvent *ke = (TQKeyEvent*)ev; - if ( ke->key() == Key_Enter || ke->key() == Key_Return ) - { - doneCompletion(); - return true; - } - else if ( ke->key() == Key_Left || ke->key() == Key_Right || - ke->key() == Key_Up || ke->key() == Key_Down || - ke->key() == Key_Home || ke->key() == Key_End || - ke->key() == Key_Prior || ke->key() == Key_Next ) - return false; - - d->hintLabel->hide(); - d->completionPopup->close(); - d->editor->setFocus(); - TQApplication::sendEvent( d->editor, ev ); - return true; - } - - if ( ev->type() == TQEvent::MouseButtonDblClick ) - { - doneCompletion(); - return true; - } - } - - return false; -} - -void FunctionCompletion::doneCompletion() -{ - d->hintLabel->hide(); - d->completionPopup->close(); - d->editor->setFocus(); - emit selectedCompletion( d->completionListBox->currentText() ); -} - -void FunctionCompletion::showCompletion( const TQStringList &choices ) -{ - if( !choices.count() ) return; - - d->completionListBox->clear(); - for( unsigned i = 0; i < choices.count(); i++ ) - new TQListBoxText( (TQListBox*)d->completionListBox, choices[i] ); - d->completionListBox->setCurrentItem( 0 ); - - // size of the pop-up - d->completionPopup->setMaximumHeight( 100 ); - d->completionPopup->resize( d->completionListBox->sizeHint() + - TQSize( d->completionListBox->verticalScrollBar()->width() + 4, - d->completionListBox->horizontalScrollBar()->height() + 4 ) ); - int h = d->completionListBox->height(); - int w = d->completionListBox->width(); - - TQPoint pos = d->editor->globalCursorPosition(); - - // if popup is partially invisible, move to other position - // FIXME check it if it works in Xinerama multihead - int screen_num = TQApplication::desktop()->screenNumber( d->completionPopup ); - TQRect screen = TQApplication::desktop()->screenGeometry( screen_num ); - if( pos.y() + h > screen.y()+screen.height() ) - pos.setY( pos.y() - h - d->editor->height() ); - if( pos.x() + w > screen.x()+screen.width() ) - pos.setX( screen.x()+screen.width() - w ); - - d->completionPopup->move( pos ); - d->completionListBox->setFocus(); - d->completionPopup->show(); -} - - - -/**************************************************************************** - * - * CellEditor - * - ****************************************************************************/ - -class CellEditor::Private -{ -public: - Cell* cell; - Canvas* canvas; - KTextEdit* textEdit; - FormulaEditorHighlighter* highlighter; - FunctionCompletion* functionCompletion; - TQTimer* functionCompletionTimer; - - TQPoint globalCursorPos; - - bool captureAllKeyEvents : 1; - bool checkChoice : 1; - bool updateChoice : 1; - bool updatingChoice : 1; - - uint length; - uint fontLength; - uint length_namecell; - uint length_text; - uint currentToken; - uint rangeCount; -}; - - -CellEditor::CellEditor( Cell* _cell, Canvas* _parent, bool captureAllKeyEvents, const char* _name ) - : TQWidget( _parent, _name ) -{ - d = new Private(); - d->cell = _cell; - d->canvas = _parent; - d->textEdit = new KTextEdit(this); - d->globalCursorPos = TQPoint(); - d->captureAllKeyEvents = captureAllKeyEvents; - d->checkChoice = true; - d->updateChoice = true; - d->updatingChoice = false; - d->length = 0; - d->fontLength = 0; - d->length_namecell = 0; - d->length_text = 0; - d->currentToken = 0; - d->rangeCount = 0; - -//TODO - Get rid of TQTextEdit margins, this doesn't seem easily possible in TQt 3.3, so a job for TQt 4 porting. - - d->textEdit->setHScrollBarMode(TQScrollView::AlwaysOff); - d->textEdit->setVScrollBarMode(TQScrollView::AlwaysOff); - d->textEdit->setFrameStyle(TQFrame::NoFrame); - d->textEdit->setLineWidth(0); - d->textEdit->installEventFilter( this ); - - d->highlighter = new FormulaEditorHighlighter(d->textEdit, _parent); - - d->functionCompletion = new FunctionCompletion( this ); - d->functionCompletionTimer = new TQTimer( this ); - connect( d->functionCompletion, TQT_SIGNAL( selectedCompletion( const TQString& ) ), - TQT_SLOT( functionAutoComplete( const TQString& ) ) ); - connect( d->textEdit, TQT_SIGNAL( textChanged() ), TQT_SLOT( checkFunctionAutoComplete() ) ); - connect( d->functionCompletionTimer, TQT_SIGNAL( timeout() ), - TQT_SLOT( triggerFunctionAutoComplete() ) ); - - if (!cell()->format()->multiRow(cell()->column(),cell()->row())) - d->textEdit->setWordWrap(TQTextEdit::NoWrap); - else - d->textEdit->setWrapPolicy(TQTextEdit::AtWordOrDocumentBoundary); - -//TODO - Custom KTextEdit class which supports text completion -/* - d->textEdit->setFrame( false ); - d->textEdit->setCompletionMode((TDEGlobalSettings::Completion)canvas()->view()->doc()->completionMode() ); - d->textEdit->setCompletionObject( &canvas()->view()->doc()->completion(),true ); -*/ - setFocusProxy( d->textEdit ); - - connect( d->textEdit, TQT_SIGNAL( cursorPositionChanged(int,int) ), this, TQT_SLOT (slotCursorPositionChanged(int,int))); - connect( d->textEdit, TQT_SIGNAL( cursorPositionChanged(TQTextCursor*) ), this, TQT_SLOT (slotTextCursorChanged(TQTextCursor*))); - connect( d->textEdit, TQT_SIGNAL( textChanged() ), this, TQT_SLOT( slotTextChanged() ) ); - -// connect( d->textEdit, TQT_SIGNAL(completionModeChanged( TDEGlobalSettings::Completion )),this,TQT_SLOT (slotCompletionModeChanged(TDEGlobalSettings::Completion))); - - // A choose should always start at the edited cell -// canvas()->setChooseMarkerRow( canvas()->markerRow() ); -// canvas()->setChooseMarkerColumn( canvas()->markerColumn() ); - - // set font size according to zoom factor - TQFont font( _cell->format()->font() ); - font.setPointSizeFloat( 0.01 * _parent->doc()->zoom() * font.pointSizeFloat() ); - d->textEdit->setFont( font ); - - if (d->fontLength == 0) - { - TQFontMetrics fm( d->textEdit->font() ); - d->fontLength = fm.width('x'); - } -} - -CellEditor::~CellEditor() -{ - canvas()->endChoose(); - - delete d->highlighter; - delete d->functionCompletion; - delete d->functionCompletionTimer; - delete d; -} - -Cell* CellEditor::cell() const -{ - return d->cell; -} - -Canvas* CellEditor::canvas() const -{ - return d->canvas; -} - -TQPoint CellEditor::globalCursorPosition() const -{ - return d->globalCursorPos; -} - -void CellEditor::checkFunctionAutoComplete() -{ - d->functionCompletionTimer->stop(); - d->functionCompletionTimer->start( 2000, true ); -} - -void CellEditor::triggerFunctionAutoComplete() -{ - // tokenize the expression (don't worry, this is very fast) - int para = 0, curPos = 0; - d->textEdit->getCursorPosition( ¶, &curPos ); - TQString subtext = d->textEdit->text().left( curPos ); - - KSpread::Formula f; - KSpread::Tokens tokens = f.scan( subtext ); - if( !tokens.valid() ) return; - if( tokens.count()<1 ) return; - - KSpread::Token lastToken = tokens[ tokens.count()-1 ]; - - // last token must be an identifier - if( !lastToken.isIdentifier() ) return; - TQString id = lastToken.text(); - if( id.length() < 1 ) return; - - // find matches in function names - TQStringList fnames = KSpread::FunctionRepository::self()->functionNames(); - TQStringList choices; - for( unsigned i=0; ifunctionCompletion->showCompletion( choices ); -} - -void CellEditor::functionAutoComplete( const TQString& item ) -{ - if( item.isEmpty() ) return; - - int para = 0, curPos = 0; - d->textEdit->getCursorPosition( ¶, &curPos ); - TQString subtext = text().left( curPos ); - - KSpread::Formula f; - KSpread::Tokens tokens = f.scan( subtext ); - if( !tokens.valid() ) return; - if( tokens.count()<1 ) return; - - KSpread::Token lastToken = tokens[ tokens.count()-1 ]; - if( !lastToken.isIdentifier() ) return; - - d->textEdit->blockSignals( true ); - d->textEdit->setSelection( 0, lastToken.pos()+1, 0, lastToken.pos()+lastToken.text().length()+1 ); - d->textEdit->insert( item ); - d->textEdit->blockSignals( false ); -} - -void CellEditor::slotCursorPositionChanged(int /* para */, int pos) -{ -// kdDebug() << k_funcinfo << endl; - - // TODO Stefan: optimize this function! - - // turn choose mode on/off - if (!checkChoice()) - return; - - d->highlighter->rehighlight(); - - Tokens tokens = d->highlighter->formulaTokens(); - uint rangeCounter = 0; - uint currentRange = 0; - uint regionStart = 0; - uint regionEnd = 0; - bool lastWasASemicolon = false; - d->currentToken = 0; - uint rangeCount = d->highlighter->rangeCount(); - d->rangeCount = rangeCount; - - Token token; - Token::Type type; - // search the current token - // determine the subregion number, btw - for (uint i = 0; i < tokens.count(); ++i) - { - if (tokens[i].pos() >= pos - 1) // without '=' - { -/* kdDebug() << "token.pos >= cursor.pos" << endl;*/ - type = tokens[i].type(); - if (type == Token::Cell || type == Token::Range) - { - if (lastWasASemicolon) - { - regionEnd = rangeCounter++; - lastWasASemicolon = false; - continue; - } - } - if (type == Token::Operator && tokens[i].asOperator() == Token::Semicolon) - { - lastWasASemicolon = true; - continue; - } - lastWasASemicolon = false; - break; - } - token = tokens[i]; - d->currentToken = i; - - type = token.type(); - if (type == Token::Cell || type == Token::Range) - { - if (!lastWasASemicolon) - { - regionStart = rangeCounter; - } - regionEnd = rangeCounter; - currentRange = rangeCounter++; - } - // semicolons are use as deliminiters in regions - if (type == Token::Operator) - { - if (token.asOperator() == Token::Semicolon) - { - lastWasASemicolon = true; - } - else - { - lastWasASemicolon = false; - // set the region start to the next element - regionStart = currentRange + 1; - regionEnd = regionStart - 1; // len = 0 - } - } - } - -// kdDebug() << "regionStart = " << regionStart/* << endl*/ -// << ", regionEnd = " << regionEnd/* << endl*/ -// << ", currentRange = " << currentRange << endl; - - d->canvas->choice()->setActiveElement(currentRange); - d->canvas->choice()->setActiveSubRegion(regionStart, regionEnd-regionStart+1); - - // triggered by keyboard action? - if (!d->updatingChoice) - { - if (d->highlighter->rangeChanged()) - { - d->highlighter->resetRangeChanged(); - - disconnect( d->canvas->choice(), TQT_SIGNAL(changed(const Region&)), - d->canvas->view(), TQT_SLOT(slotScrollChoice(const Region&)) ); - d->canvas->doc()->emitBeginOperation(); - setUpdateChoice(false); - - Tokens tokens = d->highlighter->formulaTokens(); - d->canvas->choice()->update(); // set the old one dirty - d->canvas->choice()->clear(); - Region tmpRegion; - Region::ConstIterator it; - - //A list of regions which have already been highlighted on the spreadsheet. - //This is so that we don't end up highlighting the same region twice in two different - //colours. - TQValueList alreadyUsedRegions; - - for (uint i = 0; i < tokens.count(); ++i) - { - Token token = tokens[i]; - Token::Type type = token.type(); - if (type == Token::Cell || type == Token::Range) - { - Region region(d->canvas->view(), token.text()); - it = region.constBegin(); - - if (!alreadyUsedRegions.contains(region)) - { - TQRect r=(*it)->rect(); - - if (d->canvas->choice()->isEmpty()) - d->canvas->choice()->initialize((*it)->rect(), (*it)->sheet()); - else - d->canvas->choice()->extend((*it)->rect(), (*it)->sheet()); - - alreadyUsedRegions.append(region); - } - } - } - setUpdateChoice(true); - d->canvas->doc()->emitEndOperation(*d->canvas->choice()); - connect( d->canvas->choice(), TQT_SIGNAL(changed(const Region&)), - d->canvas->view(), TQT_SLOT(slotScrollChoice(const Region&)) ); - } - } -} - -void CellEditor::slotTextCursorChanged(TQTextCursor* cursor) -{ - TQTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); - int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); - int x = cursor->paragraph()->rect().x() + chr->x; - int y, dummy; - cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); - y += cursor->paragraph()->rect().y(); - - d->globalCursorPos = d->textEdit->mapToGlobal( d->textEdit-> contentsToViewport( TQPoint( x, y + h ) ) ); -} - -void CellEditor::cut() -{ - d->textEdit->cut(); -} - -void CellEditor::paste() -{ - d->textEdit->paste(); -} - -void CellEditor::copy() -{ - d->textEdit->copy(); -} - -void CellEditor::setEditorFont(TQFont const & font, bool updateSize) -{ - TQFont tmpFont( font ); - tmpFont.setPointSizeFloat( 0.01 * canvas()->doc()->zoom() * tmpFont.pointSizeFloat() ); - d->textEdit->setFont( tmpFont ); - - if (updateSize) - { - TQFontMetrics fm( d->textEdit->font() ); - d->fontLength = fm.width('x'); - - int mw = fm.width( d->textEdit->text() ) + d->fontLength; - // don't make it smaller: then we would have to repaint the obscured cells - if (mw < width()) - mw = width(); - - int mh = fm.height(); - if (mh < height()) - mh = height(); - - setGeometry(x(), y(), mw, mh); - } -} - -void CellEditor::slotCompletionModeChanged(TDEGlobalSettings::Completion _completion) -{ - canvas()->view()->doc()->setCompletionMode( _completion ); -} - -void CellEditor::slotTextChanged() -{ -// kdDebug() << k_funcinfo << endl; - - //FIXME - text() may return richtext? - TQString t = text(); - - if (t.length() > d->length) - { - d->length = t.length(); - - TQFontMetrics fm(d->textEdit->font()); - // - requiredWidth = width of text plus some spacer characters - int requiredWidth = fm.width(t) + (2*fm.width('x')); - - //For normal single-row cells, the text editor must be expanded horizontally to - //allow the text to fit if the new text is too wide - //For multi-row (word-wrap enabled) cells, the text editor must expand vertically to - //allow for new rows of text & the width of the text editor is not affected - if (d->textEdit->wordWrap() == TQTextEdit::NoWrap) - { - if (requiredWidth > width()) - { - if (t.isRightToLeft()) - { - setGeometry(x() - requiredWidth + width(), y(), requiredWidth,height()); - } - else - { - setGeometry(x(), y(), requiredWidth,height()); - } - } - } - else - { - int requiredHeight = d->textEdit->heightForWidth(width()); - - if (requiredHeight > height()) - { - setGeometry(x(), y(), width(), requiredHeight); - } - } - - /* // allocate more space than needed. Otherwise it might be too slow - d->length = t.length(); - - // Too slow for long texts - // TQFontMetrics fm( d->textEdit->font() ); - // int mw = fm.width( t ) + fm.width('x'); - int mw = d->fontLength * d->length; - - if (mw < width()) - mw = width(); - - if (t.isRightToLeft()) - setGeometry(x() - mw + width(), y(), mw, height()); - else - setGeometry(x(), y(), mw, height()); - - d->length -= 2; */ - } - - if ( (cell()->formatType()) == Percentage_format ) - { - if ( (t.length() == 1) && t[0].isDigit() ) - { - TQString tmp = t + " %"; - d->textEdit->setText(tmp); - d->textEdit->setCursorPosition(0,1); - return; - } - } - - canvas()->view()->editWidget()->setText( t ); - // canvas()->view()->editWidget()->setCursorPosition( d->textEdit->cursorPosition() ); -} - -void CellEditor::setCheckChoice(bool state) -{ - d->checkChoice = state; -} - -bool CellEditor::checkChoice() -{ - if (!d->checkChoice) - return false; - -// // prevent recursion -// d->checkChoice = false; // TODO nescessary? - - d->length_namecell = 0; - d->currentToken = 0; - - TQString text = d->textEdit->text(); - if ( text[0] != '=' ) - { - canvas()->setChooseMode(false); - } - else - { - int para, cur; - d->textEdit->getCursorPosition(¶, &cur); - - Tokens tokens = d->highlighter->formulaTokens(); - - // empty formula? - if (tokens.count() < 1) - { - canvas()->startChoose(); - } - else - { - Token token; - for (uint i = 0; i < tokens.count(); ++i) - { - if (tokens[i].pos() >= cur - 1) // without '=' - { - break; - } - token = tokens[i]; - d->currentToken = i; - } - - Token::Type type = token.type(); - if (type == Token::Operator && token.asOperator() != Token::RightPar) - { - canvas()->setChooseMode(true); - } - else if (type == Token::Cell || type == Token::Range) - { - d->length_namecell = token.text().length(); - canvas()->setChooseMode(true); - } - else - { - canvas()->setChooseMode(false); - } - } - } - -// d->checkChoice = true; - - return true; -} - -void CellEditor::setUpdateChoice(bool state) -{ - d->updateChoice = state; -} - -void CellEditor::updateChoice() -{ -// kdDebug() << k_funcinfo << endl; - - if (!d->updateChoice) - return; - -// // prevent recursion -// d->updateChoice = false; // TODO nescessary? - d->updatingChoice = true; - - Selection* choice = d->canvas->choice(); - - if (choice->isEmpty()) - return; - - if (!choice->activeElement()) - return; - - // only one element TODO - if (++choice->constBegin() == choice->constEnd()) - { - } - - TQString name_cell = choice->activeSubRegionName(); - - Tokens tokens = d->highlighter->formulaTokens(); - uint start = 1; - uint length = 0; - if (!tokens.empty()) - { - Token token = tokens[d->currentToken]; - Token::Type type = token.type(); - if (type == Token::Cell || type == Token::Range) - { - start = token.pos() + 1; // don't forget the '='! - length = token.text().length(); - } - else - { - start = token.pos() + token.text().length() + 1; - } - } - - d->length_namecell = name_cell.length(); - d->length_text = text().length(); - //kdDebug(36001) << "updateChooseMarker2 len=" << d->length_namecell << endl; - - TQString oldText = text(); - TQString newText = oldText.left(start) + name_cell + oldText.right(d->length_text - start - length); - - setCheckChoice( false ); - setText( newText ); - setCheckChoice( true ); - setCursorPosition( start + d->length_namecell ); - - d->canvas->view()->editWidget()->setText( newText ); - //kdDebug(36001) << "old=" << old << " len=" << d->length_namecell << " pos=" << pos << endl; - -// d->updateChoice = false; - d->updatingChoice = false; -} - -void CellEditor::resizeEvent( TQResizeEvent* ) -{ - d->textEdit->setGeometry( 0, 0, width(), height() ); -} - -void CellEditor::handleKeyPressEvent( TQKeyEvent * _ev ) -{ - if (_ev->key() == TQt::Key_F4) - { - if (d->textEdit == 0) - { - TQApplication::sendEvent( d->textEdit, _ev ); - return; - } - - TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); - - int para,cur; - d->textEdit->getCursorPosition(¶,&cur); - // int cur = d->textEdit->cursorPosition(); - TQString tmp, tmp2; - int n = -1; - - // this is ugly, and sort of hack - // FIXME rewrite to use the real Tokenizer - unsigned i; - for( i = 0; i < 10; i++ ) - { - tmp = d->textEdit->text().left( cur+i ); - tmp2 = d->textEdit->text().right( d->textEdit->text().length() - cur - i ); - - n = exp.search(tmp); - if( n >= 0 ) break; - } - - if (n == -1) return; - - TQString newPart; - if ((exp.cap(1) == "$") && (exp.cap(3) == "$")) - newPart = "$" + exp.cap(2) + exp.cap(4); - else if ((exp.cap(1) != "$") && (exp.cap(3) != "$")) - newPart = "$" + exp.cap(2) + "$" + exp.cap(4); - else if ((exp.cap(1) == "$") && (exp.cap(3) != "$")) - newPart = exp.cap(2) + "$" + exp.cap(4); - else if ((exp.cap(1) != "$") && (exp.cap(3) == "$")) - newPart = exp.cap(2) + exp.cap(4); - - TQString newString = tmp.left(n); - newString += newPart; - cur = newString.length() - i; - newString += tmp2; - - d->textEdit->setText(newString); - d->textEdit->setCursorPosition( 0, cur ); - - _ev->accept(); - - return; - } - - // Send the key event to the KLineEdit - TQApplication::sendEvent( d->textEdit, _ev ); -} - -void CellEditor::handleIMEvent( TQIMEvent * _ev ) -{ - // send the IM event to the KLineEdit - TQApplication::sendEvent( d->textEdit, _ev ); -} - -TQString CellEditor::text() const -{ - return d->textEdit->text(); -} - -void CellEditor::setText(TQString text) -{ - d->textEdit->setText(text); - //Usability : It is usually more convenient if the cursor is positioned at the end of the text so it can - //be quickly deleted using the backspace key - - //This also ensures that the caret is sized correctly for the text - d->textEdit->setCursorPosition(0,text.length()); - - if (d->fontLength == 0) - { - TQFontMetrics fm( d->textEdit->font() ); - d->fontLength = fm.width('x'); - } -} - -int CellEditor::cursorPosition() const -{ - int para,cur; - d->textEdit->getCursorPosition(¶,&cur); - return cur; - // return d->textEdit->cursorPosition(); -} - -void CellEditor::setCursorPosition( int pos ) -{ - d->textEdit->setCursorPosition(0,pos); - canvas()->view()->editWidget()->setCursorPosition( pos ); -} - -bool CellEditor::eventFilter( TQObject* o, TQEvent* e ) -{ - // Only interested in KTextEdit - if ( TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(d->textEdit) ) - return false; - if ( e->type() == TQEvent::FocusOut ) - { - canvas()->setLastEditorWithFocus( Canvas::CellEditor ); - return false; - } - - if ( e->type() == TQEvent::KeyPress || e->type() == TQEvent::KeyRelease ) - { - TQKeyEvent* k = (TQKeyEvent*)e; - if (!(k->state() & TQt::ShiftButton) || canvas()->chooseMode()) - { - //If the user presses the return key to finish editing this cell, choose mode must be turned off first - //otherwise it will merely select a different cell - if (k->key() == Key_Return || k->key() == Key_Enter) - { - kdDebug() << "CellEditor::eventFilter: canvas()->endChoose();" << endl; - canvas()->endChoose(); - } - - //NB - Added check for Key_Return when migrating text edit from KLineEdit to KTextEdit, since - //normal behaviour for KTextEdit is to swallow return key presses - if ( k->key() == Key_Up || k->key() == Key_Down || - k->key() == Key_Next || k->key() == Key_Prior || - k->key() == Key_Escape || k->key() == Key_Tab || - k->key() == Key_Return || k->key() == Key_Enter) - { - // Send directly to canvas - TQApplication::sendEvent( parent(), e ); - return true; - } - } - else if ( k->state() & TQt::ShiftButton && ( k->key() == Key_Return || k->key() == Key_Enter ) ) - { - // enable content wrapping - d->cell->format()->setMultiRow( true ); - } - // End choosing. May be restarted by CellEditor::slotTextChanged - if ( e->type() == TQEvent::KeyPress && !k->text().isEmpty() ) - { - canvas()->setChooseMode(false); - } - // forward Left/Right keys - so that pressing left/right in this - // editor leaves editing mode ... otherwise editing is annoying - // left/right arrows still work with the F2-editor. - - // Forward left & right arrows to parent, unless this editor has been set to capture arrow key events - // Changed to this behaviour for consistancy with OO Calc & MS Office. - if ( ((k->key() == TQt::Key_Left) || (k->key() == TQt::Key_Right)) && (!d->captureAllKeyEvents)) { - TQApplication::sendEvent (parent(), e); - return true; - } - } - - return false; -} - -void CellEditor::setCursorToRange(uint pos) -{ -// kdDebug() << k_funcinfo << endl; - - d->updatingChoice = true; - uint counter = 0; - Tokens tokens = d->highlighter->formulaTokens(); - for (uint i = 0; i < tokens.count(); ++i) - { - Token token = tokens[i]; - Token::Type type = token.type(); - if (type == Token::Cell || type == Token::Range) - { - if (counter == pos) - { - setCursorPosition(token.pos() + token.text().length() + 1); - } - counter++; - } - } - d->updatingChoice = false; -} - - - -/***************************************************************************** - * - * ComboboxLocationEditWidget - * - ****************************************************************************/ - -ComboboxLocationEditWidget::ComboboxLocationEditWidget( TQWidget * _parent, - View * _view ) - : KComboBox( _parent, "ComboboxLocationEditWidget" ) -{ - m_locationWidget = new LocationEditWidget( _parent, _view ); - setLineEdit( m_locationWidget ); - insertItem( "" ); - - TQValueList::Iterator it; - TQValueList area = _view->doc()->listArea(); - for ( it = area.begin(); it != area.end(); ++it ) - slotAddAreaName( (*it).ref_name); - connect( this, TQT_SIGNAL( activated ( const TQString & ) ), m_locationWidget, TQT_SLOT( slotActivateItem() ) ); -} - - -void ComboboxLocationEditWidget::slotAddAreaName( const TQString &_name) -{ - insertItem( _name ); - m_locationWidget->addCompletionItem( _name ); -} - -void ComboboxLocationEditWidget::slotRemoveAreaName( const TQString &_name ) -{ - for ( int i = 0; iremoveCompletionItem( _name ); -} - - - -/***************************************************************************** - * - * LocationEditWidget - * - ****************************************************************************/ - -LocationEditWidget::LocationEditWidget( TQWidget * _parent, - View * _view ) - : KLineEdit( _parent, "LocationEditWidget" ), - m_pView(_view) -{ - setCompletionObject( &completionList,true ); - setCompletionMode(TDEGlobalSettings::CompletionAuto ); -} - -void LocationEditWidget::addCompletionItem( const TQString &_item ) -{ - kdDebug()<<" LocationEditWidget::addCompletionItem add :"<<_item<::Iterator it; - TQValueList area = m_pView->doc()->listArea(); - for ( it = area.begin(); it != area.end(); ++it ) - { - if ((*it).ref_name == tmp) - { - TQString tmp = (*it).sheet_name; - tmp += "!"; - tmp += util_rangeName((*it).rect); - m_pView->selectionInfo()->initialize( Region(m_pView,tmp) ); - return true; - } - } - - // Set the cell component to uppercase: - // Sheet1!a1 -> Sheet1!A2 - int pos = ltext.find('!'); - if ( pos !=- 1 ) - tmp = ltext.left(pos)+ltext.mid(pos).upper(); - else - tmp = ltext.upper(); - - // Selection entered in location widget - if ( ltext.contains( ':' ) ) - m_pView->selectionInfo()->initialize( Region(m_pView,tmp) ); - // Location entered in location widget - else - { - Region region(m_pView,tmp); - bool validName = true; - for (unsigned int i = 0; i < ltext.length(); ++i) - { - if (!ltext[i].isLetter()) - { - validName = false; - break; - } - } - if ( !region.isValid() && validName) - { - TQRect rect( m_pView->selectionInfo()->selection() ); - Sheet * t = m_pView->activeSheet(); - // set area name on current selection/cell - - m_pView->doc()->addAreaName(rect, ltext.lower(), t->sheetName()); - } - - if (!validName) - { - m_pView->selectionInfo()->initialize(region); - } - } - - // Set the focus back on the canvas. - m_pView->canvasWidget()->setFocus(); - return false; -} - - -void LocationEditWidget::keyPressEvent( TQKeyEvent * _ev ) -{ - // Do not handle special keys and accelerators. This is - // done by TQLineEdit. - if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) ) - { - TQLineEdit::keyPressEvent( _ev ); - // Never allow that keys are passed on to the parent. - _ev->accept(); - - return; - } - - // Handle some special keys here. Eve - switch( _ev->key() ) - { - case Key_Return: - case Key_Enter: - { - if ( activateItem() ) - return; - _ev->accept(); - } - break; - // Escape pressed, restore original value - case Key_Escape: - // #### Torben says: This is duplicated code. Bad. - if ( m_pView->selectionInfo()->isSingular() ) { - setText( Cell::columnName( m_pView->canvasWidget()->markerColumn() ) - + TQString::number( m_pView->canvasWidget()->markerRow() ) ); - } else { - setText( Cell::columnName( m_pView->selectionInfo()->lastRange().left() ) - + TQString::number( m_pView->selectionInfo()->lastRange().top() ) - + ":" - + Cell::columnName( m_pView->selectionInfo()->lastRange().right() ) - + TQString::number( m_pView->selectionInfo()->lastRange().bottom() ) ); - } - m_pView->canvasWidget()->setFocus(); - _ev->accept(); - break; - default: - TQLineEdit::keyPressEvent( _ev ); - // Never allow that keys are passed on to the parent. - _ev->accept(); - } -} - - - -/**************************************************************** - * - * EditWidget - * The line-editor that appears above the sheet and allows to - * edit the cells content. - * - ****************************************************************/ - -EditWidget::EditWidget( TQWidget *_parent, Canvas *_canvas, - TQButton *cancelButton, TQButton *okButton ) - : TQLineEdit( _parent, "EditWidget" ) -{ - m_pCanvas = _canvas; - Q_ASSERT(m_pCanvas != NULL); - // Those buttons are created by the caller, so that they are inserted - // properly in the layout - but they are then managed here. - m_pCancelButton = cancelButton; - m_pOkButton = okButton; - isArray = false; - - installEventFilter(m_pCanvas); - - if ( !m_pCanvas->doc()->isReadWrite() || !m_pCanvas->activeSheet() ) - setEnabled( false ); - - TQObject::connect( m_pCancelButton, TQT_SIGNAL( clicked() ), - this, TQT_SLOT( slotAbortEdit() ) ); - TQObject::connect( m_pOkButton, TQT_SIGNAL( clicked() ), - this, TQT_SLOT( slotDoneEdit() ) ); - - setEditMode( false ); // disable buttons -} - -void EditWidget::showEditWidget(bool _show) -{ - if (_show) - { - m_pCancelButton->show(); - m_pOkButton->show(); - show(); - } - else - { - m_pCancelButton->hide(); - m_pOkButton->hide(); - hide(); - } -} - -void EditWidget::slotAbortEdit() -{ - m_pCanvas->deleteEditor( false /*discard changes*/ ); - // will take care of the buttons -} - -void EditWidget::slotDoneEdit() -{ - m_pCanvas->deleteEditor( true /*keep changes*/, isArray); - isArray = false; - // will take care of the buttons -} - -void EditWidget::keyPressEvent ( TQKeyEvent* _ev ) -{ - // Dont handle special keys and accelerators, except Enter ones - if (( ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) ) - || ( _ev->state() & TQt::ShiftButton ) - || ( _ev->key() == Key_Shift ) - || ( _ev->key() == Key_Control ) ) - && (_ev->key() != Key_Return) && (_ev->key() != Key_Enter)) - { - TQLineEdit::keyPressEvent( _ev ); - _ev->accept(); - return; - } - - if ( !m_pCanvas->doc()->isReadWrite() ) - return; - - if ( !m_pCanvas->editor() ) - { - // Start editing the current cell - m_pCanvas->createEditor( Canvas::CellEditor,false ); - } - CellEditor * cellEditor = (CellEditor*) m_pCanvas->editor(); - - switch ( _ev->key() ) - { - case Key_Down: - case Key_Up: - case Key_Return: - case Key_Enter: - cellEditor->setText( text()); - // Don't allow to start a chooser when pressing the arrow keys - // in this widget, since only up and down would work anyway. - // This is why we call slotDoneEdit now, instead of sending - // to the canvas. - //TQApplication::sendEvent( m_pCanvas, _ev ); - isArray = (_ev->state() & TQt::AltButton) && - (_ev->state() & TQt::ControlButton); - slotDoneEdit(); - m_pCanvas->view()->updateEditWidget(); - _ev->accept(); - break; - case Key_F2: - cellEditor->setFocus(); - cellEditor->setText( text()); - cellEditor->setCursorPosition(cursorPosition()); - break; - default: - - TQLineEdit::keyPressEvent( _ev ); - - setFocus(); - cellEditor->setCheckChoice( false ); - cellEditor->setText( text() ); - cellEditor->setCheckChoice( true ); - cellEditor->setCursorPosition( cursorPosition() ); - } -} - -void EditWidget::setEditMode( bool mode ) -{ - m_pCancelButton->setEnabled(mode); - m_pOkButton->setEnabled(mode); -} - -void EditWidget::focusOutEvent( TQFocusEvent* ev ) -{ - //kdDebug(36001) << "EditWidget lost focus" << endl; - // See comment about setLastEditorWithFocus - m_pCanvas->setLastEditorWithFocus( Canvas::EditWidget ); - - TQLineEdit::focusOutEvent( ev ); -} - -void EditWidget::setText( const TQString& t ) -{ - if ( t == text() ) // Why this? (David) - return; - - TQLineEdit::setText( t ); -} - - - -#include "kspread_editors.moc" diff --git a/kspread/kspread_editors.cpp b/kspread/kspread_editors.cpp new file mode 100644 index 00000000..4af76159 --- /dev/null +++ b/kspread/kspread_editors.cpp @@ -0,0 +1,1589 @@ +/* This file is part of the KDE project + + Copyright 1999-2006 The KSpread Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_editors.h" +#include "kspread_canvas.h" +#include "kspread_cell.h" +#include "kspread_doc.h" +#include "selection.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "kspread_util.h" +#include "formula.h" +#include "functions.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +//#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KSpread; + + + +/***************************************************************************** + * + * FormulaEditorHighlighter + * + ****************************************************************************/ + +namespace KSpread +{ + +class FormulaEditorHighlighter::Private +{ +public: + Private() + { + canvas = 0; + tokens = Tokens(); + rangeCount = 0; + rangeChanged = false; + } + + // source for cell reference checking + Canvas* canvas; + Tokens tokens; + uint rangeCount; + bool rangeChanged; +}; + + +FormulaEditorHighlighter::FormulaEditorHighlighter(TQTextEdit* textEdit, Canvas* canvas) + : TQSyntaxHighlighter(textEdit) +{ + d = new Private(); + d->canvas = canvas; +} + +FormulaEditorHighlighter::~FormulaEditorHighlighter() +{ + delete d; +} + +const Tokens& FormulaEditorHighlighter::formulaTokens() const +{ + return d->tokens; +} + +int FormulaEditorHighlighter::highlightParagraph(const TQString& text, int /* endStateOfLastPara */) +{ + // reset syntax highlighting + setFormat(0, text.length(), TQt::black); + + // save the old ones to identify range changes + Tokens oldTokens = d->tokens; + + // interpret the text as formula + // we accept invalid/incomplete formulas + Formula f; + d->tokens = f.scan(text); + + TQFont editorFont = textEdit()->currentFont(); + TQFont font; + + uint oldRangeCount = d->rangeCount; + + d->rangeCount = 0; + TQValueList colors = d->canvas->choice()->colors(); + TQValueList alreadyFoundRanges; + + for (uint i = 0; i < d->tokens.count(); ++i) + { + Token token = d->tokens[i]; + Token::Type type = token.type(); + + switch (type) + { + case Token::Cell: + case Token::Range: + { + // don't compare, if we have already found a change + if (!d->rangeChanged && i < oldTokens.count() && token.text() != oldTokens[i].text()) + { + d->rangeChanged = true; + } + + Range newRange( token.text() ); + + if (!alreadyFoundRanges.contains(newRange)) + { + alreadyFoundRanges.append(newRange); + d->rangeCount++; + } + setFormat(token.pos() + 1, token.text().length(), colors[ alreadyFoundRanges.findIndex(newRange) % colors.size()] ); + } + break; + case Token::Boolean: // True, False (also i18n-ized) +/* font = TQFont(editorFont); + font.setBold(true); + setFormat(token.pos() + 1, token.text().length(), font);*/ + break; + case Token::Identifier: // function name or named area*/ +/* font = TQFont(editorFont); + font.setBold(true); + setFormat(token.pos() + 1, token.text().length(), font);*/ + break; + + case Token::Unknown: + case Token::Integer: // 14, 3, 1977 + case Token::Float: // 3.141592, 1e10, 5.9e-7 + case Token::String: // "KOffice", "The quick brown fox..." + case Token::Operator: // +, *, /, - + { + switch (token.asOperator()) + { + case Token::LeftPar: + case Token::RightPar: + //Check where this brace is in relation to the cursor and highlight it if necessary. + handleBrace( i ); + break; + default: + break; + } + } + break; + } + } + + if (oldRangeCount != d->rangeCount) + d->rangeChanged = true; + + return 0; +} + +void FormulaEditorHighlighter::handleBrace( uint index ) +{ + int cursorParagraph; + int cursorPos; + const Token& token = d->tokens.at( index ); + + textEdit()->getCursorPosition( &cursorParagraph , &cursorPos ); + + int distance = cursorPos-token.pos(); + int opType = token.asOperator(); + bool highlightBrace=false; + + //Check where the cursor is in relation to this left or right parenthesis token. + //Only one pair of braces should be highlighted at a time, and if the cursor + //is between two braces, the inner-most pair should be highlighted. + + if ( opType == Token::LeftPar ) + { + //If cursor is directly to the left of this left brace, highlight it + if ( distance == 1 ) + highlightBrace=true; + else + //Cursor is directly to the right of this left brace, highlight it unless + //there is another left brace to the right (in which case that should be highlighted instead as it + //is the inner-most brace) + if (distance==2) + if ( (index == d->tokens.count()-1) || ( d->tokens.at(index+1).asOperator() != Token::LeftPar) ) + highlightBrace=true; + + } + else + { + //If cursor is directly to the right of this right brace, highlight it + if ( distance == 2 ) + highlightBrace=true; + else + //Cursor is directly to the left of this right brace, so highlight it unless + //there is another right brace to the left (in which case that should be highlighted instead as it + //is the inner-most brace) + if ( distance == 1 ) + if ( (index == 0) || (d->tokens.at(index-1).asOperator() != Token::RightPar) ) + highlightBrace=true; + } + + if (highlightBrace) + { + TQFont font = TQFont( textEdit()->currentFont() ); + font.setBold(true); + setFormat(token.pos() + 1, token.text().length(), font); + + int matching = findMatchingBrace( index ); + + if (matching != -1) + { + Token matchingBrace = d->tokens.at(matching); + setFormat( matchingBrace.pos() + 1 , matchingBrace.text().length() , font); + } + } +} + +int FormulaEditorHighlighter::findMatchingBrace(int pos) +{ + int depth=0; + int step=0; + + Tokens tokens = d->tokens; + + //If this is a left brace we need to step forwards through the text to find the matching right brace, + //otherwise, it is a right brace so we need to step backwards through the text to find the matching left + //brace. + if (tokens.at(pos).asOperator() == Token::LeftPar) + step = 1; + else + step = -1; + + for (int index=pos ; (index >= 0) && (index < (int) tokens.count() ) ; index += step ) + { + if (tokens.at(index).asOperator() == Token::LeftPar) + depth++; + if (tokens.at(index).asOperator() == Token::RightPar) + depth--; + + if (depth == 0) + { + return index; + } + } + + return -1; +} + +uint FormulaEditorHighlighter::rangeCount() const +{ + return d->rangeCount; +} + +bool FormulaEditorHighlighter::rangeChanged() const +{ + return d->rangeChanged; +} + +void FormulaEditorHighlighter::resetRangeChanged() +{ + d->rangeChanged=false; +} + +} // namespace KSpread + + + +/***************************************************************************** + * + * FunctionCompletion + * + ****************************************************************************/ + +class FunctionCompletion::Private +{ +public: + CellEditor* editor; + TQVBox *completionPopup; + TDEListBox *completionListBox; + TQLabel* hintLabel; +}; + +FunctionCompletion::FunctionCompletion( CellEditor* editor ): +TQObject( editor ) +{ + d = new Private; + d->editor = editor; + d->hintLabel = 0; + + d->completionPopup = new TQVBox( editor->topLevelWidget(), 0, WType_Popup ); + d->completionPopup->setFrameStyle( TQFrame::Box | TQFrame::Plain ); + d->completionPopup->setLineWidth( 1 ); + d->completionPopup->installEventFilter( this ); + d->completionPopup->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Minimum); + + d->completionListBox = new TDEListBox( d->completionPopup ); + d->completionPopup->setFocusProxy( d->completionListBox ); + d->completionListBox->setFrameStyle( TQFrame::NoFrame ); + d->completionListBox->setVariableWidth( true ); + d->completionListBox->installEventFilter( this ); + connect( d->completionListBox, TQT_SIGNAL(selected(const TQString&)), this, + TQT_SLOT(itemSelected(const TQString&)) ); + connect( d->completionListBox, TQT_SIGNAL(highlighted(const TQString&)), this, + TQT_SLOT(itemSelected(const TQString&)) ); + + d->hintLabel = new TQLabel( 0, "autocalc", TQt::WStyle_StaysOnTop | + TQt::WStyle_Customize | TQt::WStyle_NoBorder | TQt::WStyle_Tool | TQt::WX11BypassWM ); + d->hintLabel->setFrameStyle( TQFrame::Plain | TQFrame::Box ); + d->hintLabel->setPalette( TQToolTip::palette() ); + d->hintLabel->hide(); +} + +FunctionCompletion::~FunctionCompletion() +{ + delete d->hintLabel; + delete d; +} + +void FunctionCompletion::itemSelected( const TQString& item ) +{ + KSpread::FunctionDescription* desc; + desc = KSpread::FunctionRepository::self()->functionInfo(item); + if(!desc) + { + d->hintLabel->hide(); + return; + } + + TQString helpText = desc->helpText()[0]; + if( helpText.isEmpty() ) + { + d->hintLabel->hide(); + return; + } + + helpText.append("").prepend(""); + d->hintLabel->setText( helpText ); + d->hintLabel->adjustSize(); + + // reposition nicely + TQPoint pos = d->editor->mapToGlobal( TQPoint( d->editor->width(), 0 ) ); + pos.setY( pos.y() - d->hintLabel->height() - 1 ); + d->hintLabel->move( pos ); + d->hintLabel->show(); + d->hintLabel->raise(); + + // do not show it forever + //TQTimer::singleShot( 5000, d->hintLabel, TQT_SLOT( hide()) ); +} + +bool FunctionCompletion::eventFilter( TQObject *obj, TQEvent *ev ) +{ + if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(d->completionPopup) || TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(d->completionListBox) ) + { + if ( ev->type() == TQEvent::KeyPress ) + { + TQKeyEvent *ke = (TQKeyEvent*)ev; + if ( ke->key() == Key_Enter || ke->key() == Key_Return ) + { + doneCompletion(); + return true; + } + else if ( ke->key() == Key_Left || ke->key() == Key_Right || + ke->key() == Key_Up || ke->key() == Key_Down || + ke->key() == Key_Home || ke->key() == Key_End || + ke->key() == Key_Prior || ke->key() == Key_Next ) + return false; + + d->hintLabel->hide(); + d->completionPopup->close(); + d->editor->setFocus(); + TQApplication::sendEvent( d->editor, ev ); + return true; + } + + if ( ev->type() == TQEvent::MouseButtonDblClick ) + { + doneCompletion(); + return true; + } + } + + return false; +} + +void FunctionCompletion::doneCompletion() +{ + d->hintLabel->hide(); + d->completionPopup->close(); + d->editor->setFocus(); + emit selectedCompletion( d->completionListBox->currentText() ); +} + +void FunctionCompletion::showCompletion( const TQStringList &choices ) +{ + if( !choices.count() ) return; + + d->completionListBox->clear(); + for( unsigned i = 0; i < choices.count(); i++ ) + new TQListBoxText( (TQListBox*)d->completionListBox, choices[i] ); + d->completionListBox->setCurrentItem( 0 ); + + // size of the pop-up + d->completionPopup->setMaximumHeight( 100 ); + d->completionPopup->resize( d->completionListBox->sizeHint() + + TQSize( d->completionListBox->verticalScrollBar()->width() + 4, + d->completionListBox->horizontalScrollBar()->height() + 4 ) ); + int h = d->completionListBox->height(); + int w = d->completionListBox->width(); + + TQPoint pos = d->editor->globalCursorPosition(); + + // if popup is partially invisible, move to other position + // FIXME check it if it works in Xinerama multihead + int screen_num = TQApplication::desktop()->screenNumber( d->completionPopup ); + TQRect screen = TQApplication::desktop()->screenGeometry( screen_num ); + if( pos.y() + h > screen.y()+screen.height() ) + pos.setY( pos.y() - h - d->editor->height() ); + if( pos.x() + w > screen.x()+screen.width() ) + pos.setX( screen.x()+screen.width() - w ); + + d->completionPopup->move( pos ); + d->completionListBox->setFocus(); + d->completionPopup->show(); +} + + + +/**************************************************************************** + * + * CellEditor + * + ****************************************************************************/ + +class CellEditor::Private +{ +public: + Cell* cell; + Canvas* canvas; + KTextEdit* textEdit; + FormulaEditorHighlighter* highlighter; + FunctionCompletion* functionCompletion; + TQTimer* functionCompletionTimer; + + TQPoint globalCursorPos; + + bool captureAllKeyEvents : 1; + bool checkChoice : 1; + bool updateChoice : 1; + bool updatingChoice : 1; + + uint length; + uint fontLength; + uint length_namecell; + uint length_text; + uint currentToken; + uint rangeCount; +}; + + +CellEditor::CellEditor( Cell* _cell, Canvas* _parent, bool captureAllKeyEvents, const char* _name ) + : TQWidget( _parent, _name ) +{ + d = new Private(); + d->cell = _cell; + d->canvas = _parent; + d->textEdit = new KTextEdit(this); + d->globalCursorPos = TQPoint(); + d->captureAllKeyEvents = captureAllKeyEvents; + d->checkChoice = true; + d->updateChoice = true; + d->updatingChoice = false; + d->length = 0; + d->fontLength = 0; + d->length_namecell = 0; + d->length_text = 0; + d->currentToken = 0; + d->rangeCount = 0; + +//TODO - Get rid of TQTextEdit margins, this doesn't seem easily possible in TQt 3.3, so a job for TQt 4 porting. + + d->textEdit->setHScrollBarMode(TQScrollView::AlwaysOff); + d->textEdit->setVScrollBarMode(TQScrollView::AlwaysOff); + d->textEdit->setFrameStyle(TQFrame::NoFrame); + d->textEdit->setLineWidth(0); + d->textEdit->installEventFilter( this ); + + d->highlighter = new FormulaEditorHighlighter(d->textEdit, _parent); + + d->functionCompletion = new FunctionCompletion( this ); + d->functionCompletionTimer = new TQTimer( this ); + connect( d->functionCompletion, TQT_SIGNAL( selectedCompletion( const TQString& ) ), + TQT_SLOT( functionAutoComplete( const TQString& ) ) ); + connect( d->textEdit, TQT_SIGNAL( textChanged() ), TQT_SLOT( checkFunctionAutoComplete() ) ); + connect( d->functionCompletionTimer, TQT_SIGNAL( timeout() ), + TQT_SLOT( triggerFunctionAutoComplete() ) ); + + if (!cell()->format()->multiRow(cell()->column(),cell()->row())) + d->textEdit->setWordWrap(TQTextEdit::NoWrap); + else + d->textEdit->setWrapPolicy(TQTextEdit::AtWordOrDocumentBoundary); + +//TODO - Custom KTextEdit class which supports text completion +/* + d->textEdit->setFrame( false ); + d->textEdit->setCompletionMode((TDEGlobalSettings::Completion)canvas()->view()->doc()->completionMode() ); + d->textEdit->setCompletionObject( &canvas()->view()->doc()->completion(),true ); +*/ + setFocusProxy( d->textEdit ); + + connect( d->textEdit, TQT_SIGNAL( cursorPositionChanged(int,int) ), this, TQT_SLOT (slotCursorPositionChanged(int,int))); + connect( d->textEdit, TQT_SIGNAL( cursorPositionChanged(TQTextCursor*) ), this, TQT_SLOT (slotTextCursorChanged(TQTextCursor*))); + connect( d->textEdit, TQT_SIGNAL( textChanged() ), this, TQT_SLOT( slotTextChanged() ) ); + +// connect( d->textEdit, TQT_SIGNAL(completionModeChanged( TDEGlobalSettings::Completion )),this,TQT_SLOT (slotCompletionModeChanged(TDEGlobalSettings::Completion))); + + // A choose should always start at the edited cell +// canvas()->setChooseMarkerRow( canvas()->markerRow() ); +// canvas()->setChooseMarkerColumn( canvas()->markerColumn() ); + + // set font size according to zoom factor + TQFont font( _cell->format()->font() ); + font.setPointSizeFloat( 0.01 * _parent->doc()->zoom() * font.pointSizeFloat() ); + d->textEdit->setFont( font ); + + if (d->fontLength == 0) + { + TQFontMetrics fm( d->textEdit->font() ); + d->fontLength = fm.width('x'); + } +} + +CellEditor::~CellEditor() +{ + canvas()->endChoose(); + + delete d->highlighter; + delete d->functionCompletion; + delete d->functionCompletionTimer; + delete d; +} + +Cell* CellEditor::cell() const +{ + return d->cell; +} + +Canvas* CellEditor::canvas() const +{ + return d->canvas; +} + +TQPoint CellEditor::globalCursorPosition() const +{ + return d->globalCursorPos; +} + +void CellEditor::checkFunctionAutoComplete() +{ + d->functionCompletionTimer->stop(); + d->functionCompletionTimer->start( 2000, true ); +} + +void CellEditor::triggerFunctionAutoComplete() +{ + // tokenize the expression (don't worry, this is very fast) + int para = 0, curPos = 0; + d->textEdit->getCursorPosition( ¶, &curPos ); + TQString subtext = d->textEdit->text().left( curPos ); + + KSpread::Formula f; + KSpread::Tokens tokens = f.scan( subtext ); + if( !tokens.valid() ) return; + if( tokens.count()<1 ) return; + + KSpread::Token lastToken = tokens[ tokens.count()-1 ]; + + // last token must be an identifier + if( !lastToken.isIdentifier() ) return; + TQString id = lastToken.text(); + if( id.length() < 1 ) return; + + // find matches in function names + TQStringList fnames = KSpread::FunctionRepository::self()->functionNames(); + TQStringList choices; + for( unsigned i=0; ifunctionCompletion->showCompletion( choices ); +} + +void CellEditor::functionAutoComplete( const TQString& item ) +{ + if( item.isEmpty() ) return; + + int para = 0, curPos = 0; + d->textEdit->getCursorPosition( ¶, &curPos ); + TQString subtext = text().left( curPos ); + + KSpread::Formula f; + KSpread::Tokens tokens = f.scan( subtext ); + if( !tokens.valid() ) return; + if( tokens.count()<1 ) return; + + KSpread::Token lastToken = tokens[ tokens.count()-1 ]; + if( !lastToken.isIdentifier() ) return; + + d->textEdit->blockSignals( true ); + d->textEdit->setSelection( 0, lastToken.pos()+1, 0, lastToken.pos()+lastToken.text().length()+1 ); + d->textEdit->insert( item ); + d->textEdit->blockSignals( false ); +} + +void CellEditor::slotCursorPositionChanged(int /* para */, int pos) +{ +// kdDebug() << k_funcinfo << endl; + + // TODO Stefan: optimize this function! + + // turn choose mode on/off + if (!checkChoice()) + return; + + d->highlighter->rehighlight(); + + Tokens tokens = d->highlighter->formulaTokens(); + uint rangeCounter = 0; + uint currentRange = 0; + uint regionStart = 0; + uint regionEnd = 0; + bool lastWasASemicolon = false; + d->currentToken = 0; + uint rangeCount = d->highlighter->rangeCount(); + d->rangeCount = rangeCount; + + Token token; + Token::Type type; + // search the current token + // determine the subregion number, btw + for (uint i = 0; i < tokens.count(); ++i) + { + if (tokens[i].pos() >= pos - 1) // without '=' + { +/* kdDebug() << "token.pos >= cursor.pos" << endl;*/ + type = tokens[i].type(); + if (type == Token::Cell || type == Token::Range) + { + if (lastWasASemicolon) + { + regionEnd = rangeCounter++; + lastWasASemicolon = false; + continue; + } + } + if (type == Token::Operator && tokens[i].asOperator() == Token::Semicolon) + { + lastWasASemicolon = true; + continue; + } + lastWasASemicolon = false; + break; + } + token = tokens[i]; + d->currentToken = i; + + type = token.type(); + if (type == Token::Cell || type == Token::Range) + { + if (!lastWasASemicolon) + { + regionStart = rangeCounter; + } + regionEnd = rangeCounter; + currentRange = rangeCounter++; + } + // semicolons are use as deliminiters in regions + if (type == Token::Operator) + { + if (token.asOperator() == Token::Semicolon) + { + lastWasASemicolon = true; + } + else + { + lastWasASemicolon = false; + // set the region start to the next element + regionStart = currentRange + 1; + regionEnd = regionStart - 1; // len = 0 + } + } + } + +// kdDebug() << "regionStart = " << regionStart/* << endl*/ +// << ", regionEnd = " << regionEnd/* << endl*/ +// << ", currentRange = " << currentRange << endl; + + d->canvas->choice()->setActiveElement(currentRange); + d->canvas->choice()->setActiveSubRegion(regionStart, regionEnd-regionStart+1); + + // triggered by keyboard action? + if (!d->updatingChoice) + { + if (d->highlighter->rangeChanged()) + { + d->highlighter->resetRangeChanged(); + + disconnect( d->canvas->choice(), TQT_SIGNAL(changed(const Region&)), + d->canvas->view(), TQT_SLOT(slotScrollChoice(const Region&)) ); + d->canvas->doc()->emitBeginOperation(); + setUpdateChoice(false); + + Tokens tokens = d->highlighter->formulaTokens(); + d->canvas->choice()->update(); // set the old one dirty + d->canvas->choice()->clear(); + Region tmpRegion; + Region::ConstIterator it; + + //A list of regions which have already been highlighted on the spreadsheet. + //This is so that we don't end up highlighting the same region twice in two different + //colours. + TQValueList alreadyUsedRegions; + + for (uint i = 0; i < tokens.count(); ++i) + { + Token token = tokens[i]; + Token::Type type = token.type(); + if (type == Token::Cell || type == Token::Range) + { + Region region(d->canvas->view(), token.text()); + it = region.constBegin(); + + if (!alreadyUsedRegions.contains(region)) + { + TQRect r=(*it)->rect(); + + if (d->canvas->choice()->isEmpty()) + d->canvas->choice()->initialize((*it)->rect(), (*it)->sheet()); + else + d->canvas->choice()->extend((*it)->rect(), (*it)->sheet()); + + alreadyUsedRegions.append(region); + } + } + } + setUpdateChoice(true); + d->canvas->doc()->emitEndOperation(*d->canvas->choice()); + connect( d->canvas->choice(), TQT_SIGNAL(changed(const Region&)), + d->canvas->view(), TQT_SLOT(slotScrollChoice(const Region&)) ); + } + } +} + +void CellEditor::slotTextCursorChanged(TQTextCursor* cursor) +{ + TQTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x; + int y, dummy; + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y(); + + d->globalCursorPos = d->textEdit->mapToGlobal( d->textEdit-> contentsToViewport( TQPoint( x, y + h ) ) ); +} + +void CellEditor::cut() +{ + d->textEdit->cut(); +} + +void CellEditor::paste() +{ + d->textEdit->paste(); +} + +void CellEditor::copy() +{ + d->textEdit->copy(); +} + +void CellEditor::setEditorFont(TQFont const & font, bool updateSize) +{ + TQFont tmpFont( font ); + tmpFont.setPointSizeFloat( 0.01 * canvas()->doc()->zoom() * tmpFont.pointSizeFloat() ); + d->textEdit->setFont( tmpFont ); + + if (updateSize) + { + TQFontMetrics fm( d->textEdit->font() ); + d->fontLength = fm.width('x'); + + int mw = fm.width( d->textEdit->text() ) + d->fontLength; + // don't make it smaller: then we would have to repaint the obscured cells + if (mw < width()) + mw = width(); + + int mh = fm.height(); + if (mh < height()) + mh = height(); + + setGeometry(x(), y(), mw, mh); + } +} + +void CellEditor::slotCompletionModeChanged(TDEGlobalSettings::Completion _completion) +{ + canvas()->view()->doc()->setCompletionMode( _completion ); +} + +void CellEditor::slotTextChanged() +{ +// kdDebug() << k_funcinfo << endl; + + //FIXME - text() may return richtext? + TQString t = text(); + + if (t.length() > d->length) + { + d->length = t.length(); + + TQFontMetrics fm(d->textEdit->font()); + // - requiredWidth = width of text plus some spacer characters + int requiredWidth = fm.width(t) + (2*fm.width('x')); + + //For normal single-row cells, the text editor must be expanded horizontally to + //allow the text to fit if the new text is too wide + //For multi-row (word-wrap enabled) cells, the text editor must expand vertically to + //allow for new rows of text & the width of the text editor is not affected + if (d->textEdit->wordWrap() == TQTextEdit::NoWrap) + { + if (requiredWidth > width()) + { + if (t.isRightToLeft()) + { + setGeometry(x() - requiredWidth + width(), y(), requiredWidth,height()); + } + else + { + setGeometry(x(), y(), requiredWidth,height()); + } + } + } + else + { + int requiredHeight = d->textEdit->heightForWidth(width()); + + if (requiredHeight > height()) + { + setGeometry(x(), y(), width(), requiredHeight); + } + } + + /* // allocate more space than needed. Otherwise it might be too slow + d->length = t.length(); + + // Too slow for long texts + // TQFontMetrics fm( d->textEdit->font() ); + // int mw = fm.width( t ) + fm.width('x'); + int mw = d->fontLength * d->length; + + if (mw < width()) + mw = width(); + + if (t.isRightToLeft()) + setGeometry(x() - mw + width(), y(), mw, height()); + else + setGeometry(x(), y(), mw, height()); + + d->length -= 2; */ + } + + if ( (cell()->formatType()) == Percentage_format ) + { + if ( (t.length() == 1) && t[0].isDigit() ) + { + TQString tmp = t + " %"; + d->textEdit->setText(tmp); + d->textEdit->setCursorPosition(0,1); + return; + } + } + + canvas()->view()->editWidget()->setText( t ); + // canvas()->view()->editWidget()->setCursorPosition( d->textEdit->cursorPosition() ); +} + +void CellEditor::setCheckChoice(bool state) +{ + d->checkChoice = state; +} + +bool CellEditor::checkChoice() +{ + if (!d->checkChoice) + return false; + +// // prevent recursion +// d->checkChoice = false; // TODO nescessary? + + d->length_namecell = 0; + d->currentToken = 0; + + TQString text = d->textEdit->text(); + if ( text[0] != '=' ) + { + canvas()->setChooseMode(false); + } + else + { + int para, cur; + d->textEdit->getCursorPosition(¶, &cur); + + Tokens tokens = d->highlighter->formulaTokens(); + + // empty formula? + if (tokens.count() < 1) + { + canvas()->startChoose(); + } + else + { + Token token; + for (uint i = 0; i < tokens.count(); ++i) + { + if (tokens[i].pos() >= cur - 1) // without '=' + { + break; + } + token = tokens[i]; + d->currentToken = i; + } + + Token::Type type = token.type(); + if (type == Token::Operator && token.asOperator() != Token::RightPar) + { + canvas()->setChooseMode(true); + } + else if (type == Token::Cell || type == Token::Range) + { + d->length_namecell = token.text().length(); + canvas()->setChooseMode(true); + } + else + { + canvas()->setChooseMode(false); + } + } + } + +// d->checkChoice = true; + + return true; +} + +void CellEditor::setUpdateChoice(bool state) +{ + d->updateChoice = state; +} + +void CellEditor::updateChoice() +{ +// kdDebug() << k_funcinfo << endl; + + if (!d->updateChoice) + return; + +// // prevent recursion +// d->updateChoice = false; // TODO nescessary? + d->updatingChoice = true; + + Selection* choice = d->canvas->choice(); + + if (choice->isEmpty()) + return; + + if (!choice->activeElement()) + return; + + // only one element TODO + if (++choice->constBegin() == choice->constEnd()) + { + } + + TQString name_cell = choice->activeSubRegionName(); + + Tokens tokens = d->highlighter->formulaTokens(); + uint start = 1; + uint length = 0; + if (!tokens.empty()) + { + Token token = tokens[d->currentToken]; + Token::Type type = token.type(); + if (type == Token::Cell || type == Token::Range) + { + start = token.pos() + 1; // don't forget the '='! + length = token.text().length(); + } + else + { + start = token.pos() + token.text().length() + 1; + } + } + + d->length_namecell = name_cell.length(); + d->length_text = text().length(); + //kdDebug(36001) << "updateChooseMarker2 len=" << d->length_namecell << endl; + + TQString oldText = text(); + TQString newText = oldText.left(start) + name_cell + oldText.right(d->length_text - start - length); + + setCheckChoice( false ); + setText( newText ); + setCheckChoice( true ); + setCursorPosition( start + d->length_namecell ); + + d->canvas->view()->editWidget()->setText( newText ); + //kdDebug(36001) << "old=" << old << " len=" << d->length_namecell << " pos=" << pos << endl; + +// d->updateChoice = false; + d->updatingChoice = false; +} + +void CellEditor::resizeEvent( TQResizeEvent* ) +{ + d->textEdit->setGeometry( 0, 0, width(), height() ); +} + +void CellEditor::handleKeyPressEvent( TQKeyEvent * _ev ) +{ + if (_ev->key() == TQt::Key_F4) + { + if (d->textEdit == 0) + { + TQApplication::sendEvent( d->textEdit, _ev ); + return; + } + + TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)$"); + + int para,cur; + d->textEdit->getCursorPosition(¶,&cur); + // int cur = d->textEdit->cursorPosition(); + TQString tmp, tmp2; + int n = -1; + + // this is ugly, and sort of hack + // FIXME rewrite to use the real Tokenizer + unsigned i; + for( i = 0; i < 10; i++ ) + { + tmp = d->textEdit->text().left( cur+i ); + tmp2 = d->textEdit->text().right( d->textEdit->text().length() - cur - i ); + + n = exp.search(tmp); + if( n >= 0 ) break; + } + + if (n == -1) return; + + TQString newPart; + if ((exp.cap(1) == "$") && (exp.cap(3) == "$")) + newPart = "$" + exp.cap(2) + exp.cap(4); + else if ((exp.cap(1) != "$") && (exp.cap(3) != "$")) + newPart = "$" + exp.cap(2) + "$" + exp.cap(4); + else if ((exp.cap(1) == "$") && (exp.cap(3) != "$")) + newPart = exp.cap(2) + "$" + exp.cap(4); + else if ((exp.cap(1) != "$") && (exp.cap(3) == "$")) + newPart = exp.cap(2) + exp.cap(4); + + TQString newString = tmp.left(n); + newString += newPart; + cur = newString.length() - i; + newString += tmp2; + + d->textEdit->setText(newString); + d->textEdit->setCursorPosition( 0, cur ); + + _ev->accept(); + + return; + } + + // Send the key event to the KLineEdit + TQApplication::sendEvent( d->textEdit, _ev ); +} + +void CellEditor::handleIMEvent( TQIMEvent * _ev ) +{ + // send the IM event to the KLineEdit + TQApplication::sendEvent( d->textEdit, _ev ); +} + +TQString CellEditor::text() const +{ + return d->textEdit->text(); +} + +void CellEditor::setText(TQString text) +{ + d->textEdit->setText(text); + //Usability : It is usually more convenient if the cursor is positioned at the end of the text so it can + //be quickly deleted using the backspace key + + //This also ensures that the caret is sized correctly for the text + d->textEdit->setCursorPosition(0,text.length()); + + if (d->fontLength == 0) + { + TQFontMetrics fm( d->textEdit->font() ); + d->fontLength = fm.width('x'); + } +} + +int CellEditor::cursorPosition() const +{ + int para,cur; + d->textEdit->getCursorPosition(¶,&cur); + return cur; + // return d->textEdit->cursorPosition(); +} + +void CellEditor::setCursorPosition( int pos ) +{ + d->textEdit->setCursorPosition(0,pos); + canvas()->view()->editWidget()->setCursorPosition( pos ); +} + +bool CellEditor::eventFilter( TQObject* o, TQEvent* e ) +{ + // Only interested in KTextEdit + if ( TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(d->textEdit) ) + return false; + if ( e->type() == TQEvent::FocusOut ) + { + canvas()->setLastEditorWithFocus( Canvas::CellEditor ); + return false; + } + + if ( e->type() == TQEvent::KeyPress || e->type() == TQEvent::KeyRelease ) + { + TQKeyEvent* k = (TQKeyEvent*)e; + if (!(k->state() & TQt::ShiftButton) || canvas()->chooseMode()) + { + //If the user presses the return key to finish editing this cell, choose mode must be turned off first + //otherwise it will merely select a different cell + if (k->key() == Key_Return || k->key() == Key_Enter) + { + kdDebug() << "CellEditor::eventFilter: canvas()->endChoose();" << endl; + canvas()->endChoose(); + } + + //NB - Added check for Key_Return when migrating text edit from KLineEdit to KTextEdit, since + //normal behaviour for KTextEdit is to swallow return key presses + if ( k->key() == Key_Up || k->key() == Key_Down || + k->key() == Key_Next || k->key() == Key_Prior || + k->key() == Key_Escape || k->key() == Key_Tab || + k->key() == Key_Return || k->key() == Key_Enter) + { + // Send directly to canvas + TQApplication::sendEvent( parent(), e ); + return true; + } + } + else if ( k->state() & TQt::ShiftButton && ( k->key() == Key_Return || k->key() == Key_Enter ) ) + { + // enable content wrapping + d->cell->format()->setMultiRow( true ); + } + // End choosing. May be restarted by CellEditor::slotTextChanged + if ( e->type() == TQEvent::KeyPress && !k->text().isEmpty() ) + { + canvas()->setChooseMode(false); + } + // forward Left/Right keys - so that pressing left/right in this + // editor leaves editing mode ... otherwise editing is annoying + // left/right arrows still work with the F2-editor. + + // Forward left & right arrows to parent, unless this editor has been set to capture arrow key events + // Changed to this behaviour for consistancy with OO Calc & MS Office. + if ( ((k->key() == TQt::Key_Left) || (k->key() == TQt::Key_Right)) && (!d->captureAllKeyEvents)) { + TQApplication::sendEvent (parent(), e); + return true; + } + } + + return false; +} + +void CellEditor::setCursorToRange(uint pos) +{ +// kdDebug() << k_funcinfo << endl; + + d->updatingChoice = true; + uint counter = 0; + Tokens tokens = d->highlighter->formulaTokens(); + for (uint i = 0; i < tokens.count(); ++i) + { + Token token = tokens[i]; + Token::Type type = token.type(); + if (type == Token::Cell || type == Token::Range) + { + if (counter == pos) + { + setCursorPosition(token.pos() + token.text().length() + 1); + } + counter++; + } + } + d->updatingChoice = false; +} + + + +/***************************************************************************** + * + * ComboboxLocationEditWidget + * + ****************************************************************************/ + +ComboboxLocationEditWidget::ComboboxLocationEditWidget( TQWidget * _parent, + View * _view ) + : KComboBox( _parent, "ComboboxLocationEditWidget" ) +{ + m_locationWidget = new LocationEditWidget( _parent, _view ); + setLineEdit( m_locationWidget ); + insertItem( "" ); + + TQValueList::Iterator it; + TQValueList area = _view->doc()->listArea(); + for ( it = area.begin(); it != area.end(); ++it ) + slotAddAreaName( (*it).ref_name); + connect( this, TQT_SIGNAL( activated ( const TQString & ) ), m_locationWidget, TQT_SLOT( slotActivateItem() ) ); +} + + +void ComboboxLocationEditWidget::slotAddAreaName( const TQString &_name) +{ + insertItem( _name ); + m_locationWidget->addCompletionItem( _name ); +} + +void ComboboxLocationEditWidget::slotRemoveAreaName( const TQString &_name ) +{ + for ( int i = 0; iremoveCompletionItem( _name ); +} + + + +/***************************************************************************** + * + * LocationEditWidget + * + ****************************************************************************/ + +LocationEditWidget::LocationEditWidget( TQWidget * _parent, + View * _view ) + : KLineEdit( _parent, "LocationEditWidget" ), + m_pView(_view) +{ + setCompletionObject( &completionList,true ); + setCompletionMode(TDEGlobalSettings::CompletionAuto ); +} + +void LocationEditWidget::addCompletionItem( const TQString &_item ) +{ + kdDebug()<<" LocationEditWidget::addCompletionItem add :"<<_item<::Iterator it; + TQValueList area = m_pView->doc()->listArea(); + for ( it = area.begin(); it != area.end(); ++it ) + { + if ((*it).ref_name == tmp) + { + TQString tmp = (*it).sheet_name; + tmp += "!"; + tmp += util_rangeName((*it).rect); + m_pView->selectionInfo()->initialize( Region(m_pView,tmp) ); + return true; + } + } + + // Set the cell component to uppercase: + // Sheet1!a1 -> Sheet1!A2 + int pos = ltext.find('!'); + if ( pos !=- 1 ) + tmp = ltext.left(pos)+ltext.mid(pos).upper(); + else + tmp = ltext.upper(); + + // Selection entered in location widget + if ( ltext.contains( ':' ) ) + m_pView->selectionInfo()->initialize( Region(m_pView,tmp) ); + // Location entered in location widget + else + { + Region region(m_pView,tmp); + bool validName = true; + for (unsigned int i = 0; i < ltext.length(); ++i) + { + if (!ltext[i].isLetter()) + { + validName = false; + break; + } + } + if ( !region.isValid() && validName) + { + TQRect rect( m_pView->selectionInfo()->selection() ); + Sheet * t = m_pView->activeSheet(); + // set area name on current selection/cell + + m_pView->doc()->addAreaName(rect, ltext.lower(), t->sheetName()); + } + + if (!validName) + { + m_pView->selectionInfo()->initialize(region); + } + } + + // Set the focus back on the canvas. + m_pView->canvasWidget()->setFocus(); + return false; +} + + +void LocationEditWidget::keyPressEvent( TQKeyEvent * _ev ) +{ + // Do not handle special keys and accelerators. This is + // done by TQLineEdit. + if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) ) + { + TQLineEdit::keyPressEvent( _ev ); + // Never allow that keys are passed on to the parent. + _ev->accept(); + + return; + } + + // Handle some special keys here. Eve + switch( _ev->key() ) + { + case Key_Return: + case Key_Enter: + { + if ( activateItem() ) + return; + _ev->accept(); + } + break; + // Escape pressed, restore original value + case Key_Escape: + // #### Torben says: This is duplicated code. Bad. + if ( m_pView->selectionInfo()->isSingular() ) { + setText( Cell::columnName( m_pView->canvasWidget()->markerColumn() ) + + TQString::number( m_pView->canvasWidget()->markerRow() ) ); + } else { + setText( Cell::columnName( m_pView->selectionInfo()->lastRange().left() ) + + TQString::number( m_pView->selectionInfo()->lastRange().top() ) + + ":" + + Cell::columnName( m_pView->selectionInfo()->lastRange().right() ) + + TQString::number( m_pView->selectionInfo()->lastRange().bottom() ) ); + } + m_pView->canvasWidget()->setFocus(); + _ev->accept(); + break; + default: + TQLineEdit::keyPressEvent( _ev ); + // Never allow that keys are passed on to the parent. + _ev->accept(); + } +} + + + +/**************************************************************** + * + * EditWidget + * The line-editor that appears above the sheet and allows to + * edit the cells content. + * + ****************************************************************/ + +EditWidget::EditWidget( TQWidget *_parent, Canvas *_canvas, + TQButton *cancelButton, TQButton *okButton ) + : TQLineEdit( _parent, "EditWidget" ) +{ + m_pCanvas = _canvas; + Q_ASSERT(m_pCanvas != NULL); + // Those buttons are created by the caller, so that they are inserted + // properly in the layout - but they are then managed here. + m_pCancelButton = cancelButton; + m_pOkButton = okButton; + isArray = false; + + installEventFilter(m_pCanvas); + + if ( !m_pCanvas->doc()->isReadWrite() || !m_pCanvas->activeSheet() ) + setEnabled( false ); + + TQObject::connect( m_pCancelButton, TQT_SIGNAL( clicked() ), + this, TQT_SLOT( slotAbortEdit() ) ); + TQObject::connect( m_pOkButton, TQT_SIGNAL( clicked() ), + this, TQT_SLOT( slotDoneEdit() ) ); + + setEditMode( false ); // disable buttons +} + +void EditWidget::showEditWidget(bool _show) +{ + if (_show) + { + m_pCancelButton->show(); + m_pOkButton->show(); + show(); + } + else + { + m_pCancelButton->hide(); + m_pOkButton->hide(); + hide(); + } +} + +void EditWidget::slotAbortEdit() +{ + m_pCanvas->deleteEditor( false /*discard changes*/ ); + // will take care of the buttons +} + +void EditWidget::slotDoneEdit() +{ + m_pCanvas->deleteEditor( true /*keep changes*/, isArray); + isArray = false; + // will take care of the buttons +} + +void EditWidget::keyPressEvent ( TQKeyEvent* _ev ) +{ + // Dont handle special keys and accelerators, except Enter ones + if (( ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) ) + || ( _ev->state() & TQt::ShiftButton ) + || ( _ev->key() == Key_Shift ) + || ( _ev->key() == Key_Control ) ) + && (_ev->key() != Key_Return) && (_ev->key() != Key_Enter)) + { + TQLineEdit::keyPressEvent( _ev ); + _ev->accept(); + return; + } + + if ( !m_pCanvas->doc()->isReadWrite() ) + return; + + if ( !m_pCanvas->editor() ) + { + // Start editing the current cell + m_pCanvas->createEditor( Canvas::CellEditor,false ); + } + CellEditor * cellEditor = (CellEditor*) m_pCanvas->editor(); + + switch ( _ev->key() ) + { + case Key_Down: + case Key_Up: + case Key_Return: + case Key_Enter: + cellEditor->setText( text()); + // Don't allow to start a chooser when pressing the arrow keys + // in this widget, since only up and down would work anyway. + // This is why we call slotDoneEdit now, instead of sending + // to the canvas. + //TQApplication::sendEvent( m_pCanvas, _ev ); + isArray = (_ev->state() & TQt::AltButton) && + (_ev->state() & TQt::ControlButton); + slotDoneEdit(); + m_pCanvas->view()->updateEditWidget(); + _ev->accept(); + break; + case Key_F2: + cellEditor->setFocus(); + cellEditor->setText( text()); + cellEditor->setCursorPosition(cursorPosition()); + break; + default: + + TQLineEdit::keyPressEvent( _ev ); + + setFocus(); + cellEditor->setCheckChoice( false ); + cellEditor->setText( text() ); + cellEditor->setCheckChoice( true ); + cellEditor->setCursorPosition( cursorPosition() ); + } +} + +void EditWidget::setEditMode( bool mode ) +{ + m_pCancelButton->setEnabled(mode); + m_pOkButton->setEnabled(mode); +} + +void EditWidget::focusOutEvent( TQFocusEvent* ev ) +{ + //kdDebug(36001) << "EditWidget lost focus" << endl; + // See comment about setLastEditorWithFocus + m_pCanvas->setLastEditorWithFocus( Canvas::EditWidget ); + + TQLineEdit::focusOutEvent( ev ); +} + +void EditWidget::setText( const TQString& t ) +{ + if ( t == text() ) // Why this? (David) + return; + + TQLineEdit::setText( t ); +} + + + +#include "kspread_editors.moc" diff --git a/kspread/kspread_events.cc b/kspread/kspread_events.cc deleted file mode 100644 index 7026be1d..00000000 --- a/kspread/kspread_events.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "kspread_events.h" - -// ---------------------------------------------------- - -using namespace KSpread; - -const char *SelectionChanged::s_strSelectionChanged = "KSpread/View/SelectionChanged"; - -SelectionChanged::SelectionChanged( const Region& region, const TQString& sheet ) - : KParts::Event( s_strSelectionChanged ) -{ - m_region = region; - m_sheet = sheet; -} - -SelectionChanged::~SelectionChanged() -{ -} - diff --git a/kspread/kspread_events.cpp b/kspread/kspread_events.cpp new file mode 100644 index 00000000..7026be1d --- /dev/null +++ b/kspread/kspread_events.cpp @@ -0,0 +1,19 @@ +#include "kspread_events.h" + +// ---------------------------------------------------- + +using namespace KSpread; + +const char *SelectionChanged::s_strSelectionChanged = "KSpread/View/SelectionChanged"; + +SelectionChanged::SelectionChanged( const Region& region, const TQString& sheet ) + : KParts::Event( s_strSelectionChanged ) +{ + m_region = region; + m_sheet = sheet; +} + +SelectionChanged::~SelectionChanged() +{ +} + diff --git a/kspread/kspread_factory.cc b/kspread/kspread_factory.cc deleted file mode 100644 index 861b9d96..00000000 --- a/kspread/kspread_factory.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998, 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include "kspread_aboutdata.h" -#include "kspread_doc.h" -#include "KSpreadAppIface.h" - -#include "kspread_factory.h" - -using namespace KSpread; - -TDEInstance* Factory::s_global = 0; -DCOPObject* Factory::s_dcopObject = 0; -TDEAboutData* Factory::s_aboutData = 0; - -Factory::Factory( TQObject* parent, const char* name ) - : KoFactory( parent, name ) -{ - //kdDebug(36001) << "Factory::Factory()" << endl; - // Create our instance, so that it becomes TDEGlobal::instance if the - // main app is KSpread. - (void)global(); - (void)dcopObject(); -} - -Factory::~Factory() -{ - //kdDebug(36001) << "Factory::~Factory()" << endl; - delete s_aboutData; - s_aboutData=0; - delete s_global; - s_global = 0L; - delete s_dcopObject; - s_dcopObject = 0L; -} - -KParts::Part* Factory::createPartObject( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, const char* classname, const TQStringList & ) -{ - bool bWantKoDocument = ( strcmp( classname, "KoDocument" ) == 0 ); - - Doc *doc = new Doc( parentWidget, widgetName, parent, name, !bWantKoDocument ); - - if ( !bWantKoDocument ) - doc->setReadWrite( false ); - - return doc; -} - -TDEAboutData* Factory::aboutData() -{ - if( !s_aboutData ) - s_aboutData = newAboutData(); - return s_aboutData; -} - -TDEInstance* Factory::global() -{ - if ( !s_global ) - { - s_global = new TDEInstance(aboutData()); - - s_global->dirs()->addResourceType( "kspread_template", - TDEStandardDirs::kde_default("data") + "kspread/templates/"); - - s_global->dirs()->addResourceType( "toolbar", - TDEStandardDirs::kde_default("data") + "koffice/toolbar/"); - s_global->dirs()->addResourceType( "extensions", TDEStandardDirs::kde_default("data") + "kspread/extensions/"); - s_global->dirs()->addResourceType( "sheet-styles", TDEStandardDirs::kde_default("data") + "kspread/sheetstyles/"); - // Tell the iconloader about share/apps/koffice/icons - s_global->iconLoader()->addAppDir("koffice"); - } - return s_global; -} - -DCOPObject* Factory::dcopObject() -{ - if ( !s_dcopObject ) - s_dcopObject = new AppIface; - return s_dcopObject; -} - -#include "kspread_factory.moc" diff --git a/kspread/kspread_factory.cpp b/kspread/kspread_factory.cpp new file mode 100644 index 00000000..861b9d96 --- /dev/null +++ b/kspread/kspread_factory.cpp @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "kspread_aboutdata.h" +#include "kspread_doc.h" +#include "KSpreadAppIface.h" + +#include "kspread_factory.h" + +using namespace KSpread; + +TDEInstance* Factory::s_global = 0; +DCOPObject* Factory::s_dcopObject = 0; +TDEAboutData* Factory::s_aboutData = 0; + +Factory::Factory( TQObject* parent, const char* name ) + : KoFactory( parent, name ) +{ + //kdDebug(36001) << "Factory::Factory()" << endl; + // Create our instance, so that it becomes TDEGlobal::instance if the + // main app is KSpread. + (void)global(); + (void)dcopObject(); +} + +Factory::~Factory() +{ + //kdDebug(36001) << "Factory::~Factory()" << endl; + delete s_aboutData; + s_aboutData=0; + delete s_global; + s_global = 0L; + delete s_dcopObject; + s_dcopObject = 0L; +} + +KParts::Part* Factory::createPartObject( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, const char* classname, const TQStringList & ) +{ + bool bWantKoDocument = ( strcmp( classname, "KoDocument" ) == 0 ); + + Doc *doc = new Doc( parentWidget, widgetName, parent, name, !bWantKoDocument ); + + if ( !bWantKoDocument ) + doc->setReadWrite( false ); + + return doc; +} + +TDEAboutData* Factory::aboutData() +{ + if( !s_aboutData ) + s_aboutData = newAboutData(); + return s_aboutData; +} + +TDEInstance* Factory::global() +{ + if ( !s_global ) + { + s_global = new TDEInstance(aboutData()); + + s_global->dirs()->addResourceType( "kspread_template", + TDEStandardDirs::kde_default("data") + "kspread/templates/"); + + s_global->dirs()->addResourceType( "toolbar", + TDEStandardDirs::kde_default("data") + "koffice/toolbar/"); + s_global->dirs()->addResourceType( "extensions", TDEStandardDirs::kde_default("data") + "kspread/extensions/"); + s_global->dirs()->addResourceType( "sheet-styles", TDEStandardDirs::kde_default("data") + "kspread/sheetstyles/"); + // Tell the iconloader about share/apps/koffice/icons + s_global->iconLoader()->addAppDir("koffice"); + } + return s_global; +} + +DCOPObject* Factory::dcopObject() +{ + if ( !s_dcopObject ) + s_dcopObject = new AppIface; + return s_dcopObject; +} + +#include "kspread_factory.moc" diff --git a/kspread/kspread_factory_init.cc b/kspread/kspread_factory_init.cc deleted file mode 100644 index d62e304f..00000000 --- a/kspread/kspread_factory_init.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2005 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kspread_factory.h" - -K_EXPORT_COMPONENT_FACTORY( libkspreadpart, KSpread::Factory ) - diff --git a/kspread/kspread_factory_init.cpp b/kspread/kspread_factory_init.cpp new file mode 100644 index 00000000..d62e304f --- /dev/null +++ b/kspread/kspread_factory_init.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2005 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kspread_factory.h" + +K_EXPORT_COMPONENT_FACTORY( libkspreadpart, KSpread::Factory ) + diff --git a/kspread/kspread_format.cc b/kspread/kspread_format.cc deleted file mode 100644 index 430e2386..00000000 --- a/kspread/kspread_format.cc +++ /dev/null @@ -1,3581 +0,0 @@ -/* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis - Copyright (C) 2000 - 2005 The KSpread Team - www.koffice.org/kspread - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_global.h" -#include "kspread_sheet.h" -#include "kspread_sheetprint.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "KSpreadColumnIface.h" -#include "KSpreadLayoutIface.h" -#include "KSpreadRowIface.h" - -#include "kspread_format.h" - -using namespace std; -using namespace KSpread; - -/***************************************************************************** - * - * Format - * - *****************************************************************************/ - -// static variable construction -// NOTE Stefan: These values are always overridden by the Doc c'tor. -double Format::s_columnWidth = 100.0; -double Format::s_rowHeight = 20.0; - -Format::Format( Sheet * _sheet, Style * _style ) - : m_pSheet( _sheet ), - m_pStyle( _style ), - m_mask( 0 ), - m_bNoFallBack( 0 ), - m_flagsMask( 0 ), - m_strComment( 0 ), - m_pCell( 0 ) -{ -} - -Format::~Format() -{ - if ( m_pStyle->release() ) - delete m_pStyle; -} - -void Format::defaultStyleFormat() -{ - if ( m_pStyle->release() ) - delete m_pStyle; - - if ( m_pSheet ) - m_pStyle = m_pSheet->doc()->styleManager()->defaultStyle(); - - delete m_strComment; -} - - -void Format::setGlobalColWidth( double width ) -{ - s_columnWidth = width; -} - -void Format::setGlobalRowHeight( double height ) -{ - s_rowHeight = height; -} - -double Format::globalRowHeight() -{ - return s_rowHeight; -} - -double Format::globalColWidth() -{ - return s_columnWidth; -} - -void Format::copy( const Format & _l ) -{ - // TODO why is the sheet not copied? - - setStyle( _l.m_pStyle ); - - m_mask = _l.m_mask; - m_flagsMask = _l.m_flagsMask; - m_bNoFallBack = _l.m_bNoFallBack; - - if ( _l.m_strComment ) - { - if (m_strComment) - delete m_strComment; - m_strComment = new TQString( *_l.m_strComment ); - } -} - -void Format::setStyle( Style * style ) -{ - if ( style == m_pStyle ) - return; - - if ( m_pStyle && m_pStyle->release() ) - delete m_pStyle; - - m_bNoFallBack = 0; - m_pStyle = style; - m_pStyle->addRef(); - formatChanged(); - // kdDebug() << "Newly assigned style: " << m_pStyle << ", type: " << m_pStyle->type() << endl; - if ( style->type() == Style::BUILTIN || style->type() == Style::CUSTOM ) - kdDebug() << "Style name: " << ((CustomStyle *) m_pStyle)->name() << endl; -} - -void Format::clearFlag( FormatFlags flag ) -{ - m_flagsMask &= ~(TQ_UINT32)flag; -} - -void Format::setFlag( FormatFlags flag ) -{ - m_flagsMask |= (TQ_UINT32)flag; -} - -bool Format::testFlag( FormatFlags flag ) const -{ - return ( m_flagsMask & (TQ_UINT32)flag ); -} - -void Format::clearProperties() -{ - m_mask = 0; - m_pStyle->clearFeature( (Style::FlagsSet) ~(uint)0 ); - formatChanged(); -} - -void Format::clearProperty( Properties p ) -{ - m_mask &= ~(uint)p; - m_pStyle->clearFeature( (Style::FlagsSet) p ); - formatChanged(); -} - -// FIXME according to Valgrind, this function consumes too much time -// find a way to optimize it ! -bool Format::hasProperty( Properties p, bool withoutParent ) const -{ - if ( m_pStyle->hasFeature( (Style::FlagsSet) p, withoutParent ) ) - return true; - - return ( m_mask & (uint)p ); -} - -void Format::setProperty( Properties p ) -{ - m_mask |= (uint)p; -} - -void Format::clearNoFallBackProperties() -{ - m_bNoFallBack = 0; - - formatChanged(); -} - -void Format::clearNoFallBackProperties( Properties p ) -{ - m_bNoFallBack &= ~(uint)p; - - formatChanged(); -} - -bool Format::hasNoFallBackProperties( Properties p ) const -{ - return ( m_bNoFallBack & (uint)p ); -} - -void Format::setNoFallBackProperties( Properties p ) -{ - m_bNoFallBack |= (uint)p; -} - - -///////////// -// -// Loading and saving -// -///////////// - - -TQString Format::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles ) -{ - TQString styleName; - styleName = m_pStyle->saveOasis( currentCellStyle, mainStyles ); - - // user styles are already stored - if ( currentCellStyle.type() == Doc::STYLE_CELL_AUTO ) - { - styleName = mainStyles.lookup( currentCellStyle, "ce" ); - } - - return styleName; -} - -TQDomElement Format::saveFormat( TQDomDocument & doc, int _col, int _row, bool force, bool copy ) const -{ - TQDomElement format( doc.createElement( "format" ) ); - - if ( m_pStyle->type() == Style::BUILTIN || m_pStyle->type() == Style::CUSTOM ) - { - format.setAttribute( "style-name", ((CustomStyle *) m_pStyle)->name() ); - - if ( !copy ) - return format; - } - else - { - if ( m_pStyle->parent() && m_pStyle->parent()->name().length() > 0 ) - format.setAttribute( "parent", m_pStyle->parent()->name() ); - } - - if ( hasProperty( PAlign, true ) || hasNoFallBackProperties( PAlign ) || force ) - format.setAttribute( "align", (int) align( _col, _row ) ); - if ( hasProperty( PAlignY, true ) || hasNoFallBackProperties( PAlignY ) || force ) - format.setAttribute( "alignY", (int)alignY( _col, _row ) ); - if ( ( hasProperty( PBackgroundColor, false ) || hasNoFallBackProperties( PBackgroundColor) - || force ) && bgColor( _col, _row ).isValid() ) - format.setAttribute( "bgcolor", bgColor( _col, _row ).name() ); - if ( ( hasProperty( PMultiRow, true ) || hasNoFallBackProperties( PMultiRow ) - || force ) && multiRow( _col, _row ) ) - format.setAttribute( "multirow", "yes" ); - if ( ( hasProperty( PVerticalText, true ) || hasNoFallBackProperties( PVerticalText ) - || force ) && verticalText( _col, _row ) ) - format.setAttribute( "verticaltext", "yes" ); - if ( hasProperty( PPrecision, true ) || hasNoFallBackProperties( PPrecision ) || force ) - format.setAttribute( "precision", precision( _col, _row ) ); - if ( ( hasProperty( PPrefix, true ) || hasNoFallBackProperties( PPrefix ) || force ) - && !prefix( _col, _row ).isEmpty() ) - format.setAttribute( "prefix", prefix( _col, _row ) ); - if ( ( hasProperty( PPostfix, true ) || hasNoFallBackProperties( PPostfix ) || force ) - && !postfix( _col, _row ).isEmpty() ) - format.setAttribute( "postfix", postfix( _col, _row ) ); - if ( hasProperty( PFloatFormat, true ) || hasNoFallBackProperties( PFloatFormat ) || force ) - format.setAttribute( "float", (int) floatFormat( _col, _row ) ); - if ( hasProperty( PFloatColor, true ) || hasNoFallBackProperties( PFloatColor ) || force ) - format.setAttribute( "floatcolor", (int) floatColor( _col, _row ) ); - if ( hasProperty( PFormatType, true ) || hasNoFallBackProperties( PFormatType ) || force ) - format.setAttribute( "format", (int)getFormatType( _col, _row )); - if ( hasProperty( PCustomFormat, true ) || hasNoFallBackProperties( PCustomFormat ) || force ) - { - TQString s( getFormatString( _col, _row ) ); - if ( s.length() > 0 ) - format.setAttribute( "custom", s ); - } - if ( getFormatType( _col, _row ) == Money_format ) - { - format.setAttribute( "type", (int) m_pStyle->currency().type ); // TODO: fallback? - format.setAttribute( "symbol", m_pStyle->currency().symbol ); - } - if ( hasProperty( PAngle, true ) || hasNoFallBackProperties( PAngle ) || force ) - format.setAttribute( "angle", getAngle( _col, _row ) ); - if ( hasProperty( PIndent, true ) || hasNoFallBackProperties( PIndent ) || force ) - format.setAttribute( "indent", getIndent( _col, _row ) ); - if( ( hasProperty( PDontPrintText, true ) || hasNoFallBackProperties( PDontPrintText ) - || force ) && getDontprintText( _col, _row ) ) - format.setAttribute( "dontprinttext", "yes" ); - if( ( hasProperty( PNotProtected, true ) || hasNoFallBackProperties( PNotProtected ) - || force ) && notProtected( _col, _row ) ) - format.setAttribute( "noprotection", "yes" ); - if( ( hasProperty( PHideAll, true ) || hasNoFallBackProperties( PHideAll ) - || force ) && isHideAll( _col, _row ) ) - format.setAttribute( "hideall", "yes" ); - if( ( hasProperty( PHideFormula, true ) || hasNoFallBackProperties( PHideFormula ) - || force ) && isHideFormula( _col, _row ) ) - format.setAttribute( "hideformula", "yes" ); - if ( hasProperty( PFont, true ) || hasNoFallBackProperties( PFont ) || force ) - format.appendChild( util_createElement( "font", textFont( _col, _row ), doc ) ); - if ( ( hasProperty( PTextPen, true ) || hasNoFallBackProperties( PTextPen ) || force ) - && textPen( _col, _row ).color().isValid() ) - format.appendChild( util_createElement( "pen", textPen( _col, _row ), doc ) ); - if ( hasProperty( PBackgroundBrush, true ) || hasNoFallBackProperties( PBackgroundBrush ) || force ) - { - format.setAttribute( "brushcolor", backGroundBrushColor( _col, _row ).name() ); - format.setAttribute( "brushstyle", (int)backGroundBrushStyle( _col, _row ) ); - } - if ( hasProperty( PLeftBorder, true ) || hasNoFallBackProperties( PLeftBorder ) || force ) - { - TQDomElement left = doc.createElement( "left-border" ); - left.appendChild( util_createElement( "pen", leftBorderPen( _col, _row ), doc ) ); - format.appendChild( left ); - } - if ( hasProperty( PTopBorder, true ) || hasNoFallBackProperties( PTopBorder ) || force ) - { - TQDomElement top = doc.createElement( "top-border" ); - top.appendChild( util_createElement( "pen", topBorderPen( _col, _row ), doc ) ); - format.appendChild( top ); - } - if ( hasProperty( PRightBorder, true ) || hasNoFallBackProperties( PRightBorder ) || force ) - { - TQDomElement right = doc.createElement( "right-border" ); - right.appendChild( util_createElement( "pen", rightBorderPen( _col, _row ), doc ) ); - format.appendChild( right ); - } - if ( hasProperty( PBottomBorder, true ) || hasNoFallBackProperties( PBottomBorder ) || force ) - { - TQDomElement bottom = doc.createElement( "bottom-border" ); - bottom.appendChild( util_createElement( "pen", bottomBorderPen( _col, _row ), doc ) ); - format.appendChild( bottom ); - } - if ( hasProperty( PFallDiagonal, true ) || hasNoFallBackProperties( PFallDiagonal ) || force ) - { - TQDomElement fallDiagonal = doc.createElement( "fall-diagonal" ); - fallDiagonal.appendChild( util_createElement( "pen", fallDiagonalPen( _col, _row ), doc ) ); - format.appendChild( fallDiagonal ); - } - if ( hasProperty( PGoUpDiagonal, true ) || hasNoFallBackProperties( PGoUpDiagonal ) || force ) - { - TQDomElement goUpDiagonal = doc.createElement( "up-diagonal" ); - goUpDiagonal.appendChild( util_createElement( "pen", goUpDiagonalPen( _col, _row ), doc ) ); - format.appendChild( goUpDiagonal ); - } - return format; -} - - -TQDomElement Format::saveFormat( TQDomDocument& doc, bool force, bool copy ) const -{ - TQDomElement format( doc.createElement( "format" ) ); - - if ( m_pStyle->type() == Style::BUILTIN || m_pStyle->type() == Style::CUSTOM ) - { - format.setAttribute( "style-name", ((CustomStyle *) m_pStyle)->name() ); - - if ( !copy ) - return format; - } - else - { - if ( m_pStyle->parent() && m_pStyle->parentName().length() > 0 ) - format.setAttribute( "parent", m_pStyle->parentName() ); - } - - if ( hasProperty( PAlign, true ) || hasNoFallBackProperties( PAlign ) || force ) - format.setAttribute( "align", (int)m_pStyle->alignX() ); - if ( hasProperty( PAlignY, true ) || hasNoFallBackProperties( PAlignY ) || force ) - format.setAttribute( "alignY", (int)m_pStyle->alignY() ); - if ( ( hasProperty( PBackgroundColor, true ) || hasNoFallBackProperties( PBackgroundColor ) - || force ) && m_pStyle->bgColor().isValid() ) - format.setAttribute( "bgcolor", m_pStyle->bgColor().name() ); - - if ( ( hasProperty( PMultiRow, true ) || hasNoFallBackProperties( PMultiRow ) || force ) - && m_pStyle->hasProperty( Style::PMultiRow ) ) - format.setAttribute( "multirow", "yes" ); - if ( ( hasProperty( PVerticalText, true ) || hasNoFallBackProperties( PVerticalText ) || force ) - && m_pStyle->hasProperty( Style::PVerticalText ) ) - format.setAttribute( "verticaltext", "yes" ); - - if ( hasProperty( PPrecision, true ) || hasNoFallBackProperties( PPrecision ) || force ) - format.setAttribute( "precision", m_pStyle->precision() ); - if ( ( hasProperty( PPrefix, true ) || hasNoFallBackProperties( PPrefix ) || force ) - && !m_pStyle->prefix().isEmpty() ) - format.setAttribute( "prefix", m_pStyle->prefix() ); - if ( ( hasProperty( PPostfix, true ) || hasNoFallBackProperties( PPostfix ) || force ) - && !m_pStyle->postfix().isEmpty() ) - format.setAttribute( "postfix", m_pStyle->postfix() ); - - if ( hasProperty( PFloatFormat, true ) || hasNoFallBackProperties( PFloatFormat ) || force ) - format.setAttribute( "float", (int) m_pStyle->floatFormat() ); - if ( hasProperty( PFloatColor, true ) || hasNoFallBackProperties( PFloatColor ) || force ) - format.setAttribute( "floatcolor", (int) m_pStyle->floatColor() ); - if ( hasProperty( PFormatType, true ) || hasNoFallBackProperties( PFormatType ) || force ) - format.setAttribute( "format", (int) m_pStyle->formatType() ); - if ( hasProperty( PCustomFormat, true ) || hasNoFallBackProperties( PCustomFormat ) || force ) - if ( m_pStyle->strFormat().length() > 0 ) - format.setAttribute( "custom", m_pStyle->strFormat() ); - if ( m_pStyle->formatType() == Money_format ) - { - format.setAttribute( "type", (int) m_pStyle->currency().type ); - format.setAttribute( "symbol", m_pStyle->currency().symbol ); - } - if ( hasProperty( PAngle, true ) || hasNoFallBackProperties( PAngle ) || force ) - format.setAttribute( "angle", m_pStyle->rotateAngle() ); - if ( hasProperty( PIndent, true ) || hasNoFallBackProperties( PIndent ) || force ) - format.setAttribute( "indent", m_pStyle->indent() ); - if ( ( hasProperty( PDontPrintText, true ) || hasNoFallBackProperties( PDontPrintText ) || force ) - && m_pStyle->hasProperty( Style::PDontPrintText ) ) - format.setAttribute( "dontprinttext", "yes" ); - if ( ( hasProperty( PNotProtected, true ) || hasNoFallBackProperties( PNotProtected ) - || force ) && m_pStyle->hasProperty( Style::PNotProtected ) ) - format.setAttribute( "noprotection", "yes" ); - if( ( hasProperty( PHideAll, true ) || hasNoFallBackProperties( PHideAll ) - || force ) && m_pStyle->hasProperty( Style::PHideAll ) ) - format.setAttribute( "hideall", "yes" ); - if( ( hasProperty( PHideFormula, true ) || hasNoFallBackProperties( PHideFormula ) - || force ) && m_pStyle->hasProperty( Style::PHideFormula ) ) - format.setAttribute( "hideformula", "yes" ); - if ( hasProperty( PFont, true ) || hasNoFallBackProperties( PFont ) || force ) - format.appendChild( util_createElement( "font", m_pStyle->font(), doc ) ); - if ( ( hasProperty( PTextPen, true ) || hasNoFallBackProperties( PTextPen ) || force ) - && m_pStyle->pen().color().isValid() ) - format.appendChild( util_createElement( "pen", m_pStyle->pen(), doc ) ); - if ( hasProperty( PBackgroundBrush, true ) || hasNoFallBackProperties( PBackgroundBrush ) || force ) - { - format.setAttribute( "brushcolor", m_pStyle->backGroundBrush().color().name() ); - format.setAttribute( "brushstyle", (int) m_pStyle->backGroundBrush().style() ); - } - if ( hasProperty( PLeftBorder, true ) || hasNoFallBackProperties( PLeftBorder ) || force ) - { - TQDomElement left = doc.createElement( "left-border" ); - left.appendChild( util_createElement( "pen", m_pStyle->leftBorderPen(), doc ) ); - format.appendChild( left ); - } - if ( hasProperty( PTopBorder, true ) || hasNoFallBackProperties( PTopBorder ) || force ) - { - TQDomElement top = doc.createElement( "top-border" ); - top.appendChild( util_createElement( "pen", m_pStyle->topBorderPen(), doc ) ); - format.appendChild( top ); - } - if ( hasProperty( PRightBorder, true ) || hasNoFallBackProperties( PRightBorder ) || force ) - { - TQDomElement right = doc.createElement( "right-border" ); - right.appendChild( util_createElement( "pen", m_pStyle->rightBorderPen(), doc ) ); - format.appendChild( right ); - } - if ( hasProperty( PBottomBorder, true ) || hasNoFallBackProperties( PBottomBorder ) || force ) - { - TQDomElement bottom = doc.createElement( "bottom-border" ); - bottom.appendChild( util_createElement( "pen", m_pStyle->bottomBorderPen(), doc ) ); - format.appendChild( bottom ); - } - if ( hasProperty( PFallDiagonal, true ) || hasNoFallBackProperties( PFallDiagonal ) || force ) - { - TQDomElement fallDiagonal = doc.createElement( "fall-diagonal" ); - fallDiagonal.appendChild( util_createElement( "pen", m_pStyle->fallDiagonalPen(), doc ) ); - format.appendChild( fallDiagonal ); - } - if ( hasProperty( PGoUpDiagonal, true ) || hasNoFallBackProperties( PGoUpDiagonal ) || force ) - { - TQDomElement goUpDiagonal = doc.createElement( "up-diagonal" ); - goUpDiagonal.appendChild( util_createElement( "pen", m_pStyle->goUpDiagonalPen(), doc ) ); - format.appendChild( goUpDiagonal ); - } - return format; -} - -TQDomElement Format::save( TQDomDocument & doc, int _col, int _row, bool force, bool copy ) const -{ - TQDomElement format = saveFormat( doc, _col, _row, force, copy ); - return format; -} - -bool Format::loadFormat( const TQDomElement & f, Paste::Mode pm, bool paste ) -{ - if ( f.hasAttribute( "style-name" ) ) - { - Style * s = m_pSheet->doc()->styleManager()->style( f.attribute( "style-name" ) ); - - //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; - if ( s ) - { - setStyle( s ); - - return true; - } - else if ( !paste ) - return false; - } - else - if ( f.hasAttribute( "parent" ) ) - { - CustomStyle* s = static_cast( m_pSheet->doc()->styleManager()->style( f.attribute( "parent" ) ) ); - //kdDebug() << "Loading Style, parent: " << s->name() << ": " << s << endl; - - if ( s ) - { - if ( m_pStyle && m_pStyle->release() ) - delete m_pStyle; - - m_pStyle = new Style(); - m_pStyle->setParent( s ); - } - } - - bool ok; - if ( f.hasAttribute( "align" ) ) - { - Align a = (Align) f.attribute( "align" ).toInt( &ok ); - if ( !ok ) - return false; - // Validation - if ( (unsigned int) a >= 1 || (unsigned int) a <= 4 ) - { - setAlign( a ); - } - } - if ( f.hasAttribute( "alignY" ) ) - { - AlignY a = (AlignY) f.attribute( "alignY" ).toInt( &ok ); - if ( !ok ) - return false; - // Validation - if ( (unsigned int) a >= 1 || (unsigned int) a <= 4 ) - { - setAlignY( a ); - } - } - - if ( f.hasAttribute( "bgcolor" ) ) { - TQColor col( f.attribute( "bgcolor" ) ); - if ( col != TQt::white ) - setBgColor( col ); - } - - if ( f.hasAttribute( "multirow" ) ) - setMultiRow( true ); - - if ( f.hasAttribute( "verticaltext" ) ) - setVerticalText( true ); - - if ( f.hasAttribute( "precision" ) ) - { - int i = f.attribute( "precision" ).toInt( &ok ); - if ( i < -1 ) - { - kdDebug(36001) << "Value out of range Cell::precision=" << i << endl; - return false; - } - // Assignment - setPrecision( i ); - } - - if ( f.hasAttribute( "float" ) ) - { - FloatFormat a = (FloatFormat) f.attribute( "float" ).toInt( &ok ); - if ( !ok ) return false; - if ( (unsigned int) a >= 1 && (unsigned int) a <= 3 ) - { - setFloatFormat( a ); - } - } - - if ( f.hasAttribute( "floatcolor" ) ) - { - FloatColor a = (FloatColor) f.attribute( "floatcolor" ).toInt( &ok ); - if ( !ok ) return false; - if ( (unsigned int) a >= 1 && (unsigned int) a <= 4 ) - { - setFloatColor( a ); - } - } - - if ( f.hasAttribute( "format" ) ) - { - int fo = f.attribute( "format" ).toInt( &ok ); - if ( ! ok ) - return false; - setFormatType( ( FormatType ) fo ); - } - if ( f.hasAttribute( "custom" ) ) - { - setFormatString( f.attribute( "custom" ) ); - } - if ( m_pStyle->formatType() == Money_format ) - { - Currency c; - c.type = -1; - if ( f.hasAttribute( "type" ) ) - { - c.type = f.attribute( "type" ).toInt( &ok ); - if ( !ok ) - c.type = 1; - } - if ( f.hasAttribute( "symbol" ) ) - { - c.symbol = f.attribute( "symbol" ); - } - if ( c.type != -1 ) - setCurrency( c ); - } - if ( f.hasAttribute( "angle" ) ) - { - setAngle( f.attribute( "angle" ).toInt( &ok ) ); - if ( !ok ) - return false; - } - if ( f.hasAttribute( "indent" ) ) - { - setIndent( f.attribute( "indent" ).toDouble( &ok ) ); - if ( !ok ) - return false; - } - if ( f.hasAttribute( "dontprinttext" ) ) - setDontPrintText( true ); - - if ( f.hasAttribute( "noprotection" ) ) - setNotProtected( true ); - - if ( f.hasAttribute( "hideall" ) ) - setHideAll( true ); - - if ( f.hasAttribute( "hideformula" ) ) - setHideFormula( true ); - - if ( f.hasAttribute( "brushstyle" ) ) - { - setBackGroundBrushStyle( (Qt::BrushStyle) f.attribute( "brushstyle" ).toInt( &ok ) ); - if ( !ok ) - return false; - } - - if ( f.hasAttribute( "brushcolor" ) ) - setBackGroundBrushColor( TQColor( f.attribute( "brushcolor" ) ) ); - - TQDomElement pen( f.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setTextPen( util_toPen( pen ) ); - - TQDomElement font( f.namedItem( "font" ).toElement() ); - if ( !font.isNull() ) - setTextFont( util_toFont( font ) ); - - if ( ( pm != Paste::NoBorder ) && ( pm != Paste::Text ) && ( pm != Paste::Comment ) ) - { - TQDomElement left( f.namedItem( "left-border" ).toElement() ); - if ( !left.isNull() ) - { - TQDomElement pen( left.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setLeftBorderPen( util_toPen( pen ) ); - } - - TQDomElement top( f.namedItem( "top-border" ).toElement() ); - if ( !top.isNull() ) - { - TQDomElement pen( top.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setTopBorderPen( util_toPen( pen ) ); - } - - TQDomElement right( f.namedItem( "right-border" ).toElement() ); - if ( !right.isNull() ) - { - TQDomElement pen( right.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setRightBorderPen( util_toPen( pen ) ); - } - - TQDomElement bottom( f.namedItem( "bottom-border" ).toElement() ); - if ( !bottom.isNull() ) - { - TQDomElement pen( bottom.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setBottomBorderPen( util_toPen( pen ) ); - } - - TQDomElement fallDiagonal( f.namedItem( "fall-diagonal" ).toElement() ); - if ( !fallDiagonal.isNull() ) - { - TQDomElement pen( fallDiagonal.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setFallDiagonalPen( util_toPen( pen ) ); - } - - TQDomElement goUpDiagonal( f.namedItem( "up-diagonal" ).toElement() ); - if ( !goUpDiagonal.isNull() ) - { - TQDomElement pen( goUpDiagonal.namedItem( "pen" ).toElement() ); - if ( !pen.isNull() ) - setGoUpDiagonalPen( util_toPen( pen ) ); - } - } - - if ( f.hasAttribute( "prefix" ) ) - setPrefix( f.attribute( "prefix" ) ); - if ( f.hasAttribute( "postfix" ) ) - setPostfix( f.attribute( "postfix" ) ); - - return true; -} - -bool Format::load( const TQDomElement & f, Paste::Mode pm, bool paste ) -{ - if ( !loadFormat( f, pm, paste ) ) - return false; - return true; -} - - -#if 0 -bool Format::loadFontOasisStyle( KoStyleStack & font ) -{ - font.setTypeProperties( "text" ); // load all style attributes from "style:text-properties" - //TODO remember to change type properties - - if ( font.hasAttributeNS( KoXmlNS::fo, "font-family" ) ) - setTextFontFamily( font.attributeNS( KoXmlNS::fo, "font-family" ) ); - - if ( font.hasAttributeNS( KoXmlNS::fo, "color" ) ) - setTextColor( TQColor( font.attributeNS( KoXmlNS::fo, "color" ) ) ); - - if ( font.hasAttributeNS( KoXmlNS::fo, "font-size" ) ) - setTextFontSize( (int) KoUnit::parseValue( font.attributeNS( KoXmlNS::fo, "font-size" ), 10.0 ) ); - - if ( font.hasAttributeNS( KoXmlNS::fo, "font-style" ) && ( font.attributeNS( KoXmlNS::fo,"font-style" )== "italic" )) - { - kdDebug(30518) << "italic" << endl; - setTextFontItalic( true ); // only thing we support - } - if ( font.hasAttributeNS( KoXmlNS::fo, "font-weight" ) - && ( font.attributeNS( KoXmlNS::fo, "font-weight" ) == "bold") ) - setTextFontBold( true ); // only thing we support - - //TODO add "style:text-underline-width" "style:text-underline-color" - if ( ( font.hasAttributeNS( KoXmlNS::fo, "text-underline-style" ) && font.attributeNS( KoXmlNS::fo, "text-underline-style" ) != "none" ) - || ( font.hasAttributeNS( KoXmlNS::style, "text-underline-style" ) && font.attributeNS( KoXmlNS::style, "text-underline-style" )!="none" ) ) - setTextFontUnderline( true ); // only thing we support - - if ( font.hasAttributeNS( KoXmlNS::style, "text-line-through-style" ) - && font.attributeNS( KoXmlNS::style, "text-line-through-style" ) != "none" - /*&& ( font.attributeNS( KoXmlNS::style, "text-crossing-out" ) == "single-line" )*/) - setTextFontStrike( true ); // only thing we support - - if ( font.hasAttributeNS( KoXmlNS::style, "font-pitch" ) ) - { - // TODO: possible values: fixed, variable - } - - // TODO: for the future when we will use kotext - // text-underline-color - return true; -} - -void Format::loadOasisStyle( /*const TQDomElement& style,*/ KoOasisLoadingContext& context ) -{ - TQString str; // multi purpose string - KoOasisStyles& oasisStyles = context.oasisStyles(); - -/* context.styleStack().save(); - context.addStyles( &style );*/ -/* KoStyleStack styleStack; - styleStack.push( style ); - styleStack.setTypeProperties( "table-cell" );*/ - - KoStyleStack& styleStack = context.styleStack(); - loadOasisStyleProperties( styleStack, context.oasisStyles() ); -/* loadOasisStyleProperties( context.styleStack(), context.oasisStyles() ); - context.styleStack().restore();*/ - - kdDebug() << "*** Loading style attributes *****" << endl; - - if ( styleStack.hasAttributeNS( KoXmlNS::style, "data-style-name" ) ) - { - str = styleStack.attributeNS( KoXmlNS::style, "data-style-name" ); - kdDebug() << " style:data-style-name: " << str << endl << endl; - - if ( !str.isEmpty() ) - { - TQString tmp = oasisStyles.dataFormats()[str].prefix; - if ( !tmp.isEmpty() ) - { - setPrefix( tmp ); - } - tmp = oasisStyles.dataFormats()[str].suffix; - if ( !tmp.isEmpty() ) - { - setPostfix( tmp ); - } - tmp = oasisStyles.dataFormats()[str].formatStr; - if ( !tmp.isEmpty() ) - { - setFormatType( Style::formatType( tmp ) ); - } - } - } - - if ( styleStack.hasAttributeNS( KoXmlNS::style, "decimal-places" ) ) - { - bool ok = false; - int p = styleStack.attributeNS( KoXmlNS::style, "decimal-places" ).toInt( &ok ); - kdDebug() << " style:decimal-places: " << p << endl; - if (ok ) - setPrecision( p ); - } -} - -bool Format::loadOasisStyleProperties( KoStyleStack & styleStack, const KoOasisStyles& oasisStyles ) -{ - kdDebug() << "*** Loading style properties *****" << endl; -#if 0 - if ( f.hasAttribute( "style-name" ) ) - { - Style * s = m_pSheet->doc()->styleManager()->style( f.attribute( "style-name" ) ); - - //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; - if ( s ) - { - setStyle( s ); - - return true; - } - else if ( !paste ) - return false; - } - else - if ( f.hasAttribute( "parent" ) ) - { - CustomStyle * s = (CustomStyle *) m_pSheet->doc()->styleManager()->style( f.attribute( "parent" ) ); - //kdDebug() << "Loading Style, parent: " << s->name() << ": " << s << endl; - - if ( s ) - { - if ( m_pStyle && m_pStyle->release() ) - delete m_pStyle; - - m_pStyle = new Style(); - m_pStyle->setParent( s ); - } - } -#endif - if ( styleStack.hasAttributeNS( KoXmlNS::style, "parent-style-name" ) ) - { - Style * s = m_pSheet->doc()->styleManager()->style( styleStack.attributeNS( KoXmlNS::style, "parent-style-name" ) ); - - //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; - if ( s ) - { - setStyle( s ); - } - } - else - { - setStyle( m_pSheet->doc()->styleManager()->defaultStyle() ); - } - - - if ( styleStack.hasAttributeNS( KoXmlNS::style, "font-name" ) ) - { - const TQDomElement * font = oasisStyles.findStyle( styleStack.attributeNS( KoXmlNS::style, "font-name" ) ); - if ( font ) - { - styleStack.save(); - styleStack.push( *font ); - loadFontOasisStyle( styleStack ); // general font style - styleStack.restore(); - } - } - - kdDebug() << " [text properties]" << endl; - //Text properties - loadFontOasisStyle( styleStack ); // specific font style - //End Text properties - - kdDebug() << " [paragraph properties]" << endl; - //Paragraph properties - styleStack.setTypeProperties( "paragraph" ); // load all style attributes from "style:paragraph-properties" - if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-left" ) ) - { - kdDebug()<<" margin-left:"< style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/> - - if ( styleStack.hasAttributeNS( KoXmlNS::style, "rotation-angle" ) ) - { - bool ok = false; - int a = styleStack.attributeNS( KoXmlNS::style, "rotation-angle" ).toInt( &ok ); - if ( ok && ( a != 0 )) - setAngle( -a ); - } - if ( styleStack.hasAttributeNS( KoXmlNS::style, "direction" ) ) - { - TQString dir = styleStack.attributeNS( KoXmlNS::fo, "direction" ); - if ( dir == "ttb" ) - setVerticalText( true ); - else if ( dir == "ltr" ) - setVerticalText( false ); - } - - kdDebug()<<"property.hasAttribute( fo:background-color ) :"<setStrFormat( format ); - formatChanged(); -} - -void Format::setAlign( Align _align ) -{ - if ( _align == Format::Undefined ) - { - clearProperty( PAlign ); - setNoFallBackProperties(PAlign ); - } - else - { - setProperty( PAlign ); - clearNoFallBackProperties(PAlign ); - } - - m_pStyle = m_pStyle->setAlignX( _align ); - formatChanged(); -} - -void Format::setAlignY( AlignY _alignY) -{ - //kdDebug() << "Format: AlignY: " << _alignY << endl; - if ( _alignY == Format::Middle ) - { - //kdDebug() << "Middle" << endl; - clearProperty( PAlignY ); - setNoFallBackProperties(PAlignY ); - } - else - { - //kdDebug() << "Not middle: " << _alignY << endl; - setProperty( PAlignY ); - clearNoFallBackProperties( PAlignY ); - } - - m_pStyle = m_pStyle->setAlignY( _alignY ); - formatChanged(); -} - -void Format::setPrefix( const TQString& _prefix ) -{ - if ( _prefix.isEmpty() ) - { - clearProperty( PPrefix ); - setNoFallBackProperties( PPrefix ); - } - else - { - setProperty( PPrefix ); - clearNoFallBackProperties( PPrefix ); - } - - m_pStyle = m_pStyle->setPrefix( _prefix ); - formatChanged(); -} - -void Format::setPostfix( const TQString& _postfix ) -{ - if ( _postfix.isEmpty() ) - { - clearProperty( PPostfix ); - setNoFallBackProperties( PPostfix ); - } - else - { - setProperty( PPostfix ); - clearNoFallBackProperties( PPostfix ); - } - - m_pStyle = m_pStyle->setPostfix( _postfix ); - formatChanged(); -} - -void Format::setPrecision( int _p ) -{ - if ( _p == -1 ) - { - clearProperty( PPrecision ); - setNoFallBackProperties( PPrecision ); - } - else - { - setProperty( PPrecision ); - clearNoFallBackProperties( PPrecision ); - } - - m_pStyle = m_pStyle->setPrecision( _p ); - formatChanged(); -} - -void Format::setLeftBorderPen( const TQPen & _p ) -{ - if ( _p.style() == TQt::NoPen ) - { - clearProperty( PLeftBorder ); - setNoFallBackProperties( PLeftBorder ); - } - else - { - setProperty( PLeftBorder ); - clearNoFallBackProperties( PLeftBorder ); - } - - m_pStyle = m_pStyle->setLeftBorderPen( _p ); - formatChanged(); -} - -void Format::setLeftBorderStyle( Qt::PenStyle s ) -{ - TQPen p( m_pStyle->leftBorderPen() ); - p.setStyle( s ); - setLeftBorderPen( p ); -} - -void Format::setLeftBorderColor( const TQColor & c ) -{ - TQPen p( m_pStyle->leftBorderPen() ); - p.setColor( c ); - setLeftBorderPen( p ); -} - -void Format::setLeftBorderWidth( int _w ) -{ - TQPen p( m_pStyle->leftBorderPen() ); - p.setWidth( _w ); - setLeftBorderPen( p ); -} - -void Format::setTopBorderPen( const TQPen & _p ) -{ - if ( _p.style() == TQt::NoPen ) - { - clearProperty( PTopBorder ); - setNoFallBackProperties( PTopBorder ); - } - else - { - setProperty( PTopBorder ); - clearNoFallBackProperties( PTopBorder ); - } - - m_pStyle = m_pStyle->setTopBorderPen( _p ); - formatChanged(); -} - -void Format::setTopBorderStyle( Qt::PenStyle s ) -{ - TQPen p( m_pStyle->topBorderPen() ); - p.setStyle( s ); - setTopBorderPen( p ); -} - -void Format::setTopBorderColor( const TQColor& c ) -{ - TQPen p( m_pStyle->topBorderPen() ); - p.setColor( c ); - setTopBorderPen( p ); -} - -void Format::setTopBorderWidth( int _w ) -{ - TQPen p( m_pStyle->topBorderPen() ); - p.setWidth( _w ); - setTopBorderPen( p ); -} - -void Format::setRightBorderPen( const TQPen& p ) -{ - if ( p.style() == TQt::NoPen ) - { - clearProperty( PRightBorder ); - setNoFallBackProperties( PRightBorder ); - } - else - { - setProperty( PRightBorder ); - clearNoFallBackProperties( PRightBorder ); - } - - m_pStyle = m_pStyle->setRightBorderPen( p ); - formatChanged(); -} - -void Format::setRightBorderStyle( Qt::PenStyle _s ) -{ - TQPen p( m_pStyle->rightBorderPen() ); - p.setStyle( _s ); - setRightBorderPen( p ); -} - -void Format::setRightBorderColor( const TQColor & _c ) -{ - TQPen p( m_pStyle->rightBorderPen() ); - p.setColor( _c ); - setRightBorderPen( p ); -} - -void Format::setRightBorderWidth( int _w ) -{ - TQPen p( m_pStyle->rightBorderPen() ); - p.setWidth( _w ); - setRightBorderPen( p ); -} - -void Format::setBottomBorderPen( const TQPen& p ) -{ - if ( p.style() == TQt::NoPen ) - { - clearProperty( PBottomBorder ); - setNoFallBackProperties( PBottomBorder ); - } - else - { - setProperty( PBottomBorder ); - clearNoFallBackProperties( PBottomBorder ); - } - - m_pStyle = m_pStyle->setBottomBorderPen( p ); - formatChanged(); -} - -void Format::setBottomBorderStyle( Qt::PenStyle _s ) -{ - TQPen p( m_pStyle->bottomBorderPen() ); - p.setStyle( _s ); - setBottomBorderPen( p ); -} - -void Format::setBottomBorderColor( const TQColor & _c ) -{ - TQPen p( m_pStyle->bottomBorderPen() ); - p.setColor( _c ); - setBottomBorderPen( p ); -} - -void Format::setBottomBorderWidth( int _w ) -{ - TQPen p( m_pStyle->bottomBorderPen() ); - p.setWidth( _w ); - setBottomBorderPen( p ); -} - -void Format::setFallDiagonalPen( const TQPen & _p ) -{ - if ( _p.style() == TQt::NoPen ) - { - clearProperty( PFallDiagonal ); - setNoFallBackProperties( PFallDiagonal ); - } - else - { - setProperty( PFallDiagonal ); - clearNoFallBackProperties( PFallDiagonal ); - } - - m_pStyle = m_pStyle->setFallDiagonalPen( _p ); - formatChanged(); -} - -void Format::setFallDiagonalStyle( Qt::PenStyle s ) -{ - TQPen p( m_pStyle->fallDiagonalPen() ); - p.setStyle( s ); - setFallDiagonalPen( p ); -} - -void Format::setFallDiagonalColor( const TQColor& c ) -{ - TQPen p( m_pStyle->fallDiagonalPen() ); - p.setColor( c ); - setFallDiagonalPen( p ); -} - -void Format::setFallDiagonalWidth( int _w ) -{ - TQPen p( m_pStyle->fallDiagonalPen() ); - p.setWidth( _w ); - setFallDiagonalPen( p ); -} - -void Format::setGoUpDiagonalPen( const TQPen & _p ) -{ - if ( _p.style() == TQt::NoPen ) - { - clearProperty( PGoUpDiagonal ); - setNoFallBackProperties( PGoUpDiagonal ); - } - else - { - setProperty( PGoUpDiagonal ); - clearNoFallBackProperties( PGoUpDiagonal ); - } - - m_pStyle = m_pStyle->setGoUpDiagonalPen( _p ); - formatChanged(); -} - -void Format::setGoUpDiagonalStyle( Qt::PenStyle s ) -{ - TQPen p( m_pStyle->goUpDiagonalPen() ); - p.setStyle( s ); - setGoUpDiagonalPen( p ); -} - -void Format::setGoUpDiagonalColor( const TQColor& c ) -{ - TQPen p( m_pStyle->goUpDiagonalPen() ); - p.setColor( c ); - setGoUpDiagonalPen( p ); -} - -void Format::setGoUpDiagonalWidth( int _w ) -{ - TQPen p( m_pStyle->goUpDiagonalPen() ); - p.setWidth( _w ); - setGoUpDiagonalPen( p ); -} - -void Format::setBackGroundBrush( const TQBrush & _p) -{ - if ( _p.style() == TQt::NoBrush ) - { - clearProperty( PBackgroundBrush ); - setNoFallBackProperties( PBackgroundBrush ); - } - else - { - setProperty( PBackgroundBrush ); - clearNoFallBackProperties( PBackgroundBrush ); - } - - m_pStyle = m_pStyle->setBackGroundBrush( _p ); - formatChanged(); -} - -void Format::setBackGroundBrushStyle( Qt::BrushStyle s ) -{ - TQBrush b( m_pStyle->backGroundBrush() ); - b.setStyle( s ); - setBackGroundBrush( b ); -} - -void Format::setBackGroundBrushColor( const TQColor & c ) -{ - TQBrush b( m_pStyle->backGroundBrush() ); - b.setColor( c ); - setBackGroundBrush( b ); -} - -void Format::setTextFont( const TQFont & _f ) -{ - if( m_pStyle->parent() && _f == m_pStyle->parent()->font()) - { - clearProperty( PFont ); - setNoFallBackProperties( PFont ); - } - else if( !m_pStyle->parent() && _f == KoGlobal::defaultFont() ) - { - clearProperty( PFont ); - setNoFallBackProperties( PFont ); - } - else - { - setProperty( PFont ); - clearNoFallBackProperties( PFont ); - } - - - m_pStyle = m_pStyle->setFont( _f ); - formatChanged(); -} - -void Format::setTextFontSize( int _s ) -{ - TQFont f( m_pStyle->font() ); - f.setPointSize( _s ); - setTextFont( f ); -} - -void Format::setTextFontFamily( const TQString & _f ) -{ - TQFont f( m_pStyle->font() ); - f.setFamily( _f ); - setTextFont( f ); -} - -void Format::setTextFontBold( bool _b ) -{ - TQFont f( m_pStyle->font() ); - f.setBold( _b ); - setTextFont( f ); -} - -void Format::setTextFontItalic( bool _i ) -{ - TQFont f( m_pStyle->font() ); - f.setItalic( _i ); - setTextFont( f ); -} - -void Format::setTextFontUnderline( bool _i ) -{ - TQFont f( m_pStyle->font() ); - f.setUnderline( _i ); - setTextFont( f ); -} - -void Format::setTextFontStrike( bool _i ) -{ - TQFont f( m_pStyle->font() ); - f.setStrikeOut( _i ); - setTextFont( f ); -} - -void Format::setTextPen( const TQPen & _p ) -{ - // An invalid color means "the default text color, from the color scheme" - // It doesn't mean "no setting here, look at fallback" - // Maybe we should look at the fallback color, in fact. - /*if(!_p.color().isValid()) - { - clearProperty( PTextPen ); - setNoFallBackProperties( PTextPen ); - } - else*/ - { - setProperty( PTextPen ); - clearNoFallBackProperties( PTextPen ); - } - - //setProperty( PTextPen ); - m_pStyle = m_pStyle->setPen( _p ); - //kdDebug(36001) << "setTextPen: this=" << this << " pen=" << m_textPen.color().name() << " valid:" << m_textPen.color().isValid() << endl; - formatChanged(); -} - -void Format::setTextColor( const TQColor & _c ) -{ - TQPen p( m_pStyle->pen() ); - p.setColor( _c ); - setTextPen( p ); -} - -void Format::setBgColor( const TQColor & _c ) -{ - if ( !_c.isValid() ) - { - clearProperty( PBackgroundColor ); - setNoFallBackProperties( PBackgroundColor ); - } - else - { - setProperty( PBackgroundColor ); - clearNoFallBackProperties( PBackgroundColor ); - } - - m_pStyle = m_pStyle->setBgColor( _c ); - formatChanged(); -} - -void Format::setFloatFormat( FloatFormat _f ) -{ - setProperty( PFloatFormat ); - - m_pStyle = m_pStyle->setFloatFormat( _f ); - formatChanged(); -} - -void Format::setFloatColor( FloatColor _c ) -{ - setProperty( PFloatColor ); - - m_pStyle = m_pStyle->setFloatColor( _c ); - formatChanged(); -} - -void Format::setMultiRow( bool _b ) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PMultiRow ); - clearProperty( PMultiRow ); - setNoFallBackProperties( PMultiRow ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PMultiRow ); - setProperty( PMultiRow ); - clearNoFallBackProperties( PMultiRow ); - } - formatChanged(); -} - -void Format::setVerticalText( bool _b ) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PVerticalText ); - setNoFallBackProperties( PVerticalText); - clearFlag( Flag_VerticalText ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PVerticalText ); - clearNoFallBackProperties( PVerticalText); - setFlag( Flag_VerticalText ); - } - formatChanged(); -} - -void Format::setFormatType( FormatType _format ) -{ - if ( _format == Number_format ) - { - clearProperty( PFormatType ); - setNoFallBackProperties( PFormatType); - } - else - { - setProperty( PFormatType ); - clearNoFallBackProperties( PFormatType); - } - - m_pStyle = m_pStyle->setFormatType( _format ); - formatChanged(); -} - -void Format::setAngle( int _angle ) -{ - if ( _angle == 0 ) - { - clearProperty( PAngle ); - setNoFallBackProperties( PAngle); - } - else - { - setProperty( PAngle ); - clearNoFallBackProperties( PAngle); - } - - m_pStyle = m_pStyle->setRotateAngle( _angle ); - formatChanged(); -} - -void Format::setIndent( double _indent ) -{ - if ( _indent == 0.0 ) - { - clearProperty( PIndent ); - setNoFallBackProperties( PIndent ); - } - else - { - setProperty( PIndent ); - clearNoFallBackProperties( PIndent ); - } - - m_pStyle = m_pStyle->setIndent( _indent ); - formatChanged(); -} - -void Format::setComment( const TQString & _comment ) -{ - if ( _comment.isEmpty() ) - { - clearProperty( PComment ); - setNoFallBackProperties( PComment ); - } - else - { - setProperty( PComment ); - clearNoFallBackProperties( PComment ); - } - - // not part of the style - delete m_strComment; - if ( !_comment.isEmpty() ) - m_strComment = new TQString( _comment ); - else - m_strComment = 0; - formatChanged(); -} - -void Format::setNotProtected( bool _b) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PNotProtected ); - setNoFallBackProperties( PNotProtected ); - clearFlag( Flag_NotProtected ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PNotProtected ); - clearNoFallBackProperties( PNotProtected ); - setFlag( Flag_NotProtected ); - } - formatChanged(); -} - -void Format::setDontPrintText( bool _b ) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PDontPrintText ); - setNoFallBackProperties(PDontPrintText); - clearFlag( Flag_DontPrintText ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PDontPrintText ); - clearNoFallBackProperties( PDontPrintText); - setFlag( Flag_DontPrintText ); - } - formatChanged(); -} - -void Format::setHideAll( bool _b ) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PHideAll ); - setNoFallBackProperties(PHideAll); - clearFlag( Flag_HideAll ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PHideAll ); - clearNoFallBackProperties( PHideAll); - setFlag( Flag_HideAll ); - } - formatChanged(); -} - -void Format::setHideFormula( bool _b ) -{ - if ( _b == false ) - { - m_pStyle = m_pStyle->clearProperty( Style::PHideFormula ); - setNoFallBackProperties( PHideFormula ); - clearFlag( Flag_HideFormula ); - } - else - { - m_pStyle = m_pStyle->setProperty( Style::PHideFormula ); - clearNoFallBackProperties( PHideFormula ); - setFlag( Flag_HideFormula ); - } - formatChanged(); -} - -void Format::setCurrency( Currency const & c ) -{ - m_pStyle = m_pStyle->setCurrency( c ); -} - -void Format::setCurrency( int type, TQString const & symbol ) -{ - Currency c; - - c.symbol = symbol.simplifyWhiteSpace(); - c.type = type; - - if (c.symbol.length() == 0) - { - c.type = 0; - c.symbol = sheet()->doc()->locale()->currencySymbol(); - } - - m_pStyle = m_pStyle->setCurrency( c ); -} - -///////////// -// -// Get methods -// -///////////// - -TQString const & Format::getFormatString( int col, int row ) const -{ - if ( !hasProperty( PCustomFormat, false ) && !hasNoFallBackProperties( PCustomFormat )) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->getFormatString( col, row ); - } - return m_pStyle->strFormat(); -} - -TQString Format::prefix( int col, int row ) const -{ - if ( !hasProperty( PPrefix, false ) && !hasNoFallBackProperties(PPrefix )) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->prefix( col, row ); - } - return m_pStyle->prefix(); -} - -TQString Format::postfix( int col, int row ) const -{ - if ( !hasProperty( PPostfix, false ) && !hasNoFallBackProperties(PPostfix )) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->postfix( col, row ); - } - return m_pStyle->postfix(); -} - -const TQPen& Format::fallDiagonalPen( int col, int row ) const -{ - if ( !hasProperty( PFallDiagonal, false ) && !hasNoFallBackProperties(PFallDiagonal )) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->fallDiagonalPen( col, row ); - } - return m_pStyle->fallDiagonalPen(); -} - -int Format::fallDiagonalWidth( int col, int row ) const -{ - return fallDiagonalPen( col, row ).width(); -} - -Qt::PenStyle Format::fallDiagonalStyle( int col, int row ) const -{ - return fallDiagonalPen( col, row ).style(); -} - -const TQColor & Format::fallDiagonalColor( int col, int row ) const -{ - return fallDiagonalPen( col, row ).color(); -} - -const TQPen & Format::goUpDiagonalPen( int col, int row ) const -{ - if ( !hasProperty( PGoUpDiagonal, false ) && !hasNoFallBackProperties( PGoUpDiagonal ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->goUpDiagonalPen( col, row ); - } - return m_pStyle->goUpDiagonalPen(); -} - -int Format::goUpDiagonalWidth( int col, int row ) const -{ - return goUpDiagonalPen( col, row ).width(); -} - -Qt::PenStyle Format::goUpDiagonalStyle( int col, int row ) const -{ - return goUpDiagonalPen( col, row ).style(); -} - -const TQColor& Format::goUpDiagonalColor( int col, int row ) const -{ - return goUpDiagonalPen( col, row ).color(); -} - -uint Format::bottomBorderValue( int col, int row ) const -{ - if ( !hasProperty( PBottomBorder, false ) && !hasNoFallBackProperties( PBottomBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->bottomBorderValue( col, row ); - - return 0; - } - - return m_pStyle->bottomPenValue(); -} - -uint Format::rightBorderValue( int col, int row ) const -{ - if ( !hasProperty( PRightBorder, false ) && !hasNoFallBackProperties( PRightBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->rightBorderValue( col, row ); - - return 0; - } - - return m_pStyle->rightPenValue(); -} - -uint Format::leftBorderValue( int col, int row ) const -{ - if ( !hasProperty( PLeftBorder, false ) && !hasNoFallBackProperties( PLeftBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->leftBorderValue( col, row ); - - return 0; - } - - return m_pStyle->leftPenValue(); -} - -uint Format::topBorderValue( int col, int row ) const -{ - if ( !hasProperty( PTopBorder, false ) && !hasNoFallBackProperties( PTopBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->topBorderValue( col, row ); - - return 0; - } - - return m_pStyle->topPenValue(); -} - -const TQPen& Format::leftBorderPen( int col, int row ) const -{ - if ( !hasProperty( PLeftBorder, false ) && !hasNoFallBackProperties( PLeftBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->leftBorderPen( col, row ); - return sheet()->emptyPen(); - } - - return m_pStyle->leftBorderPen(); -} - -Qt::PenStyle Format::leftBorderStyle( int col, int row ) const -{ - return leftBorderPen( col, row ).style(); -} - -const TQColor& Format::leftBorderColor( int col, int row ) const -{ - return leftBorderPen( col, row ).color(); -} - -int Format::leftBorderWidth( int col, int row ) const -{ - return leftBorderPen( col, row ).width(); -} - -const TQPen& Format::topBorderPen( int col, int row ) const -{ - if ( !hasProperty( PTopBorder, false ) && !hasNoFallBackProperties( PTopBorder ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->topBorderPen( col, row ); - return sheet()->emptyPen(); - } - - return m_pStyle->topBorderPen(); -} - -const TQColor& Format::topBorderColor( int col, int row ) const -{ - return topBorderPen( col, row ).color(); -} - -Qt::PenStyle Format::topBorderStyle( int col, int row ) const -{ - return topBorderPen( col, row ).style(); -} - -int Format::topBorderWidth( int col, int row ) const -{ - return topBorderPen( col, row ).width(); -} - -const TQPen& Format::rightBorderPen( int col, int row ) const -{ - if ( !hasProperty( PRightBorder, false ) && !hasNoFallBackProperties( PRightBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->rightBorderPen( col, row ); - return sheet()->emptyPen(); - } - - return m_pStyle->rightBorderPen(); -} - -int Format::rightBorderWidth( int col, int row ) const -{ - return rightBorderPen( col, row ).width(); -} - -Qt::PenStyle Format::rightBorderStyle( int col, int row ) const -{ - return rightBorderPen( col, row ).style(); -} - -const TQColor& Format::rightBorderColor( int col, int row ) const -{ - return rightBorderPen( col, row ).color(); -} - -const TQPen& Format::bottomBorderPen( int col, int row ) const -{ - if ( !hasProperty( PBottomBorder, false )&& !hasNoFallBackProperties( PBottomBorder ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->bottomBorderPen( col, row ); - return sheet()->emptyPen(); - } - - return m_pStyle->bottomBorderPen(); -} - -int Format::bottomBorderWidth( int col, int row ) const -{ - return bottomBorderPen( col, row ).width(); -} - -Qt::PenStyle Format::bottomBorderStyle( int col, int row ) const -{ - return bottomBorderPen( col, row ).style(); -} - -const TQColor& Format::bottomBorderColor( int col, int row ) const -{ - return bottomBorderPen( col, row ).color(); -} - -const TQBrush& Format::backGroundBrush( int col, int row ) const -{ - if ( !hasProperty( PBackgroundBrush, false ) && !hasNoFallBackProperties(PBackgroundBrush )) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->backGroundBrush( col, row ); - } - return m_pStyle->backGroundBrush(); -} - -Qt::BrushStyle Format::backGroundBrushStyle( int col, int row ) const -{ - return backGroundBrush( col, row ).style(); -} - -const TQColor& Format::backGroundBrushColor( int col, int row ) const -{ - return backGroundBrush( col, row ).color(); -} - -int Format::precision( int col, int row ) const -{ - if ( !hasProperty( PPrecision, false )&& !hasNoFallBackProperties( PPrecision ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->precision( col, row ); - } - return m_pStyle->precision(); -} - -Format::FloatFormat Format::floatFormat( int col, int row ) const -{ - if ( !hasProperty( PFloatFormat, false ) && !hasNoFallBackProperties( PFloatFormat ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->floatFormat( col, row ); - } - return m_pStyle->floatFormat(); -} - -Format::FloatColor Format::floatColor( int col, int row ) const -{ - if ( !hasProperty( PFloatColor, false ) && !hasNoFallBackProperties( PFloatColor ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->floatColor( col, row ); - } - return m_pStyle->floatColor(); -} - -const TQColor& Format::bgColor( int col, int row ) const -{ - if ( !hasProperty( PBackgroundColor, false ) && !hasNoFallBackProperties( PBackgroundColor ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->bgColor( col, row ); - } - - return m_pStyle->bgColor(); -} - -const TQPen& Format::textPen( int col, int row ) const -{ - if ( !hasProperty( PTextPen, false ) && !hasNoFallBackProperties( PTextPen ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textPen( col, row ); - } - return m_pStyle->pen(); -} - -const TQColor& Format::textColor( int col, int row ) const -{ - return textPen( col, row ).color(); -} - -const TQFont Format::textFont( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFont( col, row ); - } - - return m_pStyle->font(); -} - -int Format::textFontSize( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontSize( col, row ); - } - - return m_pStyle->fontSize(); -} - -TQString const & Format::textFontFamily( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontFamily( col, row ); - } - - return m_pStyle->fontFamily(); -} - -bool Format::textFontBold( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontBold( col, row ); - } - - return ( m_pStyle->fontFlags() & Style::FBold ); -} - -bool Format::textFontItalic( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontItalic( col, row ); - } - - return ( m_pStyle->fontFlags() & Style::FItalic ); -} - -bool Format::textFontUnderline( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontUnderline( col, row ); - } - - return ( m_pStyle->fontFlags() & Style::FUnderline ); -} - -bool Format::textFontStrike( int col, int row ) const -{ - if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->textFontStrike( col, row ); - } - - return ( m_pStyle->fontFlags() & Style::FStrike ); -} - -Format::Align Format::align( int col, int row ) const -{ - if ( !hasProperty( PAlign, false ) && !hasNoFallBackProperties( PAlign ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->align( col, row ); - } - - return m_pStyle->alignX(); -} - -Format::AlignY Format::alignY( int col, int row ) const -{ - if ( !hasProperty( PAlignY, false )&& !hasNoFallBackProperties( PAlignY ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->alignY( col, row ); - } - - return m_pStyle->alignY(); -} - -bool Format::multiRow( int col, int row ) const -{ - if ( !hasProperty( PMultiRow, false ) && !hasNoFallBackProperties( PMultiRow ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->multiRow( col, row ); - } - - return m_pStyle->hasProperty( Style::PMultiRow ); -} - -bool Format::verticalText( int col, int row ) const -{ - if ( !hasProperty( PVerticalText, false )&& !hasNoFallBackProperties( PVerticalText ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->verticalText( col, row ); - } - - return m_pStyle->hasProperty( Style::PVerticalText ); -} - -FormatType Format::getFormatType( int col, int row ) const -{ - if ( !hasProperty( PFormatType, false ) && !hasNoFallBackProperties( PFormatType ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->getFormatType( col, row ); - } - - return m_pStyle->formatType(); -} - -int Format::getAngle( int col, int row ) const -{ - if ( !hasProperty( PAngle, false ) && !hasNoFallBackProperties( PAngle ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->getAngle( col, row ); - } - - return m_pStyle->rotateAngle(); -} - -TQString Format::comment( int col, int row ) const -{ - if ( !hasProperty( PComment, false ) && !hasNoFallBackProperties( PComment )) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->comment( col, row ); - } - - if ( !m_strComment ) - return TQString(); - - // not part of the style - return *m_strComment; -} - -TQString * Format::commentP( int col, int row ) const -{ - if ( !hasProperty( PComment, false ) && !hasNoFallBackProperties( PComment )) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->commentP( col, row ); - } - - return m_strComment; -} - -double Format::getIndent( int col, int row ) const -{ - if ( !hasProperty( PIndent, false ) && !hasNoFallBackProperties( PIndent ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->getIndent( col, row ); - } - - return m_pStyle->indent(); -} - -bool Format::getDontprintText( int col, int row ) const -{ - if ( !hasProperty( PDontPrintText, false )&& !hasNoFallBackProperties( PDontPrintText ) ) - { - const Format* l = fallbackFormat( col, row ); - if ( l ) - return l->getDontprintText( col, row ); - } - - return m_pStyle->hasProperty( Style::PDontPrintText ); -} - -bool Format::isProtected( int col, int row ) const -{ - return ( m_pSheet->isProtected() && !notProtected( col, row ) ); -} - - -bool Format::notProtected( int col, int row) const -{ - if ( !hasProperty( PNotProtected, false )&& !hasNoFallBackProperties( PNotProtected ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->notProtected( col, row ); - } - - return m_pStyle->hasProperty( Style::PNotProtected ); -} - -bool Format::isHideAll( int col, int row) const -{ - if ( !hasProperty( PHideAll, false )&& !hasNoFallBackProperties( PHideAll ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->isHideAll( col, row ); - } - - return m_pStyle->hasProperty( Style::PHideAll ); -} - -bool Format::isHideFormula( int col, int row) const -{ - if ( !hasProperty( PHideFormula, false )&& !hasNoFallBackProperties( PHideFormula ) ) - { - const Format * l = fallbackFormat( col, row ); - if ( l ) - return l->isHideFormula( col, row ); - } - - return m_pStyle->hasProperty( Style::PHideFormula ); -} - -bool Format::currencyInfo( Currency & currency) const -{ - // TODO: fallback ? - if ( m_pStyle->formatType() != Money_format ) - return false; - - currency.symbol = m_pStyle->currency().symbol; - currency.type = m_pStyle->currency().type; - - return true; -} - -TQString Format::getCurrencySymbol() const -{ - // TODO: fallback ? - return m_pStyle->currency().symbol; -} - -TQFont Format::font() const -{ - return m_pStyle->font(); -} - - -///////////// -// -// Get methods -// -///////////// - -const TQPen & Format::leftBorderPen() const -{ - return m_pStyle->leftBorderPen(); -} - -const TQPen & Format::topBorderPen() const -{ - return m_pStyle->topBorderPen(); -} - -const TQPen & Format::rightBorderPen() const -{ - return m_pStyle->rightBorderPen(); -} - -const TQPen & Format::bottomBorderPen() const -{ - return m_pStyle->bottomBorderPen(); -} - -const TQPen & Format::fallDiagonalPen() const -{ - return m_pStyle->fallDiagonalPen(); -} - -const TQPen & Format::goUpDiagonalPen() const -{ - return m_pStyle->goUpDiagonalPen(); -} - -const TQBrush & Format::backGroundBrush() const -{ - return m_pStyle->backGroundBrush(); -} - -const TQFont Format::textFont() const -{ - return m_pStyle->font(); -} - -const TQPen & Format::textPen() const -{ - return m_pStyle->pen(); -} - -///////////// -// -// Misc -// -///////////// - -void Format::formatChanged() -{ - if (m_pCell) - { - m_pCell->setFlag(Cell::Flag_LayoutDirty); - m_pCell->setFlag(Cell::Flag_TextFormatDirty); - } -} - -Format* Format::fallbackFormat( int, int row ) -{ - return m_pCell ? m_pSheet->rowFormat( row ) : 0; -} - -const Format* Format::fallbackFormat( int, int row ) const -{ - return m_pCell ? m_pSheet->rowFormat( row ) : 0; -} - -bool Format::isDefault() const -{ - // NOTE Stefan: Don't compare sheet and cell. - // Because of the comment we have to check m_mask. - if ( ( m_mask & PComment ) && m_strComment != 0 ) - return false; -#if 0 // These are copied in Style. - if ( m_mask ) // Properties - return false; - if ( m_flagsMask != 0 ) // FormatFlags - return false; -#endif - if ( m_bNoFallBack != 0 ) - return false; - return ( *m_pStyle == *m_pSheet->doc()->styleManager()->defaultStyle() ); -} - -bool Format::operator==( const Format& other ) const -{ - // NOTE Stefan: Don't compare sheet and cell. - // Because of the comment we have to check m_mask. - if ( ( m_mask & other.m_mask & PComment ) && m_strComment != other.m_strComment ) - return false; -#if 0 // These are copied in Style. - if ( m_mask != other.m_mask ) // Properties - return false; - if ( m_flagsMask != other.m_flagsMask ) // FormatFlags - return false; -#endif - if ( m_bNoFallBack != other.m_bNoFallBack ) - return false; - return ( *m_pStyle == *other.m_pStyle ); -} - -/***************************************************************************** - * - * RowFormat - * - *****************************************************************************/ - -//#define UPDATE_BEGIN bool b_update_begin = m_bDisplayDirtyFlag; m_bDisplayDirtyFlag = true; -//#define UPDATE_END if ( !b_update_begin && m_bDisplayDirtyFlag ) m_pSheet->emit_updateRow( this, m_iRow ); - -RowFormat::RowFormat( Sheet * _sheet, int _row ) - : Format( _sheet, _sheet->doc()->styleManager()->defaultStyle() ) -{ - m_next = 0; - m_prev = 0; - - m_bDisplayDirtyFlag = false; - m_fHeight = s_rowHeight; - m_iRow = _row; - m_bDefault = false; - m_bHide = false; - m_dcop = 0L; -} - -RowFormat::~RowFormat() -{ - if ( m_next ) - m_next->setPrevious( m_prev ); - if ( m_prev ) - m_prev->setNext( m_next ); - delete m_dcop; -} - -DCOPObject * RowFormat::dcopObject() -{ - if ( !m_dcop ) - m_dcop = new RowIface( this ); - return m_dcop; -} - - -void RowFormat::setMMHeight( double _h ) -{ - setDblHeight( MM_TO_POINT ( _h ) ); -} - -void RowFormat::setHeight( int _h, const Canvas * _canvas ) -{ - setDblHeight( (double) _h, _canvas ); -} - -void RowFormat::setDblHeight( double _h, const Canvas * _canvas ) -{ - Sheet *_sheet = _canvas ? _canvas->activeSheet() : m_pSheet; - - // avoid unnecessary updates - if ( kAbs( _h - dblHeight( _canvas ) ) < DBL_EPSILON ) - return; - -// UPDATE_BEGIN; - - // Lower maximum size by old height - _sheet->adjustSizeMaxY ( - dblHeight() ); - - if ( _canvas ) - m_fHeight = ( _h / _canvas->zoom() ); - else - m_fHeight = _h; - - // Rise maximum size by new height - _sheet->adjustSizeMaxY ( dblHeight() ); - _sheet->print()->updatePrintRepeatRowsHeight(); - _sheet->print()->updateNewPageListY ( row() ); - - _sheet->emit_updateRow(this,m_iRow); -// UPDATE_END; -} - -int RowFormat::height( const Canvas *_canvas ) const -{ - return (int) dblHeight( _canvas ); -} - -double RowFormat::dblHeight( const Canvas *_canvas ) const -{ - if( m_bHide ) - return 0.0; - - if ( _canvas ) - return _canvas->zoom() * (m_iRow == 0) ? s_rowHeight : m_fHeight; - else - return (m_iRow == 0) ? s_rowHeight : m_fHeight; -} - -double RowFormat::mmHeight() const -{ - return POINT_TO_MM ( dblHeight() ); -} - -TQDomElement RowFormat::save( TQDomDocument& doc, int yshift, bool copy ) const -{ - TQDomElement row = doc.createElement( "row" ); - row.setAttribute( "height", m_fHeight ); - row.setAttribute( "row", m_iRow - yshift ); - if( m_bHide ) - row.setAttribute( "hide", (int) m_bHide ); - - TQDomElement format( saveFormat( doc, false, copy ) ); - row.appendChild( format ); - return row; -} - -#if 0 -bool RowFormat::loadOasis( const TQDomElement& /*row*/, TQDomElement * /*rowStyle*/ ) -{ - return true; -} -#endif - -bool RowFormat::load( const TQDomElement & row, int yshift, Paste::Mode sp, bool paste ) -{ - bool ok; - - m_iRow = row.attribute( "row" ).toInt( &ok ) + yshift; - if ( !ok ) - return false; - - if ( row.hasAttribute( "height" ) ) - { - if ( m_pSheet->doc()->syntaxVersion() < 1 ) //compatibility with old format - was in millimeter - m_fHeight = tqRound( MM_TO_POINT( row.attribute( "height" ).toDouble( &ok ) ) ); - else - m_fHeight = row.attribute( "height" ).toDouble( &ok ); - - if ( !ok ) return false; - } - - // Validation - if ( m_fHeight < 0 ) - { - kdDebug(36001) << "Value height=" << m_fHeight << " out of range" << endl; - return false; - } - if ( m_iRow < 1 || m_iRow > KS_rowMax ) - { - kdDebug(36001) << "Value row=" << m_iRow << " out of range" << endl; - return false; - } - - if ( row.hasAttribute( "hide" ) ) - { - setHide( (int) row.attribute( "hide" ).toInt( &ok ) ); - if ( !ok ) - return false; - } - - TQDomElement f( row.namedItem( "format" ).toElement() ); - - if ( !f.isNull() && ( sp == Paste::Normal || sp == Paste::Format || sp == Paste::NoBorder ) ) - { - if ( !loadFormat( f, sp, paste ) ) - return false; - return true; - } - - return true; -} - -const TQPen & RowFormat::topBorderPen( int _col, int _row ) const -{ - // First look at the row above us - if ( !hasProperty( PTopBorder, false ) ) - { - const RowFormat * rl = sheet()->rowFormat( _row - 1 ); - if ( rl->hasProperty( PBottomBorder ) ) - return rl->bottomBorderPen( _col, _row - 1 ); - } - - return Format::topBorderPen( _col, _row ); -} - -void RowFormat::setTopBorderPen( const TQPen & p ) -{ - RowFormat * cl = sheet()->nonDefaultRowFormat( row() - 1, false ); - if ( cl ) - cl->clearProperty( PBottomBorder ); - - Format::setTopBorderPen( p ); -} - -const TQPen & RowFormat::bottomBorderPen( int _col, int _row ) const -{ - // First look at the row below of us - if ( !hasProperty( PBottomBorder, false ) && ( _row < KS_rowMax ) ) - { - const RowFormat * rl = sheet()->rowFormat( _row + 1 ); - if ( rl->hasProperty( PTopBorder ) ) - return rl->topBorderPen( _col, _row + 1 ); - } - - return Format::bottomBorderPen( _col, _row ); -} - -void RowFormat::setBottomBorderPen( const TQPen & p ) -{ - if ( row() < KS_rowMax ) - { - RowFormat * cl = sheet()->nonDefaultRowFormat( row() + 1, false ); - if ( cl ) - cl->clearProperty( PTopBorder ); - } - - Format::setBottomBorderPen( p ); -} - -void RowFormat::setHide( bool _hide, bool repaint ) -{ - if ( _hide != m_bHide ) // only if we change the status - { - if ( _hide ) - { - // Lower maximum size by height of row - m_pSheet->adjustSizeMaxY ( - dblHeight() ); - m_bHide = _hide; //hide must be set after we requested the height - m_pSheet->emit_updateRow( this, m_iRow, repaint ); - } - else - { - // Rise maximum size by height of row - m_bHide = _hide; //unhide must be set before we request the height - m_pSheet->adjustSizeMaxY ( dblHeight() ); - m_pSheet->emit_updateRow( this, m_iRow, repaint ); - } - } -} - -Format* RowFormat::fallbackFormat( int col, int ) -{ - return sheet()->columnFormat( col ); -} - -const Format* RowFormat::fallbackFormat( int col, int ) const -{ - return sheet()->columnFormat( col ); -} - -bool RowFormat::isDefault() const -{ - if ( m_fHeight != s_rowHeight ) - return false; - if ( m_bHide == true ) - return false; - return Format::isDefault(); -} - -bool RowFormat::operator==( const RowFormat& other ) const -{ - // NOTE Stefan: Don't compare sheet and cell. - if ( m_fHeight != other.m_fHeight ) - return false; - if ( m_bHide != other.m_bHide ) - return false; - return Format::operator==( other ); -} - -/***************************************************************************** - * - * ColumnFormat - * - *****************************************************************************/ - -#undef UPDATE_BEGIN -#undef UPDATE_END - -#define UPDATE_BEGIN bool b_update_begin = m_bDisplayDirtyFlag; m_bDisplayDirtyFlag = true; -#define UPDATE_END if ( !b_update_begin && m_bDisplayDirtyFlag ) m_pSheet->emit_updateColumn( this, m_iColumn ); - -ColumnFormat::ColumnFormat( Sheet * _sheet, int _column ) - : Format( _sheet, _sheet->doc()->styleManager()->defaultStyle() ) -{ - m_bDisplayDirtyFlag = false; - m_fWidth = s_columnWidth; - m_iColumn = _column; - m_bDefault=false; - m_bHide=false; - m_prev = 0; - m_next = 0; - m_dcop = 0; -} - -ColumnFormat::~ColumnFormat() -{ - if ( m_next ) - m_next->setPrevious( m_prev ); - if ( m_prev ) - m_prev->setNext( m_next ); - delete m_dcop; -} - -DCOPObject * ColumnFormat::dcopObject() -{ - if ( !m_dcop ) - m_dcop = new ColumnIface( this ); - return m_dcop; -} - -void ColumnFormat::setMMWidth( double _w ) -{ - setDblWidth( MM_TO_POINT ( _w ) ); -} - -void ColumnFormat::setWidth( int _w, const Canvas * _canvas ) -{ - setDblWidth( (double)_w, _canvas ); -} - -void ColumnFormat::setDblWidth( double _w, const Canvas * _canvas ) -{ - Sheet *_sheet = _canvas ? _canvas->activeSheet() : m_pSheet; - - // avoid unnecessary updates - if ( kAbs( _w - dblWidth( _canvas ) ) < DBL_EPSILON ) - return; - - // UPDATE_BEGIN; - - // Lower maximum size by old width - _sheet->adjustSizeMaxX ( - dblWidth() ); - - if ( _canvas ) - m_fWidth = ( _w / _canvas->zoom() ); - else - m_fWidth = _w; - - // Rise maximum size by new width - _sheet->adjustSizeMaxX ( dblWidth() ); - _sheet->print()->updatePrintRepeatColumnsWidth(); - _sheet->print()->updateNewPageListX ( column() ); - - _sheet->emit_updateColumn(this,m_iColumn); - // UPDATE_END; -} - -int ColumnFormat::width( const Canvas * _canvas ) const -{ - return (int) dblWidth( _canvas ); -} - -double ColumnFormat::dblWidth( const Canvas * _canvas ) const -{ - if ( m_bHide ) - return 0.0; - - if ( _canvas ) - return _canvas->zoom() * (m_iColumn == 0) ? s_columnWidth : m_fWidth; - else - return (m_iColumn == 0) ? s_columnWidth : m_fWidth; -} - -double ColumnFormat::mmWidth() const -{ - return POINT_TO_MM( dblWidth() ); -} - - -TQDomElement ColumnFormat::save( TQDomDocument& doc, int xshift, bool copy ) const -{ - TQDomElement col( doc.createElement( "column" ) ); - col.setAttribute( "width", m_fWidth ); - col.setAttribute( "column", m_iColumn - xshift ); - - if ( m_bHide ) - col.setAttribute( "hide", (int) m_bHide ); - - TQDomElement format( saveFormat( doc, false, copy ) ); - col.appendChild( format ); - - return col; -} - -bool ColumnFormat::load( const TQDomElement & col, int xshift, Paste::Mode sp, bool paste ) -{ - bool ok; - if ( col.hasAttribute( "width" ) ) - { - if ( m_pSheet->doc()->syntaxVersion() < 1 ) //combatibility to old format - was in millimeter - m_fWidth = tqRound( MM_TO_POINT ( col.attribute( "width" ).toDouble( &ok ) ) ); - else - m_fWidth = col.attribute( "width" ).toDouble( &ok ); - - if ( !ok ) - return false; - } - - m_iColumn = col.attribute( "column" ).toInt( &ok ) + xshift; - - if ( !ok ) - return false; - - // Validation - if ( m_fWidth < 0 ) - { - kdDebug(36001) << "Value width=" << m_fWidth << " out of range" << endl; - return false; - } - if ( m_iColumn < 1 || m_iColumn > KS_colMax ) - { - kdDebug(36001) << "Value col=" << m_iColumn << " out of range" << endl; - return false; - } - if ( col.hasAttribute( "hide" ) ) - { - setHide( (int) col.attribute( "hide" ).toInt( &ok ) ); - if ( !ok ) - return false; - } - - TQDomElement f( col.namedItem( "format" ).toElement() ); - - if ( !f.isNull() && ( sp == Paste::Normal || sp == Paste::Format || sp == Paste::NoBorder )) - { - if ( !loadFormat( f, sp, paste ) ) - return false; - return true; - } - - return true; -} - -const TQPen & ColumnFormat::leftBorderPen( int _col, int _row ) const -{ - // First look ar the right column at the right - if ( !hasProperty( PLeftBorder, false ) ) - { - const ColumnFormat * cl = sheet()->columnFormat( _col - 1 ); - if ( cl->hasProperty( PRightBorder ) ) - return cl->rightBorderPen( _col - 1, _row ); - } - - return Format::leftBorderPen( _col, _row ); -} - -void ColumnFormat::setLeftBorderPen( const TQPen & p ) -{ - ColumnFormat * cl = sheet()->nonDefaultColumnFormat( column() - 1, false ); - if ( cl ) - cl->clearProperty( PRightBorder ); - - Format::setLeftBorderPen( p ); -} - -const TQPen & ColumnFormat::rightBorderPen( int _col, int _row ) const -{ - // First look ar the right column at the right - if ( !hasProperty( PRightBorder, false ) && ( _col < KS_colMax ) ) - { - const ColumnFormat * cl = sheet()->columnFormat( _col + 1 ); - if ( cl->hasProperty( PLeftBorder ) ) - return cl->leftBorderPen( _col + 1, _row ); - } - - return Format::rightBorderPen( _col, _row ); -} - -void ColumnFormat::setRightBorderPen( const TQPen & p ) -{ - if ( column() < KS_colMax ) - { - ColumnFormat * cl = sheet()->nonDefaultColumnFormat( column() + 1, false ); - if ( cl ) - cl->clearProperty( PLeftBorder ); - } - - Format::setRightBorderPen( p ); -} - -Format * ColumnFormat::fallbackFormat( int, int ) -{ - return sheet()->defaultFormat(); -} - -void ColumnFormat::setHide( bool _hide ) -{ - if ( _hide != m_bHide ) // only if we change the status - { - if ( _hide ) - { - // Lower maximum size by width of column - m_pSheet->adjustSizeMaxX ( - dblWidth() ); - m_bHide = _hide; //hide must be set after we requested the width - // m_pSheet->emit_updateColumn( this, m_iColumn ); - } - else - { - // Rise maximum size by width of column - m_bHide = _hide; //unhide must be set before we request the width - m_pSheet->adjustSizeMaxX ( dblWidth() ); - // m_pSheet->emit_updateColumn( this, m_iColumn ); - } - } -} - -const Format * ColumnFormat::fallbackFormat( int, int ) const -{ - return sheet()->defaultFormat(); -} - -bool ColumnFormat::isDefault() const -{ - if ( m_fWidth != s_columnWidth ) - return false; - if ( m_bHide == true ) - return false; - return Format::isDefault(); -} - -bool ColumnFormat::operator==( const ColumnFormat& other ) const -{ - // NOTE Stefan: Don't compare sheet and cell. - if ( m_fWidth != other.m_fWidth ) - return false; - if ( m_bHide != other.m_bHide ) - return false; - return Format::operator==( other ); -} - - - -namespace Currency_LNS -{ - typedef struct - { - char const * code; - char const * country; - char const * name; - char const * display; - } Money; - - // codes and names as defined in ISO 3166-1 - // first column: saved code - // second column: country name (localized) - // third column: currency name (localized) - // fourth column: displayed currency code (localized but maybe only in - // the country language it belongs to) - // WARNING: change the "24" in getChooseString if you change this array - static const Money lMoney[] = { - { "", "", "", ""}, // auto - { "", "", "", ""}, // extension (codes imported) - { "$", "", "Dollar", "$" }, // unspecified - { "$", I18N_NOOP("Australia"), I18N_NOOP("Dollar"), "$" }, - { "$", I18N_NOOP("Canada"), I18N_NOOP("Dollar"), "$" }, - { "$", I18N_NOOP("Caribbea"), I18N_NOOP("Dollar"), "$" }, - { "$", I18N_NOOP("New Zealand"), I18N_NOOP("Dollar"), "$" }, - { "$", I18N_NOOP("United States"), I18N_NOOP("Dollar"), "$" }, - - // € == Euro sign in utf8 - { "€", "", "€", "€" }, // unspecified - { "€", I18N_NOOP("Austria"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Belgium"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Finland"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("France"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Germany"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Greece"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Ireland"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Italy"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Luxembourg"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Monaco"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Netherlands"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Portugal"), I18N_NOOP("Euro"), "€" }, - { "€", I18N_NOOP("Spain"), I18N_NOOP("Euro"), "€" }, - - { "£", I18N_NOOP("United Kingdom"), I18N_NOOP("Pound"), "£" }, - - { "Â¥", I18N_NOOP("Japan"), I18N_NOOP("Yen"), "Â¥" }, - - { "AFA", I18N_NOOP("Afghanistan"), I18N_NOOP("Afghani"), I18N_NOOP("AFA") }, - { "ALL", I18N_NOOP("Albania"), I18N_NOOP("Lek"), I18N_NOOP("Lek") }, - { "DZD", I18N_NOOP("Algeria"), I18N_NOOP("Algerian Dinar"), I18N_NOOP("DZD") }, - { "USD", I18N_NOOP("American Samoa"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "EUR", I18N_NOOP("Andorra"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "ADP", I18N_NOOP("Andorra"), I18N_NOOP("Andorran Peseta"), I18N_NOOP("ADP") }, - { "AOA", I18N_NOOP("Angola"), I18N_NOOP("Kwanza"), I18N_NOOP("AOA") }, - { "XCD", I18N_NOOP("Anguilla"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "XCD", I18N_NOOP("Antigua And Barbuda"), I18N_NOOP("East Carribean Dollar"), I18N_NOOP("XCD") }, - { "ARS", I18N_NOOP("Argentina"), I18N_NOOP("Argentine Peso"), I18N_NOOP("ARS") }, - { "AMD", I18N_NOOP("Armenia"), I18N_NOOP("Armenian Dram"), I18N_NOOP("AMD") }, - { "AWG", I18N_NOOP("Aruba"), I18N_NOOP("Aruban Guilder"), I18N_NOOP("AWG") }, - { "AUD", I18N_NOOP("Australia"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "EUR", I18N_NOOP("Austria"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "ATS", I18N_NOOP("Austria"), I18N_NOOP("Schilling"), I18N_NOOP("S") }, - { "AZM", I18N_NOOP("Azerbaijan"), I18N_NOOP("Azerbaijanian Manat"), I18N_NOOP("AZM") }, - { "BSD", I18N_NOOP("Bahamas"), I18N_NOOP("Bahamian Dollar"), I18N_NOOP("BSD") }, - { "BHD", I18N_NOOP("Bahrain"), I18N_NOOP("Bahraini Dinar"), I18N_NOOP("BHD") }, - { "BDT", I18N_NOOP("Bangladesh"), I18N_NOOP("Taka"), I18N_NOOP("BDT") }, - { "BBD", I18N_NOOP("Barbados"), I18N_NOOP("Barbados Dollar"), I18N_NOOP("BBD") }, - { "BYR", I18N_NOOP("Belarus"), I18N_NOOP("Belarussian Ruble"), I18N_NOOP("p.") }, - { "EUR", I18N_NOOP("Belgium"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "BEF", I18N_NOOP("Belgium"), I18N_NOOP("Franc"), I18N_NOOP("BF") }, - { "BZD", I18N_NOOP("Belize"), I18N_NOOP("Belize Dollar"), I18N_NOOP("BZ$") }, - { "XOF", I18N_NOOP("Benin"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "BMD", I18N_NOOP("Bermuda"), I18N_NOOP("Bermudian Dollar"), I18N_NOOP("BMD") }, - { "INR", I18N_NOOP("Bhutan"), I18N_NOOP("Indian Rupee"), I18N_NOOP("INR") }, - { "BTN", I18N_NOOP("Bhutan"), I18N_NOOP("Ngultrum"), I18N_NOOP("BTN") }, - { "BOB", I18N_NOOP("Bolivia"), I18N_NOOP("Boliviano"), I18N_NOOP("Bs") }, - { "BOV", I18N_NOOP("Bolivia"), I18N_NOOP("Mvdol"), I18N_NOOP("BOV") }, - { "BAM", I18N_NOOP("Bosnia And Herzegovina"), I18N_NOOP("Convertible Marks"), I18N_NOOP("BAM") }, - { "BWP", I18N_NOOP("Botswana"), I18N_NOOP("Pula"), I18N_NOOP("BWP") }, - { "NOK", I18N_NOOP("Bouvet Island"), I18N_NOOP("Norvegian Krone"), I18N_NOOP("NOK") }, - { "BRL", I18N_NOOP("Brazil"), I18N_NOOP("Brazilian Real"), I18N_NOOP("R$") }, - { "USD", I18N_NOOP("British Indian Ocean Territory"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "BND", I18N_NOOP("Brunei Darussalam"), I18N_NOOP("Brunei Dollar"), I18N_NOOP("BND") }, - { "BGL", I18N_NOOP("Bulgaria"), I18N_NOOP("Lev"), I18N_NOOP("BGL") }, - { "BGN", I18N_NOOP("Bulgaria"), I18N_NOOP("Bulgarian Lev"), I18N_NOOP("BGN") }, - { "XOF", I18N_NOOP("Burkina Faso"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "BIF", I18N_NOOP("Burundi"), I18N_NOOP("Burundi Franc"), I18N_NOOP("BIF") }, - { "KHR", I18N_NOOP("Cambodia"), I18N_NOOP("Riel"), I18N_NOOP("KHR") }, - { "XAF", I18N_NOOP("Cameroon"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "CAD", I18N_NOOP("Canada"), I18N_NOOP("Canadian Dollar"), I18N_NOOP("CAD") }, - { "CVE", I18N_NOOP("Cape Verde"), I18N_NOOP("Cape Verde Escudo"), I18N_NOOP("CVE") }, - { "KYD", I18N_NOOP("Cayman Islands"), I18N_NOOP("Cayman Islands Dollar"), I18N_NOOP("KYD") }, - { "XAF", I18N_NOOP("Central African Republic"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "XAF", I18N_NOOP("Chad"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "CLP", I18N_NOOP("Chile"), I18N_NOOP("Chilean Peso"), I18N_NOOP("Ch$") }, - { "CLF", I18N_NOOP("Chile"), I18N_NOOP("Unidades de fomento"), I18N_NOOP("CLF") }, - { "CNY", I18N_NOOP("China"), I18N_NOOP("Yuan Renminbi"), I18N_NOOP("CNY") }, - { "AUD", I18N_NOOP("Christmas Island"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "AUD", I18N_NOOP("Cocos (Keeling) Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "COP", I18N_NOOP("Colombia"), I18N_NOOP("Colombian Peso"), I18N_NOOP("C$") }, - { "KMF", I18N_NOOP("Comoros"), I18N_NOOP("Comoro Franc"), I18N_NOOP("KMF") }, - { "XAF", I18N_NOOP("Congo"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "CDF", I18N_NOOP("Congo, The Democratic Republic Of"), I18N_NOOP("Franc Congolais"), I18N_NOOP("CDF") }, - { "NZD", I18N_NOOP("Cook Islands"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, - { "CRC", I18N_NOOP("Costa Rica"), I18N_NOOP("Costa Rican Colon"), I18N_NOOP("C") }, - { "XOF", I18N_NOOP("Cote D'Ivoire"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "HRK", I18N_NOOP("Croatia"), I18N_NOOP("Croatian kuna"), I18N_NOOP("kn") }, - { "CUP", I18N_NOOP("Cuba"), I18N_NOOP("Cuban Peso"), I18N_NOOP("CUP") }, - { "CYP", I18N_NOOP("Cyprus"), I18N_NOOP("Cyprus Pound"), I18N_NOOP("CYP") }, - { "CZK", I18N_NOOP("Czech Republic"), I18N_NOOP("Czech Koruna"), I18N_NOOP("Kc") }, - { "DKK", I18N_NOOP("Denmark"), I18N_NOOP("Danish Krone"), I18N_NOOP("kr") }, - { "DJF", I18N_NOOP("Djibouti"), I18N_NOOP("Djibouti Franc"), I18N_NOOP("DJF") }, - { "XCD", I18N_NOOP("Dominica"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("RD$") }, - { "DOP", I18N_NOOP("Dominican Republic"), I18N_NOOP("Dominican Peso"), I18N_NOOP("DOP") }, - { "TPE", I18N_NOOP("East Timor"), I18N_NOOP("Timor Escudo"), I18N_NOOP("TPE") }, - { "USD", I18N_NOOP("East Timor"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "USD", I18N_NOOP("Ecuador"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "EGP", I18N_NOOP("Egypt"), I18N_NOOP("Egyptian Pound"), I18N_NOOP("EGP") }, - { "SVC", I18N_NOOP("El Salvador"), I18N_NOOP("El Salvador Colon"), I18N_NOOP("C") }, - { "USD", I18N_NOOP("El Salvador"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "XAF", I18N_NOOP("Equatorial Guinea"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "ERN", I18N_NOOP("Eritrea"), I18N_NOOP("Nakfa"), I18N_NOOP("ERN") }, - { "EEK", I18N_NOOP("Estonia"), I18N_NOOP("Kroon"), I18N_NOOP("kr") }, - { "ETB", I18N_NOOP("Ethiopia"), I18N_NOOP("Ethiopian Birr"), I18N_NOOP("ETB") }, - { "FKP", I18N_NOOP("Falkland Island (Malvinas)"), I18N_NOOP("Falkland Islands Pound"), I18N_NOOP("FKP") }, - { "DKK", I18N_NOOP("Faeroe Islands"), I18N_NOOP("Danish Krone"), I18N_NOOP("kr") }, - { "FJD", I18N_NOOP("Fiji"), I18N_NOOP("Fiji Dollar"), I18N_NOOP("FJD") }, - { "EUR", I18N_NOOP("Finland"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "FIM", I18N_NOOP("Finland"), I18N_NOOP("Markka"), I18N_NOOP("mk") }, - { "EUR", I18N_NOOP("France"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "FRF", I18N_NOOP("France"), I18N_NOOP("Franc"), I18N_NOOP("F") }, - { "EUR", I18N_NOOP("French Guiana"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "XPF", I18N_NOOP("French Polynesia"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, - { "EUR", I18N_NOOP("Franc Southern Territories"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "XAF", I18N_NOOP("Gabon"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, - { "GMD", I18N_NOOP("Gambia"), I18N_NOOP("Dalasi"), I18N_NOOP("GMD") }, - { "GEL", I18N_NOOP("Georgia"), I18N_NOOP("Lari"), I18N_NOOP("GEL") }, - { "EUR", I18N_NOOP("Germany"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "DEM", I18N_NOOP("Germany"), I18N_NOOP("German Mark"), I18N_NOOP("DM") }, - { "GHC", I18N_NOOP("Ghana"), I18N_NOOP("Cedi"), I18N_NOOP("GHC") }, - { "GIP", I18N_NOOP("Gibraltar"), I18N_NOOP("Gibraltar Pound"), I18N_NOOP("GIP") }, - { "EUR", I18N_NOOP("Greece"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "GRD", I18N_NOOP("Greece"), I18N_NOOP("Drachma"), I18N_NOOP("GRD") }, - { "DKK", I18N_NOOP("Greenland"), I18N_NOOP("Danish Krone"), I18N_NOOP("DKK") }, - { "XCD", I18N_NOOP("Grenada"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "EUR", I18N_NOOP("Guadeloupe"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "USD", I18N_NOOP("Guam"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "GTQ", I18N_NOOP("Guatemala"), I18N_NOOP("Quetzal"), I18N_NOOP("Q") }, - { "GNF", I18N_NOOP("Guinea"), I18N_NOOP("Guinea Franc"), I18N_NOOP("GNF") }, - { "GWP", I18N_NOOP("Guinea-Bissau"), I18N_NOOP("Guinea-Bissau Peso"), I18N_NOOP("GWP") }, - { "XOF", I18N_NOOP("Guinea-Bissau"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "GYD", I18N_NOOP("Guyana"), I18N_NOOP("Guyana Dollar"), I18N_NOOP("GYD") }, - { "HTG", I18N_NOOP("Haiti"), I18N_NOOP("Gourde"), I18N_NOOP("HTG") }, - { "USD", I18N_NOOP("Haiti"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "AUD", I18N_NOOP("Heard Island And McDonald Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "EUR", I18N_NOOP("Holy See (Vatican City State)"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "HNL", I18N_NOOP("Honduras"), I18N_NOOP("Lempira"), I18N_NOOP("L") }, - { "HKD", I18N_NOOP("Hong Kong"), I18N_NOOP("Hong Kong Dollar"), I18N_NOOP("HKD") }, - { "HUF", I18N_NOOP("Hungary"), I18N_NOOP("Forint"), I18N_NOOP("Ft") }, - { "ISK", I18N_NOOP("Iceland"), I18N_NOOP("Iceland Krona"), I18N_NOOP("kr.") }, - { "INR", I18N_NOOP("India"), I18N_NOOP("Indian Rupee"), I18N_NOOP("INR") }, - { "IDR", I18N_NOOP("Indonesia"), I18N_NOOP("Rupiah"), I18N_NOOP("Rp") }, - { "IRR", I18N_NOOP("Iran, Islamic Republic Of"), I18N_NOOP("Iranian Rial"), I18N_NOOP("IRR") }, - { "IQD", I18N_NOOP("Iraq"), I18N_NOOP("Iraqi Dinar"), I18N_NOOP("IQD") }, - { "EUR", I18N_NOOP("Ireland"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "IEP", I18N_NOOP("Ireland"), I18N_NOOP("Punt"), I18N_NOOP("IR----") }, - { "IEX", I18N_NOOP("Ireland"), I18N_NOOP("Pence"), I18N_NOOP("IEX") }, - { "ILS", I18N_NOOP("Israel"), I18N_NOOP("New Israeli Sheqel"), I18N_NOOP("ILS") }, - { "EUR", I18N_NOOP("Italy"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "ITL", I18N_NOOP("Italy"), I18N_NOOP("Lira"), I18N_NOOP("L.") }, - { "JMD", I18N_NOOP("Jamaica"), I18N_NOOP("Jamaican Dollar"), I18N_NOOP("J$") }, - { "JPY", I18N_NOOP("Japan"), I18N_NOOP("Yen"), I18N_NOOP("JPY") }, - { "JOD", I18N_NOOP("Jordan"), I18N_NOOP("Jordanian Dinar"), I18N_NOOP("JOD") }, - { "KZT", I18N_NOOP("Kazakhstan"), I18N_NOOP("Tenge"), I18N_NOOP("KZT") }, - { "KES", I18N_NOOP("Kenya"), I18N_NOOP("Kenyan Shilling"), I18N_NOOP("KES") }, - { "AUD", I18N_NOOP("Kiribati"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "KPW", I18N_NOOP("Korea, Democratic People's Republic Of"), I18N_NOOP("North Korean Won"), I18N_NOOP("KPW") }, - { "KRW", I18N_NOOP("Korea, Republic Of"), I18N_NOOP("Won"), I18N_NOOP("KRW") }, - { "KWD", I18N_NOOP("Kuwait"), I18N_NOOP("Kuwaiti Dinar"), I18N_NOOP("KWD") }, - { "KGS", I18N_NOOP("Kyrgyzstan"), I18N_NOOP("Som"), I18N_NOOP("KGS") }, - { "LAK", I18N_NOOP("Lao People's Democratic Republic"), I18N_NOOP("Kip"), I18N_NOOP("LAK") }, - { "LVL", I18N_NOOP("Latvia"), I18N_NOOP("Latvian Lats"), I18N_NOOP("Ls") }, - { "LBP", I18N_NOOP("Lebanon"), I18N_NOOP("Lebanese Pound"), I18N_NOOP("LBP") }, - { "ZAR", I18N_NOOP("Lesotho"), I18N_NOOP("Rand"), I18N_NOOP("ZAR") }, - { "LSL", I18N_NOOP("Lesotho"), I18N_NOOP("Loti"), I18N_NOOP("LSL") }, - { "LRD", I18N_NOOP("Liberia"), I18N_NOOP("Liberian Dollar"), I18N_NOOP("LRD") }, - { "LYD", I18N_NOOP("Libyan Arab Jamahiriya"), I18N_NOOP("Lybian Dinar"), I18N_NOOP("LYD") }, - { "CHF", I18N_NOOP("Liechtenstein"), I18N_NOOP("Swiss Franc"), I18N_NOOP("CHF") }, - { "LTL", I18N_NOOP("Lithuania"), I18N_NOOP("Lithuanian Litus"), I18N_NOOP("Lt") }, - { "EUR", I18N_NOOP("Luxembourg"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "LUF", I18N_NOOP("Luxembourg"), I18N_NOOP("Franc"), I18N_NOOP("F") }, - { "MOP", I18N_NOOP("Macao"), I18N_NOOP("Pataca"), I18N_NOOP("MOP") }, - { "MKD", I18N_NOOP("Macedonia, The Former Yugoslav Republic Of"), I18N_NOOP("Denar"), I18N_NOOP("MKD") }, - { "MGF", I18N_NOOP("Madagascar"), I18N_NOOP("Malagasy Franc"), I18N_NOOP("MGF") }, - { "MWK", I18N_NOOP("Malawi"), I18N_NOOP("Kwacha"), I18N_NOOP("MWK") }, - { "MYR", I18N_NOOP("Malaysia"), I18N_NOOP("Malaysian Ringgit"), I18N_NOOP("MYR") }, - { "MVR", I18N_NOOP("Maldives"), I18N_NOOP("Rufiyaa"), I18N_NOOP("MVR") }, - { "XOF", I18N_NOOP("Mali"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "MTL", I18N_NOOP("Malta"), I18N_NOOP("Maltese Lira"), I18N_NOOP("MTL") }, - { "USD", I18N_NOOP("Marshall Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "EUR", I18N_NOOP("Martinique"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "MRO", I18N_NOOP("Mauritania"), I18N_NOOP("Ouguiya"), I18N_NOOP("MRO") }, - { "MUR", I18N_NOOP("Mauritius"), I18N_NOOP("Mauritius Rupee"), I18N_NOOP("MUR") }, - { "EUR", I18N_NOOP("Mayotte"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "MXN", I18N_NOOP("Mexico"), I18N_NOOP("Mexican Peso"), I18N_NOOP("MXN") }, - { "MXV", I18N_NOOP("Mexico"), I18N_NOOP("Mexican Unidad de Inversion (UDI)"), I18N_NOOP("MXV") }, - { "USD", I18N_NOOP("Micronesia, Federated States Of"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "MDL", I18N_NOOP("Moldova, Republic Of"), I18N_NOOP("Moldovan Leu"), I18N_NOOP("MDL") }, - { "EUR", I18N_NOOP("Monaco"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "MNT", I18N_NOOP("Mongolia"), I18N_NOOP("Tugrik"), I18N_NOOP("MNT") }, - { "XCD", I18N_NOOP("Montserrat"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "MAD", I18N_NOOP("Morocco"), I18N_NOOP("Moroccan Dirham"), I18N_NOOP("MAD") }, - { "MZM", I18N_NOOP("Mozambique"), I18N_NOOP("Metical"), I18N_NOOP("MZM") }, - { "MMK", I18N_NOOP("Myanmar"), I18N_NOOP("Kyat"), I18N_NOOP("MMK") }, - { "ZAR", I18N_NOOP("Namibia"), I18N_NOOP("Rand"), I18N_NOOP("ZAR") }, - { "NAD", I18N_NOOP("Namibia"), I18N_NOOP("Namibia Dollar"), I18N_NOOP("NAD") }, - { "AUD", I18N_NOOP("Nauru"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "NPR", I18N_NOOP("Nepal"), I18N_NOOP("Nepalese Rupee"), I18N_NOOP("NPR") }, - { "EUR", I18N_NOOP("Netherlands"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "NLG", I18N_NOOP("Netherlands"), I18N_NOOP("Guilder"), I18N_NOOP("fl") }, - { "ANG", I18N_NOOP("Netherlands Antilles"), I18N_NOOP("Netherlands Antillan Guilder"), I18N_NOOP("ANG") }, - { "XPF", I18N_NOOP("New Caledonia"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, - { "NZD", I18N_NOOP("New Zealand"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, - { "NIO", I18N_NOOP("Nicaragua"), I18N_NOOP("Cordoba Oro"), I18N_NOOP("NIO") }, - { "XOF", I18N_NOOP("Niger"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "NGN", I18N_NOOP("Nigeria"), I18N_NOOP("Naira"), I18N_NOOP("NGN") }, - { "NZD", I18N_NOOP("Niue"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, - { "AUD", I18N_NOOP("Norfolk Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "USD", I18N_NOOP("Northern Mariana Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "NOK", I18N_NOOP("Norway"), I18N_NOOP("Norwegian Krone"), I18N_NOOP("kr") }, - { "OMR", I18N_NOOP("Oman"), I18N_NOOP("Rial Omani"), I18N_NOOP("OMR") }, - { "PKR", I18N_NOOP("Pakistan"), I18N_NOOP("Pakistan Rupee"), I18N_NOOP("PKR") }, - { "USD", I18N_NOOP("Palau"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "PAB", I18N_NOOP("Panama"), I18N_NOOP("Balboa"), I18N_NOOP("PAB") }, - { "USD", I18N_NOOP("Panama"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "PGK", I18N_NOOP("Papua New Guinea"), I18N_NOOP("Kina"), I18N_NOOP("PGK") }, - { "PYG", I18N_NOOP("Paraguay"), I18N_NOOP("Guarani"), I18N_NOOP("G") }, - { "PEN", I18N_NOOP("Peru"), I18N_NOOP("Nuevo Sol"), I18N_NOOP("PEN") }, - { "PHP", I18N_NOOP("Philippines"), I18N_NOOP("Philippine Peso"), I18N_NOOP("PHP") }, - { "NZD", I18N_NOOP("Pitcairn"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, - { "PLN", I18N_NOOP("Poland"), I18N_NOOP("Zloty"), I18N_NOOP("zt") }, - { "EUR", I18N_NOOP("Portugal"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "PTE", I18N_NOOP("Portugal"), I18N_NOOP("Escudo"), I18N_NOOP("Esc.") }, - { "USD", I18N_NOOP("Puerto Rico"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "QAR", I18N_NOOP("Qatar"), I18N_NOOP("Qatari Rial"), I18N_NOOP("QAR") }, - { "ROL", I18N_NOOP("Romania"), I18N_NOOP("Leu"), I18N_NOOP("LEI") }, - { "RUR", I18N_NOOP("Russian Federation"), I18N_NOOP("Russian Ruble"), I18N_NOOP("RUR") }, - { "RUB", I18N_NOOP("Russian Federation"), I18N_NOOP("Russian Ruble"), I18N_NOOP("RUB") }, - { "RWF", I18N_NOOP("Rwanda"), I18N_NOOP("Rwanda Franc"), I18N_NOOP("RWF") }, - { "SHP", I18N_NOOP("Saint Helena"), I18N_NOOP("Saint Helena Pound"), I18N_NOOP("SHP") }, - { "XCD", I18N_NOOP("Saint Kitts And Nevis"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "XCD", I18N_NOOP("Saint Lucia"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "EUR", I18N_NOOP("Saint Pierre And Miquelon"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "XCD", I18N_NOOP("Saint Vincent And The Grenadines"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, - { "WST", I18N_NOOP("Samoa"), I18N_NOOP("Tala"), I18N_NOOP("WST") }, - { "EUR", I18N_NOOP("San Marino"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "STD", I18N_NOOP("Sao Tome And Principe"), I18N_NOOP("Dobra"), I18N_NOOP("STD") }, - { "SAR", I18N_NOOP("Saudi Arabia"), I18N_NOOP("Saudi Riyal"), I18N_NOOP("SAR") }, - { "XOF", I18N_NOOP("Senegal"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "SCR", I18N_NOOP("Seychelles"), I18N_NOOP("Seychelles Rupee"), I18N_NOOP("SCR") }, - { "SLL", I18N_NOOP("Sierra Leone"), I18N_NOOP("Leone"), I18N_NOOP("SLL") }, - { "SGD", I18N_NOOP("Singapore"), I18N_NOOP("Singapore Dollar"), I18N_NOOP("SGD") }, - { "SKK", I18N_NOOP("Slovakia"), I18N_NOOP("Slovak Koruna"), I18N_NOOP("Sk") }, - { "EUR", I18N_NOOP("Slovenia"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "SBD", I18N_NOOP("Solomon Islands"), I18N_NOOP("Solomon Islands Dollar"), I18N_NOOP("SBD") }, - { "SOS", I18N_NOOP("Somalia"), I18N_NOOP("Somali Shilling"), I18N_NOOP("SOS") }, - { "ZAR", I18N_NOOP("South Africa"), I18N_NOOP("Rand"), I18N_NOOP("R") }, - { "EUR", I18N_NOOP("Spain"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, - { "ESP", I18N_NOOP("Spain"), I18N_NOOP("Peseta"), I18N_NOOP("Pts") }, - { "LKR", I18N_NOOP("Sri Lanka"), I18N_NOOP("Sri Lanka Rupee"), I18N_NOOP("LKR") }, - { "SDD", I18N_NOOP("Sudan"), I18N_NOOP("Sudanese Dinar"), I18N_NOOP("SDD") }, - { "SRG", I18N_NOOP("Suriname"), I18N_NOOP("Suriname Guilder"), I18N_NOOP("SRG") }, - { "NOK", I18N_NOOP("Svalbard And Jan Mayen"), I18N_NOOP("Norwegian Krone"), I18N_NOOP("NOK") }, - { "SZL", I18N_NOOP("Swaziland"), I18N_NOOP("Lilangeni"), I18N_NOOP("SZL") }, - { "SEK", I18N_NOOP("Sweden"), I18N_NOOP("Swedish Krona"), I18N_NOOP("kr") }, - { "CHF", I18N_NOOP("Switzerland"), I18N_NOOP("Swiss Franc"), I18N_NOOP("SFr.") }, - { "SYP", I18N_NOOP("Syrian Arab Republic"), I18N_NOOP("Syrian Pound"), I18N_NOOP("SYP") }, - { "TWD", I18N_NOOP("Taiwan, Province Of China"), I18N_NOOP("New Taiwan Dollar"), I18N_NOOP("TWD") }, - { "TJS", I18N_NOOP("Tajikistan"), I18N_NOOP("Somoni"), I18N_NOOP("TJS") }, - { "TZS", I18N_NOOP("Tanzania, United Republic Of"), I18N_NOOP("Tanzanian Shilling"), I18N_NOOP("TZS") }, - { "THB", I18N_NOOP("Thailand"), I18N_NOOP("Baht"), I18N_NOOP("THB") }, - { "XOF", I18N_NOOP("Togo"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, - { "NZD", I18N_NOOP("Tokelau"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, - { "TOP", I18N_NOOP("Tonga"), I18N_NOOP("Pa'anga"), I18N_NOOP("TOP") }, - { "TTD", I18N_NOOP("Trinidad And Tobago"), I18N_NOOP("Trinidad and Tobago Dollar"), I18N_NOOP("TT$") }, - { "TND", I18N_NOOP("Tunisia"), I18N_NOOP("Tunisian Dinar"), I18N_NOOP("TND") }, - { "TRL", I18N_NOOP("Turkey"), I18N_NOOP("Turkish Lira"), I18N_NOOP("TL") }, - { "TMM", I18N_NOOP("Turkmenistan"), I18N_NOOP("Manat"), I18N_NOOP("TMM") }, - { "USD", I18N_NOOP("Turks And Caicos Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "AUD", I18N_NOOP("Tuvalu"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, - { "UGX", I18N_NOOP("Uganda"), I18N_NOOP("Uganda Shilling"), I18N_NOOP("UGX") }, - { "UAH", I18N_NOOP("Ukraine"), I18N_NOOP("Hryvnia"), I18N_NOOP("UAH") }, - { "AED", I18N_NOOP("United Arab Emirates"), I18N_NOOP("UAE Dirham"), I18N_NOOP("AED") }, - { "GBP", I18N_NOOP("United Kingdom"), I18N_NOOP("Pound Sterling"), I18N_NOOP("GBP") }, - { "USD", I18N_NOOP("United States"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "USN", I18N_NOOP("United States"), I18N_NOOP("US Dollar (Next day)"), I18N_NOOP("USN") }, - { "USS", I18N_NOOP("United States"), I18N_NOOP("US Dollar (Same day)"), I18N_NOOP("USS") }, - { "UYU", I18N_NOOP("Uruguay"), I18N_NOOP("Peso Uruguayo"), I18N_NOOP("NU$") }, - { "UZS", I18N_NOOP("Uzbekistan"), I18N_NOOP("Uzbekistan Sum"), I18N_NOOP("UZS") }, - { "VUV", I18N_NOOP("Vanuatu"), I18N_NOOP("Vatu"), I18N_NOOP("VUV") }, - { "VEB", I18N_NOOP("Venezuela"), I18N_NOOP("Bolivar"), I18N_NOOP("Bs") }, - { "VND", I18N_NOOP("Viet Nam"), I18N_NOOP("Dong"), I18N_NOOP("VND") }, - { "USD", I18N_NOOP("Virgin Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, - { "XPF", I18N_NOOP("Wallis And Futuna"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, - { "MAD", I18N_NOOP("Western Sahara"), I18N_NOOP("Moroccan Dirham"), I18N_NOOP("MAD") }, - { "YER", I18N_NOOP("Yemen"), I18N_NOOP("Yemeni Rial"), I18N_NOOP("YER") }, - { "YUM", I18N_NOOP("Yugoslavia"), I18N_NOOP("Yugoslavian Dinar"), I18N_NOOP("YUM") }, - { "ZMK", I18N_NOOP("Zambia"), I18N_NOOP("Kwacha"), I18N_NOOP("ZMK") }, - { "ZWD", I18N_NOOP("Zimbabwe"), I18N_NOOP("Zimbabwe Dollar"), I18N_NOOP("ZWD") }, - { 0, 0, 0, 0}, // Last must be empty! - }; - - - class CurrencyMap - { - public: - CurrencyMap() - : m_List(lMoney) - { - } - - // Those return the _untranslated_ strings from the above array - TQString getCode(int t) const - { - return TQString::fromUtf8( m_List[t].code ); - } - - TQString getCountry(int t) const - { - return TQString::fromUtf8( m_List[t].country ); - } - - TQString getName(int t) const - { - return TQString::fromUtf8( m_List[t].name ); - } - - TQString getDisplayCode(int t) const - { - return TQString::fromUtf8( m_List[t].display ); - } - - int getIndex(const TQString& code) const - { - int index = 0; - while (m_List[index].code != 0 && m_List[index].code != code) - ++index; - return (m_List[index].code != 0) ? index : 1 /*undef*/; - } - - private: - const Money * m_List; - }; - - const CurrencyMap gCurrencyMap; - const Money * gMoneyList(lMoney); -} - - -using namespace Currency_LNS; - -Currency::Currency() - : m_type( 0 ) -{ -} - -Currency::~Currency() -{ -} - -Currency::Currency(int index) - : m_type( index ), - m_code( gCurrencyMap.getCode( index ) ) -{ -} - -Currency::Currency(int index, TQString const & code) - : m_type ( 1 ), // unspec - m_code( code ) -{ - if ( gCurrencyMap.getCode( index ) == code ) - m_type = index; -} - -Currency::Currency(TQString const & code, currencyFormat format) - : m_type( 1 ), // unspec - m_code( code ) -{ - if ( format == Gnumeric ) - { - // I use TQChar(c,r) here so that this file can be opened in any encoding... - if ( code.find( TQChar( 172, 32 ) ) != -1 ) // Euro sign - m_code = TQChar( 172, 32 ); - else if ( code.find( TQChar( 163, 0 ) ) != -1 ) // Pound sign - m_code = TQChar( 163, 0 ); - else if ( code.find( TQChar( 165, 0 ) ) != -1 ) // Yen sign - m_code = TQChar( 165, 0 ); - else if ( code[0] == '[' && code[1] == '$' ) - { - int n = code.find(']'); - if (n != -1) - { - m_code = code.mid( 2, n - 2 ); - } - else - { - m_type = 0; - } - } - else if ( code.find( '$' ) != -1 ) - m_code = "$"; - } // end gnumeric - m_type = gCurrencyMap.getIndex( m_code ); -} - -Currency & Currency::operator=(int type) -{ - m_type = type; - m_code = gCurrencyMap.getCode( m_type ); - - return *this; -} - -Currency & Currency::operator=(char const * code) -{ - m_type = 1; - m_code = code; - - return *this; -} - -bool Currency::operator==(Currency const & cur) const -{ - if ( m_type == cur.m_type ) - return true; - - if ( m_code == cur.m_code ) - return true; - - return false; -} - -bool Currency::operator==(int type) const -{ - if ( m_type == type ) - return true; - - return false; -} - -Currency::operator int() const -{ - return m_type; -} - -TQString Currency::getCode() const -{ - return m_code; -} - -TQString Currency::getCountry() const -{ - return gCurrencyMap.getCountry( m_type ); -} - -TQString Currency::getName() const -{ - return gCurrencyMap.getName( m_type ); -} - -TQString Currency::getDisplayCode() const -{ - return gMoneyList[m_type].display; -} - -int Currency::getIndex() const -{ - return m_type; -} - -TQString Currency::getExportCode( currencyFormat format ) const -{ - if ( format == Gnumeric ) - { - if ( m_code.length() == 1 ) // symbol - return m_code; - - TQString ret( "[$"); - ret += m_code; - ret += "]"; - - return ret; - } - - return m_code; -} - -TQString Currency::getChooseString( int type, bool & ok ) -{ - if ( !gMoneyList[type].country ) - { - ok = false; - return TQString(); - } - if ( type < 24 ) - { - TQString ret( i18n( gMoneyList[type].name ) ); - if ( gMoneyList[type].country[0] ) - { - ret += " ("; - ret += i18n( gMoneyList[type].country ); - ret += ")"; - } - return ret; - } - else - { - TQString ret( i18n( gMoneyList[type].country ) ); - if ( gMoneyList[type].name[0] ) - { - ret += " ("; - ret += i18n( gMoneyList[type].name ); - ret += ")"; - } - return ret; - } -} - -TQString Currency::getDisplaySymbol( int type ) -{ - return i18n( gMoneyList[type].display ); -} - -// Currently unused -TQString Currency::getCurrencyCode( int type ) -{ - return TQString::fromUtf8( gMoneyList[type].code ); -} - -#undef UPDATE_BEGIN -#undef UPDATE_END diff --git a/kspread/kspread_format.cpp b/kspread/kspread_format.cpp new file mode 100644 index 00000000..430e2386 --- /dev/null +++ b/kspread/kspread_format.cpp @@ -0,0 +1,3581 @@ +/* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis + Copyright (C) 2000 - 2005 The KSpread Team + www.koffice.org/kspread + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_global.h" +#include "kspread_sheet.h" +#include "kspread_sheetprint.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "KSpreadColumnIface.h" +#include "KSpreadLayoutIface.h" +#include "KSpreadRowIface.h" + +#include "kspread_format.h" + +using namespace std; +using namespace KSpread; + +/***************************************************************************** + * + * Format + * + *****************************************************************************/ + +// static variable construction +// NOTE Stefan: These values are always overridden by the Doc c'tor. +double Format::s_columnWidth = 100.0; +double Format::s_rowHeight = 20.0; + +Format::Format( Sheet * _sheet, Style * _style ) + : m_pSheet( _sheet ), + m_pStyle( _style ), + m_mask( 0 ), + m_bNoFallBack( 0 ), + m_flagsMask( 0 ), + m_strComment( 0 ), + m_pCell( 0 ) +{ +} + +Format::~Format() +{ + if ( m_pStyle->release() ) + delete m_pStyle; +} + +void Format::defaultStyleFormat() +{ + if ( m_pStyle->release() ) + delete m_pStyle; + + if ( m_pSheet ) + m_pStyle = m_pSheet->doc()->styleManager()->defaultStyle(); + + delete m_strComment; +} + + +void Format::setGlobalColWidth( double width ) +{ + s_columnWidth = width; +} + +void Format::setGlobalRowHeight( double height ) +{ + s_rowHeight = height; +} + +double Format::globalRowHeight() +{ + return s_rowHeight; +} + +double Format::globalColWidth() +{ + return s_columnWidth; +} + +void Format::copy( const Format & _l ) +{ + // TODO why is the sheet not copied? + + setStyle( _l.m_pStyle ); + + m_mask = _l.m_mask; + m_flagsMask = _l.m_flagsMask; + m_bNoFallBack = _l.m_bNoFallBack; + + if ( _l.m_strComment ) + { + if (m_strComment) + delete m_strComment; + m_strComment = new TQString( *_l.m_strComment ); + } +} + +void Format::setStyle( Style * style ) +{ + if ( style == m_pStyle ) + return; + + if ( m_pStyle && m_pStyle->release() ) + delete m_pStyle; + + m_bNoFallBack = 0; + m_pStyle = style; + m_pStyle->addRef(); + formatChanged(); + // kdDebug() << "Newly assigned style: " << m_pStyle << ", type: " << m_pStyle->type() << endl; + if ( style->type() == Style::BUILTIN || style->type() == Style::CUSTOM ) + kdDebug() << "Style name: " << ((CustomStyle *) m_pStyle)->name() << endl; +} + +void Format::clearFlag( FormatFlags flag ) +{ + m_flagsMask &= ~(TQ_UINT32)flag; +} + +void Format::setFlag( FormatFlags flag ) +{ + m_flagsMask |= (TQ_UINT32)flag; +} + +bool Format::testFlag( FormatFlags flag ) const +{ + return ( m_flagsMask & (TQ_UINT32)flag ); +} + +void Format::clearProperties() +{ + m_mask = 0; + m_pStyle->clearFeature( (Style::FlagsSet) ~(uint)0 ); + formatChanged(); +} + +void Format::clearProperty( Properties p ) +{ + m_mask &= ~(uint)p; + m_pStyle->clearFeature( (Style::FlagsSet) p ); + formatChanged(); +} + +// FIXME according to Valgrind, this function consumes too much time +// find a way to optimize it ! +bool Format::hasProperty( Properties p, bool withoutParent ) const +{ + if ( m_pStyle->hasFeature( (Style::FlagsSet) p, withoutParent ) ) + return true; + + return ( m_mask & (uint)p ); +} + +void Format::setProperty( Properties p ) +{ + m_mask |= (uint)p; +} + +void Format::clearNoFallBackProperties() +{ + m_bNoFallBack = 0; + + formatChanged(); +} + +void Format::clearNoFallBackProperties( Properties p ) +{ + m_bNoFallBack &= ~(uint)p; + + formatChanged(); +} + +bool Format::hasNoFallBackProperties( Properties p ) const +{ + return ( m_bNoFallBack & (uint)p ); +} + +void Format::setNoFallBackProperties( Properties p ) +{ + m_bNoFallBack |= (uint)p; +} + + +///////////// +// +// Loading and saving +// +///////////// + + +TQString Format::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles ) +{ + TQString styleName; + styleName = m_pStyle->saveOasis( currentCellStyle, mainStyles ); + + // user styles are already stored + if ( currentCellStyle.type() == Doc::STYLE_CELL_AUTO ) + { + styleName = mainStyles.lookup( currentCellStyle, "ce" ); + } + + return styleName; +} + +TQDomElement Format::saveFormat( TQDomDocument & doc, int _col, int _row, bool force, bool copy ) const +{ + TQDomElement format( doc.createElement( "format" ) ); + + if ( m_pStyle->type() == Style::BUILTIN || m_pStyle->type() == Style::CUSTOM ) + { + format.setAttribute( "style-name", ((CustomStyle *) m_pStyle)->name() ); + + if ( !copy ) + return format; + } + else + { + if ( m_pStyle->parent() && m_pStyle->parent()->name().length() > 0 ) + format.setAttribute( "parent", m_pStyle->parent()->name() ); + } + + if ( hasProperty( PAlign, true ) || hasNoFallBackProperties( PAlign ) || force ) + format.setAttribute( "align", (int) align( _col, _row ) ); + if ( hasProperty( PAlignY, true ) || hasNoFallBackProperties( PAlignY ) || force ) + format.setAttribute( "alignY", (int)alignY( _col, _row ) ); + if ( ( hasProperty( PBackgroundColor, false ) || hasNoFallBackProperties( PBackgroundColor) + || force ) && bgColor( _col, _row ).isValid() ) + format.setAttribute( "bgcolor", bgColor( _col, _row ).name() ); + if ( ( hasProperty( PMultiRow, true ) || hasNoFallBackProperties( PMultiRow ) + || force ) && multiRow( _col, _row ) ) + format.setAttribute( "multirow", "yes" ); + if ( ( hasProperty( PVerticalText, true ) || hasNoFallBackProperties( PVerticalText ) + || force ) && verticalText( _col, _row ) ) + format.setAttribute( "verticaltext", "yes" ); + if ( hasProperty( PPrecision, true ) || hasNoFallBackProperties( PPrecision ) || force ) + format.setAttribute( "precision", precision( _col, _row ) ); + if ( ( hasProperty( PPrefix, true ) || hasNoFallBackProperties( PPrefix ) || force ) + && !prefix( _col, _row ).isEmpty() ) + format.setAttribute( "prefix", prefix( _col, _row ) ); + if ( ( hasProperty( PPostfix, true ) || hasNoFallBackProperties( PPostfix ) || force ) + && !postfix( _col, _row ).isEmpty() ) + format.setAttribute( "postfix", postfix( _col, _row ) ); + if ( hasProperty( PFloatFormat, true ) || hasNoFallBackProperties( PFloatFormat ) || force ) + format.setAttribute( "float", (int) floatFormat( _col, _row ) ); + if ( hasProperty( PFloatColor, true ) || hasNoFallBackProperties( PFloatColor ) || force ) + format.setAttribute( "floatcolor", (int) floatColor( _col, _row ) ); + if ( hasProperty( PFormatType, true ) || hasNoFallBackProperties( PFormatType ) || force ) + format.setAttribute( "format", (int)getFormatType( _col, _row )); + if ( hasProperty( PCustomFormat, true ) || hasNoFallBackProperties( PCustomFormat ) || force ) + { + TQString s( getFormatString( _col, _row ) ); + if ( s.length() > 0 ) + format.setAttribute( "custom", s ); + } + if ( getFormatType( _col, _row ) == Money_format ) + { + format.setAttribute( "type", (int) m_pStyle->currency().type ); // TODO: fallback? + format.setAttribute( "symbol", m_pStyle->currency().symbol ); + } + if ( hasProperty( PAngle, true ) || hasNoFallBackProperties( PAngle ) || force ) + format.setAttribute( "angle", getAngle( _col, _row ) ); + if ( hasProperty( PIndent, true ) || hasNoFallBackProperties( PIndent ) || force ) + format.setAttribute( "indent", getIndent( _col, _row ) ); + if( ( hasProperty( PDontPrintText, true ) || hasNoFallBackProperties( PDontPrintText ) + || force ) && getDontprintText( _col, _row ) ) + format.setAttribute( "dontprinttext", "yes" ); + if( ( hasProperty( PNotProtected, true ) || hasNoFallBackProperties( PNotProtected ) + || force ) && notProtected( _col, _row ) ) + format.setAttribute( "noprotection", "yes" ); + if( ( hasProperty( PHideAll, true ) || hasNoFallBackProperties( PHideAll ) + || force ) && isHideAll( _col, _row ) ) + format.setAttribute( "hideall", "yes" ); + if( ( hasProperty( PHideFormula, true ) || hasNoFallBackProperties( PHideFormula ) + || force ) && isHideFormula( _col, _row ) ) + format.setAttribute( "hideformula", "yes" ); + if ( hasProperty( PFont, true ) || hasNoFallBackProperties( PFont ) || force ) + format.appendChild( util_createElement( "font", textFont( _col, _row ), doc ) ); + if ( ( hasProperty( PTextPen, true ) || hasNoFallBackProperties( PTextPen ) || force ) + && textPen( _col, _row ).color().isValid() ) + format.appendChild( util_createElement( "pen", textPen( _col, _row ), doc ) ); + if ( hasProperty( PBackgroundBrush, true ) || hasNoFallBackProperties( PBackgroundBrush ) || force ) + { + format.setAttribute( "brushcolor", backGroundBrushColor( _col, _row ).name() ); + format.setAttribute( "brushstyle", (int)backGroundBrushStyle( _col, _row ) ); + } + if ( hasProperty( PLeftBorder, true ) || hasNoFallBackProperties( PLeftBorder ) || force ) + { + TQDomElement left = doc.createElement( "left-border" ); + left.appendChild( util_createElement( "pen", leftBorderPen( _col, _row ), doc ) ); + format.appendChild( left ); + } + if ( hasProperty( PTopBorder, true ) || hasNoFallBackProperties( PTopBorder ) || force ) + { + TQDomElement top = doc.createElement( "top-border" ); + top.appendChild( util_createElement( "pen", topBorderPen( _col, _row ), doc ) ); + format.appendChild( top ); + } + if ( hasProperty( PRightBorder, true ) || hasNoFallBackProperties( PRightBorder ) || force ) + { + TQDomElement right = doc.createElement( "right-border" ); + right.appendChild( util_createElement( "pen", rightBorderPen( _col, _row ), doc ) ); + format.appendChild( right ); + } + if ( hasProperty( PBottomBorder, true ) || hasNoFallBackProperties( PBottomBorder ) || force ) + { + TQDomElement bottom = doc.createElement( "bottom-border" ); + bottom.appendChild( util_createElement( "pen", bottomBorderPen( _col, _row ), doc ) ); + format.appendChild( bottom ); + } + if ( hasProperty( PFallDiagonal, true ) || hasNoFallBackProperties( PFallDiagonal ) || force ) + { + TQDomElement fallDiagonal = doc.createElement( "fall-diagonal" ); + fallDiagonal.appendChild( util_createElement( "pen", fallDiagonalPen( _col, _row ), doc ) ); + format.appendChild( fallDiagonal ); + } + if ( hasProperty( PGoUpDiagonal, true ) || hasNoFallBackProperties( PGoUpDiagonal ) || force ) + { + TQDomElement goUpDiagonal = doc.createElement( "up-diagonal" ); + goUpDiagonal.appendChild( util_createElement( "pen", goUpDiagonalPen( _col, _row ), doc ) ); + format.appendChild( goUpDiagonal ); + } + return format; +} + + +TQDomElement Format::saveFormat( TQDomDocument& doc, bool force, bool copy ) const +{ + TQDomElement format( doc.createElement( "format" ) ); + + if ( m_pStyle->type() == Style::BUILTIN || m_pStyle->type() == Style::CUSTOM ) + { + format.setAttribute( "style-name", ((CustomStyle *) m_pStyle)->name() ); + + if ( !copy ) + return format; + } + else + { + if ( m_pStyle->parent() && m_pStyle->parentName().length() > 0 ) + format.setAttribute( "parent", m_pStyle->parentName() ); + } + + if ( hasProperty( PAlign, true ) || hasNoFallBackProperties( PAlign ) || force ) + format.setAttribute( "align", (int)m_pStyle->alignX() ); + if ( hasProperty( PAlignY, true ) || hasNoFallBackProperties( PAlignY ) || force ) + format.setAttribute( "alignY", (int)m_pStyle->alignY() ); + if ( ( hasProperty( PBackgroundColor, true ) || hasNoFallBackProperties( PBackgroundColor ) + || force ) && m_pStyle->bgColor().isValid() ) + format.setAttribute( "bgcolor", m_pStyle->bgColor().name() ); + + if ( ( hasProperty( PMultiRow, true ) || hasNoFallBackProperties( PMultiRow ) || force ) + && m_pStyle->hasProperty( Style::PMultiRow ) ) + format.setAttribute( "multirow", "yes" ); + if ( ( hasProperty( PVerticalText, true ) || hasNoFallBackProperties( PVerticalText ) || force ) + && m_pStyle->hasProperty( Style::PVerticalText ) ) + format.setAttribute( "verticaltext", "yes" ); + + if ( hasProperty( PPrecision, true ) || hasNoFallBackProperties( PPrecision ) || force ) + format.setAttribute( "precision", m_pStyle->precision() ); + if ( ( hasProperty( PPrefix, true ) || hasNoFallBackProperties( PPrefix ) || force ) + && !m_pStyle->prefix().isEmpty() ) + format.setAttribute( "prefix", m_pStyle->prefix() ); + if ( ( hasProperty( PPostfix, true ) || hasNoFallBackProperties( PPostfix ) || force ) + && !m_pStyle->postfix().isEmpty() ) + format.setAttribute( "postfix", m_pStyle->postfix() ); + + if ( hasProperty( PFloatFormat, true ) || hasNoFallBackProperties( PFloatFormat ) || force ) + format.setAttribute( "float", (int) m_pStyle->floatFormat() ); + if ( hasProperty( PFloatColor, true ) || hasNoFallBackProperties( PFloatColor ) || force ) + format.setAttribute( "floatcolor", (int) m_pStyle->floatColor() ); + if ( hasProperty( PFormatType, true ) || hasNoFallBackProperties( PFormatType ) || force ) + format.setAttribute( "format", (int) m_pStyle->formatType() ); + if ( hasProperty( PCustomFormat, true ) || hasNoFallBackProperties( PCustomFormat ) || force ) + if ( m_pStyle->strFormat().length() > 0 ) + format.setAttribute( "custom", m_pStyle->strFormat() ); + if ( m_pStyle->formatType() == Money_format ) + { + format.setAttribute( "type", (int) m_pStyle->currency().type ); + format.setAttribute( "symbol", m_pStyle->currency().symbol ); + } + if ( hasProperty( PAngle, true ) || hasNoFallBackProperties( PAngle ) || force ) + format.setAttribute( "angle", m_pStyle->rotateAngle() ); + if ( hasProperty( PIndent, true ) || hasNoFallBackProperties( PIndent ) || force ) + format.setAttribute( "indent", m_pStyle->indent() ); + if ( ( hasProperty( PDontPrintText, true ) || hasNoFallBackProperties( PDontPrintText ) || force ) + && m_pStyle->hasProperty( Style::PDontPrintText ) ) + format.setAttribute( "dontprinttext", "yes" ); + if ( ( hasProperty( PNotProtected, true ) || hasNoFallBackProperties( PNotProtected ) + || force ) && m_pStyle->hasProperty( Style::PNotProtected ) ) + format.setAttribute( "noprotection", "yes" ); + if( ( hasProperty( PHideAll, true ) || hasNoFallBackProperties( PHideAll ) + || force ) && m_pStyle->hasProperty( Style::PHideAll ) ) + format.setAttribute( "hideall", "yes" ); + if( ( hasProperty( PHideFormula, true ) || hasNoFallBackProperties( PHideFormula ) + || force ) && m_pStyle->hasProperty( Style::PHideFormula ) ) + format.setAttribute( "hideformula", "yes" ); + if ( hasProperty( PFont, true ) || hasNoFallBackProperties( PFont ) || force ) + format.appendChild( util_createElement( "font", m_pStyle->font(), doc ) ); + if ( ( hasProperty( PTextPen, true ) || hasNoFallBackProperties( PTextPen ) || force ) + && m_pStyle->pen().color().isValid() ) + format.appendChild( util_createElement( "pen", m_pStyle->pen(), doc ) ); + if ( hasProperty( PBackgroundBrush, true ) || hasNoFallBackProperties( PBackgroundBrush ) || force ) + { + format.setAttribute( "brushcolor", m_pStyle->backGroundBrush().color().name() ); + format.setAttribute( "brushstyle", (int) m_pStyle->backGroundBrush().style() ); + } + if ( hasProperty( PLeftBorder, true ) || hasNoFallBackProperties( PLeftBorder ) || force ) + { + TQDomElement left = doc.createElement( "left-border" ); + left.appendChild( util_createElement( "pen", m_pStyle->leftBorderPen(), doc ) ); + format.appendChild( left ); + } + if ( hasProperty( PTopBorder, true ) || hasNoFallBackProperties( PTopBorder ) || force ) + { + TQDomElement top = doc.createElement( "top-border" ); + top.appendChild( util_createElement( "pen", m_pStyle->topBorderPen(), doc ) ); + format.appendChild( top ); + } + if ( hasProperty( PRightBorder, true ) || hasNoFallBackProperties( PRightBorder ) || force ) + { + TQDomElement right = doc.createElement( "right-border" ); + right.appendChild( util_createElement( "pen", m_pStyle->rightBorderPen(), doc ) ); + format.appendChild( right ); + } + if ( hasProperty( PBottomBorder, true ) || hasNoFallBackProperties( PBottomBorder ) || force ) + { + TQDomElement bottom = doc.createElement( "bottom-border" ); + bottom.appendChild( util_createElement( "pen", m_pStyle->bottomBorderPen(), doc ) ); + format.appendChild( bottom ); + } + if ( hasProperty( PFallDiagonal, true ) || hasNoFallBackProperties( PFallDiagonal ) || force ) + { + TQDomElement fallDiagonal = doc.createElement( "fall-diagonal" ); + fallDiagonal.appendChild( util_createElement( "pen", m_pStyle->fallDiagonalPen(), doc ) ); + format.appendChild( fallDiagonal ); + } + if ( hasProperty( PGoUpDiagonal, true ) || hasNoFallBackProperties( PGoUpDiagonal ) || force ) + { + TQDomElement goUpDiagonal = doc.createElement( "up-diagonal" ); + goUpDiagonal.appendChild( util_createElement( "pen", m_pStyle->goUpDiagonalPen(), doc ) ); + format.appendChild( goUpDiagonal ); + } + return format; +} + +TQDomElement Format::save( TQDomDocument & doc, int _col, int _row, bool force, bool copy ) const +{ + TQDomElement format = saveFormat( doc, _col, _row, force, copy ); + return format; +} + +bool Format::loadFormat( const TQDomElement & f, Paste::Mode pm, bool paste ) +{ + if ( f.hasAttribute( "style-name" ) ) + { + Style * s = m_pSheet->doc()->styleManager()->style( f.attribute( "style-name" ) ); + + //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; + if ( s ) + { + setStyle( s ); + + return true; + } + else if ( !paste ) + return false; + } + else + if ( f.hasAttribute( "parent" ) ) + { + CustomStyle* s = static_cast( m_pSheet->doc()->styleManager()->style( f.attribute( "parent" ) ) ); + //kdDebug() << "Loading Style, parent: " << s->name() << ": " << s << endl; + + if ( s ) + { + if ( m_pStyle && m_pStyle->release() ) + delete m_pStyle; + + m_pStyle = new Style(); + m_pStyle->setParent( s ); + } + } + + bool ok; + if ( f.hasAttribute( "align" ) ) + { + Align a = (Align) f.attribute( "align" ).toInt( &ok ); + if ( !ok ) + return false; + // Validation + if ( (unsigned int) a >= 1 || (unsigned int) a <= 4 ) + { + setAlign( a ); + } + } + if ( f.hasAttribute( "alignY" ) ) + { + AlignY a = (AlignY) f.attribute( "alignY" ).toInt( &ok ); + if ( !ok ) + return false; + // Validation + if ( (unsigned int) a >= 1 || (unsigned int) a <= 4 ) + { + setAlignY( a ); + } + } + + if ( f.hasAttribute( "bgcolor" ) ) { + TQColor col( f.attribute( "bgcolor" ) ); + if ( col != TQt::white ) + setBgColor( col ); + } + + if ( f.hasAttribute( "multirow" ) ) + setMultiRow( true ); + + if ( f.hasAttribute( "verticaltext" ) ) + setVerticalText( true ); + + if ( f.hasAttribute( "precision" ) ) + { + int i = f.attribute( "precision" ).toInt( &ok ); + if ( i < -1 ) + { + kdDebug(36001) << "Value out of range Cell::precision=" << i << endl; + return false; + } + // Assignment + setPrecision( i ); + } + + if ( f.hasAttribute( "float" ) ) + { + FloatFormat a = (FloatFormat) f.attribute( "float" ).toInt( &ok ); + if ( !ok ) return false; + if ( (unsigned int) a >= 1 && (unsigned int) a <= 3 ) + { + setFloatFormat( a ); + } + } + + if ( f.hasAttribute( "floatcolor" ) ) + { + FloatColor a = (FloatColor) f.attribute( "floatcolor" ).toInt( &ok ); + if ( !ok ) return false; + if ( (unsigned int) a >= 1 && (unsigned int) a <= 4 ) + { + setFloatColor( a ); + } + } + + if ( f.hasAttribute( "format" ) ) + { + int fo = f.attribute( "format" ).toInt( &ok ); + if ( ! ok ) + return false; + setFormatType( ( FormatType ) fo ); + } + if ( f.hasAttribute( "custom" ) ) + { + setFormatString( f.attribute( "custom" ) ); + } + if ( m_pStyle->formatType() == Money_format ) + { + Currency c; + c.type = -1; + if ( f.hasAttribute( "type" ) ) + { + c.type = f.attribute( "type" ).toInt( &ok ); + if ( !ok ) + c.type = 1; + } + if ( f.hasAttribute( "symbol" ) ) + { + c.symbol = f.attribute( "symbol" ); + } + if ( c.type != -1 ) + setCurrency( c ); + } + if ( f.hasAttribute( "angle" ) ) + { + setAngle( f.attribute( "angle" ).toInt( &ok ) ); + if ( !ok ) + return false; + } + if ( f.hasAttribute( "indent" ) ) + { + setIndent( f.attribute( "indent" ).toDouble( &ok ) ); + if ( !ok ) + return false; + } + if ( f.hasAttribute( "dontprinttext" ) ) + setDontPrintText( true ); + + if ( f.hasAttribute( "noprotection" ) ) + setNotProtected( true ); + + if ( f.hasAttribute( "hideall" ) ) + setHideAll( true ); + + if ( f.hasAttribute( "hideformula" ) ) + setHideFormula( true ); + + if ( f.hasAttribute( "brushstyle" ) ) + { + setBackGroundBrushStyle( (Qt::BrushStyle) f.attribute( "brushstyle" ).toInt( &ok ) ); + if ( !ok ) + return false; + } + + if ( f.hasAttribute( "brushcolor" ) ) + setBackGroundBrushColor( TQColor( f.attribute( "brushcolor" ) ) ); + + TQDomElement pen( f.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setTextPen( util_toPen( pen ) ); + + TQDomElement font( f.namedItem( "font" ).toElement() ); + if ( !font.isNull() ) + setTextFont( util_toFont( font ) ); + + if ( ( pm != Paste::NoBorder ) && ( pm != Paste::Text ) && ( pm != Paste::Comment ) ) + { + TQDomElement left( f.namedItem( "left-border" ).toElement() ); + if ( !left.isNull() ) + { + TQDomElement pen( left.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setLeftBorderPen( util_toPen( pen ) ); + } + + TQDomElement top( f.namedItem( "top-border" ).toElement() ); + if ( !top.isNull() ) + { + TQDomElement pen( top.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setTopBorderPen( util_toPen( pen ) ); + } + + TQDomElement right( f.namedItem( "right-border" ).toElement() ); + if ( !right.isNull() ) + { + TQDomElement pen( right.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setRightBorderPen( util_toPen( pen ) ); + } + + TQDomElement bottom( f.namedItem( "bottom-border" ).toElement() ); + if ( !bottom.isNull() ) + { + TQDomElement pen( bottom.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setBottomBorderPen( util_toPen( pen ) ); + } + + TQDomElement fallDiagonal( f.namedItem( "fall-diagonal" ).toElement() ); + if ( !fallDiagonal.isNull() ) + { + TQDomElement pen( fallDiagonal.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setFallDiagonalPen( util_toPen( pen ) ); + } + + TQDomElement goUpDiagonal( f.namedItem( "up-diagonal" ).toElement() ); + if ( !goUpDiagonal.isNull() ) + { + TQDomElement pen( goUpDiagonal.namedItem( "pen" ).toElement() ); + if ( !pen.isNull() ) + setGoUpDiagonalPen( util_toPen( pen ) ); + } + } + + if ( f.hasAttribute( "prefix" ) ) + setPrefix( f.attribute( "prefix" ) ); + if ( f.hasAttribute( "postfix" ) ) + setPostfix( f.attribute( "postfix" ) ); + + return true; +} + +bool Format::load( const TQDomElement & f, Paste::Mode pm, bool paste ) +{ + if ( !loadFormat( f, pm, paste ) ) + return false; + return true; +} + + +#if 0 +bool Format::loadFontOasisStyle( KoStyleStack & font ) +{ + font.setTypeProperties( "text" ); // load all style attributes from "style:text-properties" + //TODO remember to change type properties + + if ( font.hasAttributeNS( KoXmlNS::fo, "font-family" ) ) + setTextFontFamily( font.attributeNS( KoXmlNS::fo, "font-family" ) ); + + if ( font.hasAttributeNS( KoXmlNS::fo, "color" ) ) + setTextColor( TQColor( font.attributeNS( KoXmlNS::fo, "color" ) ) ); + + if ( font.hasAttributeNS( KoXmlNS::fo, "font-size" ) ) + setTextFontSize( (int) KoUnit::parseValue( font.attributeNS( KoXmlNS::fo, "font-size" ), 10.0 ) ); + + if ( font.hasAttributeNS( KoXmlNS::fo, "font-style" ) && ( font.attributeNS( KoXmlNS::fo,"font-style" )== "italic" )) + { + kdDebug(30518) << "italic" << endl; + setTextFontItalic( true ); // only thing we support + } + if ( font.hasAttributeNS( KoXmlNS::fo, "font-weight" ) + && ( font.attributeNS( KoXmlNS::fo, "font-weight" ) == "bold") ) + setTextFontBold( true ); // only thing we support + + //TODO add "style:text-underline-width" "style:text-underline-color" + if ( ( font.hasAttributeNS( KoXmlNS::fo, "text-underline-style" ) && font.attributeNS( KoXmlNS::fo, "text-underline-style" ) != "none" ) + || ( font.hasAttributeNS( KoXmlNS::style, "text-underline-style" ) && font.attributeNS( KoXmlNS::style, "text-underline-style" )!="none" ) ) + setTextFontUnderline( true ); // only thing we support + + if ( font.hasAttributeNS( KoXmlNS::style, "text-line-through-style" ) + && font.attributeNS( KoXmlNS::style, "text-line-through-style" ) != "none" + /*&& ( font.attributeNS( KoXmlNS::style, "text-crossing-out" ) == "single-line" )*/) + setTextFontStrike( true ); // only thing we support + + if ( font.hasAttributeNS( KoXmlNS::style, "font-pitch" ) ) + { + // TODO: possible values: fixed, variable + } + + // TODO: for the future when we will use kotext + // text-underline-color + return true; +} + +void Format::loadOasisStyle( /*const TQDomElement& style,*/ KoOasisLoadingContext& context ) +{ + TQString str; // multi purpose string + KoOasisStyles& oasisStyles = context.oasisStyles(); + +/* context.styleStack().save(); + context.addStyles( &style );*/ +/* KoStyleStack styleStack; + styleStack.push( style ); + styleStack.setTypeProperties( "table-cell" );*/ + + KoStyleStack& styleStack = context.styleStack(); + loadOasisStyleProperties( styleStack, context.oasisStyles() ); +/* loadOasisStyleProperties( context.styleStack(), context.oasisStyles() ); + context.styleStack().restore();*/ + + kdDebug() << "*** Loading style attributes *****" << endl; + + if ( styleStack.hasAttributeNS( KoXmlNS::style, "data-style-name" ) ) + { + str = styleStack.attributeNS( KoXmlNS::style, "data-style-name" ); + kdDebug() << " style:data-style-name: " << str << endl << endl; + + if ( !str.isEmpty() ) + { + TQString tmp = oasisStyles.dataFormats()[str].prefix; + if ( !tmp.isEmpty() ) + { + setPrefix( tmp ); + } + tmp = oasisStyles.dataFormats()[str].suffix; + if ( !tmp.isEmpty() ) + { + setPostfix( tmp ); + } + tmp = oasisStyles.dataFormats()[str].formatStr; + if ( !tmp.isEmpty() ) + { + setFormatType( Style::formatType( tmp ) ); + } + } + } + + if ( styleStack.hasAttributeNS( KoXmlNS::style, "decimal-places" ) ) + { + bool ok = false; + int p = styleStack.attributeNS( KoXmlNS::style, "decimal-places" ).toInt( &ok ); + kdDebug() << " style:decimal-places: " << p << endl; + if (ok ) + setPrecision( p ); + } +} + +bool Format::loadOasisStyleProperties( KoStyleStack & styleStack, const KoOasisStyles& oasisStyles ) +{ + kdDebug() << "*** Loading style properties *****" << endl; +#if 0 + if ( f.hasAttribute( "style-name" ) ) + { + Style * s = m_pSheet->doc()->styleManager()->style( f.attribute( "style-name" ) ); + + //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; + if ( s ) + { + setStyle( s ); + + return true; + } + else if ( !paste ) + return false; + } + else + if ( f.hasAttribute( "parent" ) ) + { + CustomStyle * s = (CustomStyle *) m_pSheet->doc()->styleManager()->style( f.attribute( "parent" ) ); + //kdDebug() << "Loading Style, parent: " << s->name() << ": " << s << endl; + + if ( s ) + { + if ( m_pStyle && m_pStyle->release() ) + delete m_pStyle; + + m_pStyle = new Style(); + m_pStyle->setParent( s ); + } + } +#endif + if ( styleStack.hasAttributeNS( KoXmlNS::style, "parent-style-name" ) ) + { + Style * s = m_pSheet->doc()->styleManager()->style( styleStack.attributeNS( KoXmlNS::style, "parent-style-name" ) ); + + //kdDebug() << "Using style: " << f.attribute( "style-name" ) << ", s: " << s << endl; + if ( s ) + { + setStyle( s ); + } + } + else + { + setStyle( m_pSheet->doc()->styleManager()->defaultStyle() ); + } + + + if ( styleStack.hasAttributeNS( KoXmlNS::style, "font-name" ) ) + { + const TQDomElement * font = oasisStyles.findStyle( styleStack.attributeNS( KoXmlNS::style, "font-name" ) ); + if ( font ) + { + styleStack.save(); + styleStack.push( *font ); + loadFontOasisStyle( styleStack ); // general font style + styleStack.restore(); + } + } + + kdDebug() << " [text properties]" << endl; + //Text properties + loadFontOasisStyle( styleStack ); // specific font style + //End Text properties + + kdDebug() << " [paragraph properties]" << endl; + //Paragraph properties + styleStack.setTypeProperties( "paragraph" ); // load all style attributes from "style:paragraph-properties" + if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-left" ) ) + { + kdDebug()<<" margin-left:"< style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/> + + if ( styleStack.hasAttributeNS( KoXmlNS::style, "rotation-angle" ) ) + { + bool ok = false; + int a = styleStack.attributeNS( KoXmlNS::style, "rotation-angle" ).toInt( &ok ); + if ( ok && ( a != 0 )) + setAngle( -a ); + } + if ( styleStack.hasAttributeNS( KoXmlNS::style, "direction" ) ) + { + TQString dir = styleStack.attributeNS( KoXmlNS::fo, "direction" ); + if ( dir == "ttb" ) + setVerticalText( true ); + else if ( dir == "ltr" ) + setVerticalText( false ); + } + + kdDebug()<<"property.hasAttribute( fo:background-color ) :"<setStrFormat( format ); + formatChanged(); +} + +void Format::setAlign( Align _align ) +{ + if ( _align == Format::Undefined ) + { + clearProperty( PAlign ); + setNoFallBackProperties(PAlign ); + } + else + { + setProperty( PAlign ); + clearNoFallBackProperties(PAlign ); + } + + m_pStyle = m_pStyle->setAlignX( _align ); + formatChanged(); +} + +void Format::setAlignY( AlignY _alignY) +{ + //kdDebug() << "Format: AlignY: " << _alignY << endl; + if ( _alignY == Format::Middle ) + { + //kdDebug() << "Middle" << endl; + clearProperty( PAlignY ); + setNoFallBackProperties(PAlignY ); + } + else + { + //kdDebug() << "Not middle: " << _alignY << endl; + setProperty( PAlignY ); + clearNoFallBackProperties( PAlignY ); + } + + m_pStyle = m_pStyle->setAlignY( _alignY ); + formatChanged(); +} + +void Format::setPrefix( const TQString& _prefix ) +{ + if ( _prefix.isEmpty() ) + { + clearProperty( PPrefix ); + setNoFallBackProperties( PPrefix ); + } + else + { + setProperty( PPrefix ); + clearNoFallBackProperties( PPrefix ); + } + + m_pStyle = m_pStyle->setPrefix( _prefix ); + formatChanged(); +} + +void Format::setPostfix( const TQString& _postfix ) +{ + if ( _postfix.isEmpty() ) + { + clearProperty( PPostfix ); + setNoFallBackProperties( PPostfix ); + } + else + { + setProperty( PPostfix ); + clearNoFallBackProperties( PPostfix ); + } + + m_pStyle = m_pStyle->setPostfix( _postfix ); + formatChanged(); +} + +void Format::setPrecision( int _p ) +{ + if ( _p == -1 ) + { + clearProperty( PPrecision ); + setNoFallBackProperties( PPrecision ); + } + else + { + setProperty( PPrecision ); + clearNoFallBackProperties( PPrecision ); + } + + m_pStyle = m_pStyle->setPrecision( _p ); + formatChanged(); +} + +void Format::setLeftBorderPen( const TQPen & _p ) +{ + if ( _p.style() == TQt::NoPen ) + { + clearProperty( PLeftBorder ); + setNoFallBackProperties( PLeftBorder ); + } + else + { + setProperty( PLeftBorder ); + clearNoFallBackProperties( PLeftBorder ); + } + + m_pStyle = m_pStyle->setLeftBorderPen( _p ); + formatChanged(); +} + +void Format::setLeftBorderStyle( Qt::PenStyle s ) +{ + TQPen p( m_pStyle->leftBorderPen() ); + p.setStyle( s ); + setLeftBorderPen( p ); +} + +void Format::setLeftBorderColor( const TQColor & c ) +{ + TQPen p( m_pStyle->leftBorderPen() ); + p.setColor( c ); + setLeftBorderPen( p ); +} + +void Format::setLeftBorderWidth( int _w ) +{ + TQPen p( m_pStyle->leftBorderPen() ); + p.setWidth( _w ); + setLeftBorderPen( p ); +} + +void Format::setTopBorderPen( const TQPen & _p ) +{ + if ( _p.style() == TQt::NoPen ) + { + clearProperty( PTopBorder ); + setNoFallBackProperties( PTopBorder ); + } + else + { + setProperty( PTopBorder ); + clearNoFallBackProperties( PTopBorder ); + } + + m_pStyle = m_pStyle->setTopBorderPen( _p ); + formatChanged(); +} + +void Format::setTopBorderStyle( Qt::PenStyle s ) +{ + TQPen p( m_pStyle->topBorderPen() ); + p.setStyle( s ); + setTopBorderPen( p ); +} + +void Format::setTopBorderColor( const TQColor& c ) +{ + TQPen p( m_pStyle->topBorderPen() ); + p.setColor( c ); + setTopBorderPen( p ); +} + +void Format::setTopBorderWidth( int _w ) +{ + TQPen p( m_pStyle->topBorderPen() ); + p.setWidth( _w ); + setTopBorderPen( p ); +} + +void Format::setRightBorderPen( const TQPen& p ) +{ + if ( p.style() == TQt::NoPen ) + { + clearProperty( PRightBorder ); + setNoFallBackProperties( PRightBorder ); + } + else + { + setProperty( PRightBorder ); + clearNoFallBackProperties( PRightBorder ); + } + + m_pStyle = m_pStyle->setRightBorderPen( p ); + formatChanged(); +} + +void Format::setRightBorderStyle( Qt::PenStyle _s ) +{ + TQPen p( m_pStyle->rightBorderPen() ); + p.setStyle( _s ); + setRightBorderPen( p ); +} + +void Format::setRightBorderColor( const TQColor & _c ) +{ + TQPen p( m_pStyle->rightBorderPen() ); + p.setColor( _c ); + setRightBorderPen( p ); +} + +void Format::setRightBorderWidth( int _w ) +{ + TQPen p( m_pStyle->rightBorderPen() ); + p.setWidth( _w ); + setRightBorderPen( p ); +} + +void Format::setBottomBorderPen( const TQPen& p ) +{ + if ( p.style() == TQt::NoPen ) + { + clearProperty( PBottomBorder ); + setNoFallBackProperties( PBottomBorder ); + } + else + { + setProperty( PBottomBorder ); + clearNoFallBackProperties( PBottomBorder ); + } + + m_pStyle = m_pStyle->setBottomBorderPen( p ); + formatChanged(); +} + +void Format::setBottomBorderStyle( Qt::PenStyle _s ) +{ + TQPen p( m_pStyle->bottomBorderPen() ); + p.setStyle( _s ); + setBottomBorderPen( p ); +} + +void Format::setBottomBorderColor( const TQColor & _c ) +{ + TQPen p( m_pStyle->bottomBorderPen() ); + p.setColor( _c ); + setBottomBorderPen( p ); +} + +void Format::setBottomBorderWidth( int _w ) +{ + TQPen p( m_pStyle->bottomBorderPen() ); + p.setWidth( _w ); + setBottomBorderPen( p ); +} + +void Format::setFallDiagonalPen( const TQPen & _p ) +{ + if ( _p.style() == TQt::NoPen ) + { + clearProperty( PFallDiagonal ); + setNoFallBackProperties( PFallDiagonal ); + } + else + { + setProperty( PFallDiagonal ); + clearNoFallBackProperties( PFallDiagonal ); + } + + m_pStyle = m_pStyle->setFallDiagonalPen( _p ); + formatChanged(); +} + +void Format::setFallDiagonalStyle( Qt::PenStyle s ) +{ + TQPen p( m_pStyle->fallDiagonalPen() ); + p.setStyle( s ); + setFallDiagonalPen( p ); +} + +void Format::setFallDiagonalColor( const TQColor& c ) +{ + TQPen p( m_pStyle->fallDiagonalPen() ); + p.setColor( c ); + setFallDiagonalPen( p ); +} + +void Format::setFallDiagonalWidth( int _w ) +{ + TQPen p( m_pStyle->fallDiagonalPen() ); + p.setWidth( _w ); + setFallDiagonalPen( p ); +} + +void Format::setGoUpDiagonalPen( const TQPen & _p ) +{ + if ( _p.style() == TQt::NoPen ) + { + clearProperty( PGoUpDiagonal ); + setNoFallBackProperties( PGoUpDiagonal ); + } + else + { + setProperty( PGoUpDiagonal ); + clearNoFallBackProperties( PGoUpDiagonal ); + } + + m_pStyle = m_pStyle->setGoUpDiagonalPen( _p ); + formatChanged(); +} + +void Format::setGoUpDiagonalStyle( Qt::PenStyle s ) +{ + TQPen p( m_pStyle->goUpDiagonalPen() ); + p.setStyle( s ); + setGoUpDiagonalPen( p ); +} + +void Format::setGoUpDiagonalColor( const TQColor& c ) +{ + TQPen p( m_pStyle->goUpDiagonalPen() ); + p.setColor( c ); + setGoUpDiagonalPen( p ); +} + +void Format::setGoUpDiagonalWidth( int _w ) +{ + TQPen p( m_pStyle->goUpDiagonalPen() ); + p.setWidth( _w ); + setGoUpDiagonalPen( p ); +} + +void Format::setBackGroundBrush( const TQBrush & _p) +{ + if ( _p.style() == TQt::NoBrush ) + { + clearProperty( PBackgroundBrush ); + setNoFallBackProperties( PBackgroundBrush ); + } + else + { + setProperty( PBackgroundBrush ); + clearNoFallBackProperties( PBackgroundBrush ); + } + + m_pStyle = m_pStyle->setBackGroundBrush( _p ); + formatChanged(); +} + +void Format::setBackGroundBrushStyle( Qt::BrushStyle s ) +{ + TQBrush b( m_pStyle->backGroundBrush() ); + b.setStyle( s ); + setBackGroundBrush( b ); +} + +void Format::setBackGroundBrushColor( const TQColor & c ) +{ + TQBrush b( m_pStyle->backGroundBrush() ); + b.setColor( c ); + setBackGroundBrush( b ); +} + +void Format::setTextFont( const TQFont & _f ) +{ + if( m_pStyle->parent() && _f == m_pStyle->parent()->font()) + { + clearProperty( PFont ); + setNoFallBackProperties( PFont ); + } + else if( !m_pStyle->parent() && _f == KoGlobal::defaultFont() ) + { + clearProperty( PFont ); + setNoFallBackProperties( PFont ); + } + else + { + setProperty( PFont ); + clearNoFallBackProperties( PFont ); + } + + + m_pStyle = m_pStyle->setFont( _f ); + formatChanged(); +} + +void Format::setTextFontSize( int _s ) +{ + TQFont f( m_pStyle->font() ); + f.setPointSize( _s ); + setTextFont( f ); +} + +void Format::setTextFontFamily( const TQString & _f ) +{ + TQFont f( m_pStyle->font() ); + f.setFamily( _f ); + setTextFont( f ); +} + +void Format::setTextFontBold( bool _b ) +{ + TQFont f( m_pStyle->font() ); + f.setBold( _b ); + setTextFont( f ); +} + +void Format::setTextFontItalic( bool _i ) +{ + TQFont f( m_pStyle->font() ); + f.setItalic( _i ); + setTextFont( f ); +} + +void Format::setTextFontUnderline( bool _i ) +{ + TQFont f( m_pStyle->font() ); + f.setUnderline( _i ); + setTextFont( f ); +} + +void Format::setTextFontStrike( bool _i ) +{ + TQFont f( m_pStyle->font() ); + f.setStrikeOut( _i ); + setTextFont( f ); +} + +void Format::setTextPen( const TQPen & _p ) +{ + // An invalid color means "the default text color, from the color scheme" + // It doesn't mean "no setting here, look at fallback" + // Maybe we should look at the fallback color, in fact. + /*if(!_p.color().isValid()) + { + clearProperty( PTextPen ); + setNoFallBackProperties( PTextPen ); + } + else*/ + { + setProperty( PTextPen ); + clearNoFallBackProperties( PTextPen ); + } + + //setProperty( PTextPen ); + m_pStyle = m_pStyle->setPen( _p ); + //kdDebug(36001) << "setTextPen: this=" << this << " pen=" << m_textPen.color().name() << " valid:" << m_textPen.color().isValid() << endl; + formatChanged(); +} + +void Format::setTextColor( const TQColor & _c ) +{ + TQPen p( m_pStyle->pen() ); + p.setColor( _c ); + setTextPen( p ); +} + +void Format::setBgColor( const TQColor & _c ) +{ + if ( !_c.isValid() ) + { + clearProperty( PBackgroundColor ); + setNoFallBackProperties( PBackgroundColor ); + } + else + { + setProperty( PBackgroundColor ); + clearNoFallBackProperties( PBackgroundColor ); + } + + m_pStyle = m_pStyle->setBgColor( _c ); + formatChanged(); +} + +void Format::setFloatFormat( FloatFormat _f ) +{ + setProperty( PFloatFormat ); + + m_pStyle = m_pStyle->setFloatFormat( _f ); + formatChanged(); +} + +void Format::setFloatColor( FloatColor _c ) +{ + setProperty( PFloatColor ); + + m_pStyle = m_pStyle->setFloatColor( _c ); + formatChanged(); +} + +void Format::setMultiRow( bool _b ) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PMultiRow ); + clearProperty( PMultiRow ); + setNoFallBackProperties( PMultiRow ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PMultiRow ); + setProperty( PMultiRow ); + clearNoFallBackProperties( PMultiRow ); + } + formatChanged(); +} + +void Format::setVerticalText( bool _b ) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PVerticalText ); + setNoFallBackProperties( PVerticalText); + clearFlag( Flag_VerticalText ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PVerticalText ); + clearNoFallBackProperties( PVerticalText); + setFlag( Flag_VerticalText ); + } + formatChanged(); +} + +void Format::setFormatType( FormatType _format ) +{ + if ( _format == Number_format ) + { + clearProperty( PFormatType ); + setNoFallBackProperties( PFormatType); + } + else + { + setProperty( PFormatType ); + clearNoFallBackProperties( PFormatType); + } + + m_pStyle = m_pStyle->setFormatType( _format ); + formatChanged(); +} + +void Format::setAngle( int _angle ) +{ + if ( _angle == 0 ) + { + clearProperty( PAngle ); + setNoFallBackProperties( PAngle); + } + else + { + setProperty( PAngle ); + clearNoFallBackProperties( PAngle); + } + + m_pStyle = m_pStyle->setRotateAngle( _angle ); + formatChanged(); +} + +void Format::setIndent( double _indent ) +{ + if ( _indent == 0.0 ) + { + clearProperty( PIndent ); + setNoFallBackProperties( PIndent ); + } + else + { + setProperty( PIndent ); + clearNoFallBackProperties( PIndent ); + } + + m_pStyle = m_pStyle->setIndent( _indent ); + formatChanged(); +} + +void Format::setComment( const TQString & _comment ) +{ + if ( _comment.isEmpty() ) + { + clearProperty( PComment ); + setNoFallBackProperties( PComment ); + } + else + { + setProperty( PComment ); + clearNoFallBackProperties( PComment ); + } + + // not part of the style + delete m_strComment; + if ( !_comment.isEmpty() ) + m_strComment = new TQString( _comment ); + else + m_strComment = 0; + formatChanged(); +} + +void Format::setNotProtected( bool _b) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PNotProtected ); + setNoFallBackProperties( PNotProtected ); + clearFlag( Flag_NotProtected ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PNotProtected ); + clearNoFallBackProperties( PNotProtected ); + setFlag( Flag_NotProtected ); + } + formatChanged(); +} + +void Format::setDontPrintText( bool _b ) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PDontPrintText ); + setNoFallBackProperties(PDontPrintText); + clearFlag( Flag_DontPrintText ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PDontPrintText ); + clearNoFallBackProperties( PDontPrintText); + setFlag( Flag_DontPrintText ); + } + formatChanged(); +} + +void Format::setHideAll( bool _b ) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PHideAll ); + setNoFallBackProperties(PHideAll); + clearFlag( Flag_HideAll ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PHideAll ); + clearNoFallBackProperties( PHideAll); + setFlag( Flag_HideAll ); + } + formatChanged(); +} + +void Format::setHideFormula( bool _b ) +{ + if ( _b == false ) + { + m_pStyle = m_pStyle->clearProperty( Style::PHideFormula ); + setNoFallBackProperties( PHideFormula ); + clearFlag( Flag_HideFormula ); + } + else + { + m_pStyle = m_pStyle->setProperty( Style::PHideFormula ); + clearNoFallBackProperties( PHideFormula ); + setFlag( Flag_HideFormula ); + } + formatChanged(); +} + +void Format::setCurrency( Currency const & c ) +{ + m_pStyle = m_pStyle->setCurrency( c ); +} + +void Format::setCurrency( int type, TQString const & symbol ) +{ + Currency c; + + c.symbol = symbol.simplifyWhiteSpace(); + c.type = type; + + if (c.symbol.length() == 0) + { + c.type = 0; + c.symbol = sheet()->doc()->locale()->currencySymbol(); + } + + m_pStyle = m_pStyle->setCurrency( c ); +} + +///////////// +// +// Get methods +// +///////////// + +TQString const & Format::getFormatString( int col, int row ) const +{ + if ( !hasProperty( PCustomFormat, false ) && !hasNoFallBackProperties( PCustomFormat )) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->getFormatString( col, row ); + } + return m_pStyle->strFormat(); +} + +TQString Format::prefix( int col, int row ) const +{ + if ( !hasProperty( PPrefix, false ) && !hasNoFallBackProperties(PPrefix )) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->prefix( col, row ); + } + return m_pStyle->prefix(); +} + +TQString Format::postfix( int col, int row ) const +{ + if ( !hasProperty( PPostfix, false ) && !hasNoFallBackProperties(PPostfix )) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->postfix( col, row ); + } + return m_pStyle->postfix(); +} + +const TQPen& Format::fallDiagonalPen( int col, int row ) const +{ + if ( !hasProperty( PFallDiagonal, false ) && !hasNoFallBackProperties(PFallDiagonal )) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->fallDiagonalPen( col, row ); + } + return m_pStyle->fallDiagonalPen(); +} + +int Format::fallDiagonalWidth( int col, int row ) const +{ + return fallDiagonalPen( col, row ).width(); +} + +Qt::PenStyle Format::fallDiagonalStyle( int col, int row ) const +{ + return fallDiagonalPen( col, row ).style(); +} + +const TQColor & Format::fallDiagonalColor( int col, int row ) const +{ + return fallDiagonalPen( col, row ).color(); +} + +const TQPen & Format::goUpDiagonalPen( int col, int row ) const +{ + if ( !hasProperty( PGoUpDiagonal, false ) && !hasNoFallBackProperties( PGoUpDiagonal ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->goUpDiagonalPen( col, row ); + } + return m_pStyle->goUpDiagonalPen(); +} + +int Format::goUpDiagonalWidth( int col, int row ) const +{ + return goUpDiagonalPen( col, row ).width(); +} + +Qt::PenStyle Format::goUpDiagonalStyle( int col, int row ) const +{ + return goUpDiagonalPen( col, row ).style(); +} + +const TQColor& Format::goUpDiagonalColor( int col, int row ) const +{ + return goUpDiagonalPen( col, row ).color(); +} + +uint Format::bottomBorderValue( int col, int row ) const +{ + if ( !hasProperty( PBottomBorder, false ) && !hasNoFallBackProperties( PBottomBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->bottomBorderValue( col, row ); + + return 0; + } + + return m_pStyle->bottomPenValue(); +} + +uint Format::rightBorderValue( int col, int row ) const +{ + if ( !hasProperty( PRightBorder, false ) && !hasNoFallBackProperties( PRightBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->rightBorderValue( col, row ); + + return 0; + } + + return m_pStyle->rightPenValue(); +} + +uint Format::leftBorderValue( int col, int row ) const +{ + if ( !hasProperty( PLeftBorder, false ) && !hasNoFallBackProperties( PLeftBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->leftBorderValue( col, row ); + + return 0; + } + + return m_pStyle->leftPenValue(); +} + +uint Format::topBorderValue( int col, int row ) const +{ + if ( !hasProperty( PTopBorder, false ) && !hasNoFallBackProperties( PTopBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->topBorderValue( col, row ); + + return 0; + } + + return m_pStyle->topPenValue(); +} + +const TQPen& Format::leftBorderPen( int col, int row ) const +{ + if ( !hasProperty( PLeftBorder, false ) && !hasNoFallBackProperties( PLeftBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->leftBorderPen( col, row ); + return sheet()->emptyPen(); + } + + return m_pStyle->leftBorderPen(); +} + +Qt::PenStyle Format::leftBorderStyle( int col, int row ) const +{ + return leftBorderPen( col, row ).style(); +} + +const TQColor& Format::leftBorderColor( int col, int row ) const +{ + return leftBorderPen( col, row ).color(); +} + +int Format::leftBorderWidth( int col, int row ) const +{ + return leftBorderPen( col, row ).width(); +} + +const TQPen& Format::topBorderPen( int col, int row ) const +{ + if ( !hasProperty( PTopBorder, false ) && !hasNoFallBackProperties( PTopBorder ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->topBorderPen( col, row ); + return sheet()->emptyPen(); + } + + return m_pStyle->topBorderPen(); +} + +const TQColor& Format::topBorderColor( int col, int row ) const +{ + return topBorderPen( col, row ).color(); +} + +Qt::PenStyle Format::topBorderStyle( int col, int row ) const +{ + return topBorderPen( col, row ).style(); +} + +int Format::topBorderWidth( int col, int row ) const +{ + return topBorderPen( col, row ).width(); +} + +const TQPen& Format::rightBorderPen( int col, int row ) const +{ + if ( !hasProperty( PRightBorder, false ) && !hasNoFallBackProperties( PRightBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->rightBorderPen( col, row ); + return sheet()->emptyPen(); + } + + return m_pStyle->rightBorderPen(); +} + +int Format::rightBorderWidth( int col, int row ) const +{ + return rightBorderPen( col, row ).width(); +} + +Qt::PenStyle Format::rightBorderStyle( int col, int row ) const +{ + return rightBorderPen( col, row ).style(); +} + +const TQColor& Format::rightBorderColor( int col, int row ) const +{ + return rightBorderPen( col, row ).color(); +} + +const TQPen& Format::bottomBorderPen( int col, int row ) const +{ + if ( !hasProperty( PBottomBorder, false )&& !hasNoFallBackProperties( PBottomBorder ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->bottomBorderPen( col, row ); + return sheet()->emptyPen(); + } + + return m_pStyle->bottomBorderPen(); +} + +int Format::bottomBorderWidth( int col, int row ) const +{ + return bottomBorderPen( col, row ).width(); +} + +Qt::PenStyle Format::bottomBorderStyle( int col, int row ) const +{ + return bottomBorderPen( col, row ).style(); +} + +const TQColor& Format::bottomBorderColor( int col, int row ) const +{ + return bottomBorderPen( col, row ).color(); +} + +const TQBrush& Format::backGroundBrush( int col, int row ) const +{ + if ( !hasProperty( PBackgroundBrush, false ) && !hasNoFallBackProperties(PBackgroundBrush )) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->backGroundBrush( col, row ); + } + return m_pStyle->backGroundBrush(); +} + +Qt::BrushStyle Format::backGroundBrushStyle( int col, int row ) const +{ + return backGroundBrush( col, row ).style(); +} + +const TQColor& Format::backGroundBrushColor( int col, int row ) const +{ + return backGroundBrush( col, row ).color(); +} + +int Format::precision( int col, int row ) const +{ + if ( !hasProperty( PPrecision, false )&& !hasNoFallBackProperties( PPrecision ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->precision( col, row ); + } + return m_pStyle->precision(); +} + +Format::FloatFormat Format::floatFormat( int col, int row ) const +{ + if ( !hasProperty( PFloatFormat, false ) && !hasNoFallBackProperties( PFloatFormat ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->floatFormat( col, row ); + } + return m_pStyle->floatFormat(); +} + +Format::FloatColor Format::floatColor( int col, int row ) const +{ + if ( !hasProperty( PFloatColor, false ) && !hasNoFallBackProperties( PFloatColor ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->floatColor( col, row ); + } + return m_pStyle->floatColor(); +} + +const TQColor& Format::bgColor( int col, int row ) const +{ + if ( !hasProperty( PBackgroundColor, false ) && !hasNoFallBackProperties( PBackgroundColor ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->bgColor( col, row ); + } + + return m_pStyle->bgColor(); +} + +const TQPen& Format::textPen( int col, int row ) const +{ + if ( !hasProperty( PTextPen, false ) && !hasNoFallBackProperties( PTextPen ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textPen( col, row ); + } + return m_pStyle->pen(); +} + +const TQColor& Format::textColor( int col, int row ) const +{ + return textPen( col, row ).color(); +} + +const TQFont Format::textFont( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFont( col, row ); + } + + return m_pStyle->font(); +} + +int Format::textFontSize( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontSize( col, row ); + } + + return m_pStyle->fontSize(); +} + +TQString const & Format::textFontFamily( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontFamily( col, row ); + } + + return m_pStyle->fontFamily(); +} + +bool Format::textFontBold( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontBold( col, row ); + } + + return ( m_pStyle->fontFlags() & Style::FBold ); +} + +bool Format::textFontItalic( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontItalic( col, row ); + } + + return ( m_pStyle->fontFlags() & Style::FItalic ); +} + +bool Format::textFontUnderline( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontUnderline( col, row ); + } + + return ( m_pStyle->fontFlags() & Style::FUnderline ); +} + +bool Format::textFontStrike( int col, int row ) const +{ + if ( !hasProperty( PFont, false ) && !hasNoFallBackProperties( PFont ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->textFontStrike( col, row ); + } + + return ( m_pStyle->fontFlags() & Style::FStrike ); +} + +Format::Align Format::align( int col, int row ) const +{ + if ( !hasProperty( PAlign, false ) && !hasNoFallBackProperties( PAlign ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->align( col, row ); + } + + return m_pStyle->alignX(); +} + +Format::AlignY Format::alignY( int col, int row ) const +{ + if ( !hasProperty( PAlignY, false )&& !hasNoFallBackProperties( PAlignY ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->alignY( col, row ); + } + + return m_pStyle->alignY(); +} + +bool Format::multiRow( int col, int row ) const +{ + if ( !hasProperty( PMultiRow, false ) && !hasNoFallBackProperties( PMultiRow ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->multiRow( col, row ); + } + + return m_pStyle->hasProperty( Style::PMultiRow ); +} + +bool Format::verticalText( int col, int row ) const +{ + if ( !hasProperty( PVerticalText, false )&& !hasNoFallBackProperties( PVerticalText ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->verticalText( col, row ); + } + + return m_pStyle->hasProperty( Style::PVerticalText ); +} + +FormatType Format::getFormatType( int col, int row ) const +{ + if ( !hasProperty( PFormatType, false ) && !hasNoFallBackProperties( PFormatType ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->getFormatType( col, row ); + } + + return m_pStyle->formatType(); +} + +int Format::getAngle( int col, int row ) const +{ + if ( !hasProperty( PAngle, false ) && !hasNoFallBackProperties( PAngle ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->getAngle( col, row ); + } + + return m_pStyle->rotateAngle(); +} + +TQString Format::comment( int col, int row ) const +{ + if ( !hasProperty( PComment, false ) && !hasNoFallBackProperties( PComment )) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->comment( col, row ); + } + + if ( !m_strComment ) + return TQString(); + + // not part of the style + return *m_strComment; +} + +TQString * Format::commentP( int col, int row ) const +{ + if ( !hasProperty( PComment, false ) && !hasNoFallBackProperties( PComment )) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->commentP( col, row ); + } + + return m_strComment; +} + +double Format::getIndent( int col, int row ) const +{ + if ( !hasProperty( PIndent, false ) && !hasNoFallBackProperties( PIndent ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->getIndent( col, row ); + } + + return m_pStyle->indent(); +} + +bool Format::getDontprintText( int col, int row ) const +{ + if ( !hasProperty( PDontPrintText, false )&& !hasNoFallBackProperties( PDontPrintText ) ) + { + const Format* l = fallbackFormat( col, row ); + if ( l ) + return l->getDontprintText( col, row ); + } + + return m_pStyle->hasProperty( Style::PDontPrintText ); +} + +bool Format::isProtected( int col, int row ) const +{ + return ( m_pSheet->isProtected() && !notProtected( col, row ) ); +} + + +bool Format::notProtected( int col, int row) const +{ + if ( !hasProperty( PNotProtected, false )&& !hasNoFallBackProperties( PNotProtected ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->notProtected( col, row ); + } + + return m_pStyle->hasProperty( Style::PNotProtected ); +} + +bool Format::isHideAll( int col, int row) const +{ + if ( !hasProperty( PHideAll, false )&& !hasNoFallBackProperties( PHideAll ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->isHideAll( col, row ); + } + + return m_pStyle->hasProperty( Style::PHideAll ); +} + +bool Format::isHideFormula( int col, int row) const +{ + if ( !hasProperty( PHideFormula, false )&& !hasNoFallBackProperties( PHideFormula ) ) + { + const Format * l = fallbackFormat( col, row ); + if ( l ) + return l->isHideFormula( col, row ); + } + + return m_pStyle->hasProperty( Style::PHideFormula ); +} + +bool Format::currencyInfo( Currency & currency) const +{ + // TODO: fallback ? + if ( m_pStyle->formatType() != Money_format ) + return false; + + currency.symbol = m_pStyle->currency().symbol; + currency.type = m_pStyle->currency().type; + + return true; +} + +TQString Format::getCurrencySymbol() const +{ + // TODO: fallback ? + return m_pStyle->currency().symbol; +} + +TQFont Format::font() const +{ + return m_pStyle->font(); +} + + +///////////// +// +// Get methods +// +///////////// + +const TQPen & Format::leftBorderPen() const +{ + return m_pStyle->leftBorderPen(); +} + +const TQPen & Format::topBorderPen() const +{ + return m_pStyle->topBorderPen(); +} + +const TQPen & Format::rightBorderPen() const +{ + return m_pStyle->rightBorderPen(); +} + +const TQPen & Format::bottomBorderPen() const +{ + return m_pStyle->bottomBorderPen(); +} + +const TQPen & Format::fallDiagonalPen() const +{ + return m_pStyle->fallDiagonalPen(); +} + +const TQPen & Format::goUpDiagonalPen() const +{ + return m_pStyle->goUpDiagonalPen(); +} + +const TQBrush & Format::backGroundBrush() const +{ + return m_pStyle->backGroundBrush(); +} + +const TQFont Format::textFont() const +{ + return m_pStyle->font(); +} + +const TQPen & Format::textPen() const +{ + return m_pStyle->pen(); +} + +///////////// +// +// Misc +// +///////////// + +void Format::formatChanged() +{ + if (m_pCell) + { + m_pCell->setFlag(Cell::Flag_LayoutDirty); + m_pCell->setFlag(Cell::Flag_TextFormatDirty); + } +} + +Format* Format::fallbackFormat( int, int row ) +{ + return m_pCell ? m_pSheet->rowFormat( row ) : 0; +} + +const Format* Format::fallbackFormat( int, int row ) const +{ + return m_pCell ? m_pSheet->rowFormat( row ) : 0; +} + +bool Format::isDefault() const +{ + // NOTE Stefan: Don't compare sheet and cell. + // Because of the comment we have to check m_mask. + if ( ( m_mask & PComment ) && m_strComment != 0 ) + return false; +#if 0 // These are copied in Style. + if ( m_mask ) // Properties + return false; + if ( m_flagsMask != 0 ) // FormatFlags + return false; +#endif + if ( m_bNoFallBack != 0 ) + return false; + return ( *m_pStyle == *m_pSheet->doc()->styleManager()->defaultStyle() ); +} + +bool Format::operator==( const Format& other ) const +{ + // NOTE Stefan: Don't compare sheet and cell. + // Because of the comment we have to check m_mask. + if ( ( m_mask & other.m_mask & PComment ) && m_strComment != other.m_strComment ) + return false; +#if 0 // These are copied in Style. + if ( m_mask != other.m_mask ) // Properties + return false; + if ( m_flagsMask != other.m_flagsMask ) // FormatFlags + return false; +#endif + if ( m_bNoFallBack != other.m_bNoFallBack ) + return false; + return ( *m_pStyle == *other.m_pStyle ); +} + +/***************************************************************************** + * + * RowFormat + * + *****************************************************************************/ + +//#define UPDATE_BEGIN bool b_update_begin = m_bDisplayDirtyFlag; m_bDisplayDirtyFlag = true; +//#define UPDATE_END if ( !b_update_begin && m_bDisplayDirtyFlag ) m_pSheet->emit_updateRow( this, m_iRow ); + +RowFormat::RowFormat( Sheet * _sheet, int _row ) + : Format( _sheet, _sheet->doc()->styleManager()->defaultStyle() ) +{ + m_next = 0; + m_prev = 0; + + m_bDisplayDirtyFlag = false; + m_fHeight = s_rowHeight; + m_iRow = _row; + m_bDefault = false; + m_bHide = false; + m_dcop = 0L; +} + +RowFormat::~RowFormat() +{ + if ( m_next ) + m_next->setPrevious( m_prev ); + if ( m_prev ) + m_prev->setNext( m_next ); + delete m_dcop; +} + +DCOPObject * RowFormat::dcopObject() +{ + if ( !m_dcop ) + m_dcop = new RowIface( this ); + return m_dcop; +} + + +void RowFormat::setMMHeight( double _h ) +{ + setDblHeight( MM_TO_POINT ( _h ) ); +} + +void RowFormat::setHeight( int _h, const Canvas * _canvas ) +{ + setDblHeight( (double) _h, _canvas ); +} + +void RowFormat::setDblHeight( double _h, const Canvas * _canvas ) +{ + Sheet *_sheet = _canvas ? _canvas->activeSheet() : m_pSheet; + + // avoid unnecessary updates + if ( kAbs( _h - dblHeight( _canvas ) ) < DBL_EPSILON ) + return; + +// UPDATE_BEGIN; + + // Lower maximum size by old height + _sheet->adjustSizeMaxY ( - dblHeight() ); + + if ( _canvas ) + m_fHeight = ( _h / _canvas->zoom() ); + else + m_fHeight = _h; + + // Rise maximum size by new height + _sheet->adjustSizeMaxY ( dblHeight() ); + _sheet->print()->updatePrintRepeatRowsHeight(); + _sheet->print()->updateNewPageListY ( row() ); + + _sheet->emit_updateRow(this,m_iRow); +// UPDATE_END; +} + +int RowFormat::height( const Canvas *_canvas ) const +{ + return (int) dblHeight( _canvas ); +} + +double RowFormat::dblHeight( const Canvas *_canvas ) const +{ + if( m_bHide ) + return 0.0; + + if ( _canvas ) + return _canvas->zoom() * (m_iRow == 0) ? s_rowHeight : m_fHeight; + else + return (m_iRow == 0) ? s_rowHeight : m_fHeight; +} + +double RowFormat::mmHeight() const +{ + return POINT_TO_MM ( dblHeight() ); +} + +TQDomElement RowFormat::save( TQDomDocument& doc, int yshift, bool copy ) const +{ + TQDomElement row = doc.createElement( "row" ); + row.setAttribute( "height", m_fHeight ); + row.setAttribute( "row", m_iRow - yshift ); + if( m_bHide ) + row.setAttribute( "hide", (int) m_bHide ); + + TQDomElement format( saveFormat( doc, false, copy ) ); + row.appendChild( format ); + return row; +} + +#if 0 +bool RowFormat::loadOasis( const TQDomElement& /*row*/, TQDomElement * /*rowStyle*/ ) +{ + return true; +} +#endif + +bool RowFormat::load( const TQDomElement & row, int yshift, Paste::Mode sp, bool paste ) +{ + bool ok; + + m_iRow = row.attribute( "row" ).toInt( &ok ) + yshift; + if ( !ok ) + return false; + + if ( row.hasAttribute( "height" ) ) + { + if ( m_pSheet->doc()->syntaxVersion() < 1 ) //compatibility with old format - was in millimeter + m_fHeight = tqRound( MM_TO_POINT( row.attribute( "height" ).toDouble( &ok ) ) ); + else + m_fHeight = row.attribute( "height" ).toDouble( &ok ); + + if ( !ok ) return false; + } + + // Validation + if ( m_fHeight < 0 ) + { + kdDebug(36001) << "Value height=" << m_fHeight << " out of range" << endl; + return false; + } + if ( m_iRow < 1 || m_iRow > KS_rowMax ) + { + kdDebug(36001) << "Value row=" << m_iRow << " out of range" << endl; + return false; + } + + if ( row.hasAttribute( "hide" ) ) + { + setHide( (int) row.attribute( "hide" ).toInt( &ok ) ); + if ( !ok ) + return false; + } + + TQDomElement f( row.namedItem( "format" ).toElement() ); + + if ( !f.isNull() && ( sp == Paste::Normal || sp == Paste::Format || sp == Paste::NoBorder ) ) + { + if ( !loadFormat( f, sp, paste ) ) + return false; + return true; + } + + return true; +} + +const TQPen & RowFormat::topBorderPen( int _col, int _row ) const +{ + // First look at the row above us + if ( !hasProperty( PTopBorder, false ) ) + { + const RowFormat * rl = sheet()->rowFormat( _row - 1 ); + if ( rl->hasProperty( PBottomBorder ) ) + return rl->bottomBorderPen( _col, _row - 1 ); + } + + return Format::topBorderPen( _col, _row ); +} + +void RowFormat::setTopBorderPen( const TQPen & p ) +{ + RowFormat * cl = sheet()->nonDefaultRowFormat( row() - 1, false ); + if ( cl ) + cl->clearProperty( PBottomBorder ); + + Format::setTopBorderPen( p ); +} + +const TQPen & RowFormat::bottomBorderPen( int _col, int _row ) const +{ + // First look at the row below of us + if ( !hasProperty( PBottomBorder, false ) && ( _row < KS_rowMax ) ) + { + const RowFormat * rl = sheet()->rowFormat( _row + 1 ); + if ( rl->hasProperty( PTopBorder ) ) + return rl->topBorderPen( _col, _row + 1 ); + } + + return Format::bottomBorderPen( _col, _row ); +} + +void RowFormat::setBottomBorderPen( const TQPen & p ) +{ + if ( row() < KS_rowMax ) + { + RowFormat * cl = sheet()->nonDefaultRowFormat( row() + 1, false ); + if ( cl ) + cl->clearProperty( PTopBorder ); + } + + Format::setBottomBorderPen( p ); +} + +void RowFormat::setHide( bool _hide, bool repaint ) +{ + if ( _hide != m_bHide ) // only if we change the status + { + if ( _hide ) + { + // Lower maximum size by height of row + m_pSheet->adjustSizeMaxY ( - dblHeight() ); + m_bHide = _hide; //hide must be set after we requested the height + m_pSheet->emit_updateRow( this, m_iRow, repaint ); + } + else + { + // Rise maximum size by height of row + m_bHide = _hide; //unhide must be set before we request the height + m_pSheet->adjustSizeMaxY ( dblHeight() ); + m_pSheet->emit_updateRow( this, m_iRow, repaint ); + } + } +} + +Format* RowFormat::fallbackFormat( int col, int ) +{ + return sheet()->columnFormat( col ); +} + +const Format* RowFormat::fallbackFormat( int col, int ) const +{ + return sheet()->columnFormat( col ); +} + +bool RowFormat::isDefault() const +{ + if ( m_fHeight != s_rowHeight ) + return false; + if ( m_bHide == true ) + return false; + return Format::isDefault(); +} + +bool RowFormat::operator==( const RowFormat& other ) const +{ + // NOTE Stefan: Don't compare sheet and cell. + if ( m_fHeight != other.m_fHeight ) + return false; + if ( m_bHide != other.m_bHide ) + return false; + return Format::operator==( other ); +} + +/***************************************************************************** + * + * ColumnFormat + * + *****************************************************************************/ + +#undef UPDATE_BEGIN +#undef UPDATE_END + +#define UPDATE_BEGIN bool b_update_begin = m_bDisplayDirtyFlag; m_bDisplayDirtyFlag = true; +#define UPDATE_END if ( !b_update_begin && m_bDisplayDirtyFlag ) m_pSheet->emit_updateColumn( this, m_iColumn ); + +ColumnFormat::ColumnFormat( Sheet * _sheet, int _column ) + : Format( _sheet, _sheet->doc()->styleManager()->defaultStyle() ) +{ + m_bDisplayDirtyFlag = false; + m_fWidth = s_columnWidth; + m_iColumn = _column; + m_bDefault=false; + m_bHide=false; + m_prev = 0; + m_next = 0; + m_dcop = 0; +} + +ColumnFormat::~ColumnFormat() +{ + if ( m_next ) + m_next->setPrevious( m_prev ); + if ( m_prev ) + m_prev->setNext( m_next ); + delete m_dcop; +} + +DCOPObject * ColumnFormat::dcopObject() +{ + if ( !m_dcop ) + m_dcop = new ColumnIface( this ); + return m_dcop; +} + +void ColumnFormat::setMMWidth( double _w ) +{ + setDblWidth( MM_TO_POINT ( _w ) ); +} + +void ColumnFormat::setWidth( int _w, const Canvas * _canvas ) +{ + setDblWidth( (double)_w, _canvas ); +} + +void ColumnFormat::setDblWidth( double _w, const Canvas * _canvas ) +{ + Sheet *_sheet = _canvas ? _canvas->activeSheet() : m_pSheet; + + // avoid unnecessary updates + if ( kAbs( _w - dblWidth( _canvas ) ) < DBL_EPSILON ) + return; + + // UPDATE_BEGIN; + + // Lower maximum size by old width + _sheet->adjustSizeMaxX ( - dblWidth() ); + + if ( _canvas ) + m_fWidth = ( _w / _canvas->zoom() ); + else + m_fWidth = _w; + + // Rise maximum size by new width + _sheet->adjustSizeMaxX ( dblWidth() ); + _sheet->print()->updatePrintRepeatColumnsWidth(); + _sheet->print()->updateNewPageListX ( column() ); + + _sheet->emit_updateColumn(this,m_iColumn); + // UPDATE_END; +} + +int ColumnFormat::width( const Canvas * _canvas ) const +{ + return (int) dblWidth( _canvas ); +} + +double ColumnFormat::dblWidth( const Canvas * _canvas ) const +{ + if ( m_bHide ) + return 0.0; + + if ( _canvas ) + return _canvas->zoom() * (m_iColumn == 0) ? s_columnWidth : m_fWidth; + else + return (m_iColumn == 0) ? s_columnWidth : m_fWidth; +} + +double ColumnFormat::mmWidth() const +{ + return POINT_TO_MM( dblWidth() ); +} + + +TQDomElement ColumnFormat::save( TQDomDocument& doc, int xshift, bool copy ) const +{ + TQDomElement col( doc.createElement( "column" ) ); + col.setAttribute( "width", m_fWidth ); + col.setAttribute( "column", m_iColumn - xshift ); + + if ( m_bHide ) + col.setAttribute( "hide", (int) m_bHide ); + + TQDomElement format( saveFormat( doc, false, copy ) ); + col.appendChild( format ); + + return col; +} + +bool ColumnFormat::load( const TQDomElement & col, int xshift, Paste::Mode sp, bool paste ) +{ + bool ok; + if ( col.hasAttribute( "width" ) ) + { + if ( m_pSheet->doc()->syntaxVersion() < 1 ) //combatibility to old format - was in millimeter + m_fWidth = tqRound( MM_TO_POINT ( col.attribute( "width" ).toDouble( &ok ) ) ); + else + m_fWidth = col.attribute( "width" ).toDouble( &ok ); + + if ( !ok ) + return false; + } + + m_iColumn = col.attribute( "column" ).toInt( &ok ) + xshift; + + if ( !ok ) + return false; + + // Validation + if ( m_fWidth < 0 ) + { + kdDebug(36001) << "Value width=" << m_fWidth << " out of range" << endl; + return false; + } + if ( m_iColumn < 1 || m_iColumn > KS_colMax ) + { + kdDebug(36001) << "Value col=" << m_iColumn << " out of range" << endl; + return false; + } + if ( col.hasAttribute( "hide" ) ) + { + setHide( (int) col.attribute( "hide" ).toInt( &ok ) ); + if ( !ok ) + return false; + } + + TQDomElement f( col.namedItem( "format" ).toElement() ); + + if ( !f.isNull() && ( sp == Paste::Normal || sp == Paste::Format || sp == Paste::NoBorder )) + { + if ( !loadFormat( f, sp, paste ) ) + return false; + return true; + } + + return true; +} + +const TQPen & ColumnFormat::leftBorderPen( int _col, int _row ) const +{ + // First look ar the right column at the right + if ( !hasProperty( PLeftBorder, false ) ) + { + const ColumnFormat * cl = sheet()->columnFormat( _col - 1 ); + if ( cl->hasProperty( PRightBorder ) ) + return cl->rightBorderPen( _col - 1, _row ); + } + + return Format::leftBorderPen( _col, _row ); +} + +void ColumnFormat::setLeftBorderPen( const TQPen & p ) +{ + ColumnFormat * cl = sheet()->nonDefaultColumnFormat( column() - 1, false ); + if ( cl ) + cl->clearProperty( PRightBorder ); + + Format::setLeftBorderPen( p ); +} + +const TQPen & ColumnFormat::rightBorderPen( int _col, int _row ) const +{ + // First look ar the right column at the right + if ( !hasProperty( PRightBorder, false ) && ( _col < KS_colMax ) ) + { + const ColumnFormat * cl = sheet()->columnFormat( _col + 1 ); + if ( cl->hasProperty( PLeftBorder ) ) + return cl->leftBorderPen( _col + 1, _row ); + } + + return Format::rightBorderPen( _col, _row ); +} + +void ColumnFormat::setRightBorderPen( const TQPen & p ) +{ + if ( column() < KS_colMax ) + { + ColumnFormat * cl = sheet()->nonDefaultColumnFormat( column() + 1, false ); + if ( cl ) + cl->clearProperty( PLeftBorder ); + } + + Format::setRightBorderPen( p ); +} + +Format * ColumnFormat::fallbackFormat( int, int ) +{ + return sheet()->defaultFormat(); +} + +void ColumnFormat::setHide( bool _hide ) +{ + if ( _hide != m_bHide ) // only if we change the status + { + if ( _hide ) + { + // Lower maximum size by width of column + m_pSheet->adjustSizeMaxX ( - dblWidth() ); + m_bHide = _hide; //hide must be set after we requested the width + // m_pSheet->emit_updateColumn( this, m_iColumn ); + } + else + { + // Rise maximum size by width of column + m_bHide = _hide; //unhide must be set before we request the width + m_pSheet->adjustSizeMaxX ( dblWidth() ); + // m_pSheet->emit_updateColumn( this, m_iColumn ); + } + } +} + +const Format * ColumnFormat::fallbackFormat( int, int ) const +{ + return sheet()->defaultFormat(); +} + +bool ColumnFormat::isDefault() const +{ + if ( m_fWidth != s_columnWidth ) + return false; + if ( m_bHide == true ) + return false; + return Format::isDefault(); +} + +bool ColumnFormat::operator==( const ColumnFormat& other ) const +{ + // NOTE Stefan: Don't compare sheet and cell. + if ( m_fWidth != other.m_fWidth ) + return false; + if ( m_bHide != other.m_bHide ) + return false; + return Format::operator==( other ); +} + + + +namespace Currency_LNS +{ + typedef struct + { + char const * code; + char const * country; + char const * name; + char const * display; + } Money; + + // codes and names as defined in ISO 3166-1 + // first column: saved code + // second column: country name (localized) + // third column: currency name (localized) + // fourth column: displayed currency code (localized but maybe only in + // the country language it belongs to) + // WARNING: change the "24" in getChooseString if you change this array + static const Money lMoney[] = { + { "", "", "", ""}, // auto + { "", "", "", ""}, // extension (codes imported) + { "$", "", "Dollar", "$" }, // unspecified + { "$", I18N_NOOP("Australia"), I18N_NOOP("Dollar"), "$" }, + { "$", I18N_NOOP("Canada"), I18N_NOOP("Dollar"), "$" }, + { "$", I18N_NOOP("Caribbea"), I18N_NOOP("Dollar"), "$" }, + { "$", I18N_NOOP("New Zealand"), I18N_NOOP("Dollar"), "$" }, + { "$", I18N_NOOP("United States"), I18N_NOOP("Dollar"), "$" }, + + // € == Euro sign in utf8 + { "€", "", "€", "€" }, // unspecified + { "€", I18N_NOOP("Austria"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Belgium"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Finland"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("France"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Germany"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Greece"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Ireland"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Italy"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Luxembourg"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Monaco"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Netherlands"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Portugal"), I18N_NOOP("Euro"), "€" }, + { "€", I18N_NOOP("Spain"), I18N_NOOP("Euro"), "€" }, + + { "£", I18N_NOOP("United Kingdom"), I18N_NOOP("Pound"), "£" }, + + { "Â¥", I18N_NOOP("Japan"), I18N_NOOP("Yen"), "Â¥" }, + + { "AFA", I18N_NOOP("Afghanistan"), I18N_NOOP("Afghani"), I18N_NOOP("AFA") }, + { "ALL", I18N_NOOP("Albania"), I18N_NOOP("Lek"), I18N_NOOP("Lek") }, + { "DZD", I18N_NOOP("Algeria"), I18N_NOOP("Algerian Dinar"), I18N_NOOP("DZD") }, + { "USD", I18N_NOOP("American Samoa"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "EUR", I18N_NOOP("Andorra"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "ADP", I18N_NOOP("Andorra"), I18N_NOOP("Andorran Peseta"), I18N_NOOP("ADP") }, + { "AOA", I18N_NOOP("Angola"), I18N_NOOP("Kwanza"), I18N_NOOP("AOA") }, + { "XCD", I18N_NOOP("Anguilla"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "XCD", I18N_NOOP("Antigua And Barbuda"), I18N_NOOP("East Carribean Dollar"), I18N_NOOP("XCD") }, + { "ARS", I18N_NOOP("Argentina"), I18N_NOOP("Argentine Peso"), I18N_NOOP("ARS") }, + { "AMD", I18N_NOOP("Armenia"), I18N_NOOP("Armenian Dram"), I18N_NOOP("AMD") }, + { "AWG", I18N_NOOP("Aruba"), I18N_NOOP("Aruban Guilder"), I18N_NOOP("AWG") }, + { "AUD", I18N_NOOP("Australia"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "EUR", I18N_NOOP("Austria"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "ATS", I18N_NOOP("Austria"), I18N_NOOP("Schilling"), I18N_NOOP("S") }, + { "AZM", I18N_NOOP("Azerbaijan"), I18N_NOOP("Azerbaijanian Manat"), I18N_NOOP("AZM") }, + { "BSD", I18N_NOOP("Bahamas"), I18N_NOOP("Bahamian Dollar"), I18N_NOOP("BSD") }, + { "BHD", I18N_NOOP("Bahrain"), I18N_NOOP("Bahraini Dinar"), I18N_NOOP("BHD") }, + { "BDT", I18N_NOOP("Bangladesh"), I18N_NOOP("Taka"), I18N_NOOP("BDT") }, + { "BBD", I18N_NOOP("Barbados"), I18N_NOOP("Barbados Dollar"), I18N_NOOP("BBD") }, + { "BYR", I18N_NOOP("Belarus"), I18N_NOOP("Belarussian Ruble"), I18N_NOOP("p.") }, + { "EUR", I18N_NOOP("Belgium"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "BEF", I18N_NOOP("Belgium"), I18N_NOOP("Franc"), I18N_NOOP("BF") }, + { "BZD", I18N_NOOP("Belize"), I18N_NOOP("Belize Dollar"), I18N_NOOP("BZ$") }, + { "XOF", I18N_NOOP("Benin"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "BMD", I18N_NOOP("Bermuda"), I18N_NOOP("Bermudian Dollar"), I18N_NOOP("BMD") }, + { "INR", I18N_NOOP("Bhutan"), I18N_NOOP("Indian Rupee"), I18N_NOOP("INR") }, + { "BTN", I18N_NOOP("Bhutan"), I18N_NOOP("Ngultrum"), I18N_NOOP("BTN") }, + { "BOB", I18N_NOOP("Bolivia"), I18N_NOOP("Boliviano"), I18N_NOOP("Bs") }, + { "BOV", I18N_NOOP("Bolivia"), I18N_NOOP("Mvdol"), I18N_NOOP("BOV") }, + { "BAM", I18N_NOOP("Bosnia And Herzegovina"), I18N_NOOP("Convertible Marks"), I18N_NOOP("BAM") }, + { "BWP", I18N_NOOP("Botswana"), I18N_NOOP("Pula"), I18N_NOOP("BWP") }, + { "NOK", I18N_NOOP("Bouvet Island"), I18N_NOOP("Norvegian Krone"), I18N_NOOP("NOK") }, + { "BRL", I18N_NOOP("Brazil"), I18N_NOOP("Brazilian Real"), I18N_NOOP("R$") }, + { "USD", I18N_NOOP("British Indian Ocean Territory"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "BND", I18N_NOOP("Brunei Darussalam"), I18N_NOOP("Brunei Dollar"), I18N_NOOP("BND") }, + { "BGL", I18N_NOOP("Bulgaria"), I18N_NOOP("Lev"), I18N_NOOP("BGL") }, + { "BGN", I18N_NOOP("Bulgaria"), I18N_NOOP("Bulgarian Lev"), I18N_NOOP("BGN") }, + { "XOF", I18N_NOOP("Burkina Faso"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "BIF", I18N_NOOP("Burundi"), I18N_NOOP("Burundi Franc"), I18N_NOOP("BIF") }, + { "KHR", I18N_NOOP("Cambodia"), I18N_NOOP("Riel"), I18N_NOOP("KHR") }, + { "XAF", I18N_NOOP("Cameroon"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "CAD", I18N_NOOP("Canada"), I18N_NOOP("Canadian Dollar"), I18N_NOOP("CAD") }, + { "CVE", I18N_NOOP("Cape Verde"), I18N_NOOP("Cape Verde Escudo"), I18N_NOOP("CVE") }, + { "KYD", I18N_NOOP("Cayman Islands"), I18N_NOOP("Cayman Islands Dollar"), I18N_NOOP("KYD") }, + { "XAF", I18N_NOOP("Central African Republic"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "XAF", I18N_NOOP("Chad"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "CLP", I18N_NOOP("Chile"), I18N_NOOP("Chilean Peso"), I18N_NOOP("Ch$") }, + { "CLF", I18N_NOOP("Chile"), I18N_NOOP("Unidades de fomento"), I18N_NOOP("CLF") }, + { "CNY", I18N_NOOP("China"), I18N_NOOP("Yuan Renminbi"), I18N_NOOP("CNY") }, + { "AUD", I18N_NOOP("Christmas Island"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "AUD", I18N_NOOP("Cocos (Keeling) Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "COP", I18N_NOOP("Colombia"), I18N_NOOP("Colombian Peso"), I18N_NOOP("C$") }, + { "KMF", I18N_NOOP("Comoros"), I18N_NOOP("Comoro Franc"), I18N_NOOP("KMF") }, + { "XAF", I18N_NOOP("Congo"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "CDF", I18N_NOOP("Congo, The Democratic Republic Of"), I18N_NOOP("Franc Congolais"), I18N_NOOP("CDF") }, + { "NZD", I18N_NOOP("Cook Islands"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, + { "CRC", I18N_NOOP("Costa Rica"), I18N_NOOP("Costa Rican Colon"), I18N_NOOP("C") }, + { "XOF", I18N_NOOP("Cote D'Ivoire"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "HRK", I18N_NOOP("Croatia"), I18N_NOOP("Croatian kuna"), I18N_NOOP("kn") }, + { "CUP", I18N_NOOP("Cuba"), I18N_NOOP("Cuban Peso"), I18N_NOOP("CUP") }, + { "CYP", I18N_NOOP("Cyprus"), I18N_NOOP("Cyprus Pound"), I18N_NOOP("CYP") }, + { "CZK", I18N_NOOP("Czech Republic"), I18N_NOOP("Czech Koruna"), I18N_NOOP("Kc") }, + { "DKK", I18N_NOOP("Denmark"), I18N_NOOP("Danish Krone"), I18N_NOOP("kr") }, + { "DJF", I18N_NOOP("Djibouti"), I18N_NOOP("Djibouti Franc"), I18N_NOOP("DJF") }, + { "XCD", I18N_NOOP("Dominica"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("RD$") }, + { "DOP", I18N_NOOP("Dominican Republic"), I18N_NOOP("Dominican Peso"), I18N_NOOP("DOP") }, + { "TPE", I18N_NOOP("East Timor"), I18N_NOOP("Timor Escudo"), I18N_NOOP("TPE") }, + { "USD", I18N_NOOP("East Timor"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "USD", I18N_NOOP("Ecuador"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "EGP", I18N_NOOP("Egypt"), I18N_NOOP("Egyptian Pound"), I18N_NOOP("EGP") }, + { "SVC", I18N_NOOP("El Salvador"), I18N_NOOP("El Salvador Colon"), I18N_NOOP("C") }, + { "USD", I18N_NOOP("El Salvador"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "XAF", I18N_NOOP("Equatorial Guinea"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "ERN", I18N_NOOP("Eritrea"), I18N_NOOP("Nakfa"), I18N_NOOP("ERN") }, + { "EEK", I18N_NOOP("Estonia"), I18N_NOOP("Kroon"), I18N_NOOP("kr") }, + { "ETB", I18N_NOOP("Ethiopia"), I18N_NOOP("Ethiopian Birr"), I18N_NOOP("ETB") }, + { "FKP", I18N_NOOP("Falkland Island (Malvinas)"), I18N_NOOP("Falkland Islands Pound"), I18N_NOOP("FKP") }, + { "DKK", I18N_NOOP("Faeroe Islands"), I18N_NOOP("Danish Krone"), I18N_NOOP("kr") }, + { "FJD", I18N_NOOP("Fiji"), I18N_NOOP("Fiji Dollar"), I18N_NOOP("FJD") }, + { "EUR", I18N_NOOP("Finland"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "FIM", I18N_NOOP("Finland"), I18N_NOOP("Markka"), I18N_NOOP("mk") }, + { "EUR", I18N_NOOP("France"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "FRF", I18N_NOOP("France"), I18N_NOOP("Franc"), I18N_NOOP("F") }, + { "EUR", I18N_NOOP("French Guiana"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "XPF", I18N_NOOP("French Polynesia"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, + { "EUR", I18N_NOOP("Franc Southern Territories"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "XAF", I18N_NOOP("Gabon"), I18N_NOOP("CFA Franc BEAC"), I18N_NOOP("XAF") }, + { "GMD", I18N_NOOP("Gambia"), I18N_NOOP("Dalasi"), I18N_NOOP("GMD") }, + { "GEL", I18N_NOOP("Georgia"), I18N_NOOP("Lari"), I18N_NOOP("GEL") }, + { "EUR", I18N_NOOP("Germany"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "DEM", I18N_NOOP("Germany"), I18N_NOOP("German Mark"), I18N_NOOP("DM") }, + { "GHC", I18N_NOOP("Ghana"), I18N_NOOP("Cedi"), I18N_NOOP("GHC") }, + { "GIP", I18N_NOOP("Gibraltar"), I18N_NOOP("Gibraltar Pound"), I18N_NOOP("GIP") }, + { "EUR", I18N_NOOP("Greece"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "GRD", I18N_NOOP("Greece"), I18N_NOOP("Drachma"), I18N_NOOP("GRD") }, + { "DKK", I18N_NOOP("Greenland"), I18N_NOOP("Danish Krone"), I18N_NOOP("DKK") }, + { "XCD", I18N_NOOP("Grenada"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "EUR", I18N_NOOP("Guadeloupe"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "USD", I18N_NOOP("Guam"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "GTQ", I18N_NOOP("Guatemala"), I18N_NOOP("Quetzal"), I18N_NOOP("Q") }, + { "GNF", I18N_NOOP("Guinea"), I18N_NOOP("Guinea Franc"), I18N_NOOP("GNF") }, + { "GWP", I18N_NOOP("Guinea-Bissau"), I18N_NOOP("Guinea-Bissau Peso"), I18N_NOOP("GWP") }, + { "XOF", I18N_NOOP("Guinea-Bissau"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "GYD", I18N_NOOP("Guyana"), I18N_NOOP("Guyana Dollar"), I18N_NOOP("GYD") }, + { "HTG", I18N_NOOP("Haiti"), I18N_NOOP("Gourde"), I18N_NOOP("HTG") }, + { "USD", I18N_NOOP("Haiti"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "AUD", I18N_NOOP("Heard Island And McDonald Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "EUR", I18N_NOOP("Holy See (Vatican City State)"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "HNL", I18N_NOOP("Honduras"), I18N_NOOP("Lempira"), I18N_NOOP("L") }, + { "HKD", I18N_NOOP("Hong Kong"), I18N_NOOP("Hong Kong Dollar"), I18N_NOOP("HKD") }, + { "HUF", I18N_NOOP("Hungary"), I18N_NOOP("Forint"), I18N_NOOP("Ft") }, + { "ISK", I18N_NOOP("Iceland"), I18N_NOOP("Iceland Krona"), I18N_NOOP("kr.") }, + { "INR", I18N_NOOP("India"), I18N_NOOP("Indian Rupee"), I18N_NOOP("INR") }, + { "IDR", I18N_NOOP("Indonesia"), I18N_NOOP("Rupiah"), I18N_NOOP("Rp") }, + { "IRR", I18N_NOOP("Iran, Islamic Republic Of"), I18N_NOOP("Iranian Rial"), I18N_NOOP("IRR") }, + { "IQD", I18N_NOOP("Iraq"), I18N_NOOP("Iraqi Dinar"), I18N_NOOP("IQD") }, + { "EUR", I18N_NOOP("Ireland"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "IEP", I18N_NOOP("Ireland"), I18N_NOOP("Punt"), I18N_NOOP("IR----") }, + { "IEX", I18N_NOOP("Ireland"), I18N_NOOP("Pence"), I18N_NOOP("IEX") }, + { "ILS", I18N_NOOP("Israel"), I18N_NOOP("New Israeli Sheqel"), I18N_NOOP("ILS") }, + { "EUR", I18N_NOOP("Italy"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "ITL", I18N_NOOP("Italy"), I18N_NOOP("Lira"), I18N_NOOP("L.") }, + { "JMD", I18N_NOOP("Jamaica"), I18N_NOOP("Jamaican Dollar"), I18N_NOOP("J$") }, + { "JPY", I18N_NOOP("Japan"), I18N_NOOP("Yen"), I18N_NOOP("JPY") }, + { "JOD", I18N_NOOP("Jordan"), I18N_NOOP("Jordanian Dinar"), I18N_NOOP("JOD") }, + { "KZT", I18N_NOOP("Kazakhstan"), I18N_NOOP("Tenge"), I18N_NOOP("KZT") }, + { "KES", I18N_NOOP("Kenya"), I18N_NOOP("Kenyan Shilling"), I18N_NOOP("KES") }, + { "AUD", I18N_NOOP("Kiribati"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "KPW", I18N_NOOP("Korea, Democratic People's Republic Of"), I18N_NOOP("North Korean Won"), I18N_NOOP("KPW") }, + { "KRW", I18N_NOOP("Korea, Republic Of"), I18N_NOOP("Won"), I18N_NOOP("KRW") }, + { "KWD", I18N_NOOP("Kuwait"), I18N_NOOP("Kuwaiti Dinar"), I18N_NOOP("KWD") }, + { "KGS", I18N_NOOP("Kyrgyzstan"), I18N_NOOP("Som"), I18N_NOOP("KGS") }, + { "LAK", I18N_NOOP("Lao People's Democratic Republic"), I18N_NOOP("Kip"), I18N_NOOP("LAK") }, + { "LVL", I18N_NOOP("Latvia"), I18N_NOOP("Latvian Lats"), I18N_NOOP("Ls") }, + { "LBP", I18N_NOOP("Lebanon"), I18N_NOOP("Lebanese Pound"), I18N_NOOP("LBP") }, + { "ZAR", I18N_NOOP("Lesotho"), I18N_NOOP("Rand"), I18N_NOOP("ZAR") }, + { "LSL", I18N_NOOP("Lesotho"), I18N_NOOP("Loti"), I18N_NOOP("LSL") }, + { "LRD", I18N_NOOP("Liberia"), I18N_NOOP("Liberian Dollar"), I18N_NOOP("LRD") }, + { "LYD", I18N_NOOP("Libyan Arab Jamahiriya"), I18N_NOOP("Lybian Dinar"), I18N_NOOP("LYD") }, + { "CHF", I18N_NOOP("Liechtenstein"), I18N_NOOP("Swiss Franc"), I18N_NOOP("CHF") }, + { "LTL", I18N_NOOP("Lithuania"), I18N_NOOP("Lithuanian Litus"), I18N_NOOP("Lt") }, + { "EUR", I18N_NOOP("Luxembourg"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "LUF", I18N_NOOP("Luxembourg"), I18N_NOOP("Franc"), I18N_NOOP("F") }, + { "MOP", I18N_NOOP("Macao"), I18N_NOOP("Pataca"), I18N_NOOP("MOP") }, + { "MKD", I18N_NOOP("Macedonia, The Former Yugoslav Republic Of"), I18N_NOOP("Denar"), I18N_NOOP("MKD") }, + { "MGF", I18N_NOOP("Madagascar"), I18N_NOOP("Malagasy Franc"), I18N_NOOP("MGF") }, + { "MWK", I18N_NOOP("Malawi"), I18N_NOOP("Kwacha"), I18N_NOOP("MWK") }, + { "MYR", I18N_NOOP("Malaysia"), I18N_NOOP("Malaysian Ringgit"), I18N_NOOP("MYR") }, + { "MVR", I18N_NOOP("Maldives"), I18N_NOOP("Rufiyaa"), I18N_NOOP("MVR") }, + { "XOF", I18N_NOOP("Mali"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "MTL", I18N_NOOP("Malta"), I18N_NOOP("Maltese Lira"), I18N_NOOP("MTL") }, + { "USD", I18N_NOOP("Marshall Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "EUR", I18N_NOOP("Martinique"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "MRO", I18N_NOOP("Mauritania"), I18N_NOOP("Ouguiya"), I18N_NOOP("MRO") }, + { "MUR", I18N_NOOP("Mauritius"), I18N_NOOP("Mauritius Rupee"), I18N_NOOP("MUR") }, + { "EUR", I18N_NOOP("Mayotte"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "MXN", I18N_NOOP("Mexico"), I18N_NOOP("Mexican Peso"), I18N_NOOP("MXN") }, + { "MXV", I18N_NOOP("Mexico"), I18N_NOOP("Mexican Unidad de Inversion (UDI)"), I18N_NOOP("MXV") }, + { "USD", I18N_NOOP("Micronesia, Federated States Of"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "MDL", I18N_NOOP("Moldova, Republic Of"), I18N_NOOP("Moldovan Leu"), I18N_NOOP("MDL") }, + { "EUR", I18N_NOOP("Monaco"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "MNT", I18N_NOOP("Mongolia"), I18N_NOOP("Tugrik"), I18N_NOOP("MNT") }, + { "XCD", I18N_NOOP("Montserrat"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "MAD", I18N_NOOP("Morocco"), I18N_NOOP("Moroccan Dirham"), I18N_NOOP("MAD") }, + { "MZM", I18N_NOOP("Mozambique"), I18N_NOOP("Metical"), I18N_NOOP("MZM") }, + { "MMK", I18N_NOOP("Myanmar"), I18N_NOOP("Kyat"), I18N_NOOP("MMK") }, + { "ZAR", I18N_NOOP("Namibia"), I18N_NOOP("Rand"), I18N_NOOP("ZAR") }, + { "NAD", I18N_NOOP("Namibia"), I18N_NOOP("Namibia Dollar"), I18N_NOOP("NAD") }, + { "AUD", I18N_NOOP("Nauru"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "NPR", I18N_NOOP("Nepal"), I18N_NOOP("Nepalese Rupee"), I18N_NOOP("NPR") }, + { "EUR", I18N_NOOP("Netherlands"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "NLG", I18N_NOOP("Netherlands"), I18N_NOOP("Guilder"), I18N_NOOP("fl") }, + { "ANG", I18N_NOOP("Netherlands Antilles"), I18N_NOOP("Netherlands Antillan Guilder"), I18N_NOOP("ANG") }, + { "XPF", I18N_NOOP("New Caledonia"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, + { "NZD", I18N_NOOP("New Zealand"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, + { "NIO", I18N_NOOP("Nicaragua"), I18N_NOOP("Cordoba Oro"), I18N_NOOP("NIO") }, + { "XOF", I18N_NOOP("Niger"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "NGN", I18N_NOOP("Nigeria"), I18N_NOOP("Naira"), I18N_NOOP("NGN") }, + { "NZD", I18N_NOOP("Niue"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, + { "AUD", I18N_NOOP("Norfolk Islands"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "USD", I18N_NOOP("Northern Mariana Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "NOK", I18N_NOOP("Norway"), I18N_NOOP("Norwegian Krone"), I18N_NOOP("kr") }, + { "OMR", I18N_NOOP("Oman"), I18N_NOOP("Rial Omani"), I18N_NOOP("OMR") }, + { "PKR", I18N_NOOP("Pakistan"), I18N_NOOP("Pakistan Rupee"), I18N_NOOP("PKR") }, + { "USD", I18N_NOOP("Palau"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "PAB", I18N_NOOP("Panama"), I18N_NOOP("Balboa"), I18N_NOOP("PAB") }, + { "USD", I18N_NOOP("Panama"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "PGK", I18N_NOOP("Papua New Guinea"), I18N_NOOP("Kina"), I18N_NOOP("PGK") }, + { "PYG", I18N_NOOP("Paraguay"), I18N_NOOP("Guarani"), I18N_NOOP("G") }, + { "PEN", I18N_NOOP("Peru"), I18N_NOOP("Nuevo Sol"), I18N_NOOP("PEN") }, + { "PHP", I18N_NOOP("Philippines"), I18N_NOOP("Philippine Peso"), I18N_NOOP("PHP") }, + { "NZD", I18N_NOOP("Pitcairn"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, + { "PLN", I18N_NOOP("Poland"), I18N_NOOP("Zloty"), I18N_NOOP("zt") }, + { "EUR", I18N_NOOP("Portugal"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "PTE", I18N_NOOP("Portugal"), I18N_NOOP("Escudo"), I18N_NOOP("Esc.") }, + { "USD", I18N_NOOP("Puerto Rico"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "QAR", I18N_NOOP("Qatar"), I18N_NOOP("Qatari Rial"), I18N_NOOP("QAR") }, + { "ROL", I18N_NOOP("Romania"), I18N_NOOP("Leu"), I18N_NOOP("LEI") }, + { "RUR", I18N_NOOP("Russian Federation"), I18N_NOOP("Russian Ruble"), I18N_NOOP("RUR") }, + { "RUB", I18N_NOOP("Russian Federation"), I18N_NOOP("Russian Ruble"), I18N_NOOP("RUB") }, + { "RWF", I18N_NOOP("Rwanda"), I18N_NOOP("Rwanda Franc"), I18N_NOOP("RWF") }, + { "SHP", I18N_NOOP("Saint Helena"), I18N_NOOP("Saint Helena Pound"), I18N_NOOP("SHP") }, + { "XCD", I18N_NOOP("Saint Kitts And Nevis"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "XCD", I18N_NOOP("Saint Lucia"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "EUR", I18N_NOOP("Saint Pierre And Miquelon"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "XCD", I18N_NOOP("Saint Vincent And The Grenadines"), I18N_NOOP("East Caribbean Dollar"), I18N_NOOP("XCD") }, + { "WST", I18N_NOOP("Samoa"), I18N_NOOP("Tala"), I18N_NOOP("WST") }, + { "EUR", I18N_NOOP("San Marino"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "STD", I18N_NOOP("Sao Tome And Principe"), I18N_NOOP("Dobra"), I18N_NOOP("STD") }, + { "SAR", I18N_NOOP("Saudi Arabia"), I18N_NOOP("Saudi Riyal"), I18N_NOOP("SAR") }, + { "XOF", I18N_NOOP("Senegal"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "SCR", I18N_NOOP("Seychelles"), I18N_NOOP("Seychelles Rupee"), I18N_NOOP("SCR") }, + { "SLL", I18N_NOOP("Sierra Leone"), I18N_NOOP("Leone"), I18N_NOOP("SLL") }, + { "SGD", I18N_NOOP("Singapore"), I18N_NOOP("Singapore Dollar"), I18N_NOOP("SGD") }, + { "SKK", I18N_NOOP("Slovakia"), I18N_NOOP("Slovak Koruna"), I18N_NOOP("Sk") }, + { "EUR", I18N_NOOP("Slovenia"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "SBD", I18N_NOOP("Solomon Islands"), I18N_NOOP("Solomon Islands Dollar"), I18N_NOOP("SBD") }, + { "SOS", I18N_NOOP("Somalia"), I18N_NOOP("Somali Shilling"), I18N_NOOP("SOS") }, + { "ZAR", I18N_NOOP("South Africa"), I18N_NOOP("Rand"), I18N_NOOP("R") }, + { "EUR", I18N_NOOP("Spain"), I18N_NOOP("Euro"), I18N_NOOP("EUR") }, + { "ESP", I18N_NOOP("Spain"), I18N_NOOP("Peseta"), I18N_NOOP("Pts") }, + { "LKR", I18N_NOOP("Sri Lanka"), I18N_NOOP("Sri Lanka Rupee"), I18N_NOOP("LKR") }, + { "SDD", I18N_NOOP("Sudan"), I18N_NOOP("Sudanese Dinar"), I18N_NOOP("SDD") }, + { "SRG", I18N_NOOP("Suriname"), I18N_NOOP("Suriname Guilder"), I18N_NOOP("SRG") }, + { "NOK", I18N_NOOP("Svalbard And Jan Mayen"), I18N_NOOP("Norwegian Krone"), I18N_NOOP("NOK") }, + { "SZL", I18N_NOOP("Swaziland"), I18N_NOOP("Lilangeni"), I18N_NOOP("SZL") }, + { "SEK", I18N_NOOP("Sweden"), I18N_NOOP("Swedish Krona"), I18N_NOOP("kr") }, + { "CHF", I18N_NOOP("Switzerland"), I18N_NOOP("Swiss Franc"), I18N_NOOP("SFr.") }, + { "SYP", I18N_NOOP("Syrian Arab Republic"), I18N_NOOP("Syrian Pound"), I18N_NOOP("SYP") }, + { "TWD", I18N_NOOP("Taiwan, Province Of China"), I18N_NOOP("New Taiwan Dollar"), I18N_NOOP("TWD") }, + { "TJS", I18N_NOOP("Tajikistan"), I18N_NOOP("Somoni"), I18N_NOOP("TJS") }, + { "TZS", I18N_NOOP("Tanzania, United Republic Of"), I18N_NOOP("Tanzanian Shilling"), I18N_NOOP("TZS") }, + { "THB", I18N_NOOP("Thailand"), I18N_NOOP("Baht"), I18N_NOOP("THB") }, + { "XOF", I18N_NOOP("Togo"), I18N_NOOP("CFA Franc BCEAO"), I18N_NOOP("XOF") }, + { "NZD", I18N_NOOP("Tokelau"), I18N_NOOP("New Zealand Dollar"), I18N_NOOP("NZD") }, + { "TOP", I18N_NOOP("Tonga"), I18N_NOOP("Pa'anga"), I18N_NOOP("TOP") }, + { "TTD", I18N_NOOP("Trinidad And Tobago"), I18N_NOOP("Trinidad and Tobago Dollar"), I18N_NOOP("TT$") }, + { "TND", I18N_NOOP("Tunisia"), I18N_NOOP("Tunisian Dinar"), I18N_NOOP("TND") }, + { "TRL", I18N_NOOP("Turkey"), I18N_NOOP("Turkish Lira"), I18N_NOOP("TL") }, + { "TMM", I18N_NOOP("Turkmenistan"), I18N_NOOP("Manat"), I18N_NOOP("TMM") }, + { "USD", I18N_NOOP("Turks And Caicos Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "AUD", I18N_NOOP("Tuvalu"), I18N_NOOP("Australian Dollar"), I18N_NOOP("AUD") }, + { "UGX", I18N_NOOP("Uganda"), I18N_NOOP("Uganda Shilling"), I18N_NOOP("UGX") }, + { "UAH", I18N_NOOP("Ukraine"), I18N_NOOP("Hryvnia"), I18N_NOOP("UAH") }, + { "AED", I18N_NOOP("United Arab Emirates"), I18N_NOOP("UAE Dirham"), I18N_NOOP("AED") }, + { "GBP", I18N_NOOP("United Kingdom"), I18N_NOOP("Pound Sterling"), I18N_NOOP("GBP") }, + { "USD", I18N_NOOP("United States"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "USN", I18N_NOOP("United States"), I18N_NOOP("US Dollar (Next day)"), I18N_NOOP("USN") }, + { "USS", I18N_NOOP("United States"), I18N_NOOP("US Dollar (Same day)"), I18N_NOOP("USS") }, + { "UYU", I18N_NOOP("Uruguay"), I18N_NOOP("Peso Uruguayo"), I18N_NOOP("NU$") }, + { "UZS", I18N_NOOP("Uzbekistan"), I18N_NOOP("Uzbekistan Sum"), I18N_NOOP("UZS") }, + { "VUV", I18N_NOOP("Vanuatu"), I18N_NOOP("Vatu"), I18N_NOOP("VUV") }, + { "VEB", I18N_NOOP("Venezuela"), I18N_NOOP("Bolivar"), I18N_NOOP("Bs") }, + { "VND", I18N_NOOP("Viet Nam"), I18N_NOOP("Dong"), I18N_NOOP("VND") }, + { "USD", I18N_NOOP("Virgin Islands"), I18N_NOOP("US Dollar"), I18N_NOOP("USD") }, + { "XPF", I18N_NOOP("Wallis And Futuna"), I18N_NOOP("CFP Franc"), I18N_NOOP("XPF") }, + { "MAD", I18N_NOOP("Western Sahara"), I18N_NOOP("Moroccan Dirham"), I18N_NOOP("MAD") }, + { "YER", I18N_NOOP("Yemen"), I18N_NOOP("Yemeni Rial"), I18N_NOOP("YER") }, + { "YUM", I18N_NOOP("Yugoslavia"), I18N_NOOP("Yugoslavian Dinar"), I18N_NOOP("YUM") }, + { "ZMK", I18N_NOOP("Zambia"), I18N_NOOP("Kwacha"), I18N_NOOP("ZMK") }, + { "ZWD", I18N_NOOP("Zimbabwe"), I18N_NOOP("Zimbabwe Dollar"), I18N_NOOP("ZWD") }, + { 0, 0, 0, 0}, // Last must be empty! + }; + + + class CurrencyMap + { + public: + CurrencyMap() + : m_List(lMoney) + { + } + + // Those return the _untranslated_ strings from the above array + TQString getCode(int t) const + { + return TQString::fromUtf8( m_List[t].code ); + } + + TQString getCountry(int t) const + { + return TQString::fromUtf8( m_List[t].country ); + } + + TQString getName(int t) const + { + return TQString::fromUtf8( m_List[t].name ); + } + + TQString getDisplayCode(int t) const + { + return TQString::fromUtf8( m_List[t].display ); + } + + int getIndex(const TQString& code) const + { + int index = 0; + while (m_List[index].code != 0 && m_List[index].code != code) + ++index; + return (m_List[index].code != 0) ? index : 1 /*undef*/; + } + + private: + const Money * m_List; + }; + + const CurrencyMap gCurrencyMap; + const Money * gMoneyList(lMoney); +} + + +using namespace Currency_LNS; + +Currency::Currency() + : m_type( 0 ) +{ +} + +Currency::~Currency() +{ +} + +Currency::Currency(int index) + : m_type( index ), + m_code( gCurrencyMap.getCode( index ) ) +{ +} + +Currency::Currency(int index, TQString const & code) + : m_type ( 1 ), // unspec + m_code( code ) +{ + if ( gCurrencyMap.getCode( index ) == code ) + m_type = index; +} + +Currency::Currency(TQString const & code, currencyFormat format) + : m_type( 1 ), // unspec + m_code( code ) +{ + if ( format == Gnumeric ) + { + // I use TQChar(c,r) here so that this file can be opened in any encoding... + if ( code.find( TQChar( 172, 32 ) ) != -1 ) // Euro sign + m_code = TQChar( 172, 32 ); + else if ( code.find( TQChar( 163, 0 ) ) != -1 ) // Pound sign + m_code = TQChar( 163, 0 ); + else if ( code.find( TQChar( 165, 0 ) ) != -1 ) // Yen sign + m_code = TQChar( 165, 0 ); + else if ( code[0] == '[' && code[1] == '$' ) + { + int n = code.find(']'); + if (n != -1) + { + m_code = code.mid( 2, n - 2 ); + } + else + { + m_type = 0; + } + } + else if ( code.find( '$' ) != -1 ) + m_code = "$"; + } // end gnumeric + m_type = gCurrencyMap.getIndex( m_code ); +} + +Currency & Currency::operator=(int type) +{ + m_type = type; + m_code = gCurrencyMap.getCode( m_type ); + + return *this; +} + +Currency & Currency::operator=(char const * code) +{ + m_type = 1; + m_code = code; + + return *this; +} + +bool Currency::operator==(Currency const & cur) const +{ + if ( m_type == cur.m_type ) + return true; + + if ( m_code == cur.m_code ) + return true; + + return false; +} + +bool Currency::operator==(int type) const +{ + if ( m_type == type ) + return true; + + return false; +} + +Currency::operator int() const +{ + return m_type; +} + +TQString Currency::getCode() const +{ + return m_code; +} + +TQString Currency::getCountry() const +{ + return gCurrencyMap.getCountry( m_type ); +} + +TQString Currency::getName() const +{ + return gCurrencyMap.getName( m_type ); +} + +TQString Currency::getDisplayCode() const +{ + return gMoneyList[m_type].display; +} + +int Currency::getIndex() const +{ + return m_type; +} + +TQString Currency::getExportCode( currencyFormat format ) const +{ + if ( format == Gnumeric ) + { + if ( m_code.length() == 1 ) // symbol + return m_code; + + TQString ret( "[$"); + ret += m_code; + ret += "]"; + + return ret; + } + + return m_code; +} + +TQString Currency::getChooseString( int type, bool & ok ) +{ + if ( !gMoneyList[type].country ) + { + ok = false; + return TQString(); + } + if ( type < 24 ) + { + TQString ret( i18n( gMoneyList[type].name ) ); + if ( gMoneyList[type].country[0] ) + { + ret += " ("; + ret += i18n( gMoneyList[type].country ); + ret += ")"; + } + return ret; + } + else + { + TQString ret( i18n( gMoneyList[type].country ) ); + if ( gMoneyList[type].name[0] ) + { + ret += " ("; + ret += i18n( gMoneyList[type].name ); + ret += ")"; + } + return ret; + } +} + +TQString Currency::getDisplaySymbol( int type ) +{ + return i18n( gMoneyList[type].display ); +} + +// Currently unused +TQString Currency::getCurrencyCode( int type ) +{ + return TQString::fromUtf8( gMoneyList[type].code ); +} + +#undef UPDATE_BEGIN +#undef UPDATE_END diff --git a/kspread/kspread_functions_conversion.cc b/kspread/kspread_functions_conversion.cc deleted file mode 100644 index 23f2ca01..00000000 --- a/kspread/kspread_functions_conversion.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in conversion functions - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -using namespace KSpread; - -// prototypes -Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *); -Value func_carx (valVector args, ValueCalc *calc, FuncExtra *); -Value func_cary (valVector args, ValueCalc *calc, FuncExtra *); -Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *); -Value func_polr (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pola (valVector args, ValueCalc *calc, FuncExtra *); -Value func_roman (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *); -Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *); -Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *); -Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *); -Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all conversion functions -void RegisterConversionFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("ARABIC", func_arabic); - repo->add (f); - f = new Function ("CARX", func_carx); - f->setParamCount (2); - repo->add (f); - f = new Function ("CARY", func_cary); - f->setParamCount (2); - repo->add (f); - f = new Function ("DECSEX", func_decsex); - repo->add (f); - f = new Function ("POLR", func_polr); - f->setParamCount (2); - repo->add (f); - f = new Function ("POLA", func_pola); - f->setParamCount (2); - repo->add (f); - f = new Function ("ROMAN", func_roman); - repo->add (f); - f = new Function ("SEXDEC", func_sexdec); - f->setParamCount (1, 3); - repo->add (f); - f = new Function ("ASCIITOCHAR", func_AsciiToChar); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("CHARTOASCII", func_CharToAscii); - repo->add (f); - f = new Function ("BOOL2INT", func_booltoint); - repo->add (f); - f = new Function ("INT2BOOL", func_inttobool); - repo->add (f); - f = new Function ("BOOL2STRING", func_ToString); - repo->add (f); - f = new Function ("NUM2STRING", func_ToString); - repo->add (f); - f = new Function ("STRING", func_ToString); - repo->add (f); -} - -// Function: POLR -Value func_polr (valVector args, ValueCalc *calc, FuncExtra *) -{ - // sqrt (a^2 + b^2) - Value a = args[0]; - Value b = args[1]; - Value res = calc->sqrt (calc->add (calc->sqr (a), calc->sqr (b))); - return res; -} - -// Function: POLA -Value func_pola (valVector args, ValueCalc *calc, FuncExtra *) -{ - // acos (a / polr(a,b)) - Value polr = func_polr (args, calc, 0); - if (calc->isZero (polr)) - return Value::errorDIV0(); - Value res = calc->acos (calc->div (args[0], polr)); - return res; -} - -// Function: CARX -Value func_carx (valVector args, ValueCalc *calc, FuncExtra *) -{ - // a * cos(b) - Value res = calc->mul (args[0], calc->cos (args[1])); - return res; -} - -// Function: CARY -Value func_cary (valVector args, ValueCalc *calc, FuncExtra *) -{ - // a * sin(b) - Value res = calc->mul (args[0], calc->sin (args[1])); - return res; -} - -// Function: DECSEX -Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *) -{ - // original function was very compicated, but I see no reason for that, - // when it can be done as simply as this ... - // maybe it was due to all the infrastructure not being ready back then - return calc->conv()->asTime (calc->div (args[0], 24)); -} - -// Function: SEXDEC -Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 1) - { - // convert given value to number - Value time = calc->conv()->asTime (args[0]); - return calc->mul (calc->conv()->asFloat (time), 24); - } - - // convert h/m/s to number of hours - Value h = args[0]; - Value m = args[1]; - - Value res = calc->add (h, calc->div (m, 60)); - if (args.count() == 3) { - Value s = args[2]; - res = calc->add (res, calc->div (s, 3600)); - } - return res; -} - -// Function: ROMAN -Value func_roman (valVector args, ValueCalc *calc, FuncExtra *) -{ - const TQCString RNUnits[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; - const TQCString RNTens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; - const TQCString RNHundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; - const TQCString RNThousands[] = {"", "M", "MM", "MMM"}; - - // precision loss is not a problem here, as we only use the 0-3999 range - long value = calc->conv()->asInteger (args[0]).asInteger (); - if ((value < 0) || (value > 3999)) - return Value::errorNA(); - TQString result; - result = TQString::fromLatin1 (RNThousands[(value / 1000)] + - RNHundreds[(value / 100) % 10] + - RNTens[(value / 10 ) % 10] + - RNUnits[(value) % 10]); - return Value (result); -} - -// convert single roman character to decimal -// return < 0 if invalid -int func_arabic_helper (TQChar c) -{ - switch (c.upper().unicode()) - { - case 'M': return 1000; - case 'D': return 500; - case 'C': return 100; - case 'L': return 50; - case 'X': return 10; - case 'V': return 5; - case 'I': return 1; - } - return -1; -} - -// Function: ARABIC -Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString roman = calc->conv()->asString (args[0]).asString(); - if( roman.isEmpty() ) return Value::errorVALUE(); - - int val = 0, lastd = 0, d = 0; - - for (unsigned i = 0; i < roman.length(); i++) { - d = func_arabic_helper( roman[i] ); - if( d < 0 ) return Value::errorVALUE(); - - if( lastd < d ) val -= lastd; - else val += lastd; - lastd = d; - } - if( lastd < d ) val -= lastd; - else val += lastd; - - return Value (val); -} - -// helper for AsciiToChar -void func_a2c_helper (ValueCalc *calc, TQString &s, Value val) -{ - if (val.isArray()) { - for (unsigned int row = 0; row < val.rows(); ++row) - for (unsigned int col = 0; col < val.columns(); ++col) - func_a2c_helper (calc, s, val.element (col, row)); - } else { - int v = calc->conv()->asInteger (val).asInteger(); - if (v == 0) return; - TQChar c (v); - s = s + c; - } -} - -// Function: AsciiToChar -Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str; - for (unsigned int i = 0; i < args.count(); i++) - func_a2c_helper (calc, str, args[i]); - return Value (str); -} - -// Function: CharToAscii -Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString val = calc->conv()->asString (args[0]).asString (); - if (val.length() == 1) - return Value (TQString (val[0])); - return Value::errorVALUE(); -} - -// Function: inttobool -Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asBoolean (args[0]); -} - -// Function: booltoint -Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asInteger (args[0]); -} - -// Function: BoolToString, NumberToString, String -Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asString (args[0]); -} diff --git a/kspread/kspread_functions_conversion.cpp b/kspread/kspread_functions_conversion.cpp new file mode 100644 index 00000000..23f2ca01 --- /dev/null +++ b/kspread/kspread_functions_conversion.cpp @@ -0,0 +1,266 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in conversion functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +using namespace KSpread; + +// prototypes +Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *); +Value func_carx (valVector args, ValueCalc *calc, FuncExtra *); +Value func_cary (valVector args, ValueCalc *calc, FuncExtra *); +Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_polr (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pola (valVector args, ValueCalc *calc, FuncExtra *); +Value func_roman (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *); +Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *); +Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *); +Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all conversion functions +void RegisterConversionFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("ARABIC", func_arabic); + repo->add (f); + f = new Function ("CARX", func_carx); + f->setParamCount (2); + repo->add (f); + f = new Function ("CARY", func_cary); + f->setParamCount (2); + repo->add (f); + f = new Function ("DECSEX", func_decsex); + repo->add (f); + f = new Function ("POLR", func_polr); + f->setParamCount (2); + repo->add (f); + f = new Function ("POLA", func_pola); + f->setParamCount (2); + repo->add (f); + f = new Function ("ROMAN", func_roman); + repo->add (f); + f = new Function ("SEXDEC", func_sexdec); + f->setParamCount (1, 3); + repo->add (f); + f = new Function ("ASCIITOCHAR", func_AsciiToChar); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("CHARTOASCII", func_CharToAscii); + repo->add (f); + f = new Function ("BOOL2INT", func_booltoint); + repo->add (f); + f = new Function ("INT2BOOL", func_inttobool); + repo->add (f); + f = new Function ("BOOL2STRING", func_ToString); + repo->add (f); + f = new Function ("NUM2STRING", func_ToString); + repo->add (f); + f = new Function ("STRING", func_ToString); + repo->add (f); +} + +// Function: POLR +Value func_polr (valVector args, ValueCalc *calc, FuncExtra *) +{ + // sqrt (a^2 + b^2) + Value a = args[0]; + Value b = args[1]; + Value res = calc->sqrt (calc->add (calc->sqr (a), calc->sqr (b))); + return res; +} + +// Function: POLA +Value func_pola (valVector args, ValueCalc *calc, FuncExtra *) +{ + // acos (a / polr(a,b)) + Value polr = func_polr (args, calc, 0); + if (calc->isZero (polr)) + return Value::errorDIV0(); + Value res = calc->acos (calc->div (args[0], polr)); + return res; +} + +// Function: CARX +Value func_carx (valVector args, ValueCalc *calc, FuncExtra *) +{ + // a * cos(b) + Value res = calc->mul (args[0], calc->cos (args[1])); + return res; +} + +// Function: CARY +Value func_cary (valVector args, ValueCalc *calc, FuncExtra *) +{ + // a * sin(b) + Value res = calc->mul (args[0], calc->sin (args[1])); + return res; +} + +// Function: DECSEX +Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *) +{ + // original function was very compicated, but I see no reason for that, + // when it can be done as simply as this ... + // maybe it was due to all the infrastructure not being ready back then + return calc->conv()->asTime (calc->div (args[0], 24)); +} + +// Function: SEXDEC +Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 1) + { + // convert given value to number + Value time = calc->conv()->asTime (args[0]); + return calc->mul (calc->conv()->asFloat (time), 24); + } + + // convert h/m/s to number of hours + Value h = args[0]; + Value m = args[1]; + + Value res = calc->add (h, calc->div (m, 60)); + if (args.count() == 3) { + Value s = args[2]; + res = calc->add (res, calc->div (s, 3600)); + } + return res; +} + +// Function: ROMAN +Value func_roman (valVector args, ValueCalc *calc, FuncExtra *) +{ + const TQCString RNUnits[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; + const TQCString RNTens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; + const TQCString RNHundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; + const TQCString RNThousands[] = {"", "M", "MM", "MMM"}; + + // precision loss is not a problem here, as we only use the 0-3999 range + long value = calc->conv()->asInteger (args[0]).asInteger (); + if ((value < 0) || (value > 3999)) + return Value::errorNA(); + TQString result; + result = TQString::fromLatin1 (RNThousands[(value / 1000)] + + RNHundreds[(value / 100) % 10] + + RNTens[(value / 10 ) % 10] + + RNUnits[(value) % 10]); + return Value (result); +} + +// convert single roman character to decimal +// return < 0 if invalid +int func_arabic_helper (TQChar c) +{ + switch (c.upper().unicode()) + { + case 'M': return 1000; + case 'D': return 500; + case 'C': return 100; + case 'L': return 50; + case 'X': return 10; + case 'V': return 5; + case 'I': return 1; + } + return -1; +} + +// Function: ARABIC +Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString roman = calc->conv()->asString (args[0]).asString(); + if( roman.isEmpty() ) return Value::errorVALUE(); + + int val = 0, lastd = 0, d = 0; + + for (unsigned i = 0; i < roman.length(); i++) { + d = func_arabic_helper( roman[i] ); + if( d < 0 ) return Value::errorVALUE(); + + if( lastd < d ) val -= lastd; + else val += lastd; + lastd = d; + } + if( lastd < d ) val -= lastd; + else val += lastd; + + return Value (val); +} + +// helper for AsciiToChar +void func_a2c_helper (ValueCalc *calc, TQString &s, Value val) +{ + if (val.isArray()) { + for (unsigned int row = 0; row < val.rows(); ++row) + for (unsigned int col = 0; col < val.columns(); ++col) + func_a2c_helper (calc, s, val.element (col, row)); + } else { + int v = calc->conv()->asInteger (val).asInteger(); + if (v == 0) return; + TQChar c (v); + s = s + c; + } +} + +// Function: AsciiToChar +Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str; + for (unsigned int i = 0; i < args.count(); i++) + func_a2c_helper (calc, str, args[i]); + return Value (str); +} + +// Function: CharToAscii +Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString val = calc->conv()->asString (args[0]).asString (); + if (val.length() == 1) + return Value (TQString (val[0])); + return Value::errorVALUE(); +} + +// Function: inttobool +Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asBoolean (args[0]); +} + +// Function: booltoint +Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asInteger (args[0]); +} + +// Function: BoolToString, NumberToString, String +Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asString (args[0]); +} diff --git a/kspread/kspread_functions_database.cc b/kspread/kspread_functions_database.cc deleted file mode 100644 index a294914d..00000000 --- a/kspread/kspread_functions_database.cc +++ /dev/null @@ -1,537 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in database functions - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -using namespace KSpread; - -// prototypes -Value func_daverage (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dcount (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dcounta (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dget (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dmax (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dmin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dproduct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dstdev (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dstdevp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dsum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dvar (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dvarp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_getpivotdata (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all database functions -void RegisterDatabaseFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("DAVERAGE", func_daverage); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DCOUNT", func_dcount); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DCOUNTA", func_dcounta); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DGET", func_dget); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DMAX", func_dmax); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DMIN", func_dmin); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DPRODUCT", func_dproduct); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DSTDEV", func_dstdev); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DSTDEVP", func_dstdevp); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DSUM", func_dsum); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DVAR", func_dvar); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DVARP", func_dvarp); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("GETPIVOTDATA", func_getpivotdata); // partially Excel-compatible - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); -} - -int getFieldIndex (ValueCalc *calc, Value fieldName, - Value database) -{ - if (fieldName.isNumber()) - return fieldName.asInteger() - 1; - if (!fieldName.isString ()) - return -1; - - TQString fn = fieldName.asString(); - int cols = database.columns (); - for (int i = 0; i < cols; ++i) - if (fn.lower() == - calc->conv()->asString (database.element (i, 0)).asString().lower()) - return i; - return -1; -} - -// *********************************************************** -// *** DBConditions class - maintains an array of conditions *** -// *********************************************************** - -class DBConditions { - public: - DBConditions (ValueCalc *vc, Value database, Value conds); - ~DBConditions (); - /** Does a specified row of the database match the given criteria? - The row with column names is ignored - hence 0 specifies first data row. */ - bool matches (unsigned row); - private: - void parse (Value conds); - ValueCalc *calc; - Condition **cond; - int rows, cols; - Value db; -}; - -DBConditions::DBConditions (ValueCalc *vc, Value database, - Value conds) : calc(vc), cond(0), rows(0), cols(0), db(database) -{ - parse (conds); -} - -DBConditions::~DBConditions () { - int count = rows*cols; - for (int r = 0; r < count; ++r) - delete cond[r]; - delete[] cond; -} - -void DBConditions::parse (Value conds) -{ - // initialize the array - rows = conds.rows() - 1; - cols = db.columns(); - int count = rows*cols; - cond = new Condition* [count]; - for (int r = 0; r < count; ++r) - cond[r] = 0; - - // perform the parsing itself - int cc = conds.columns (); - for (int c = 0; c < cc; ++c) - { - // first row contains column names - int col = getFieldIndex (calc, conds.element (c, 0), db); - if (col < 0) continue; // failed - ignore the column - - // fill in the conditions for a given column name - for (int r = 0; r < rows; ++r) { - Value cnd = conds.element (c, r+1); - if (cnd.isEmpty()) continue; - int idx = r * cols + col; - if (cond[idx]) delete cond[idx]; - cond[idx] = new Condition; - calc->getCond (*cond[idx], cnd); - } - } -} - -bool DBConditions::matches (unsigned row) -{ - if (row >= db.rows() - 1) - return false; // out of range - - // we have a match, if at least one row of criteria matches - for (int r = 0; r < rows; ++r) { - // within a row, all criteria must match - bool match = true; - for (int c = 0; c < cols; ++c) { - int idx = r * cols + c; - if (!cond[idx]) continue; - if (!calc->matches (*cond[idx], db.element (c, row + 1))) { - match = false; // didn't match - break; - } - } - if (match) // all conditions in this row matched - return true; - } - - // no row matched - return false; -} - - -// ******************************************* -// *** Function implementations start here *** -// ******************************************* - -// Function: DSUM -Value func_dsum (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value res( Value::Float ); - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) - res = calc->add (res, val); - } - - return res; -} - -// Function: DAVERAGE -Value func_daverage (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value res; - int count = 0; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - res = calc->add (res, val); - count++; - } - } - if (count) res = calc->div (res, count); - return res; -} - -// Function: DCOUNT -Value func_dcount (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - int count = 0; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString())) - count++; - } - - return Value (count); -} - -// Function: DCOUNTA -Value func_dcounta (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - int count = 0; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty()) - count++; - } - - return Value (count); -} - -// Function: DGET -Value func_dget (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - bool match = false; - Value result = Value::errorVALUE(); - int rows = database.rows() - 1; // first row contains column names - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - if (match) { - // error on multiple matches - result = Value::errorVALUE(); - break; - } - result = database.element (fieldIndex, r + 1); - match = true; - } - - return result; -} - -// Function: DMAX -Value func_dmax (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value res; - bool got = false; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - if (!got) { - res = val; - got = true; - } - else - if (calc->greater (val, res)) - res = val; - } - } - - return res; -} - -// Function: DMIN -Value func_dmin (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value res; - bool got = false; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - if (!got) { - res = val; - got = true; - } - else - if (calc->lower (val, res)) - res = val; - } - } - - return res; -} - -// Function: DPRODUCT -Value func_dproduct (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value res = 1.0; - bool got = false; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - got = true; - res = calc->mul (res, val); - } - } - if (got) - return res; - return Value::errorVALUE (); -} - -// Function: DSTDEV -Value func_dstdev (valVector args, ValueCalc *calc, FuncExtra *) -{ - // sqrt (dvar) - return calc->sqrt (func_dvar (args, calc, 0)); -} - -// Function: DSTDEVP -Value func_dstdevp (valVector args, ValueCalc *calc, FuncExtra *) -{ - // sqrt (dvarp) - return calc->sqrt (func_dvarp (args, calc, 0)); -} - -// Function: DVAR -Value func_dvar (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value avg; - int count = 0; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - avg = calc->add (avg, val); - count++; - } - } - if (count < 2) return Value::errorDIV0(); - avg = calc->div (avg, count); - - Value res; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) - res = calc->add (res, calc->sqr (calc->sub (val, avg))); - } - - // res / (count-1) - return calc->div (res, count - 1); -} - -// Function: DVARP -Value func_dvarp (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - Value conditions = args[2]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - - DBConditions conds (calc, database, conditions); - - int rows = database.rows() - 1; // first row contains column names - Value avg; - int count = 0; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) { - avg = calc->add (avg, val); - count++; - } - } - if (count == 0) return Value::errorDIV0(); - avg = calc->div (avg, count); - - Value res; - for (int r = 0; r < rows; ++r) - if (conds.matches (r)) { - Value val = database.element (fieldIndex, r + 1); - // include this value in the result - if (!val.isEmpty ()) - res = calc->add (res, calc->sqr (calc->sub (val, avg))); - } - - // res / count - return calc->div (res, count); -} - -// Function: GETPIVOTDATA -// FIXME implement more things with this, see Excel ! -Value func_getpivotdata (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value database = args[0]; - int fieldIndex = getFieldIndex (calc, args[1], database); - if (fieldIndex < 0) - return Value::errorVALUE(); - // the row at the bottom - int row = database.rows() - 1; - - return database.element (fieldIndex, row); -} diff --git a/kspread/kspread_functions_database.cpp b/kspread/kspread_functions_database.cpp new file mode 100644 index 00000000..a294914d --- /dev/null +++ b/kspread/kspread_functions_database.cpp @@ -0,0 +1,537 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in database functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +using namespace KSpread; + +// prototypes +Value func_daverage (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dcount (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dcounta (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dget (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dmax (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dmin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dproduct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dstdev (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dstdevp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dsum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dvar (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dvarp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_getpivotdata (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all database functions +void RegisterDatabaseFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("DAVERAGE", func_daverage); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DCOUNT", func_dcount); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DCOUNTA", func_dcounta); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DGET", func_dget); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DMAX", func_dmax); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DMIN", func_dmin); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DPRODUCT", func_dproduct); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DSTDEV", func_dstdev); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DSTDEVP", func_dstdevp); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DSUM", func_dsum); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DVAR", func_dvar); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DVARP", func_dvarp); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("GETPIVOTDATA", func_getpivotdata); // partially Excel-compatible + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); +} + +int getFieldIndex (ValueCalc *calc, Value fieldName, + Value database) +{ + if (fieldName.isNumber()) + return fieldName.asInteger() - 1; + if (!fieldName.isString ()) + return -1; + + TQString fn = fieldName.asString(); + int cols = database.columns (); + for (int i = 0; i < cols; ++i) + if (fn.lower() == + calc->conv()->asString (database.element (i, 0)).asString().lower()) + return i; + return -1; +} + +// *********************************************************** +// *** DBConditions class - maintains an array of conditions *** +// *********************************************************** + +class DBConditions { + public: + DBConditions (ValueCalc *vc, Value database, Value conds); + ~DBConditions (); + /** Does a specified row of the database match the given criteria? + The row with column names is ignored - hence 0 specifies first data row. */ + bool matches (unsigned row); + private: + void parse (Value conds); + ValueCalc *calc; + Condition **cond; + int rows, cols; + Value db; +}; + +DBConditions::DBConditions (ValueCalc *vc, Value database, + Value conds) : calc(vc), cond(0), rows(0), cols(0), db(database) +{ + parse (conds); +} + +DBConditions::~DBConditions () { + int count = rows*cols; + for (int r = 0; r < count; ++r) + delete cond[r]; + delete[] cond; +} + +void DBConditions::parse (Value conds) +{ + // initialize the array + rows = conds.rows() - 1; + cols = db.columns(); + int count = rows*cols; + cond = new Condition* [count]; + for (int r = 0; r < count; ++r) + cond[r] = 0; + + // perform the parsing itself + int cc = conds.columns (); + for (int c = 0; c < cc; ++c) + { + // first row contains column names + int col = getFieldIndex (calc, conds.element (c, 0), db); + if (col < 0) continue; // failed - ignore the column + + // fill in the conditions for a given column name + for (int r = 0; r < rows; ++r) { + Value cnd = conds.element (c, r+1); + if (cnd.isEmpty()) continue; + int idx = r * cols + col; + if (cond[idx]) delete cond[idx]; + cond[idx] = new Condition; + calc->getCond (*cond[idx], cnd); + } + } +} + +bool DBConditions::matches (unsigned row) +{ + if (row >= db.rows() - 1) + return false; // out of range + + // we have a match, if at least one row of criteria matches + for (int r = 0; r < rows; ++r) { + // within a row, all criteria must match + bool match = true; + for (int c = 0; c < cols; ++c) { + int idx = r * cols + c; + if (!cond[idx]) continue; + if (!calc->matches (*cond[idx], db.element (c, row + 1))) { + match = false; // didn't match + break; + } + } + if (match) // all conditions in this row matched + return true; + } + + // no row matched + return false; +} + + +// ******************************************* +// *** Function implementations start here *** +// ******************************************* + +// Function: DSUM +Value func_dsum (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value res( Value::Float ); + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) + res = calc->add (res, val); + } + + return res; +} + +// Function: DAVERAGE +Value func_daverage (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value res; + int count = 0; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + res = calc->add (res, val); + count++; + } + } + if (count) res = calc->div (res, count); + return res; +} + +// Function: DCOUNT +Value func_dcount (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + int count = 0; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString())) + count++; + } + + return Value (count); +} + +// Function: DCOUNTA +Value func_dcounta (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + int count = 0; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty()) + count++; + } + + return Value (count); +} + +// Function: DGET +Value func_dget (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + bool match = false; + Value result = Value::errorVALUE(); + int rows = database.rows() - 1; // first row contains column names + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + if (match) { + // error on multiple matches + result = Value::errorVALUE(); + break; + } + result = database.element (fieldIndex, r + 1); + match = true; + } + + return result; +} + +// Function: DMAX +Value func_dmax (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value res; + bool got = false; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + if (!got) { + res = val; + got = true; + } + else + if (calc->greater (val, res)) + res = val; + } + } + + return res; +} + +// Function: DMIN +Value func_dmin (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value res; + bool got = false; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + if (!got) { + res = val; + got = true; + } + else + if (calc->lower (val, res)) + res = val; + } + } + + return res; +} + +// Function: DPRODUCT +Value func_dproduct (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value res = 1.0; + bool got = false; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + got = true; + res = calc->mul (res, val); + } + } + if (got) + return res; + return Value::errorVALUE (); +} + +// Function: DSTDEV +Value func_dstdev (valVector args, ValueCalc *calc, FuncExtra *) +{ + // sqrt (dvar) + return calc->sqrt (func_dvar (args, calc, 0)); +} + +// Function: DSTDEVP +Value func_dstdevp (valVector args, ValueCalc *calc, FuncExtra *) +{ + // sqrt (dvarp) + return calc->sqrt (func_dvarp (args, calc, 0)); +} + +// Function: DVAR +Value func_dvar (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value avg; + int count = 0; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + avg = calc->add (avg, val); + count++; + } + } + if (count < 2) return Value::errorDIV0(); + avg = calc->div (avg, count); + + Value res; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) + res = calc->add (res, calc->sqr (calc->sub (val, avg))); + } + + // res / (count-1) + return calc->div (res, count - 1); +} + +// Function: DVARP +Value func_dvarp (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + Value conditions = args[2]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + + DBConditions conds (calc, database, conditions); + + int rows = database.rows() - 1; // first row contains column names + Value avg; + int count = 0; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) { + avg = calc->add (avg, val); + count++; + } + } + if (count == 0) return Value::errorDIV0(); + avg = calc->div (avg, count); + + Value res; + for (int r = 0; r < rows; ++r) + if (conds.matches (r)) { + Value val = database.element (fieldIndex, r + 1); + // include this value in the result + if (!val.isEmpty ()) + res = calc->add (res, calc->sqr (calc->sub (val, avg))); + } + + // res / count + return calc->div (res, count); +} + +// Function: GETPIVOTDATA +// FIXME implement more things with this, see Excel ! +Value func_getpivotdata (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value database = args[0]; + int fieldIndex = getFieldIndex (calc, args[1], database); + if (fieldIndex < 0) + return Value::errorVALUE(); + // the row at the bottom + int row = database.rows() - 1; + + return database.element (fieldIndex, row); +} diff --git a/kspread/kspread_functions_datetime.cc b/kspread/kspread_functions_datetime.cc deleted file mode 100644 index d322b6a4..00000000 --- a/kspread/kspread_functions_datetime.cc +++ /dev/null @@ -1,650 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2003 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in date/time functions - -#include "functions.h" -#include "kspread_functions_helper.h" -#include "valuecalc.h" -#include "valueconverter.h" - -#include -#include - -using namespace KSpread; - -// prototypes, sorted -Value func_currentDate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_currentDateTime (valVector args, ValueCalc *calc, FuncExtra *); -Value func_currentTime (valVector args, ValueCalc *calc, FuncExtra *); -Value func_date (valVector args, ValueCalc *calc, FuncExtra *); -Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *); -Value func_day (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *); -Value func_days (valVector args, ValueCalc *calc, FuncExtra *); -Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *); -Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *); -Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *); -Value func_edate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hour (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hours (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_minute (valVector args, ValueCalc *calc, FuncExtra *); -Value func_minutes (valVector args, ValueCalc *calc, FuncExtra *); -Value func_month (valVector args, ValueCalc *calc, FuncExtra *); -Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *); -Value func_months (valVector args, ValueCalc *calc, FuncExtra *); -Value func_second (valVector args, ValueCalc *calc, FuncExtra *); -Value func_seconds (valVector args, ValueCalc *calc, FuncExtra *); -Value func_time (valVector args, ValueCalc *calc, FuncExtra *); -Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *); -Value func_today (valVector args, ValueCalc *calc, FuncExtra *); -Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *); -Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *); -Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *); -Value func_year (valVector args, ValueCalc *calc, FuncExtra *); -Value func_years (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all date/time functions -// sadly, many of these functions aren't Excel compatible -void RegisterDateTimeFunctions() -{ - // missing: Excel: WORKDAY, NETWORKDAYS, WEEKNUM, DATEDIF - // Gnumeric: UNIX2DATE, DATE2UNIX - // TODO: do we really need DATEVALUE and TIMEVALUE ? - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("CURRENTDATE", func_currentDate); - f->setParamCount (0); - repo->add (f); - f = new Function ("CURRENTDATETIME", func_currentDateTime); - f->setParamCount (0); - repo->add (f); - f = new Function ("CURRENTTIME", func_currentTime); - f->setParamCount (0); - repo->add (f); - f = new Function ("DATE", func_date); - f->setParamCount (3); - repo->add (f); - f = new Function ("DATEVALUE", func_datevalue); - repo->add (f); - f = new Function ("DAY", func_day); - repo->add (f); - f = new Function ("DAYNAME", func_dayname); - repo->add (f); - f = new Function ("DAYOFYEAR", func_dayOfYear); - f->setParamCount (3); - repo->add (f); - f = new Function ("DAYS", func_days); - f->setParamCount (2); - repo->add (f); - f = new Function ("DAYS360", func_days360); - f->setParamCount (2, 3); - repo->add (f); - f = new Function ("DAYSINMONTH", func_daysInMonth); - f->setParamCount (2); - repo->add (f); - f = new Function ("DAYSINYEAR", func_daysInYear); - repo->add (f); - f = new Function ("EASTERSUNDAY", func_easterSunday); - repo->add (f); - f = new Function ("EDATE", func_edate); - f->setParamCount (2); - repo->add (f); - f = new Function ("EOMONTH", func_eomonth); - f->setParamCount (2); - repo->add (f); - f = new Function ("HOUR", func_hour); - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("HOURS", func_hour); // same as HOUR - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("ISLEAPYEAR", func_isLeapYear); - repo->add (f); - f = new Function ("ISOWEEKNUM", func_isoWeekNum); - repo->add (f); - f = new Function ("MINUTE", func_minute); - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("MINUTES", func_minute); // same as MINUTE - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("MONTH", func_month); - repo->add (f); - f = new Function ("MONTHNAME", func_monthname); - repo->add (f); - f = new Function ("MONTHS", func_months); - f->setParamCount (3); - repo->add (f); - f = new Function ("NOW", func_currentDateTime); - f->setParamCount (0); - repo->add (f); - f = new Function ("SECOND", func_second); - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("SECONDS", func_second); // same as SECOND - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("TIME", func_time); - f->setParamCount (3); - repo->add (f); - f = new Function ("TIMEVALUE", func_timevalue); - repo->add (f); - f = new Function ("TODAY", func_currentDate); - f->setParamCount (0); - repo->add (f); - f = new Function ("WEEKDAY", func_weekday); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("WEEKS", func_weeks); - f->setParamCount (3); - repo->add (f); - f = new Function ("WEEKSINYEAR", func_weeksInYear); - repo->add (f); - f = new Function ("YEAR", func_year); - repo->add (f); - f = new Function ("YEARS", func_years); - f->setParamCount (3); - repo->add (f); -} - -// Function: EDATE -Value func_edate (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date = calc->conv()->asDate (args[0]).asDate(); - int months = calc->conv()->asInteger (args[1]).asInteger(); - - date = calc->conv()->locale()->calendar()->addMonths (date, months); - - if (!date.isValid()) - return Value::errorVALUE(); - - return Value (date); -} - -// Function: EOMONTH -Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *) -{ - // add months to date using EDATE - Value modDate = func_edate (args, calc, 0); - if (modDate.isError()) return modDate; - - // modDate is currently in Date format - TQDate date = modDate.asDate(); - date.setYMD (date.year(), date.month(), date.daysInMonth()); - - return Value (date); -} - -// Function: DAYS360 -// algorithm adapted from gnumeric -Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date1 = calc->conv()->asDate (args[0]).asDate(); - TQDate date2 = calc->conv()->asDate (args[1]).asDate(); - bool european = false; - if (args.count() == 3) - european = calc->conv()->asBoolean (args[2]).asBoolean(); - - int day1, day2; - int month1, month2; - int year1, year2; - bool negative = false; - - if (date1.daysTo( date2 ) < 0) - { - TQDate tmp( date1 ); - date1 = date2; - date2 = tmp; - negative = true; - } - - day1 = date1.day(); - day2 = date2.day(); - month1 = date1.month(); - month2 = date2.month(); - year1 = date1.year(); - year2 = date2.year(); - - if ( european ) - { - if ( day1 == 31 ) - day1 = 30; - if ( day2 == 31 ) - day2 = 30; - } - else - { - // thanks to the Gnumeric developers for this... - if ( month1 == 2 && month2 == 2 - && date1.daysInMonth() == day1 - && date2.daysInMonth() == day2 ) - day2 = 30; - - if ( month1 == 2 && date1.daysInMonth() == day1 ) - day1 = 30; - - if ( day2 == 31 && day1 >= 30 ) - day2 = 30; - - if ( day1 == 31 ) - day1 = 30; - } - - int result = ( ( year2 - year1 ) * 12 + ( month2 - month1 ) ) * 30 - + ( day2 - day1 ); - - return Value (result); -} - -// Function: YEAR -Value func_year (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value v = calc->conv()->asDate (args[0]); - if (v.isError()) return v; - TQDate date = v.asDate(); - return Value (date.year ()); -} - -// Function: MONTH -Value func_month (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value v = calc->conv()->asDate (args[0]); - if (v.isError()) return v; - TQDate date = v.asDate(); - return Value (date.month ()); -} - -// Function: DAY -Value func_day (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value v = calc->conv()->asDate (args[0]); - if (v.isError()) return v; - TQDate date = v.asDate(); - return Value (date.day ()); -} - -// Function: HOUR -Value func_hour (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQTime time; - if (args.count() == 1) - { - Value v = calc->conv()->asTime (args[0]); - if (v.isError()) return v; - time = v.asTime(); - } - else - time = TQTime::currentTime (); - return Value (time.hour ()); -} - -// Function: MINUTE -Value func_minute (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQTime time; - if (args.count() == 1) - { - Value v = calc->conv()->asTime (args[0]); - if (v.isError()) return v; - time = v.asTime(); - } - else - time = TQTime::currentTime (); - return Value (time.minute ()); -} - -// Function: SECOND -Value func_second (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQTime time; - if (args.count() == 1) - { - Value v = calc->conv()->asTime (args[0]); - if (v.isError()) return v; - time = v.asTime(); - } - else - time = TQTime::currentTime (); - return Value (time.second ()); -} - -// Function: weekday -Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value v = calc->conv()->asDate (args[0]).asDate(); - if (v.isError()) return v; - TQDate date = v.asDate(); - int method = 1; - if (args.count() == 2) - method = calc->conv()->asInteger (args[1]).asInteger(); - - if ( method < 1 || method > 3 ) - return Value::errorVALUE(); - - int result = date.dayOfWeek(); - - if (method == 3) - --result; - else if (method == 1) - { - ++result; - result = result % 7; - } - - return Value (result); -} - -// Function: datevalue -// same result would be obtained by applying number format on a date value -Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args[0].isString()) { - Value v = calc->conv()->asDate (args[0]); - if (! v.isError()) - return calc->conv()->asFloat (v); - } - return Value::errorVALUE(); -} - -// Function: timevalue -// same result would be obtained by applying number format on a time value -Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args[0].isString()) { - Value v = calc->conv()->asTime (args[0]); - if (! v.isError()) - return calc->conv()->asFloat (v); - } - return Value::errorVALUE(); -} - -// Function: years -Value func_years (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date1 = calc->conv()->asDate (args[0]).asDate(); - TQDate date2 = calc->conv()->asDate (args[1]).asDate(); - if (!date1.isValid() || !date2.isValid()) - return Value::errorVALUE(); - - int type = calc->conv()->asInteger (args[2]).asInteger(); - if (type == 0) - { - // max. possible years between both dates - int years = date2.year() - date1.year(); - - if (date2.month() < date1.month()) - --years; - else if ( (date2.month() == date1.month()) && (date2.day() < date1.day()) ) - --years; - - return Value (years); - } - - // type is non-zero now - // the number of full years in between, starting on 1/1/XXXX - if ( date1.year() == date2.year() ) - return Value (0); - - if ( (date1.month() != 1) || (date1.day() != 1) ) - date1.setYMD(date1.year() + 1, 1, 1); - date2.setYMD(date2.year(), 1, 1); - - return Value (date2.year() - date1.year()); -} - -// Function: months -Value func_months (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date1 = calc->conv()->asDate (args[0]).asDate(); - TQDate date2 = calc->conv()->asDate (args[1]).asDate(); - if (!date1.isValid() || !date2.isValid()) - return Value::errorVALUE(); - - int type = calc->conv()->asInteger (args[2]).asInteger(); - if (type == 0) - { - int months = (date2.year() - date1.year()) * 12; - months += date2.month() - date1.month(); - - if (date2.day() < date1.day()) - if (date2.day() != date2.daysInMonth()) - --months; - - return Value (months); - } - - // type is now non-zero - // the number of full months in between, starting on 1/XX/XXXX - if (date1.month() == 12) - date1.setYMD(date1.year() + 1, 1, 1); - else - date1.setYMD(date1.year(), date1.month() + 1, 1); - date2.setYMD(date2.year(), date2.month(), 1); - - int months = (date2.year() - date1.year()) * 12; - months += date2.month() - date1.month(); - - return Value (months); -} - -// Function: weeks -Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date1 = calc->conv()->asDate (args[0]).asDate(); - TQDate date2 = calc->conv()->asDate (args[1]).asDate(); - if (!date1.isValid() || !date2.isValid()) - return Value::errorVALUE(); - - int type = calc->conv()->asInteger (args[2]).asInteger(); - int days = date1.daysTo (date2); - if (type == 0) - // just the number of full weeks between - return Value ((int) (days / 7)); - - // the number of full weeks between starting on mondays - int weekStartDay = calc->conv()->locale()->weekStartDay(); - - int dow1 = date1.dayOfWeek(); - int dow2 = date2.dayOfWeek(); - - days -= (7 + (weekStartDay % 7) - dow1); - days -= ((dow2 - weekStartDay) % 7); - - return Value ((int) (days / 7)); -} - -// Function: days -Value func_days (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date1 = calc->conv()->asDate (args[0]).asDate(); - TQDate date2 = calc->conv()->asDate (args[1]).asDate(); - if (!date1.isValid() || !date2.isValid()) - return Value::errorVALUE(); - - return Value (date1.daysTo (date2)); -} - -// Function: date -Value func_date (valVector args, ValueCalc *calc, FuncExtra *) -{ - int y = calc->conv()->asInteger (args[0]).asInteger(); - int m = calc->conv()->asInteger (args[1]).asInteger(); - int d = calc->conv()->asInteger (args[2]).asInteger(); - - TQDate _date; - if( _date.setYMD (y, m, d)) - return Value (_date); - return Value::errorVALUE(); -} - -// Function: day -Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *) -{ - int number = calc->conv()->asInteger (args[0]).asInteger(); - - TQString weekName = calc->conv()->locale()->calendar()->weekDayName (number); - if (weekName.isNull()) - return Value::errorVALUE(); - return Value (weekName); -} - -// Function: monthname -Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *) -{ - int number = calc->conv()->asInteger (args[0]).asInteger(); - - TQString monthName = calc->conv()->locale()->calendar()->monthName (number, - TQDate::currentDate().year()); - if (monthName.isNull()) - return Value::errorVALUE(); - return Value (monthName); -} - -// Function: time -Value func_time (valVector args, ValueCalc *calc, FuncExtra *) -{ - int h = calc->conv()->asInteger (args[0]).asInteger(); - int m = calc->conv()->asInteger (args[1]).asInteger(); - int s = calc->conv()->asInteger (args[2]).asInteger(); - - /* normalize the data */ - m += s / 60; - s = s % 60; - h += m / 60; - m = m % 60; - // we'll lose hours data that carries over into days - h = h % 24; - - // now carry down hours/minutes for negative minutes/seconds - if (s < 0) { - s += 60; - m -= 1; - } - if (m < 0) { - m += 60; - h -= 1; - } - if (h < 0) - h += 24; - - return Value (TQTime (h, m, s)); -} - -// Function: currentDate -Value func_currentDate (valVector, ValueCalc *, FuncExtra *) -{ - return Value (TQDate::currentDate ()); -} - -// Function: currentTime -Value func_currentTime (valVector, ValueCalc *, FuncExtra *) -{ - return Value (TQTime::currentTime ()); -} - -// Function: currentDateTime -Value func_currentDateTime (valVector, ValueCalc *, FuncExtra *) -{ - return Value (TQDateTime::currentDateTime ()); -} - -// Function: dayOfYear -Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value date = func_date (args, calc, 0); - if (date.isError()) return date; - return Value (date.asDate().dayOfYear()); -} - -// Function: daysInMonth -Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *) -{ - int y = calc->conv()->asInteger (args[0]).asInteger(); - int m = calc->conv()->asInteger (args[1]).asInteger(); - TQDate date (y, m, 1); - return Value (date.daysInMonth()); -} - -// Function: isLeapYear -Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *) -{ - int y = calc->conv()->asInteger (args[0]).asInteger(); - return Value (TQDate::leapYear (y)); -} - -// Function: daysInYear -Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *) -{ - int y = calc->conv()->asInteger (args[0]).asInteger(); - return Value (TQDate::leapYear (y) ? 366 : 365); -} - -// Function: weeksInYear -Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *) -{ - int y = calc->conv()->asInteger (args[0]).asInteger(); - TQDate date (y, 12, 31); // last day of the year - return Value (date.weekNumber ()); -} - -// Function: easterSunday -Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *) -{ - int nDay, nMonth; - int nYear = calc->conv()->asInteger (args[0]).asInteger(); - - // (Tomas) the person who wrote this should be hanged :> - int B,C,D,E,F,G,H,I,K,L,M,N,O; - N = nYear % 19; - B = int(nYear / 100); - C = nYear % 100; - D = int(B / 4); - E = B % 4; - F = int((B + 8) / 25); - G = int((B - F + 1) / 3); - H = (19 * N + B - D - G + 15) % 30; - I = int(C / 4); - K = C % 4; - L = (32 + 2 * E + 2 * I - H - K) % 7; - M = int((N + 11 * H + 22 * L) / 451); - O = H + L - 7 * M + 114; - nDay = O % 31 + 1; - nMonth = int(O / 31); - - return Value (TQDate (nYear, nMonth, nDay)); -} - -// Function: isoWeekNum -Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate date = calc->conv()->asDate (args[0]).asDate(); - if (!date.isValid()) - return Value::errorVALUE(); - - return Value (date.weekNumber()); -} diff --git a/kspread/kspread_functions_datetime.cpp b/kspread/kspread_functions_datetime.cpp new file mode 100644 index 00000000..d322b6a4 --- /dev/null +++ b/kspread/kspread_functions_datetime.cpp @@ -0,0 +1,650 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2003 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in date/time functions + +#include "functions.h" +#include "kspread_functions_helper.h" +#include "valuecalc.h" +#include "valueconverter.h" + +#include +#include + +using namespace KSpread; + +// prototypes, sorted +Value func_currentDate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_currentDateTime (valVector args, ValueCalc *calc, FuncExtra *); +Value func_currentTime (valVector args, ValueCalc *calc, FuncExtra *); +Value func_date (valVector args, ValueCalc *calc, FuncExtra *); +Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *); +Value func_day (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *); +Value func_days (valVector args, ValueCalc *calc, FuncExtra *); +Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *); +Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *); +Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *); +Value func_edate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hour (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hours (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_minute (valVector args, ValueCalc *calc, FuncExtra *); +Value func_minutes (valVector args, ValueCalc *calc, FuncExtra *); +Value func_month (valVector args, ValueCalc *calc, FuncExtra *); +Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *); +Value func_months (valVector args, ValueCalc *calc, FuncExtra *); +Value func_second (valVector args, ValueCalc *calc, FuncExtra *); +Value func_seconds (valVector args, ValueCalc *calc, FuncExtra *); +Value func_time (valVector args, ValueCalc *calc, FuncExtra *); +Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *); +Value func_today (valVector args, ValueCalc *calc, FuncExtra *); +Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *); +Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *); +Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *); +Value func_year (valVector args, ValueCalc *calc, FuncExtra *); +Value func_years (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all date/time functions +// sadly, many of these functions aren't Excel compatible +void RegisterDateTimeFunctions() +{ + // missing: Excel: WORKDAY, NETWORKDAYS, WEEKNUM, DATEDIF + // Gnumeric: UNIX2DATE, DATE2UNIX + // TODO: do we really need DATEVALUE and TIMEVALUE ? + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("CURRENTDATE", func_currentDate); + f->setParamCount (0); + repo->add (f); + f = new Function ("CURRENTDATETIME", func_currentDateTime); + f->setParamCount (0); + repo->add (f); + f = new Function ("CURRENTTIME", func_currentTime); + f->setParamCount (0); + repo->add (f); + f = new Function ("DATE", func_date); + f->setParamCount (3); + repo->add (f); + f = new Function ("DATEVALUE", func_datevalue); + repo->add (f); + f = new Function ("DAY", func_day); + repo->add (f); + f = new Function ("DAYNAME", func_dayname); + repo->add (f); + f = new Function ("DAYOFYEAR", func_dayOfYear); + f->setParamCount (3); + repo->add (f); + f = new Function ("DAYS", func_days); + f->setParamCount (2); + repo->add (f); + f = new Function ("DAYS360", func_days360); + f->setParamCount (2, 3); + repo->add (f); + f = new Function ("DAYSINMONTH", func_daysInMonth); + f->setParamCount (2); + repo->add (f); + f = new Function ("DAYSINYEAR", func_daysInYear); + repo->add (f); + f = new Function ("EASTERSUNDAY", func_easterSunday); + repo->add (f); + f = new Function ("EDATE", func_edate); + f->setParamCount (2); + repo->add (f); + f = new Function ("EOMONTH", func_eomonth); + f->setParamCount (2); + repo->add (f); + f = new Function ("HOUR", func_hour); + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("HOURS", func_hour); // same as HOUR + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("ISLEAPYEAR", func_isLeapYear); + repo->add (f); + f = new Function ("ISOWEEKNUM", func_isoWeekNum); + repo->add (f); + f = new Function ("MINUTE", func_minute); + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("MINUTES", func_minute); // same as MINUTE + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("MONTH", func_month); + repo->add (f); + f = new Function ("MONTHNAME", func_monthname); + repo->add (f); + f = new Function ("MONTHS", func_months); + f->setParamCount (3); + repo->add (f); + f = new Function ("NOW", func_currentDateTime); + f->setParamCount (0); + repo->add (f); + f = new Function ("SECOND", func_second); + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("SECONDS", func_second); // same as SECOND + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("TIME", func_time); + f->setParamCount (3); + repo->add (f); + f = new Function ("TIMEVALUE", func_timevalue); + repo->add (f); + f = new Function ("TODAY", func_currentDate); + f->setParamCount (0); + repo->add (f); + f = new Function ("WEEKDAY", func_weekday); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("WEEKS", func_weeks); + f->setParamCount (3); + repo->add (f); + f = new Function ("WEEKSINYEAR", func_weeksInYear); + repo->add (f); + f = new Function ("YEAR", func_year); + repo->add (f); + f = new Function ("YEARS", func_years); + f->setParamCount (3); + repo->add (f); +} + +// Function: EDATE +Value func_edate (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date = calc->conv()->asDate (args[0]).asDate(); + int months = calc->conv()->asInteger (args[1]).asInteger(); + + date = calc->conv()->locale()->calendar()->addMonths (date, months); + + if (!date.isValid()) + return Value::errorVALUE(); + + return Value (date); +} + +// Function: EOMONTH +Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *) +{ + // add months to date using EDATE + Value modDate = func_edate (args, calc, 0); + if (modDate.isError()) return modDate; + + // modDate is currently in Date format + TQDate date = modDate.asDate(); + date.setYMD (date.year(), date.month(), date.daysInMonth()); + + return Value (date); +} + +// Function: DAYS360 +// algorithm adapted from gnumeric +Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date1 = calc->conv()->asDate (args[0]).asDate(); + TQDate date2 = calc->conv()->asDate (args[1]).asDate(); + bool european = false; + if (args.count() == 3) + european = calc->conv()->asBoolean (args[2]).asBoolean(); + + int day1, day2; + int month1, month2; + int year1, year2; + bool negative = false; + + if (date1.daysTo( date2 ) < 0) + { + TQDate tmp( date1 ); + date1 = date2; + date2 = tmp; + negative = true; + } + + day1 = date1.day(); + day2 = date2.day(); + month1 = date1.month(); + month2 = date2.month(); + year1 = date1.year(); + year2 = date2.year(); + + if ( european ) + { + if ( day1 == 31 ) + day1 = 30; + if ( day2 == 31 ) + day2 = 30; + } + else + { + // thanks to the Gnumeric developers for this... + if ( month1 == 2 && month2 == 2 + && date1.daysInMonth() == day1 + && date2.daysInMonth() == day2 ) + day2 = 30; + + if ( month1 == 2 && date1.daysInMonth() == day1 ) + day1 = 30; + + if ( day2 == 31 && day1 >= 30 ) + day2 = 30; + + if ( day1 == 31 ) + day1 = 30; + } + + int result = ( ( year2 - year1 ) * 12 + ( month2 - month1 ) ) * 30 + + ( day2 - day1 ); + + return Value (result); +} + +// Function: YEAR +Value func_year (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value v = calc->conv()->asDate (args[0]); + if (v.isError()) return v; + TQDate date = v.asDate(); + return Value (date.year ()); +} + +// Function: MONTH +Value func_month (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value v = calc->conv()->asDate (args[0]); + if (v.isError()) return v; + TQDate date = v.asDate(); + return Value (date.month ()); +} + +// Function: DAY +Value func_day (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value v = calc->conv()->asDate (args[0]); + if (v.isError()) return v; + TQDate date = v.asDate(); + return Value (date.day ()); +} + +// Function: HOUR +Value func_hour (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQTime time; + if (args.count() == 1) + { + Value v = calc->conv()->asTime (args[0]); + if (v.isError()) return v; + time = v.asTime(); + } + else + time = TQTime::currentTime (); + return Value (time.hour ()); +} + +// Function: MINUTE +Value func_minute (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQTime time; + if (args.count() == 1) + { + Value v = calc->conv()->asTime (args[0]); + if (v.isError()) return v; + time = v.asTime(); + } + else + time = TQTime::currentTime (); + return Value (time.minute ()); +} + +// Function: SECOND +Value func_second (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQTime time; + if (args.count() == 1) + { + Value v = calc->conv()->asTime (args[0]); + if (v.isError()) return v; + time = v.asTime(); + } + else + time = TQTime::currentTime (); + return Value (time.second ()); +} + +// Function: weekday +Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value v = calc->conv()->asDate (args[0]).asDate(); + if (v.isError()) return v; + TQDate date = v.asDate(); + int method = 1; + if (args.count() == 2) + method = calc->conv()->asInteger (args[1]).asInteger(); + + if ( method < 1 || method > 3 ) + return Value::errorVALUE(); + + int result = date.dayOfWeek(); + + if (method == 3) + --result; + else if (method == 1) + { + ++result; + result = result % 7; + } + + return Value (result); +} + +// Function: datevalue +// same result would be obtained by applying number format on a date value +Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args[0].isString()) { + Value v = calc->conv()->asDate (args[0]); + if (! v.isError()) + return calc->conv()->asFloat (v); + } + return Value::errorVALUE(); +} + +// Function: timevalue +// same result would be obtained by applying number format on a time value +Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args[0].isString()) { + Value v = calc->conv()->asTime (args[0]); + if (! v.isError()) + return calc->conv()->asFloat (v); + } + return Value::errorVALUE(); +} + +// Function: years +Value func_years (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date1 = calc->conv()->asDate (args[0]).asDate(); + TQDate date2 = calc->conv()->asDate (args[1]).asDate(); + if (!date1.isValid() || !date2.isValid()) + return Value::errorVALUE(); + + int type = calc->conv()->asInteger (args[2]).asInteger(); + if (type == 0) + { + // max. possible years between both dates + int years = date2.year() - date1.year(); + + if (date2.month() < date1.month()) + --years; + else if ( (date2.month() == date1.month()) && (date2.day() < date1.day()) ) + --years; + + return Value (years); + } + + // type is non-zero now + // the number of full years in between, starting on 1/1/XXXX + if ( date1.year() == date2.year() ) + return Value (0); + + if ( (date1.month() != 1) || (date1.day() != 1) ) + date1.setYMD(date1.year() + 1, 1, 1); + date2.setYMD(date2.year(), 1, 1); + + return Value (date2.year() - date1.year()); +} + +// Function: months +Value func_months (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date1 = calc->conv()->asDate (args[0]).asDate(); + TQDate date2 = calc->conv()->asDate (args[1]).asDate(); + if (!date1.isValid() || !date2.isValid()) + return Value::errorVALUE(); + + int type = calc->conv()->asInteger (args[2]).asInteger(); + if (type == 0) + { + int months = (date2.year() - date1.year()) * 12; + months += date2.month() - date1.month(); + + if (date2.day() < date1.day()) + if (date2.day() != date2.daysInMonth()) + --months; + + return Value (months); + } + + // type is now non-zero + // the number of full months in between, starting on 1/XX/XXXX + if (date1.month() == 12) + date1.setYMD(date1.year() + 1, 1, 1); + else + date1.setYMD(date1.year(), date1.month() + 1, 1); + date2.setYMD(date2.year(), date2.month(), 1); + + int months = (date2.year() - date1.year()) * 12; + months += date2.month() - date1.month(); + + return Value (months); +} + +// Function: weeks +Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date1 = calc->conv()->asDate (args[0]).asDate(); + TQDate date2 = calc->conv()->asDate (args[1]).asDate(); + if (!date1.isValid() || !date2.isValid()) + return Value::errorVALUE(); + + int type = calc->conv()->asInteger (args[2]).asInteger(); + int days = date1.daysTo (date2); + if (type == 0) + // just the number of full weeks between + return Value ((int) (days / 7)); + + // the number of full weeks between starting on mondays + int weekStartDay = calc->conv()->locale()->weekStartDay(); + + int dow1 = date1.dayOfWeek(); + int dow2 = date2.dayOfWeek(); + + days -= (7 + (weekStartDay % 7) - dow1); + days -= ((dow2 - weekStartDay) % 7); + + return Value ((int) (days / 7)); +} + +// Function: days +Value func_days (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date1 = calc->conv()->asDate (args[0]).asDate(); + TQDate date2 = calc->conv()->asDate (args[1]).asDate(); + if (!date1.isValid() || !date2.isValid()) + return Value::errorVALUE(); + + return Value (date1.daysTo (date2)); +} + +// Function: date +Value func_date (valVector args, ValueCalc *calc, FuncExtra *) +{ + int y = calc->conv()->asInteger (args[0]).asInteger(); + int m = calc->conv()->asInteger (args[1]).asInteger(); + int d = calc->conv()->asInteger (args[2]).asInteger(); + + TQDate _date; + if( _date.setYMD (y, m, d)) + return Value (_date); + return Value::errorVALUE(); +} + +// Function: day +Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *) +{ + int number = calc->conv()->asInteger (args[0]).asInteger(); + + TQString weekName = calc->conv()->locale()->calendar()->weekDayName (number); + if (weekName.isNull()) + return Value::errorVALUE(); + return Value (weekName); +} + +// Function: monthname +Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *) +{ + int number = calc->conv()->asInteger (args[0]).asInteger(); + + TQString monthName = calc->conv()->locale()->calendar()->monthName (number, + TQDate::currentDate().year()); + if (monthName.isNull()) + return Value::errorVALUE(); + return Value (monthName); +} + +// Function: time +Value func_time (valVector args, ValueCalc *calc, FuncExtra *) +{ + int h = calc->conv()->asInteger (args[0]).asInteger(); + int m = calc->conv()->asInteger (args[1]).asInteger(); + int s = calc->conv()->asInteger (args[2]).asInteger(); + + /* normalize the data */ + m += s / 60; + s = s % 60; + h += m / 60; + m = m % 60; + // we'll lose hours data that carries over into days + h = h % 24; + + // now carry down hours/minutes for negative minutes/seconds + if (s < 0) { + s += 60; + m -= 1; + } + if (m < 0) { + m += 60; + h -= 1; + } + if (h < 0) + h += 24; + + return Value (TQTime (h, m, s)); +} + +// Function: currentDate +Value func_currentDate (valVector, ValueCalc *, FuncExtra *) +{ + return Value (TQDate::currentDate ()); +} + +// Function: currentTime +Value func_currentTime (valVector, ValueCalc *, FuncExtra *) +{ + return Value (TQTime::currentTime ()); +} + +// Function: currentDateTime +Value func_currentDateTime (valVector, ValueCalc *, FuncExtra *) +{ + return Value (TQDateTime::currentDateTime ()); +} + +// Function: dayOfYear +Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value date = func_date (args, calc, 0); + if (date.isError()) return date; + return Value (date.asDate().dayOfYear()); +} + +// Function: daysInMonth +Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *) +{ + int y = calc->conv()->asInteger (args[0]).asInteger(); + int m = calc->conv()->asInteger (args[1]).asInteger(); + TQDate date (y, m, 1); + return Value (date.daysInMonth()); +} + +// Function: isLeapYear +Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *) +{ + int y = calc->conv()->asInteger (args[0]).asInteger(); + return Value (TQDate::leapYear (y)); +} + +// Function: daysInYear +Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *) +{ + int y = calc->conv()->asInteger (args[0]).asInteger(); + return Value (TQDate::leapYear (y) ? 366 : 365); +} + +// Function: weeksInYear +Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *) +{ + int y = calc->conv()->asInteger (args[0]).asInteger(); + TQDate date (y, 12, 31); // last day of the year + return Value (date.weekNumber ()); +} + +// Function: easterSunday +Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *) +{ + int nDay, nMonth; + int nYear = calc->conv()->asInteger (args[0]).asInteger(); + + // (Tomas) the person who wrote this should be hanged :> + int B,C,D,E,F,G,H,I,K,L,M,N,O; + N = nYear % 19; + B = int(nYear / 100); + C = nYear % 100; + D = int(B / 4); + E = B % 4; + F = int((B + 8) / 25); + G = int((B - F + 1) / 3); + H = (19 * N + B - D - G + 15) % 30; + I = int(C / 4); + K = C % 4; + L = (32 + 2 * E + 2 * I - H - K) % 7; + M = int((N + 11 * H + 22 * L) / 451); + O = H + L - 7 * M + 114; + nDay = O % 31 + 1; + nMonth = int(O / 31); + + return Value (TQDate (nYear, nMonth, nDay)); +} + +// Function: isoWeekNum +Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate date = calc->conv()->asDate (args[0]).asDate(); + if (!date.isValid()) + return Value::errorVALUE(); + + return Value (date.weekNumber()); +} diff --git a/kspread/kspread_functions_engineering.cc b/kspread/kspread_functions_engineering.cc deleted file mode 100644 index bca81ec8..00000000 --- a/kspread/kspread_functions_engineering.cc +++ /dev/null @@ -1,1256 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in engineering functions - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -// used by the CONVERT function -#include - -// these are needed for complex functions, while we handle them in the old way -#include -#include -#include - -using namespace KSpread; - -// prototypes (sort alphabetically) -Value func_base (valVector args, ValueCalc *calc, FuncExtra *); -Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *); -Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *); -Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *); -Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *); -Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *); -Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *); -Value func_complex (valVector args, ValueCalc *calc, FuncExtra *); -Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *); -Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *); -Value func_convert (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_delta (valVector args, ValueCalc *calc, FuncExtra *); -Value func_erf (valVector args, ValueCalc *calc, FuncExtra *); -Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *); -Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imln (valVector args, ValueCalc *calc, FuncExtra *); -Value func_impower (valVector args, ValueCalc *calc, FuncExtra *); -Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *); -Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *); -Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all engineering functions -void RegisterEngineeringFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("BASE", func_base); // KSpread-specific, like in Quattro-Pro - f->setParamCount (1, 3); - repo->add (f); - f = new Function ("BESSELI", func_besseli); - f->setParamCount (2); - repo->add (f); - f = new Function ("BESSELJ", func_besselj); - f->setParamCount (2); - repo->add (f); - f = new Function ("BESSELK", func_besselk); - f->setParamCount (2); - repo->add (f); - f = new Function ("BESSELY", func_bessely); - f->setParamCount (2); - repo->add (f); - f = new Function ("BIN2DEC", func_bin2dec); - repo->add (f); - f = new Function ("BIN2OCT", func_bin2oct); - repo->add (f); - f = new Function ("BIN2HEX", func_bin2hex); - repo->add (f); - f = new Function ("COMPLEX", func_complex); - f->setParamCount (2); - repo->add (f); - f = new Function ("CONVERT", func_convert); - f->setParamCount (3); - repo->add (f); - f = new Function ("DEC2HEX", func_dec2hex); - repo->add (f); - f = new Function ("DEC2BIN", func_dec2bin); - repo->add (f); - f = new Function ("DEC2OCT", func_dec2oct); - repo->add (f); - f = new Function ("DELTA", func_delta); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("ERF", func_erf); - f->setParamCount (2); - repo->add (f); - f = new Function ("ERFC", func_erfc); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("GESTEP", func_gestep); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("HEX2BIN", func_hex2bin); - repo->add (f); - f = new Function ("HEX2DEC", func_hex2dec); - repo->add (f); - f = new Function ("HEX2OCT", func_hex2oct); - repo->add (f); - f = new Function ("IMABS", func_imabs); - repo->add (f); - f = new Function ("IMAGINARY", func_complex_imag); - repo->add (f); - f = new Function ("IMARGUMENT", func_imargument); - repo->add (f); - f = new Function ("IMCONJUGATE", func_imconjugate); - repo->add (f); - f = new Function ("IMCOS", func_imcos); - repo->add (f); - f = new Function ("IMDIV", func_imdiv); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("IMEXP", func_imexp); - repo->add (f); - f = new Function ("IMLN", func_imln); - repo->add (f); - f = new Function ("IMPOWER", func_impower); - f->setParamCount (2); - repo->add (f); - f = new Function ("IMPRODUCT", func_improduct); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("IMREAL", func_complex_real); - repo->add (f); - f = new Function ("IMSIN", func_imsin); - repo->add (f); - f = new Function ("IMSQRT", func_imsqrt); - repo->add (f); - f = new Function ("IMSUB", func_imsub); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("IMSUM", func_imsum); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("OCT2BIN", func_oct2bin); - repo->add (f); - f = new Function ("OCT2DEC", func_oct2dec); - repo->add (f); - f = new Function ("OCT2HEX", func_oct2hex); - repo->add (f); -} - -// Function: BASE -Value func_base (valVector args, ValueCalc *calc, FuncExtra *) -{ - int base = 10; - int prec = 0; - if (args.count() > 1) - base = calc->conv()->asInteger (args[1]).asInteger(); - if (args.count() == 3) - prec = calc->conv()->asInteger (args[2]).asInteger(); - - if ((base < 2) || (base > 36)) - return Value::errorVALUE(); - if (prec < 0) prec = 2; - - return calc->base (args[0], base, prec); -} - -// Function: BESSELI -Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value y = args[1]; - return calc->besseli (y, x); -} - -// Function: BESSELJ -Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value y = args[1]; - return calc->besselj (y, x); -} - -// Function: BESSELK -Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value y = args[1]; - return calc->besselk (y, x); -} - -// Function: BESSELY -Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value y = args[1]; - return calc->besseln (y, x); -} - -// Function: DEC2HEX -Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (args[0], 16); -} - -// Function: DEC2OCT -Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (args[0], 8); -} - -// Function: DEC2BIN -Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (args[0], 2); -} - -// Function: BIN2DEC -Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->fromBase (args[0], 2); -} - -// Function: BIN2OCT -Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 2), 8); -} - -// Function: BIN2HEX -Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 2), 16); -} - -// Function: OCT2DEC -Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->fromBase (args[0], 8); -} - -// Function: OCT2BIN -Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 8), 2); -} - -// Function: OCT2HEX -Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 8), 16); -} - -// Function: HEX2DEC -Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->fromBase (args[0], 16); -} - -// Function: HEX2BIN -Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 16), 2); -} - -// Function: HEX2OCT -Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->base (calc->fromBase (args[0], 16), 8); -} - - -// check if unit may contain prefix, for example "kPa" is "Pa" with -// return prefix factor found in unit, or 1.0 for no prefix -// also modify the unit, i.e stripping the prefix from it -// example: "kPa" will return 1e3 and change unit into "Pa" -static double kspread_convert_prefix( TQMap map, TQString& unit ) -{ - if( map.contains( unit ) ) - return 1.0; - - // initialize prefix mapping if necessary - static TQMap prefixMap; - if( prefixMap.isEmpty() ) - { - prefixMap[ 'E' ] = 1e18; // exa - prefixMap[ 'P' ] = 1e15; // peta - prefixMap[ 'T' ] = 1e12; // tera - prefixMap[ 'G' ] = 1e9; // giga - prefixMap[ 'M' ] = 1e6; // mega - prefixMap[ 'k' ] = 1e3; // kilo - prefixMap[ 'h' ] = 1e2; // hecto - prefixMap[ 'e' ] = 1e1; // dekao - prefixMap[ 'd' ] = 1e1; // deci - prefixMap[ 'c' ] = 1e2; // centi - prefixMap[ 'm' ] = 1e3; // milli - prefixMap[ 'u' ] = 1e6; // micro - prefixMap[ 'n' ] = 1e9; // nano - prefixMap[ 'p' ] = 1e12; // pico - prefixMap[ 'f' ] = 1e15; // femto - prefixMap[ 'a' ] = 1e18; // atto - } - - // check for possible prefix - char prefix = unit[0].latin1(); - if( prefixMap.contains( prefix ) ) - { - unit.remove( 0, 1 ); - return prefixMap[ prefix ]; - } - - // fail miserably - return 0.0; -} - -static bool kspread_convert_mass( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap massMap; - - // first-time initialization - if( massMap.isEmpty() ) - { - massMap[ "g" ] = 1.0; // Gram (the reference ) - massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces - massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound - massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass) - massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce - massMap[ "stone" ] = 1.574730e-04; // Stone - massMap[ "ton" ] = 1.102311e-06; // Ton - massMap[ "grain" ] = 1.543236E01; // Grain - massMap[ "pweight" ] = 7.054792E-01; // Pennyweight - massMap[ "hweight" ] = 1.968413E-05; // Hundredweight - massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight - massMap[ "brton" ] = 9.842065E-07; // Gross Registered Ton - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( massMap, fromU ); - double toPrefix = kspread_convert_prefix( massMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !massMap.contains( fromU ) ) return false; - if( !massMap.contains( toU ) ) return false; - - result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix); - - return true; -} - - -static bool kspread_convert_distance( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap distanceMap; - - // first-time initialization - if( distanceMap.isEmpty() ) - { - distanceMap[ "m" ] = 1.0; // meter (the reference) - distanceMap[ "in" ] = 1.0 / 0.0254; // inch - distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet - distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yar - distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile - distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile - distanceMap[ "ang" ] = 1e10; // Angstrom - distanceMap[ "parsec" ] = 3.240779e-17; // Parsec - distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( distanceMap, fromU ); - double toPrefix = kspread_convert_prefix( distanceMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !distanceMap.contains( fromU ) ) return false; - if( !distanceMap.contains( toU ) ) return false; - - result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_pressure( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap pressureMap; - - // first-time initialization - if( pressureMap.isEmpty() ) - { - pressureMap[ "Pa" ] = 1.0; - pressureMap[ "atm" ] = 0.9869233e-5; - pressureMap[ "mmHg" ] = 0.00750061708; - pressureMap[ "psi" ] = 1 / 6894.754; - pressureMap[ "Torr" ] = 1 / 133.32237; - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( pressureMap, fromU ); - double toPrefix = kspread_convert_prefix( pressureMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !pressureMap.contains( fromU ) ) return false; - if( !pressureMap.contains( toU ) ) return false; - - result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_force( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap forceMap; - - // first-time initialization - if( forceMap.isEmpty() ) - { - forceMap[ "N" ] = 1.0; // Newton (reference) - forceMap[ "dyn" ] = 1.0e5; // dyn - forceMap[ "pond" ] = 1.019716e2; // pond - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( forceMap, fromU ); - double toPrefix = kspread_convert_prefix( forceMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !forceMap.contains( fromU ) ) return false; - if( !forceMap.contains( toU ) ) return false; - - result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_energy( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap energyMap; - - // first-time initialization - if( energyMap.isEmpty() ) - { - energyMap[ "J" ] = 1.0; // Joule (the reference) - energyMap[ "e" ] = 1.0e7; //erg - energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie - energyMap[ "cal" ] = 0.238846190642017; // calorie - energyMap[ "eV" ] = 6.241457e+18; // electronvolt - energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour - energyMap[ "Wh" ] = 0.000277778; // watt-hour - energyMap[ "flb" ] = 23.73042222; - energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( energyMap, fromU ); - double toPrefix = kspread_convert_prefix( energyMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !energyMap.contains( fromU ) ) return false; - if( !energyMap.contains( toU ) ) return false; - - result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_power( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap powerMap; - - // first-time initialization - if( powerMap.isEmpty() ) - { - powerMap[ "W" ] = 1.0; // Watt (the reference) - powerMap[ "HP" ] = 1.341022e-3; // Horsepower - powerMap[ "PS" ] = 1.359622e-3; // Pferdestärke (German) - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( powerMap, fromU ); - double toPrefix = kspread_convert_prefix( powerMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !powerMap.contains( fromU ) ) return false; - if( !powerMap.contains( toU ) ) return false; - - result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_magnetism( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap magnetismMap; - - // first-time initialization - if( magnetismMap.isEmpty() ) - { - magnetismMap[ "T" ] = 1.0; // Tesla (the reference) - magnetismMap[ "ga" ] = 1.0e4; // Gauss - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( magnetismMap, fromU ); - double toPrefix = kspread_convert_prefix( magnetismMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !magnetismMap.contains( fromU ) ) return false; - if( !magnetismMap.contains( toU ) ) return false; - - result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_temperature( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap tempFactorMap; - static TQMap tempOffsetMap; - - // first-time initialization - if( tempFactorMap.isEmpty() || tempOffsetMap.isEmpty() ) - { - tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0; - tempFactorMap[ "F" ] = 5.0/9.0; tempOffsetMap[ "F" ] = -32.0; - tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15; - } - - if( !tempFactorMap.contains( fromUnit ) ) return false; - if( !tempOffsetMap.contains( fromUnit ) ) return false; - if( !tempFactorMap.contains( toUnit ) ) return false; - if( !tempOffsetMap.contains( toUnit ) ) return false; - - result = ( value + tempOffsetMap[ fromUnit ] )* tempFactorMap[ fromUnit ]; - result = ( result / tempFactorMap[ toUnit ] ) - tempOffsetMap[ toUnit ]; - - return true; -} - -static bool kspread_convert_volume( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap volumeMap; - - // first-time initialization - if( volumeMap.isEmpty() ) - { - volumeMap[ "l" ] = 1.0; // Liter (the reference) - volumeMap[ "tsp" ] = 202.84; // teaspoon - volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon - volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid - volumeMap[ "cup" ] = 4.22583333333333; // cup - volumeMap[ "pt" ] = 2.11291666666667; // pint - volumeMap[ "qt" ] = 1.05645833333333; // quart - volumeMap[ "gal" ] = 0.26411458333333; // gallone - volumeMap[ "m3" ] = 1.0e-3; // cubic meter - volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile - volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile - volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch - volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot - volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard - volumeMap[ "barrel" ] = 6.289811E-03; // barrel - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( volumeMap, fromU ); - double toPrefix = kspread_convert_prefix( volumeMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !volumeMap.contains( fromU ) ) return false; - if( !volumeMap.contains( toU ) ) return false; - - result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_area( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap areaMap; - - // first-time initialization - if( areaMap.isEmpty() ) - { - areaMap[ "m2" ] = 1.0; // square meter (the reference) - areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile - areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile - areaMap[ "in2" ] = 1.5500031000062000e3; // square inch - areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot - areaMap[ "yd2" ] = 1.0936132983377078; // square yard - areaMap[ "acre" ] = 4.046856e3; // acre - areaMap[ "ha" ] = 1.0e4; // hectare - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( areaMap, fromU ); - double toPrefix = kspread_convert_prefix( areaMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !areaMap.contains( fromU ) ) return false; - if( !areaMap.contains( toU ) ) return false; - - result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix); - - return true; -} - -static bool kspread_convert_speed( const TQString& fromUnit, - const TQString& toUnit, double value, double& result ) -{ - static TQMap speedMap; - - // first-time initialization - if( speedMap.isEmpty() ) - { - speedMap[ "m/s" ] = 1.0; // meters per second (the reference) - speedMap[ "m/h" ] = 3.6e3; // meters per hour - speedMap[ "mph" ] = 2.2369362920544023; // miles per hour - speedMap[ "kn" ] = 1.9438444924406048; // knot - } - - TQString fromU = fromUnit; - TQString toU = toUnit; - double fromPrefix = kspread_convert_prefix( speedMap, fromU ); - double toPrefix = kspread_convert_prefix( speedMap, toU ); - if( fromPrefix == 0.0 ) return false; - if( toPrefix == 0.0 ) return false; - if( !speedMap.contains( fromU ) ) return false; - if( !speedMap.contains( toU ) ) return false; - - result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix); - - return true; -} - - -// Function: CONVERT -Value func_convert (valVector args, ValueCalc *calc, FuncExtra *) -{ - // This function won't support arbitrary precision. - - double value = calc->conv()->asFloat (args[0]).asFloat (); - TQString fromUnit = calc->conv()->asString (args[1]).asString(); - TQString toUnit = calc->conv()->asString (args[2]).asString(); - - double result = value; - - if( !kspread_convert_mass( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_distance( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_pressure( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_force( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_energy( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_power( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_magnetism( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_temperature( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_volume( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_area( fromUnit, toUnit, value, result ) ) - if( !kspread_convert_speed( fromUnit, toUnit, value, result ) ) - return Value::errorNA(); - - return Value (result); -} - - -// functions operating over complex numbers ... -// these may eventually end up being merged into ValueCalc and friends -// then complex numbers will be handled transparently in most functions - -static TQString func_create_complex( double real,double imag ) -{ - TQString tmp,tmp2; - if(imag ==0) - { - return TDEGlobal::locale()->formatNumber( real); - } - if(real!=0) - tmp=TDEGlobal::locale()->formatNumber(real); - else - return TDEGlobal::locale()->formatNumber(imag)+"i"; - if (imag >0) - tmp=tmp+"+"+TDEGlobal::locale()->formatNumber(imag)+"i"; - else - tmp=tmp+TDEGlobal::locale()->formatNumber(imag)+"i"; - return tmp; - -} - -// Function: COMPLEX -Value func_complex (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (calc->isZero (args[1])) - return args[0]; - double re = calc->conv()->asFloat (args[0]).asFloat (); - double im = calc->conv()->asFloat (args[1]).asFloat (); - TQString tmp=func_create_complex (re, im); - bool ok; - double result = TDEGlobal::locale()->readNumber(tmp, &ok); - if (ok) - return Value (result); - return Value (tmp); -} - - -static double imag_complexe(TQString str, bool &ok) -{ -TQString tmp=str; -if(tmp.find('i')==-1) - { //not a complex - ok=true; - return 0; - } -else if( tmp.length()==1) - { - // i - ok=true; - return 1; - } -else if( tmp.length()==2 ) - { - //-i,+i, - int pos1; - if((pos1=tmp.find('+'))!=-1&& pos1==0) - { - ok=true; - return 1; - } - else if( (pos1=tmp.find('-'))!=-1 && pos1==0 ) - { - ok=true; - return -1; - } - else if(tmp[0].isDigit()) - { //5i - ok=true; - return TDEGlobal::locale()->readNumber(tmp.left(1)); - } - else - { - ok=false; - return 0; - } - } -else - {//12+12i - int pos1,pos2; - if((pos1=tmp.find('i'))!=-1) - { - double val; - TQString tmpStr; - - if((pos2=tmp.findRev('+'))!=-1 && pos2!=0) - { - if((pos1-pos2)==1) - { - ok=true; - return 1; - } - else - { - tmpStr=tmp.mid(pos2,(pos1-pos2)); - val=TDEGlobal::locale()->readNumber(tmpStr, &ok); - if(!ok) - val=0; - return val; - } - } - else if( (pos2=tmp.findRev('-'))!=-1&& pos2!=0) - { - if((pos1-pos2)==1) - { - ok=true; - return -1; - } - else - { - tmpStr=tmp.mid(pos2,(pos1-pos2)); - val=TDEGlobal::locale()->readNumber(tmpStr, &ok); - if(!ok) - val=0; - return val; - } - } - else - {//15.55i - tmpStr=tmp.left(pos1); - val=TDEGlobal::locale()->readNumber(tmpStr, &ok); - if(!ok) - val=0; - return val; - } - } - } -ok=false; -return 0; -} - -// Function: IMAGINARY -Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString (); - bool good; - double result=imag_complexe(tmp, good); - if (good) - return Value (result); - return Value::errorVALUE(); -} - - -static double real_complexe(TQString str, bool &ok) -{ -double val; -int pos1,pos2; -TQString tmp=str; -TQString tmpStr; -if((pos1=tmp.find('i'))==-1) - { //12.5 - val=TDEGlobal::locale()->readNumber(tmp, &ok); - if(!ok) - val=0; - return val; - } -else - { //15-xi - if((pos2=tmp.findRev('-'))!=-1 && pos2!=0) - { - tmpStr=tmp.left(pos2); - val=TDEGlobal::locale()->readNumber(tmpStr, &ok); - if(!ok) - val=0; - return val; - } //15+xi - else if((pos2=tmp.findRev('+'))!=-1) - { - tmpStr=tmp.left(pos2); - val=TDEGlobal::locale()->readNumber(tmpStr, &ok); - if(!ok) - val=0; - return val; - } - else - { - ok=true; - return 0; - } - } - -ok=false; -return 0; -} - -// Function: IMREAL -Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString (); - bool good; - double result=real_complexe(tmp, good); - if (good) - return Value (result); - return Value::errorVALUE(); -} - -void ImHelper (ValueCalc *c, Value res, Value val, - double &imag, double &real, double &imag1, double &real1) -{ - bool ok; - imag=imag_complexe(res.asString(), ok); - real=real_complexe(res.asString(), ok); - if (val.isString()) - { - imag1 = imag_complexe (val.asString(), ok); - real1 = real_complexe (val.asString(), ok); - } else { - imag1=0; - real1=c->conv()->asFloat (val).asFloat(); - } -} - -void awImSum (ValueCalc *c, Value &res, Value val, Value) -{ - double imag,real,imag1,real1; - ImHelper (c, res, val, imag, real, imag1, real1); - res=func_create_complex(real+real1,imag+imag1); -} - -void awImSub (ValueCalc *c, Value &res, Value val, Value) -{ - double imag,real,imag1,real1; - ImHelper (c, res, val, imag, real, imag1, real1); - res=func_create_complex(real-real1,imag-imag1); -} - -void awImMul (ValueCalc *c, Value &res, Value val, Value) -{ - double imag,real,imag1,real1; - ImHelper (c, res, val, imag, real, imag1, real1); - res=func_create_complex(real*real1+(imag*imag1)*-1,real*imag1+real1*imag); -} - -void awImDiv (ValueCalc *c, Value &res, Value val, Value) -{ - double imag,real,imag1,real1; - ImHelper (c, res, val, imag, real, imag1, real1); - res=func_create_complex((real*real1+imag*imag1)/(real1*real1+imag1*imag1), - (real1*imag-real*imag1)/(real1*real1+imag1*imag1)); -} - -// Function: IMSUM -Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->arrayWalk (args, result, awImSum, 0); - - bool ok; - TQString res = calc->conv()->asString (result).asString(); - double val=TDEGlobal::locale()->readNumber(res, &ok); - if (ok) - return Value (val); - return Value (result); -} - -// Function: IMSUB -Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->arrayWalk (args, result, awImSub, 0); - - bool ok; - TQString res = calc->conv()->asString (result).asString(); - double val=TDEGlobal::locale()->readNumber(res, &ok); - if (ok) - return Value (val); - return Value (result); -} - -// Function: IMPRODUCT -Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->arrayWalk (args, result, awImMul, 0); - - bool ok; - TQString res = calc->conv()->asString (result).asString(); - double val=TDEGlobal::locale()->readNumber(res, &ok); - if (ok) - return Value (val); - return Value (result); -} - -// Function: IMDIV -Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->arrayWalk (args, result, awImDiv, 0); - - bool ok; - TQString res = calc->conv()->asString (result).asString(); - double val=TDEGlobal::locale()->readNumber(res, &ok); - if (ok) - return Value (val); - return Value (result); -} - -// Function: IMCONJUGATE -Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if (!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - - tmp=func_create_complex(real,-imag); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMARGUMENT -Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if (!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if (!ok) - return Value::errorVALUE(); - if(imag==0) - return Value::errorDIV0(); - double arg=atan2(imag,real); - - return Value (arg); -} - -// Function: IMABS -Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double arg=sqrt(pow(imag,2)+pow(real,2)); - - return Value (arg); -} - -// Function: IMCOS -Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag_res=sin(real)*sinh(imag); - double real_res=cos(real)*cosh(imag); - - - tmp=func_create_complex(real_res,-imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMSIN -Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag_res=cos(real)*sinh(imag); - double real_res=sin(real)*cosh(imag); - - - tmp=func_create_complex(real_res,imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMLN -Value func_imln (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - - double arg=sqrt(pow(imag,2)+pow(real,2)); - double real_res=log(arg); - double imag_res=atan(imag/real); - tmp=func_create_complex(real_res,imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMEXP -Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag_res=exp(real)*sin(imag); - double real_res=exp(real)*cos(imag); - - - tmp=func_create_complex(real_res,imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMSQRT -Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double arg=sqrt(sqrt(pow(imag,2)+pow(real,2))); - double angle=atan(imag/real); - - double real_res=arg*cos((angle/2)); - double imag_res=arg*sin((angle/2)); - - tmp=func_create_complex(real_res,imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: IMPOWER -Value func_impower (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp = calc->conv()->asString (args[0]).asString(); - double val2 = calc->conv()->asFloat (args[1]).asFloat(); - bool ok; - double real=real_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - double imag=imag_complexe(tmp,ok); - if(!ok) - return Value::errorVALUE(); - - double arg=::pow(sqrt(pow(imag,2)+pow(real,2)),val2); - double angle=atan(imag/real); - - double real_res=arg*cos(angle*val2); - double imag_res=arg*sin(angle*val2); - - tmp=func_create_complex(real_res,imag_res); - - double result=TDEGlobal::locale()->readNumber(tmp, &ok); - if(ok) - return Value (result); - - return Value (tmp); -} - -// Function: DELTA -Value func_delta (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value val1 = args[0]; - Value val2 = 0.0; - if (args.count() == 2) - val2 = args[1]; - - return Value (calc->approxEqual (val1, val2) ? 1 : 0); -} - -// Function: ERF -Value func_erf (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 2) - return calc->sub (calc->erf (args[1]), calc->erf (args[0])); - return calc->erf (args[0]); -} - -// Function: ERFC -Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 2) - return calc->sub (calc->erfc (args[1]), calc->erfc (args[0])); - return calc->erfc (args[0]); -} - -// Function: GESTEP -Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value y = 0.0; - if (args.count() == 2) - y = args[1]; - - int result = 0; - if (calc->greater (x, y) || calc->approxEqual (x, y)) - result = 1; - - return Value (result); -} - diff --git a/kspread/kspread_functions_engineering.cpp b/kspread/kspread_functions_engineering.cpp new file mode 100644 index 00000000..bca81ec8 --- /dev/null +++ b/kspread/kspread_functions_engineering.cpp @@ -0,0 +1,1256 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in engineering functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +// used by the CONVERT function +#include + +// these are needed for complex functions, while we handle them in the old way +#include +#include +#include + +using namespace KSpread; + +// prototypes (sort alphabetically) +Value func_base (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *); +Value func_convert (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_delta (valVector args, ValueCalc *calc, FuncExtra *); +Value func_erf (valVector args, ValueCalc *calc, FuncExtra *); +Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imln (valVector args, ValueCalc *calc, FuncExtra *); +Value func_impower (valVector args, ValueCalc *calc, FuncExtra *); +Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all engineering functions +void RegisterEngineeringFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("BASE", func_base); // KSpread-specific, like in Quattro-Pro + f->setParamCount (1, 3); + repo->add (f); + f = new Function ("BESSELI", func_besseli); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELJ", func_besselj); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELK", func_besselk); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELY", func_bessely); + f->setParamCount (2); + repo->add (f); + f = new Function ("BIN2DEC", func_bin2dec); + repo->add (f); + f = new Function ("BIN2OCT", func_bin2oct); + repo->add (f); + f = new Function ("BIN2HEX", func_bin2hex); + repo->add (f); + f = new Function ("COMPLEX", func_complex); + f->setParamCount (2); + repo->add (f); + f = new Function ("CONVERT", func_convert); + f->setParamCount (3); + repo->add (f); + f = new Function ("DEC2HEX", func_dec2hex); + repo->add (f); + f = new Function ("DEC2BIN", func_dec2bin); + repo->add (f); + f = new Function ("DEC2OCT", func_dec2oct); + repo->add (f); + f = new Function ("DELTA", func_delta); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("ERF", func_erf); + f->setParamCount (2); + repo->add (f); + f = new Function ("ERFC", func_erfc); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("GESTEP", func_gestep); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("HEX2BIN", func_hex2bin); + repo->add (f); + f = new Function ("HEX2DEC", func_hex2dec); + repo->add (f); + f = new Function ("HEX2OCT", func_hex2oct); + repo->add (f); + f = new Function ("IMABS", func_imabs); + repo->add (f); + f = new Function ("IMAGINARY", func_complex_imag); + repo->add (f); + f = new Function ("IMARGUMENT", func_imargument); + repo->add (f); + f = new Function ("IMCONJUGATE", func_imconjugate); + repo->add (f); + f = new Function ("IMCOS", func_imcos); + repo->add (f); + f = new Function ("IMDIV", func_imdiv); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMEXP", func_imexp); + repo->add (f); + f = new Function ("IMLN", func_imln); + repo->add (f); + f = new Function ("IMPOWER", func_impower); + f->setParamCount (2); + repo->add (f); + f = new Function ("IMPRODUCT", func_improduct); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMREAL", func_complex_real); + repo->add (f); + f = new Function ("IMSIN", func_imsin); + repo->add (f); + f = new Function ("IMSQRT", func_imsqrt); + repo->add (f); + f = new Function ("IMSUB", func_imsub); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMSUM", func_imsum); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("OCT2BIN", func_oct2bin); + repo->add (f); + f = new Function ("OCT2DEC", func_oct2dec); + repo->add (f); + f = new Function ("OCT2HEX", func_oct2hex); + repo->add (f); +} + +// Function: BASE +Value func_base (valVector args, ValueCalc *calc, FuncExtra *) +{ + int base = 10; + int prec = 0; + if (args.count() > 1) + base = calc->conv()->asInteger (args[1]).asInteger(); + if (args.count() == 3) + prec = calc->conv()->asInteger (args[2]).asInteger(); + + if ((base < 2) || (base > 36)) + return Value::errorVALUE(); + if (prec < 0) prec = 2; + + return calc->base (args[0], base, prec); +} + +// Function: BESSELI +Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besseli (y, x); +} + +// Function: BESSELJ +Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besselj (y, x); +} + +// Function: BESSELK +Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besselk (y, x); +} + +// Function: BESSELY +Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besseln (y, x); +} + +// Function: DEC2HEX +Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 16); +} + +// Function: DEC2OCT +Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 8); +} + +// Function: DEC2BIN +Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 2); +} + +// Function: BIN2DEC +Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 2); +} + +// Function: BIN2OCT +Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 2), 8); +} + +// Function: BIN2HEX +Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 2), 16); +} + +// Function: OCT2DEC +Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 8); +} + +// Function: OCT2BIN +Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 8), 2); +} + +// Function: OCT2HEX +Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 8), 16); +} + +// Function: HEX2DEC +Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 16); +} + +// Function: HEX2BIN +Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 16), 2); +} + +// Function: HEX2OCT +Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 16), 8); +} + + +// check if unit may contain prefix, for example "kPa" is "Pa" with +// return prefix factor found in unit, or 1.0 for no prefix +// also modify the unit, i.e stripping the prefix from it +// example: "kPa" will return 1e3 and change unit into "Pa" +static double kspread_convert_prefix( TQMap map, TQString& unit ) +{ + if( map.contains( unit ) ) + return 1.0; + + // initialize prefix mapping if necessary + static TQMap prefixMap; + if( prefixMap.isEmpty() ) + { + prefixMap[ 'E' ] = 1e18; // exa + prefixMap[ 'P' ] = 1e15; // peta + prefixMap[ 'T' ] = 1e12; // tera + prefixMap[ 'G' ] = 1e9; // giga + prefixMap[ 'M' ] = 1e6; // mega + prefixMap[ 'k' ] = 1e3; // kilo + prefixMap[ 'h' ] = 1e2; // hecto + prefixMap[ 'e' ] = 1e1; // dekao + prefixMap[ 'd' ] = 1e1; // deci + prefixMap[ 'c' ] = 1e2; // centi + prefixMap[ 'm' ] = 1e3; // milli + prefixMap[ 'u' ] = 1e6; // micro + prefixMap[ 'n' ] = 1e9; // nano + prefixMap[ 'p' ] = 1e12; // pico + prefixMap[ 'f' ] = 1e15; // femto + prefixMap[ 'a' ] = 1e18; // atto + } + + // check for possible prefix + char prefix = unit[0].latin1(); + if( prefixMap.contains( prefix ) ) + { + unit.remove( 0, 1 ); + return prefixMap[ prefix ]; + } + + // fail miserably + return 0.0; +} + +static bool kspread_convert_mass( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap massMap; + + // first-time initialization + if( massMap.isEmpty() ) + { + massMap[ "g" ] = 1.0; // Gram (the reference ) + massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces + massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound + massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass) + massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce + massMap[ "stone" ] = 1.574730e-04; // Stone + massMap[ "ton" ] = 1.102311e-06; // Ton + massMap[ "grain" ] = 1.543236E01; // Grain + massMap[ "pweight" ] = 7.054792E-01; // Pennyweight + massMap[ "hweight" ] = 1.968413E-05; // Hundredweight + massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight + massMap[ "brton" ] = 9.842065E-07; // Gross Registered Ton + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( massMap, fromU ); + double toPrefix = kspread_convert_prefix( massMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !massMap.contains( fromU ) ) return false; + if( !massMap.contains( toU ) ) return false; + + result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix); + + return true; +} + + +static bool kspread_convert_distance( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap distanceMap; + + // first-time initialization + if( distanceMap.isEmpty() ) + { + distanceMap[ "m" ] = 1.0; // meter (the reference) + distanceMap[ "in" ] = 1.0 / 0.0254; // inch + distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet + distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yar + distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile + distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile + distanceMap[ "ang" ] = 1e10; // Angstrom + distanceMap[ "parsec" ] = 3.240779e-17; // Parsec + distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( distanceMap, fromU ); + double toPrefix = kspread_convert_prefix( distanceMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !distanceMap.contains( fromU ) ) return false; + if( !distanceMap.contains( toU ) ) return false; + + result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_pressure( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap pressureMap; + + // first-time initialization + if( pressureMap.isEmpty() ) + { + pressureMap[ "Pa" ] = 1.0; + pressureMap[ "atm" ] = 0.9869233e-5; + pressureMap[ "mmHg" ] = 0.00750061708; + pressureMap[ "psi" ] = 1 / 6894.754; + pressureMap[ "Torr" ] = 1 / 133.32237; + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( pressureMap, fromU ); + double toPrefix = kspread_convert_prefix( pressureMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !pressureMap.contains( fromU ) ) return false; + if( !pressureMap.contains( toU ) ) return false; + + result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_force( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap forceMap; + + // first-time initialization + if( forceMap.isEmpty() ) + { + forceMap[ "N" ] = 1.0; // Newton (reference) + forceMap[ "dyn" ] = 1.0e5; // dyn + forceMap[ "pond" ] = 1.019716e2; // pond + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( forceMap, fromU ); + double toPrefix = kspread_convert_prefix( forceMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !forceMap.contains( fromU ) ) return false; + if( !forceMap.contains( toU ) ) return false; + + result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_energy( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap energyMap; + + // first-time initialization + if( energyMap.isEmpty() ) + { + energyMap[ "J" ] = 1.0; // Joule (the reference) + energyMap[ "e" ] = 1.0e7; //erg + energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie + energyMap[ "cal" ] = 0.238846190642017; // calorie + energyMap[ "eV" ] = 6.241457e+18; // electronvolt + energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour + energyMap[ "Wh" ] = 0.000277778; // watt-hour + energyMap[ "flb" ] = 23.73042222; + energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( energyMap, fromU ); + double toPrefix = kspread_convert_prefix( energyMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !energyMap.contains( fromU ) ) return false; + if( !energyMap.contains( toU ) ) return false; + + result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_power( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap powerMap; + + // first-time initialization + if( powerMap.isEmpty() ) + { + powerMap[ "W" ] = 1.0; // Watt (the reference) + powerMap[ "HP" ] = 1.341022e-3; // Horsepower + powerMap[ "PS" ] = 1.359622e-3; // Pferdestärke (German) + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( powerMap, fromU ); + double toPrefix = kspread_convert_prefix( powerMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !powerMap.contains( fromU ) ) return false; + if( !powerMap.contains( toU ) ) return false; + + result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_magnetism( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap magnetismMap; + + // first-time initialization + if( magnetismMap.isEmpty() ) + { + magnetismMap[ "T" ] = 1.0; // Tesla (the reference) + magnetismMap[ "ga" ] = 1.0e4; // Gauss + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( magnetismMap, fromU ); + double toPrefix = kspread_convert_prefix( magnetismMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !magnetismMap.contains( fromU ) ) return false; + if( !magnetismMap.contains( toU ) ) return false; + + result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_temperature( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap tempFactorMap; + static TQMap tempOffsetMap; + + // first-time initialization + if( tempFactorMap.isEmpty() || tempOffsetMap.isEmpty() ) + { + tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0; + tempFactorMap[ "F" ] = 5.0/9.0; tempOffsetMap[ "F" ] = -32.0; + tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15; + } + + if( !tempFactorMap.contains( fromUnit ) ) return false; + if( !tempOffsetMap.contains( fromUnit ) ) return false; + if( !tempFactorMap.contains( toUnit ) ) return false; + if( !tempOffsetMap.contains( toUnit ) ) return false; + + result = ( value + tempOffsetMap[ fromUnit ] )* tempFactorMap[ fromUnit ]; + result = ( result / tempFactorMap[ toUnit ] ) - tempOffsetMap[ toUnit ]; + + return true; +} + +static bool kspread_convert_volume( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap volumeMap; + + // first-time initialization + if( volumeMap.isEmpty() ) + { + volumeMap[ "l" ] = 1.0; // Liter (the reference) + volumeMap[ "tsp" ] = 202.84; // teaspoon + volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon + volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid + volumeMap[ "cup" ] = 4.22583333333333; // cup + volumeMap[ "pt" ] = 2.11291666666667; // pint + volumeMap[ "qt" ] = 1.05645833333333; // quart + volumeMap[ "gal" ] = 0.26411458333333; // gallone + volumeMap[ "m3" ] = 1.0e-3; // cubic meter + volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile + volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile + volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch + volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot + volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard + volumeMap[ "barrel" ] = 6.289811E-03; // barrel + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( volumeMap, fromU ); + double toPrefix = kspread_convert_prefix( volumeMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !volumeMap.contains( fromU ) ) return false; + if( !volumeMap.contains( toU ) ) return false; + + result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_area( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap areaMap; + + // first-time initialization + if( areaMap.isEmpty() ) + { + areaMap[ "m2" ] = 1.0; // square meter (the reference) + areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile + areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile + areaMap[ "in2" ] = 1.5500031000062000e3; // square inch + areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot + areaMap[ "yd2" ] = 1.0936132983377078; // square yard + areaMap[ "acre" ] = 4.046856e3; // acre + areaMap[ "ha" ] = 1.0e4; // hectare + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( areaMap, fromU ); + double toPrefix = kspread_convert_prefix( areaMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !areaMap.contains( fromU ) ) return false; + if( !areaMap.contains( toU ) ) return false; + + result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_speed( const TQString& fromUnit, + const TQString& toUnit, double value, double& result ) +{ + static TQMap speedMap; + + // first-time initialization + if( speedMap.isEmpty() ) + { + speedMap[ "m/s" ] = 1.0; // meters per second (the reference) + speedMap[ "m/h" ] = 3.6e3; // meters per hour + speedMap[ "mph" ] = 2.2369362920544023; // miles per hour + speedMap[ "kn" ] = 1.9438444924406048; // knot + } + + TQString fromU = fromUnit; + TQString toU = toUnit; + double fromPrefix = kspread_convert_prefix( speedMap, fromU ); + double toPrefix = kspread_convert_prefix( speedMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !speedMap.contains( fromU ) ) return false; + if( !speedMap.contains( toU ) ) return false; + + result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix); + + return true; +} + + +// Function: CONVERT +Value func_convert (valVector args, ValueCalc *calc, FuncExtra *) +{ + // This function won't support arbitrary precision. + + double value = calc->conv()->asFloat (args[0]).asFloat (); + TQString fromUnit = calc->conv()->asString (args[1]).asString(); + TQString toUnit = calc->conv()->asString (args[2]).asString(); + + double result = value; + + if( !kspread_convert_mass( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_distance( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_pressure( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_force( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_energy( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_power( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_magnetism( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_temperature( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_volume( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_area( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_speed( fromUnit, toUnit, value, result ) ) + return Value::errorNA(); + + return Value (result); +} + + +// functions operating over complex numbers ... +// these may eventually end up being merged into ValueCalc and friends +// then complex numbers will be handled transparently in most functions + +static TQString func_create_complex( double real,double imag ) +{ + TQString tmp,tmp2; + if(imag ==0) + { + return TDEGlobal::locale()->formatNumber( real); + } + if(real!=0) + tmp=TDEGlobal::locale()->formatNumber(real); + else + return TDEGlobal::locale()->formatNumber(imag)+"i"; + if (imag >0) + tmp=tmp+"+"+TDEGlobal::locale()->formatNumber(imag)+"i"; + else + tmp=tmp+TDEGlobal::locale()->formatNumber(imag)+"i"; + return tmp; + +} + +// Function: COMPLEX +Value func_complex (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (calc->isZero (args[1])) + return args[0]; + double re = calc->conv()->asFloat (args[0]).asFloat (); + double im = calc->conv()->asFloat (args[1]).asFloat (); + TQString tmp=func_create_complex (re, im); + bool ok; + double result = TDEGlobal::locale()->readNumber(tmp, &ok); + if (ok) + return Value (result); + return Value (tmp); +} + + +static double imag_complexe(TQString str, bool &ok) +{ +TQString tmp=str; +if(tmp.find('i')==-1) + { //not a complex + ok=true; + return 0; + } +else if( tmp.length()==1) + { + // i + ok=true; + return 1; + } +else if( tmp.length()==2 ) + { + //-i,+i, + int pos1; + if((pos1=tmp.find('+'))!=-1&& pos1==0) + { + ok=true; + return 1; + } + else if( (pos1=tmp.find('-'))!=-1 && pos1==0 ) + { + ok=true; + return -1; + } + else if(tmp[0].isDigit()) + { //5i + ok=true; + return TDEGlobal::locale()->readNumber(tmp.left(1)); + } + else + { + ok=false; + return 0; + } + } +else + {//12+12i + int pos1,pos2; + if((pos1=tmp.find('i'))!=-1) + { + double val; + TQString tmpStr; + + if((pos2=tmp.findRev('+'))!=-1 && pos2!=0) + { + if((pos1-pos2)==1) + { + ok=true; + return 1; + } + else + { + tmpStr=tmp.mid(pos2,(pos1-pos2)); + val=TDEGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + else if( (pos2=tmp.findRev('-'))!=-1&& pos2!=0) + { + if((pos1-pos2)==1) + { + ok=true; + return -1; + } + else + { + tmpStr=tmp.mid(pos2,(pos1-pos2)); + val=TDEGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + else + {//15.55i + tmpStr=tmp.left(pos1); + val=TDEGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + } +ok=false; +return 0; +} + +// Function: IMAGINARY +Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString (); + bool good; + double result=imag_complexe(tmp, good); + if (good) + return Value (result); + return Value::errorVALUE(); +} + + +static double real_complexe(TQString str, bool &ok) +{ +double val; +int pos1,pos2; +TQString tmp=str; +TQString tmpStr; +if((pos1=tmp.find('i'))==-1) + { //12.5 + val=TDEGlobal::locale()->readNumber(tmp, &ok); + if(!ok) + val=0; + return val; + } +else + { //15-xi + if((pos2=tmp.findRev('-'))!=-1 && pos2!=0) + { + tmpStr=tmp.left(pos2); + val=TDEGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } //15+xi + else if((pos2=tmp.findRev('+'))!=-1) + { + tmpStr=tmp.left(pos2); + val=TDEGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + else + { + ok=true; + return 0; + } + } + +ok=false; +return 0; +} + +// Function: IMREAL +Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString (); + bool good; + double result=real_complexe(tmp, good); + if (good) + return Value (result); + return Value::errorVALUE(); +} + +void ImHelper (ValueCalc *c, Value res, Value val, + double &imag, double &real, double &imag1, double &real1) +{ + bool ok; + imag=imag_complexe(res.asString(), ok); + real=real_complexe(res.asString(), ok); + if (val.isString()) + { + imag1 = imag_complexe (val.asString(), ok); + real1 = real_complexe (val.asString(), ok); + } else { + imag1=0; + real1=c->conv()->asFloat (val).asFloat(); + } +} + +void awImSum (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real+real1,imag+imag1); +} + +void awImSub (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real-real1,imag-imag1); +} + +void awImMul (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real*real1+(imag*imag1)*-1,real*imag1+real1*imag); +} + +void awImDiv (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex((real*real1+imag*imag1)/(real1*real1+imag1*imag1), + (real1*imag-real*imag1)/(real1*real1+imag1*imag1)); +} + +// Function: IMSUM +Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImSum, 0); + + bool ok; + TQString res = calc->conv()->asString (result).asString(); + double val=TDEGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMSUB +Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImSub, 0); + + bool ok; + TQString res = calc->conv()->asString (result).asString(); + double val=TDEGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMPRODUCT +Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImMul, 0); + + bool ok; + TQString res = calc->conv()->asString (result).asString(); + double val=TDEGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMDIV +Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImDiv, 0); + + bool ok; + TQString res = calc->conv()->asString (result).asString(); + double val=TDEGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMCONJUGATE +Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + tmp=func_create_complex(real,-imag); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMARGUMENT +Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + if(imag==0) + return Value::errorDIV0(); + double arg=atan2(imag,real); + + return Value (arg); +} + +// Function: IMABS +Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double arg=sqrt(pow(imag,2)+pow(real,2)); + + return Value (arg); +} + +// Function: IMCOS +Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=sin(real)*sinh(imag); + double real_res=cos(real)*cosh(imag); + + + tmp=func_create_complex(real_res,-imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMSIN +Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=cos(real)*sinh(imag); + double real_res=sin(real)*cosh(imag); + + + tmp=func_create_complex(real_res,imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMLN +Value func_imln (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + double arg=sqrt(pow(imag,2)+pow(real,2)); + double real_res=log(arg); + double imag_res=atan(imag/real); + tmp=func_create_complex(real_res,imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMEXP +Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=exp(real)*sin(imag); + double real_res=exp(real)*cos(imag); + + + tmp=func_create_complex(real_res,imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMSQRT +Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double arg=sqrt(sqrt(pow(imag,2)+pow(real,2))); + double angle=atan(imag/real); + + double real_res=arg*cos((angle/2)); + double imag_res=arg*sin((angle/2)); + + tmp=func_create_complex(real_res,imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMPOWER +Value func_impower (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp = calc->conv()->asString (args[0]).asString(); + double val2 = calc->conv()->asFloat (args[1]).asFloat(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + double arg=::pow(sqrt(pow(imag,2)+pow(real,2)),val2); + double angle=atan(imag/real); + + double real_res=arg*cos(angle*val2); + double imag_res=arg*sin(angle*val2); + + tmp=func_create_complex(real_res,imag_res); + + double result=TDEGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: DELTA +Value func_delta (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value val1 = args[0]; + Value val2 = 0.0; + if (args.count() == 2) + val2 = args[1]; + + return Value (calc->approxEqual (val1, val2) ? 1 : 0); +} + +// Function: ERF +Value func_erf (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->sub (calc->erf (args[1]), calc->erf (args[0])); + return calc->erf (args[0]); +} + +// Function: ERFC +Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->sub (calc->erfc (args[1]), calc->erfc (args[0])); + return calc->erfc (args[0]); +} + +// Function: GESTEP +Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = 0.0; + if (args.count() == 2) + y = args[1]; + + int result = 0; + if (calc->greater (x, y) || calc->approxEqual (x, y)) + result = 1; + + return Value (result); +} + diff --git a/kspread/kspread_functions_financial.cc b/kspread/kspread_functions_financial.cc deleted file mode 100644 index daccb640..00000000 --- a/kspread/kspread_functions_financial.cc +++ /dev/null @@ -1,907 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in financial functions - -#include - -#include "functions.h" -#include "kspread_functions_helper.h" -#include "valuecalc.h" -#include "valueconverter.h" - -#include -#include - -using namespace KSpread; - -// prototypes (sorted) -Value func_accrint (valVector args, ValueCalc *calc, FuncExtra *); -Value func_accrintm (valVector args, ValueCalc *calc, FuncExtra *); -Value func_compound (valVector args, ValueCalc *calc, FuncExtra *); -Value func_continuous (valVector args, ValueCalc *calc, FuncExtra *); -Value func_coupnum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_db (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ddb (valVector args, ValueCalc *calc, FuncExtra *); -Value func_disc (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dollarde (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dollarfr (valVector args, ValueCalc *calc, FuncExtra *); -Value func_duration (valVector args, ValueCalc *calc, FuncExtra *); -Value func_effective (valVector args, ValueCalc *calc, FuncExtra *); -Value func_euro (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fv_annuity (valVector args, ValueCalc *calc, FuncExtra *); -Value func_intrate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ipmt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ispmt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_level_coupon (valVector args, ValueCalc *calc, FuncExtra *); -Value func_nominal (valVector args, ValueCalc *calc, FuncExtra *); -Value func_nper (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pmt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ppmt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pv_annuity (valVector args, ValueCalc *calc, FuncExtra *); -Value func_received (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sln (valVector args, ValueCalc *calc, FuncExtra *); -Value func_syd (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tbilleq (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tbillprice (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tbillyield (valVector args, ValueCalc *calc, FuncExtra *); -Value func_zero_coupon (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all financial functions -void RegisterFinancialFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("ACCRINT", func_accrint); - f->setParamCount (6, 7); - repo->add (f); - f = new Function ("ACCRINTM", func_accrintm); - f->setParamCount (3, 5); - repo->add (f); - f = new Function ("COMPOUND", func_compound); - f->setParamCount (4); - repo->add (f); - f = new Function ("CONTINUOUS", func_continuous); - f->setParamCount (3); - repo->add (f); - f = new Function ("COUPNUM", func_coupnum); - f->setParamCount (3, 5); - repo->add (f); - f = new Function ("DB", func_db); - f->setParamCount (4, 5); - repo->add (f); - f = new Function ("DDB", func_ddb); - f->setParamCount (4, 5); - repo->add (f); - f = new Function ("DISC", func_disc); - f->setParamCount (4, 5); - repo->add (f); - f = new Function ("DOLLARDE", func_dollarde); - f->setParamCount (2); - repo->add (f); - f = new Function ("DOLLARFR", func_dollarfr); - f->setParamCount (2); - repo->add (f); - f = new Function ("DURATION", func_duration); - f->setParamCount (3); - repo->add (f); - f = new Function ("EFFECT", func_effective); - f->setParamCount (2); - repo->add (f); - f = new Function ("EFFECTIVE", func_effective); - f->setParamCount (2); - repo->add (f); - f = new Function ("EURO", func_euro); // KSpread-specific, Gnumeric-compatible - f->setParamCount (1); - repo->add (f); - f = new Function ("FV", func_fv); - f->setParamCount (3); - repo->add (f); - f = new Function ("FV_ANNUITY", func_fv_annuity); - f->setParamCount (3); - repo->add (f); - f = new Function ("INTRATE", func_intrate); - f->setParamCount (4, 5); - repo->add (f); - f = new Function ("IPMT", func_ipmt); - f->setParamCount (4, 6); - repo->add (f); - f = new Function ("ISPMT", func_ispmt); - f->setParamCount (4); - repo->add (f); - f = new Function ("LEVEL_COUPON", func_level_coupon); - f->setParamCount (5); - repo->add (f); - f = new Function ("NOMINAL", func_nominal); - f->setParamCount (2); - repo->add (f); - f = new Function ("NPER", func_nper); - f->setParamCount (3, 5); - repo->add (f); - f = new Function ("PMT", func_pmt); - f->setParamCount (3, 5); - repo->add (f); - f = new Function ("PPMT", func_ppmt); - f->setParamCount (4, 6); - repo->add (f); - f = new Function ("PV", func_pv); - f->setParamCount (3); - repo->add (f); - f = new Function ("PV_ANNUITY", func_pv_annuity); - f->setParamCount (3); - repo->add (f); - f = new Function ("RECEIVED", func_received); - f->setParamCount (4, 5); - repo->add (f); - f = new Function ("SLN", func_sln); - f->setParamCount (3); - repo->add (f); - f = new Function ("SYD", func_syd); - f->setParamCount (4); - repo->add (f); - f = new Function ("TBILLEQ", func_tbilleq); - f->setParamCount (3); - repo->add (f); - f = new Function ("TBILLPRICE", func_tbillprice); - f->setParamCount (3); - repo->add (f); - f = new Function ("TBILLYIELD", func_tbillyield); - f->setParamCount (3); - repo->add (f); - f = new Function ("ZERO_COUPON", func_zero_coupon); - f->setParamCount (3); - repo->add (f); -} - -static Value getPay (ValueCalc *calc, Value rate, - Value nper, Value pv, Value fv, Value type) -{ - Value pvif, fvifa; - - if (calc->isZero (rate)) return Value::errorVALUE(); - - //pvif = pow( 1 + rate, nper ); - //fvifa = ( pvif - 1 ) / rate; - pvif = calc->pow (calc->add (rate, 1), nper); - fvifa = calc->div (calc->sub (pvif, 1), rate); - - // ( -pv * pvif - fv ) / ( ( 1.0 + rate * type ) * fvifa ); - Value val1 = calc->sub (calc->mul (calc->mul (-1, pv), pvif), fv); - Value val2 = calc->mul (calc->add (1.0, calc->mul (rate, type)), - fvifa); - return calc->div (val1, val2); -} - -static Value getPrinc (ValueCalc *calc, Value start, - Value pay, Value rate, Value period) -{ - // val1 = pow( 1 + rate, period ) - Value val1 = calc->pow (calc->add (rate, 1), period); - // val2 = start * val1 - Value val2 = calc->mul (start, val1); - // val3 = pay * ( ( val1 - 1 ) / rate ) - Value val3 = calc->mul (pay, calc->div (calc->sub (val1, 1), rate)); - // result = val2 + val3 - return calc->add (val2, val3); -} - -// Function: COUPNUM - taken from GNUMERIC -Value func_coupnum (valVector args, ValueCalc *calc, FuncExtra *) -{ - // dates and integers only - don't need high-precision for this - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - int frequency = calc->conv()->asInteger (args[2]).asInteger(); - int basis = 0; - bool eom = true; - if (args.count() > 3) - basis = calc->conv()->asInteger (args[3]).asInteger(); - if (args.count() == 5) - eom = calc->conv()->asBoolean (args[4]).asBoolean(); - - if (basis < 0 || basis > 5 || ( frequency == 0 ) || ( 12 % frequency != 0 ) - || settlement.daysTo( maturity ) <= 0) - return Value::errorVALUE(); - - double result; - TQDate cDate( maturity ); - - int months = maturity.month() - settlement.month() - + 12 * ( maturity.year() - settlement.year() ); - - cDate = calc->conv()->locale()->calendar()->addMonths (cDate, -months); - - if ( eom && maturity.daysInMonth() == maturity.day() ) - { - while( cDate.daysInMonth() != cDate.day() ) - cDate.addDays( 1 ); - } - - if ( settlement.day() >= cDate.day() ) - --months; - - result = ( 1 + months / ( 12 / frequency ) ); - - return Value (result); -} - -// Function: ACCRINT -Value func_accrint (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate maturity = calc->conv()->asDate (args[0]).asDate(); - TQDate firstInterest = calc->conv()->asDate (args[1]).asDate(); - TQDate settlement = calc->conv()->asDate (args[2]).asDate(); - - Value rate = args[3]; - Value par = args[4]; - int frequency = calc->conv()->asInteger (args[5]).asInteger(); - - int basis = 0; - if (args.count() == 7) - basis = calc->conv()->asInteger (args[6]).asInteger(); - - if ( basis < 0 || basis > 4 || (calc->isZero (frequency)) || - (12 % frequency != 0)) - return Value::errorVALUE(); - - if ( ( settlement.daysTo( firstInterest ) < 0 ) - || ( firstInterest.daysTo( maturity ) > 0 ) ) - return Value::errorVALUE(); - - double d = daysBetweenDates (maturity, settlement, basis); - double y = daysPerYear (maturity, basis); - - if ( d < 0 || y <= 0 || calc->lower (par, 0) || calc->lower (rate, 0) || - calc->isZero (rate)) - return Value::errorVALUE(); - - Value coeff = calc->div (calc->mul (par, rate), frequency); - double n = d / y; - - return calc->mul (coeff, n * frequency); -} - -// Function: ACCRINTM -Value func_accrintm (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate issue = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - Value rate = args[2]; - - Value par = 1000; - int basis = 0; - if (args.count() > 3) - par = args[3]; - if (args.count() == 5) - basis = calc->conv()->asInteger (args[4]).asInteger (); - - double d = daysBetweenDates (issue, maturity, basis); - double y = daysPerYear (issue, basis); - - if (d < 0 || y <= 0 || calc->isZero (par) || calc->isZero (rate) || - calc->lower (par, 0) || calc->lower (rate, 0) || basis < 0 || basis > 4) - return Value::errorVALUE(); - - // par*date * d/y - return calc->mul (calc->mul (par, rate), d / y); -} - -// Function: DISC -Value func_disc (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value par = args[2]; - Value redemp = args[3]; - - int basis = 0; - if (args.count() == 5) - basis = calc->conv()->asInteger (args[4]).asInteger(); - - double y = daysPerYear (settlement, basis); - double d = daysBetweenDates (settlement, maturity, basis); - - if ( y <= 0 || d <= 0 || basis < 0 || basis > 4 || calc->isZero (redemp) ) - return false; - - // (redemp - par) / redemp * (y / d) - return calc->mul (calc->div (calc->sub (redemp, par), redemp), y / d); -} - - -// Function: TBILLPRICE -Value func_tbillprice (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value discount = args[2]; - - double days = settlement.daysTo( maturity ); - - if (settlement > maturity || calc->lower (discount, 0) || days > 265) - return Value::errorVALUE(); - - // (discount * days) / 360.0 - Value val = calc->div (calc->mul (discount, days), 360.0); - // 100 * (1.0 - val); - return calc->mul (calc->sub (1.0, val), 100); -} - -// Function: TBILLYIELD -Value func_tbillyield (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value rate = args[2]; - - double days = settlement.daysTo( maturity ); - - if (settlement > maturity || calc->isZero (rate) || calc->lower (rate, 0) - || days > 265) - return Value::errorVALUE(); - - // (100.0 - rate) / rate * (360.0 / days); - return calc->mul (calc->div (calc->sub (100.0, rate), rate), 360.0 / days); -} - -// Function: TBILLEQ -Value func_tbilleq (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value discount = args[2]; - - double days = settlement.daysTo( maturity ); - - if (settlement > maturity || calc->lower (discount, 0) || days > 265) - return Value::errorVALUE(); - - // 360 - discount*days - Value divisor = calc->sub (360.0, calc->mul (discount, days)); - if (calc->isZero (divisor)) - return Value::errorVALUE(); - - // 365.0 * discount / divisor - return calc->mul (calc->div (discount, divisor), 356.0); -} - -// Function: RECEIVED -Value func_received (valVector args, ValueCalc *calc, FuncExtra *) -{ - - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value investment = args[2]; - Value discount = args[3]; - - int basis = 0; - if (args.count() == 5) - basis = calc->conv()->asInteger (args[4]).asInteger(); - - double d = daysBetweenDates( settlement, maturity, basis ); - double y = daysPerYear( settlement, basis ); - - if ( d <= 0 || y <= 0 || basis < 0 || basis > 4 ) - return false; - - // 1.0 - ( discount * d / y ) - Value x = calc->sub (1.0, (calc->mul (discount, d / y))); - - if (calc->isZero (x)) - return Value::errorVALUE(); - return calc->div (investment, x); -} - -// Function: DOLLARDE -Value func_dollarde (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value d = args[0]; - Value f = args[1]; - - if (!calc->greater (f, 0)) - return Value::errorVALUE(); - - Value tmp = f; - int n = 0; - while (calc->greater (tmp, 0)) - { - tmp = calc->div (tmp, 10); - ++n; - } - - Value fl = calc->roundDown (d); - Value r = calc->sub (d, fl); - - // fl + (r * pow(10.0, n) / f) - return calc->add (fl, calc->div (calc->mul (r, pow (10.0, n)), f)); -} - -// Function: DOLLARFR -Value func_dollarfr (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value d = args[0]; - Value f = args[1]; - - if (!calc->greater (f, 0)) - return Value::errorVALUE(); - - Value tmp = f; - int n = 0; - while (calc->greater (tmp, 0)) - { - tmp = calc->div (tmp, 10); - ++n; - } - - Value fl = calc->roundDown (d); - Value r = calc->sub (d, fl); - - // fl + ((r * f) / pow (10.0, n)); - return calc->add (fl, calc->div (calc->mul (r, f), pow (10.0, n))); -} - -/// *** TODO continue here *** - -// Function: INTRATE -Value func_intrate (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQDate settlement = calc->conv()->asDate (args[0]).asDate(); - TQDate maturity = calc->conv()->asDate (args[1]).asDate(); - - Value invest = args[2]; - Value redemption = args[3]; - - int basis = 0; - if (args.count() == 5) - basis = calc->conv()->asInteger (args[4]).asInteger(); - - double d = daysBetweenDates (settlement, maturity, basis); - double y = daysPerYear (settlement, basis); - - if ( d <= 0 || y <= 0 || calc->isZero (invest) || basis < 0 || basis > 4 ) - return Value::errorVALUE(); - - // (redemption - invest) / invest * (y / d) - return calc->mul (calc->div (calc->sub (redemption, invest), invest), y/d); -} - - -// Function: DURATION -Value func_duration (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rate = args[0]; - Value pv = args[1]; - Value fv = args[2]; - - if (!calc->greater (rate, 0.0)) - return Value::errorVALUE(); - if (calc->isZero (fv) || calc->isZero (pv)) - return Value::errorDIV0(); - - if (calc->lower (calc->div (fv, pv), 0)) - return Value::errorVALUE(); - - // log(fv / pv) / log(1.0 + rate) - return calc->div (calc->ln (calc->div (fv, pv)), - calc->ln (calc->add (rate, 1.0))); -} - -// Function: PMT -Value func_pmt (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rate = args[0]; - Value nper = args[1]; - Value pv = args[2]; - Value fv = 0.0; - Value type = 0; - if (args.count() > 3) fv = args[3]; - if (args.count() == 5) type = args[4]; - - return getPay (calc, rate, nper, pv, fv, type); -} - -// Function: NPER -Value func_nper (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rate = args[0]; - Value pmt = args[1]; - Value pv = args[2]; - Value fv = 0.0; - Value type = 0; - if (args.count() > 3) fv = args[3]; - if (args.count() == 5) type = args[4]; - - if (!calc->greater (rate, 0.0)) - return Value::errorVALUE(); - - // taken from Gnumeric - // v = 1.0 + rate * type - // d1 = pmt * v - fv * rate - // d2 = pmt * v - pv * rate - // res = d1 / d2; - Value v = calc->add (calc->mul (rate, type), 1.0); - Value d1 = calc->sub (calc->mul (pmt, v), calc->mul (fv, rate)); - Value d2 = calc->add (calc->mul (pmt, v), calc->mul (pv, rate)); - Value res = calc->div (d1, d2); - - if (!calc->greater (res, 0.0)) // res must be >0 - return Value::errorVALUE(); - - // ln (res) / ln (rate + 1.0) - return calc->div (calc->ln (res), calc->ln (calc->add (rate, 1.0))); -} - -// Function: ISPMT -Value func_ispmt (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rate = args[0]; - Value per = args[1]; - Value nper = args[2]; - Value pv = args[3]; - - if (calc->lower (per, 1) || calc->greater (per, nper)) - return Value::errorVALUE(); - - // d = -pv * rate - Value d = calc->mul (calc->mul (pv, -1), rate); - - // d - (d / nper * per) - return calc->sub (d, calc->mul (calc->div (d, nper), per)); -} - -// Function: IPMT -Value func_ipmt (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rate = args[0]; - Value per = args[1]; - Value nper = args[2]; - Value pv = args[3]; - - Value fv = 0.0; - Value type = 0; - if (args.count() > 4) fv = args[4]; - if (args.count() == 6) type = args[5]; - - Value payment = getPay (calc, rate, nper, pv, fv, type); - Value ineg = getPrinc (calc, pv, payment, rate, calc->sub (per, 1)); - - // -ineg * rate - return calc->mul (calc->mul (ineg, -1), rate); -} - -// Function: PPMT -// Uses IPMT. -Value func_ppmt (valVector args, ValueCalc *calc, FuncExtra *) -{ - /* -Docs partly copied from OO. -Syntax -PPMT(Rate;Period;NPER;PV;FV;Type) - -Rate is the periodic interest rate. -Period is the amortizement period. P=1 for the first and P=NPER for the last period. -NPER is the total number of periods during which annuity is paid. -PV is the present value in the sequence of payments. -FV (optional) is the desired (future) value. -Type (optional) defines the due date. F=1 for payment at the beginning of a period and F=0 for payment at the end of a period. - */ - - Value rate = args[0]; - Value per = args[1]; - Value nper = args[2]; - Value pv = args[3]; - Value fv = 0.0; - Value type = 0; - if (args.count() > 4) fv = args[4]; - if (args.count() == 6) type = args[5]; - - Value pay = getPay (calc, rate, nper, pv, fv, type); - Value ipmt = func_ipmt (args, calc, 0); - return calc->sub (pay, ipmt); -} - -// Function: FV -/* Returns future value, given current value, interest rate and time */ -Value func_fv (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value present = args[0]; - Value interest = args[1]; - Value periods = args[2]; - - // present * pow (1 + interest, periods) - return calc->mul (present, calc->pow (calc->add (interest, 1), periods)); -} - -// Function: compound -/* Returns value after compounded interest, given principal, rate, periods -per year and year */ - Value func_compound (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value principal = args[0]; - Value interest = args[1]; - Value periods = args[2]; - Value years = args[3]; - - // principal * pow(1+ (interest / periods), periods*years); - Value base = calc->add (calc->div (interest, periods), 1); - return calc->mul (principal, calc->pow (base, calc->mul (periods, years))); -} - -// Function: continuous -/* Returns value after continuous compounding of interest, given principal, -rate and years */ -Value func_continuous (valVector args, ValueCalc *calc, FuncExtra *) -{ - // If you still don't understand this, let me know! ;-) jsinger@leeta.net - Value principal = args[0]; - Value interest = args[1]; - Value years = args[2]; - - // principal * exp(interest * years) - return calc->mul (principal, calc->exp (calc->mul (interest, years))); -} - -// Function: PV -Value func_pv (valVector args, ValueCalc *calc, FuncExtra *) -{ -/* Returns presnt value, given future value, interest rate and years */ - Value future = args[0]; - Value interest = args[1]; - Value periods = args[2]; - - // future / pow(1+interest, periods) - return calc->div (future, calc->pow (calc->add (interest, 1), periods)); -} - -// Function: PV_annuity -Value func_pv_annuity (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value amount = args[0]; - Value interest = args[1]; - Value periods = args[2]; - - // recpow = 1 / pow (1 + interest, periods) - // result = amount * (1 - recpow) / interest; - Value recpow; - recpow = calc->div (1, calc->pow (calc->add (interest, 1), periods)); - return calc->mul (amount, calc->div (calc->sub (1, recpow), interest)); -} - -// Function: FV_annnuity -Value func_fv_annuity (valVector args, ValueCalc *calc, FuncExtra *) -{ - /* Returns future value of an annuity or cash flow, given payment, interest - rate and periods */ - - Value amount = args[0]; - Value interest = args[1]; - Value periods = args[2]; - - // pw = pow (1 + interest, periods) - // result = amount * ((pw - 1) / interest) - Value pw = calc->pow (calc->add (interest, 1), periods); - return calc->mul (amount, calc->div (calc->sub (pw, 1), interest)); -} - -// Function: effective -Value func_effective (valVector args, ValueCalc *calc, FuncExtra *) -{ - // Returns effective interest rate given nominal rate and periods per year - - Value nominal = args[0]; - Value periods = args[1]; - - // base = 1 + (nominal / periods) - // result = pow (base, periods) - 1 - Value base = calc->add (calc->div (nominal, periods), 1); - return calc->sub (calc->pow (base, periods), 1); -} - -// Function: zero_coupon -Value func_zero_coupon (valVector args, ValueCalc *calc, FuncExtra *) -{ - // Returns effective interest rate given nominal rate and periods per year - - Value face = args[0]; - Value rate = args[1]; - Value years = args[2]; - - // face / pow(1 + rate, years) - return calc->div (face, calc->pow (calc->add (rate, 1), years)); -} - -// Function: level_coupon -Value func_level_coupon (valVector args, ValueCalc *calc, FuncExtra *) -{ - // Returns effective interest rate given nominal rate and periods per year - Value face = args[0]; - Value coupon_rate = args[1]; - Value coupon_year = args[2]; - Value years = args[3]; - Value market_rate = args[4]; - - Value coupon, interest, pw, pv_annuity; - // coupon = coupon_rate * face / coupon_year - // interest = market_rate / coupon_year - // pw = pow(1 + interest, years * coupon_year) - // pv_annuity = (1 - 1 / pw) / interest - // result = coupon * pv_annuity + face / pw - coupon = calc->mul (coupon_rate, calc->div (face, coupon_year)); - interest = calc->div (market_rate, coupon_year); - pw = calc->pow (calc->add (interest, 1), calc->mul (years, coupon_year)); - pv_annuity = calc->div (calc->sub (1, calc->div (1, pw)), interest); - return calc->add (calc->mul (coupon, pv_annuity), calc->div (face, pw)); -} - -// Function: nominal -Value func_nominal (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value effective = args[0]; - Value periods = args[1]; - - if (calc->isZero (periods)) // Check null - return Value::errorDIV0(); - - // pw = pow (effective + 1, 1 / periods) - // result = periods * (pw - 1); - Value pw; - pw = calc->pow (calc->add (effective, 1), calc->div (1, periods)); - return calc->mul (periods, calc->sub (pw, 1)); -} - -// Function: SLN -/* straight-line depreciation for a single period */ -Value func_sln (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value cost = args[0]; - Value salvage_value = args[1]; - Value life = args[2]; - - // sentinel check - if (!calc->greater (life, 0.0)) - return Value::errorVALUE(); - - // (cost - salvage_value) / life - return calc->div (calc->sub (cost, salvage_value), life); -} - -// Function: SYD -/* sum-of-years digits depreciation */ -Value func_syd (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value cost = args[0]; - Value salvage_value = args[1]; - Value life = args[2]; - Value period = args[3]; - - // sentinel check - if (!calc->greater (life, 0.0)) - return Value::errorVALUE(); - - // v1 = cost - salvage_value - // v2 = life - period + 1 - // v3 = life * (life + 1.0) - // result = (v1 * v2 * 2) / v3 - Value v1, v2, v3; - v1 = calc->sub (cost, salvage_value); - v2 = calc->add (calc->sub (life, period), 1); - v3 = calc->mul (life, calc->add (life, 1.0)); - return calc->div (calc->mul (calc->mul (v1, v2), 2), v3); -} - -// Function: DB -/* fixed-declining depreciation */ -Value func_db (valVector args, ValueCalc *calc, FuncExtra *) -{ - // This function doesn't support extended datatypes, it simply - // converts everything to double - because it does quite a bit - // of computing, and, well, I'm lazy to convert it all (Tomas) - double cost = calc->conv()->asFloat (args[0]).asFloat(); - double salvage = calc->conv()->asFloat (args[1]).asFloat(); - double life = calc->conv()->asFloat (args[2]).asFloat(); - double period = calc->conv()->asFloat (args[3]).asFloat(); - double month = 12; - if (args.count() == 5) - month = calc->conv()->asFloat (args[4]).asFloat(); - - // sentinel check - if (cost == 0 || life <= 0.0) - return Value::errorVALUE (); - - if (calc->lower (calc->div (salvage, cost), 0)) - return Value::errorVALUE (); - - double rate = 1000 * (1 - pow( (salvage/cost), (1/life) )); - rate = floor( rate + 0.5 ) / 1000; - - double total = cost * rate * month / 12; - - if( period == 1 ) - return Value (total); - - for (int i = 1; i < life; ++i) - if (i == period - 1) - return Value (rate * (cost-total)); - else total += rate * (cost-total); - - return Value ((cost-total) * rate * (12-month)/12); -} - -// Function: DDB -/* depreciation per period */ -Value func_ddb (valVector args, ValueCalc *calc, FuncExtra *) -{ - double cost = calc->conv()->asFloat (args[0]).asFloat(); - double salvage = calc->conv()->asFloat (args[1]).asFloat(); - double life = calc->conv()->asFloat (args[2]).asFloat(); - double period = calc->conv()->asFloat (args[3]).asFloat(); - double factor = 2; - if (args.count() == 5) - factor = calc->conv()->asFloat (args[4]).asFloat(); - - double total = 0.0; - - if ( cost < 0.0 || salvage < 0.0 || life <= 0.0 || period < 0.0 || factor < 0.0 ) - return Value::errorVALUE(); - - for( int i = 0; i < life-1; ++i ) - { - double periodDep = ( cost - total ) * ( factor / life ); - if ( i == period - 1 ) - return Value (periodDep); - else - total += periodDep; - } - - return Value (cost - total - salvage); -} - -// Function: EURO -Value func_euro (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString currency = calc->conv()->asString (args[0]).asString().upper(); - double result = -1; - - if( currency == "ATS" ) result = 13.7603; // Austria - else if( currency == "BEF" ) result = 40.3399; // Belgium - else if( currency == "DEM" ) result = 1.95583; // Germany - else if( currency == "ESP" ) result = 166.386; // Spain - else if( currency == "FIM" ) result = 5.94573; // Finland - else if( currency == "FRF" ) result = 6.55957; // France - else if( currency == "GRD" ) result = 340.75; // Greece - else if( currency == "IEP" ) result = 0.787564; // Ireland - else if( currency == "ITL" ) result = 1936.27; // Italy - else if( currency == "LUX" ) result = 40.3399; // Luxemburg - else if( currency == "NLG" ) result = 2.20371; // Nederland - else if( currency == "PTE" ) result = 200.482; // Portugal - else - return Value::errorVALUE(); - - return Value (result); -} diff --git a/kspread/kspread_functions_financial.cpp b/kspread/kspread_functions_financial.cpp new file mode 100644 index 00000000..daccb640 --- /dev/null +++ b/kspread/kspread_functions_financial.cpp @@ -0,0 +1,907 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in financial functions + +#include + +#include "functions.h" +#include "kspread_functions_helper.h" +#include "valuecalc.h" +#include "valueconverter.h" + +#include +#include + +using namespace KSpread; + +// prototypes (sorted) +Value func_accrint (valVector args, ValueCalc *calc, FuncExtra *); +Value func_accrintm (valVector args, ValueCalc *calc, FuncExtra *); +Value func_compound (valVector args, ValueCalc *calc, FuncExtra *); +Value func_continuous (valVector args, ValueCalc *calc, FuncExtra *); +Value func_coupnum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_db (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ddb (valVector args, ValueCalc *calc, FuncExtra *); +Value func_disc (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dollarde (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dollarfr (valVector args, ValueCalc *calc, FuncExtra *); +Value func_duration (valVector args, ValueCalc *calc, FuncExtra *); +Value func_effective (valVector args, ValueCalc *calc, FuncExtra *); +Value func_euro (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fv_annuity (valVector args, ValueCalc *calc, FuncExtra *); +Value func_intrate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ipmt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ispmt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_level_coupon (valVector args, ValueCalc *calc, FuncExtra *); +Value func_nominal (valVector args, ValueCalc *calc, FuncExtra *); +Value func_nper (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pmt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ppmt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pv_annuity (valVector args, ValueCalc *calc, FuncExtra *); +Value func_received (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sln (valVector args, ValueCalc *calc, FuncExtra *); +Value func_syd (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tbilleq (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tbillprice (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tbillyield (valVector args, ValueCalc *calc, FuncExtra *); +Value func_zero_coupon (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all financial functions +void RegisterFinancialFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("ACCRINT", func_accrint); + f->setParamCount (6, 7); + repo->add (f); + f = new Function ("ACCRINTM", func_accrintm); + f->setParamCount (3, 5); + repo->add (f); + f = new Function ("COMPOUND", func_compound); + f->setParamCount (4); + repo->add (f); + f = new Function ("CONTINUOUS", func_continuous); + f->setParamCount (3); + repo->add (f); + f = new Function ("COUPNUM", func_coupnum); + f->setParamCount (3, 5); + repo->add (f); + f = new Function ("DB", func_db); + f->setParamCount (4, 5); + repo->add (f); + f = new Function ("DDB", func_ddb); + f->setParamCount (4, 5); + repo->add (f); + f = new Function ("DISC", func_disc); + f->setParamCount (4, 5); + repo->add (f); + f = new Function ("DOLLARDE", func_dollarde); + f->setParamCount (2); + repo->add (f); + f = new Function ("DOLLARFR", func_dollarfr); + f->setParamCount (2); + repo->add (f); + f = new Function ("DURATION", func_duration); + f->setParamCount (3); + repo->add (f); + f = new Function ("EFFECT", func_effective); + f->setParamCount (2); + repo->add (f); + f = new Function ("EFFECTIVE", func_effective); + f->setParamCount (2); + repo->add (f); + f = new Function ("EURO", func_euro); // KSpread-specific, Gnumeric-compatible + f->setParamCount (1); + repo->add (f); + f = new Function ("FV", func_fv); + f->setParamCount (3); + repo->add (f); + f = new Function ("FV_ANNUITY", func_fv_annuity); + f->setParamCount (3); + repo->add (f); + f = new Function ("INTRATE", func_intrate); + f->setParamCount (4, 5); + repo->add (f); + f = new Function ("IPMT", func_ipmt); + f->setParamCount (4, 6); + repo->add (f); + f = new Function ("ISPMT", func_ispmt); + f->setParamCount (4); + repo->add (f); + f = new Function ("LEVEL_COUPON", func_level_coupon); + f->setParamCount (5); + repo->add (f); + f = new Function ("NOMINAL", func_nominal); + f->setParamCount (2); + repo->add (f); + f = new Function ("NPER", func_nper); + f->setParamCount (3, 5); + repo->add (f); + f = new Function ("PMT", func_pmt); + f->setParamCount (3, 5); + repo->add (f); + f = new Function ("PPMT", func_ppmt); + f->setParamCount (4, 6); + repo->add (f); + f = new Function ("PV", func_pv); + f->setParamCount (3); + repo->add (f); + f = new Function ("PV_ANNUITY", func_pv_annuity); + f->setParamCount (3); + repo->add (f); + f = new Function ("RECEIVED", func_received); + f->setParamCount (4, 5); + repo->add (f); + f = new Function ("SLN", func_sln); + f->setParamCount (3); + repo->add (f); + f = new Function ("SYD", func_syd); + f->setParamCount (4); + repo->add (f); + f = new Function ("TBILLEQ", func_tbilleq); + f->setParamCount (3); + repo->add (f); + f = new Function ("TBILLPRICE", func_tbillprice); + f->setParamCount (3); + repo->add (f); + f = new Function ("TBILLYIELD", func_tbillyield); + f->setParamCount (3); + repo->add (f); + f = new Function ("ZERO_COUPON", func_zero_coupon); + f->setParamCount (3); + repo->add (f); +} + +static Value getPay (ValueCalc *calc, Value rate, + Value nper, Value pv, Value fv, Value type) +{ + Value pvif, fvifa; + + if (calc->isZero (rate)) return Value::errorVALUE(); + + //pvif = pow( 1 + rate, nper ); + //fvifa = ( pvif - 1 ) / rate; + pvif = calc->pow (calc->add (rate, 1), nper); + fvifa = calc->div (calc->sub (pvif, 1), rate); + + // ( -pv * pvif - fv ) / ( ( 1.0 + rate * type ) * fvifa ); + Value val1 = calc->sub (calc->mul (calc->mul (-1, pv), pvif), fv); + Value val2 = calc->mul (calc->add (1.0, calc->mul (rate, type)), + fvifa); + return calc->div (val1, val2); +} + +static Value getPrinc (ValueCalc *calc, Value start, + Value pay, Value rate, Value period) +{ + // val1 = pow( 1 + rate, period ) + Value val1 = calc->pow (calc->add (rate, 1), period); + // val2 = start * val1 + Value val2 = calc->mul (start, val1); + // val3 = pay * ( ( val1 - 1 ) / rate ) + Value val3 = calc->mul (pay, calc->div (calc->sub (val1, 1), rate)); + // result = val2 + val3 + return calc->add (val2, val3); +} + +// Function: COUPNUM - taken from GNUMERIC +Value func_coupnum (valVector args, ValueCalc *calc, FuncExtra *) +{ + // dates and integers only - don't need high-precision for this + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + int frequency = calc->conv()->asInteger (args[2]).asInteger(); + int basis = 0; + bool eom = true; + if (args.count() > 3) + basis = calc->conv()->asInteger (args[3]).asInteger(); + if (args.count() == 5) + eom = calc->conv()->asBoolean (args[4]).asBoolean(); + + if (basis < 0 || basis > 5 || ( frequency == 0 ) || ( 12 % frequency != 0 ) + || settlement.daysTo( maturity ) <= 0) + return Value::errorVALUE(); + + double result; + TQDate cDate( maturity ); + + int months = maturity.month() - settlement.month() + + 12 * ( maturity.year() - settlement.year() ); + + cDate = calc->conv()->locale()->calendar()->addMonths (cDate, -months); + + if ( eom && maturity.daysInMonth() == maturity.day() ) + { + while( cDate.daysInMonth() != cDate.day() ) + cDate.addDays( 1 ); + } + + if ( settlement.day() >= cDate.day() ) + --months; + + result = ( 1 + months / ( 12 / frequency ) ); + + return Value (result); +} + +// Function: ACCRINT +Value func_accrint (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate maturity = calc->conv()->asDate (args[0]).asDate(); + TQDate firstInterest = calc->conv()->asDate (args[1]).asDate(); + TQDate settlement = calc->conv()->asDate (args[2]).asDate(); + + Value rate = args[3]; + Value par = args[4]; + int frequency = calc->conv()->asInteger (args[5]).asInteger(); + + int basis = 0; + if (args.count() == 7) + basis = calc->conv()->asInteger (args[6]).asInteger(); + + if ( basis < 0 || basis > 4 || (calc->isZero (frequency)) || + (12 % frequency != 0)) + return Value::errorVALUE(); + + if ( ( settlement.daysTo( firstInterest ) < 0 ) + || ( firstInterest.daysTo( maturity ) > 0 ) ) + return Value::errorVALUE(); + + double d = daysBetweenDates (maturity, settlement, basis); + double y = daysPerYear (maturity, basis); + + if ( d < 0 || y <= 0 || calc->lower (par, 0) || calc->lower (rate, 0) || + calc->isZero (rate)) + return Value::errorVALUE(); + + Value coeff = calc->div (calc->mul (par, rate), frequency); + double n = d / y; + + return calc->mul (coeff, n * frequency); +} + +// Function: ACCRINTM +Value func_accrintm (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate issue = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + Value rate = args[2]; + + Value par = 1000; + int basis = 0; + if (args.count() > 3) + par = args[3]; + if (args.count() == 5) + basis = calc->conv()->asInteger (args[4]).asInteger (); + + double d = daysBetweenDates (issue, maturity, basis); + double y = daysPerYear (issue, basis); + + if (d < 0 || y <= 0 || calc->isZero (par) || calc->isZero (rate) || + calc->lower (par, 0) || calc->lower (rate, 0) || basis < 0 || basis > 4) + return Value::errorVALUE(); + + // par*date * d/y + return calc->mul (calc->mul (par, rate), d / y); +} + +// Function: DISC +Value func_disc (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value par = args[2]; + Value redemp = args[3]; + + int basis = 0; + if (args.count() == 5) + basis = calc->conv()->asInteger (args[4]).asInteger(); + + double y = daysPerYear (settlement, basis); + double d = daysBetweenDates (settlement, maturity, basis); + + if ( y <= 0 || d <= 0 || basis < 0 || basis > 4 || calc->isZero (redemp) ) + return false; + + // (redemp - par) / redemp * (y / d) + return calc->mul (calc->div (calc->sub (redemp, par), redemp), y / d); +} + + +// Function: TBILLPRICE +Value func_tbillprice (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value discount = args[2]; + + double days = settlement.daysTo( maturity ); + + if (settlement > maturity || calc->lower (discount, 0) || days > 265) + return Value::errorVALUE(); + + // (discount * days) / 360.0 + Value val = calc->div (calc->mul (discount, days), 360.0); + // 100 * (1.0 - val); + return calc->mul (calc->sub (1.0, val), 100); +} + +// Function: TBILLYIELD +Value func_tbillyield (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value rate = args[2]; + + double days = settlement.daysTo( maturity ); + + if (settlement > maturity || calc->isZero (rate) || calc->lower (rate, 0) + || days > 265) + return Value::errorVALUE(); + + // (100.0 - rate) / rate * (360.0 / days); + return calc->mul (calc->div (calc->sub (100.0, rate), rate), 360.0 / days); +} + +// Function: TBILLEQ +Value func_tbilleq (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value discount = args[2]; + + double days = settlement.daysTo( maturity ); + + if (settlement > maturity || calc->lower (discount, 0) || days > 265) + return Value::errorVALUE(); + + // 360 - discount*days + Value divisor = calc->sub (360.0, calc->mul (discount, days)); + if (calc->isZero (divisor)) + return Value::errorVALUE(); + + // 365.0 * discount / divisor + return calc->mul (calc->div (discount, divisor), 356.0); +} + +// Function: RECEIVED +Value func_received (valVector args, ValueCalc *calc, FuncExtra *) +{ + + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value investment = args[2]; + Value discount = args[3]; + + int basis = 0; + if (args.count() == 5) + basis = calc->conv()->asInteger (args[4]).asInteger(); + + double d = daysBetweenDates( settlement, maturity, basis ); + double y = daysPerYear( settlement, basis ); + + if ( d <= 0 || y <= 0 || basis < 0 || basis > 4 ) + return false; + + // 1.0 - ( discount * d / y ) + Value x = calc->sub (1.0, (calc->mul (discount, d / y))); + + if (calc->isZero (x)) + return Value::errorVALUE(); + return calc->div (investment, x); +} + +// Function: DOLLARDE +Value func_dollarde (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value d = args[0]; + Value f = args[1]; + + if (!calc->greater (f, 0)) + return Value::errorVALUE(); + + Value tmp = f; + int n = 0; + while (calc->greater (tmp, 0)) + { + tmp = calc->div (tmp, 10); + ++n; + } + + Value fl = calc->roundDown (d); + Value r = calc->sub (d, fl); + + // fl + (r * pow(10.0, n) / f) + return calc->add (fl, calc->div (calc->mul (r, pow (10.0, n)), f)); +} + +// Function: DOLLARFR +Value func_dollarfr (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value d = args[0]; + Value f = args[1]; + + if (!calc->greater (f, 0)) + return Value::errorVALUE(); + + Value tmp = f; + int n = 0; + while (calc->greater (tmp, 0)) + { + tmp = calc->div (tmp, 10); + ++n; + } + + Value fl = calc->roundDown (d); + Value r = calc->sub (d, fl); + + // fl + ((r * f) / pow (10.0, n)); + return calc->add (fl, calc->div (calc->mul (r, f), pow (10.0, n))); +} + +/// *** TODO continue here *** + +// Function: INTRATE +Value func_intrate (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQDate settlement = calc->conv()->asDate (args[0]).asDate(); + TQDate maturity = calc->conv()->asDate (args[1]).asDate(); + + Value invest = args[2]; + Value redemption = args[3]; + + int basis = 0; + if (args.count() == 5) + basis = calc->conv()->asInteger (args[4]).asInteger(); + + double d = daysBetweenDates (settlement, maturity, basis); + double y = daysPerYear (settlement, basis); + + if ( d <= 0 || y <= 0 || calc->isZero (invest) || basis < 0 || basis > 4 ) + return Value::errorVALUE(); + + // (redemption - invest) / invest * (y / d) + return calc->mul (calc->div (calc->sub (redemption, invest), invest), y/d); +} + + +// Function: DURATION +Value func_duration (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rate = args[0]; + Value pv = args[1]; + Value fv = args[2]; + + if (!calc->greater (rate, 0.0)) + return Value::errorVALUE(); + if (calc->isZero (fv) || calc->isZero (pv)) + return Value::errorDIV0(); + + if (calc->lower (calc->div (fv, pv), 0)) + return Value::errorVALUE(); + + // log(fv / pv) / log(1.0 + rate) + return calc->div (calc->ln (calc->div (fv, pv)), + calc->ln (calc->add (rate, 1.0))); +} + +// Function: PMT +Value func_pmt (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rate = args[0]; + Value nper = args[1]; + Value pv = args[2]; + Value fv = 0.0; + Value type = 0; + if (args.count() > 3) fv = args[3]; + if (args.count() == 5) type = args[4]; + + return getPay (calc, rate, nper, pv, fv, type); +} + +// Function: NPER +Value func_nper (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rate = args[0]; + Value pmt = args[1]; + Value pv = args[2]; + Value fv = 0.0; + Value type = 0; + if (args.count() > 3) fv = args[3]; + if (args.count() == 5) type = args[4]; + + if (!calc->greater (rate, 0.0)) + return Value::errorVALUE(); + + // taken from Gnumeric + // v = 1.0 + rate * type + // d1 = pmt * v - fv * rate + // d2 = pmt * v - pv * rate + // res = d1 / d2; + Value v = calc->add (calc->mul (rate, type), 1.0); + Value d1 = calc->sub (calc->mul (pmt, v), calc->mul (fv, rate)); + Value d2 = calc->add (calc->mul (pmt, v), calc->mul (pv, rate)); + Value res = calc->div (d1, d2); + + if (!calc->greater (res, 0.0)) // res must be >0 + return Value::errorVALUE(); + + // ln (res) / ln (rate + 1.0) + return calc->div (calc->ln (res), calc->ln (calc->add (rate, 1.0))); +} + +// Function: ISPMT +Value func_ispmt (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rate = args[0]; + Value per = args[1]; + Value nper = args[2]; + Value pv = args[3]; + + if (calc->lower (per, 1) || calc->greater (per, nper)) + return Value::errorVALUE(); + + // d = -pv * rate + Value d = calc->mul (calc->mul (pv, -1), rate); + + // d - (d / nper * per) + return calc->sub (d, calc->mul (calc->div (d, nper), per)); +} + +// Function: IPMT +Value func_ipmt (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rate = args[0]; + Value per = args[1]; + Value nper = args[2]; + Value pv = args[3]; + + Value fv = 0.0; + Value type = 0; + if (args.count() > 4) fv = args[4]; + if (args.count() == 6) type = args[5]; + + Value payment = getPay (calc, rate, nper, pv, fv, type); + Value ineg = getPrinc (calc, pv, payment, rate, calc->sub (per, 1)); + + // -ineg * rate + return calc->mul (calc->mul (ineg, -1), rate); +} + +// Function: PPMT +// Uses IPMT. +Value func_ppmt (valVector args, ValueCalc *calc, FuncExtra *) +{ + /* +Docs partly copied from OO. +Syntax +PPMT(Rate;Period;NPER;PV;FV;Type) + +Rate is the periodic interest rate. +Period is the amortizement period. P=1 for the first and P=NPER for the last period. +NPER is the total number of periods during which annuity is paid. +PV is the present value in the sequence of payments. +FV (optional) is the desired (future) value. +Type (optional) defines the due date. F=1 for payment at the beginning of a period and F=0 for payment at the end of a period. + */ + + Value rate = args[0]; + Value per = args[1]; + Value nper = args[2]; + Value pv = args[3]; + Value fv = 0.0; + Value type = 0; + if (args.count() > 4) fv = args[4]; + if (args.count() == 6) type = args[5]; + + Value pay = getPay (calc, rate, nper, pv, fv, type); + Value ipmt = func_ipmt (args, calc, 0); + return calc->sub (pay, ipmt); +} + +// Function: FV +/* Returns future value, given current value, interest rate and time */ +Value func_fv (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value present = args[0]; + Value interest = args[1]; + Value periods = args[2]; + + // present * pow (1 + interest, periods) + return calc->mul (present, calc->pow (calc->add (interest, 1), periods)); +} + +// Function: compound +/* Returns value after compounded interest, given principal, rate, periods +per year and year */ + Value func_compound (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value principal = args[0]; + Value interest = args[1]; + Value periods = args[2]; + Value years = args[3]; + + // principal * pow(1+ (interest / periods), periods*years); + Value base = calc->add (calc->div (interest, periods), 1); + return calc->mul (principal, calc->pow (base, calc->mul (periods, years))); +} + +// Function: continuous +/* Returns value after continuous compounding of interest, given principal, +rate and years */ +Value func_continuous (valVector args, ValueCalc *calc, FuncExtra *) +{ + // If you still don't understand this, let me know! ;-) jsinger@leeta.net + Value principal = args[0]; + Value interest = args[1]; + Value years = args[2]; + + // principal * exp(interest * years) + return calc->mul (principal, calc->exp (calc->mul (interest, years))); +} + +// Function: PV +Value func_pv (valVector args, ValueCalc *calc, FuncExtra *) +{ +/* Returns presnt value, given future value, interest rate and years */ + Value future = args[0]; + Value interest = args[1]; + Value periods = args[2]; + + // future / pow(1+interest, periods) + return calc->div (future, calc->pow (calc->add (interest, 1), periods)); +} + +// Function: PV_annuity +Value func_pv_annuity (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value amount = args[0]; + Value interest = args[1]; + Value periods = args[2]; + + // recpow = 1 / pow (1 + interest, periods) + // result = amount * (1 - recpow) / interest; + Value recpow; + recpow = calc->div (1, calc->pow (calc->add (interest, 1), periods)); + return calc->mul (amount, calc->div (calc->sub (1, recpow), interest)); +} + +// Function: FV_annnuity +Value func_fv_annuity (valVector args, ValueCalc *calc, FuncExtra *) +{ + /* Returns future value of an annuity or cash flow, given payment, interest + rate and periods */ + + Value amount = args[0]; + Value interest = args[1]; + Value periods = args[2]; + + // pw = pow (1 + interest, periods) + // result = amount * ((pw - 1) / interest) + Value pw = calc->pow (calc->add (interest, 1), periods); + return calc->mul (amount, calc->div (calc->sub (pw, 1), interest)); +} + +// Function: effective +Value func_effective (valVector args, ValueCalc *calc, FuncExtra *) +{ + // Returns effective interest rate given nominal rate and periods per year + + Value nominal = args[0]; + Value periods = args[1]; + + // base = 1 + (nominal / periods) + // result = pow (base, periods) - 1 + Value base = calc->add (calc->div (nominal, periods), 1); + return calc->sub (calc->pow (base, periods), 1); +} + +// Function: zero_coupon +Value func_zero_coupon (valVector args, ValueCalc *calc, FuncExtra *) +{ + // Returns effective interest rate given nominal rate and periods per year + + Value face = args[0]; + Value rate = args[1]; + Value years = args[2]; + + // face / pow(1 + rate, years) + return calc->div (face, calc->pow (calc->add (rate, 1), years)); +} + +// Function: level_coupon +Value func_level_coupon (valVector args, ValueCalc *calc, FuncExtra *) +{ + // Returns effective interest rate given nominal rate and periods per year + Value face = args[0]; + Value coupon_rate = args[1]; + Value coupon_year = args[2]; + Value years = args[3]; + Value market_rate = args[4]; + + Value coupon, interest, pw, pv_annuity; + // coupon = coupon_rate * face / coupon_year + // interest = market_rate / coupon_year + // pw = pow(1 + interest, years * coupon_year) + // pv_annuity = (1 - 1 / pw) / interest + // result = coupon * pv_annuity + face / pw + coupon = calc->mul (coupon_rate, calc->div (face, coupon_year)); + interest = calc->div (market_rate, coupon_year); + pw = calc->pow (calc->add (interest, 1), calc->mul (years, coupon_year)); + pv_annuity = calc->div (calc->sub (1, calc->div (1, pw)), interest); + return calc->add (calc->mul (coupon, pv_annuity), calc->div (face, pw)); +} + +// Function: nominal +Value func_nominal (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value effective = args[0]; + Value periods = args[1]; + + if (calc->isZero (periods)) // Check null + return Value::errorDIV0(); + + // pw = pow (effective + 1, 1 / periods) + // result = periods * (pw - 1); + Value pw; + pw = calc->pow (calc->add (effective, 1), calc->div (1, periods)); + return calc->mul (periods, calc->sub (pw, 1)); +} + +// Function: SLN +/* straight-line depreciation for a single period */ +Value func_sln (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value cost = args[0]; + Value salvage_value = args[1]; + Value life = args[2]; + + // sentinel check + if (!calc->greater (life, 0.0)) + return Value::errorVALUE(); + + // (cost - salvage_value) / life + return calc->div (calc->sub (cost, salvage_value), life); +} + +// Function: SYD +/* sum-of-years digits depreciation */ +Value func_syd (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value cost = args[0]; + Value salvage_value = args[1]; + Value life = args[2]; + Value period = args[3]; + + // sentinel check + if (!calc->greater (life, 0.0)) + return Value::errorVALUE(); + + // v1 = cost - salvage_value + // v2 = life - period + 1 + // v3 = life * (life + 1.0) + // result = (v1 * v2 * 2) / v3 + Value v1, v2, v3; + v1 = calc->sub (cost, salvage_value); + v2 = calc->add (calc->sub (life, period), 1); + v3 = calc->mul (life, calc->add (life, 1.0)); + return calc->div (calc->mul (calc->mul (v1, v2), 2), v3); +} + +// Function: DB +/* fixed-declining depreciation */ +Value func_db (valVector args, ValueCalc *calc, FuncExtra *) +{ + // This function doesn't support extended datatypes, it simply + // converts everything to double - because it does quite a bit + // of computing, and, well, I'm lazy to convert it all (Tomas) + double cost = calc->conv()->asFloat (args[0]).asFloat(); + double salvage = calc->conv()->asFloat (args[1]).asFloat(); + double life = calc->conv()->asFloat (args[2]).asFloat(); + double period = calc->conv()->asFloat (args[3]).asFloat(); + double month = 12; + if (args.count() == 5) + month = calc->conv()->asFloat (args[4]).asFloat(); + + // sentinel check + if (cost == 0 || life <= 0.0) + return Value::errorVALUE (); + + if (calc->lower (calc->div (salvage, cost), 0)) + return Value::errorVALUE (); + + double rate = 1000 * (1 - pow( (salvage/cost), (1/life) )); + rate = floor( rate + 0.5 ) / 1000; + + double total = cost * rate * month / 12; + + if( period == 1 ) + return Value (total); + + for (int i = 1; i < life; ++i) + if (i == period - 1) + return Value (rate * (cost-total)); + else total += rate * (cost-total); + + return Value ((cost-total) * rate * (12-month)/12); +} + +// Function: DDB +/* depreciation per period */ +Value func_ddb (valVector args, ValueCalc *calc, FuncExtra *) +{ + double cost = calc->conv()->asFloat (args[0]).asFloat(); + double salvage = calc->conv()->asFloat (args[1]).asFloat(); + double life = calc->conv()->asFloat (args[2]).asFloat(); + double period = calc->conv()->asFloat (args[3]).asFloat(); + double factor = 2; + if (args.count() == 5) + factor = calc->conv()->asFloat (args[4]).asFloat(); + + double total = 0.0; + + if ( cost < 0.0 || salvage < 0.0 || life <= 0.0 || period < 0.0 || factor < 0.0 ) + return Value::errorVALUE(); + + for( int i = 0; i < life-1; ++i ) + { + double periodDep = ( cost - total ) * ( factor / life ); + if ( i == period - 1 ) + return Value (periodDep); + else + total += periodDep; + } + + return Value (cost - total - salvage); +} + +// Function: EURO +Value func_euro (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString currency = calc->conv()->asString (args[0]).asString().upper(); + double result = -1; + + if( currency == "ATS" ) result = 13.7603; // Austria + else if( currency == "BEF" ) result = 40.3399; // Belgium + else if( currency == "DEM" ) result = 1.95583; // Germany + else if( currency == "ESP" ) result = 166.386; // Spain + else if( currency == "FIM" ) result = 5.94573; // Finland + else if( currency == "FRF" ) result = 6.55957; // France + else if( currency == "GRD" ) result = 340.75; // Greece + else if( currency == "IEP" ) result = 0.787564; // Ireland + else if( currency == "ITL" ) result = 1936.27; // Italy + else if( currency == "LUX" ) result = 40.3399; // Luxemburg + else if( currency == "NLG" ) result = 2.20371; // Nederland + else if( currency == "PTE" ) result = 200.482; // Portugal + else + return Value::errorVALUE(); + + return Value (result); +} diff --git a/kspread/kspread_functions_helper.cc b/kspread/kspread_functions_helper.cc deleted file mode 100644 index 92f7b1ae..00000000 --- a/kspread/kspread_functions_helper.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include - -#include "kspread_functions_helper.h" - -/* DISABLED - we use KCalendarSystem instead -void addMonths( TQDate & date, int months ) -{ - int d = date.day(); - int m = date.month() + months; - int y = date.year(); - - if ( m > 12 ) - { - y += (int) ( m / 12 ); - m %= 12; - } - - // e.g. 31 Feb: decrease day... - while ( !TQDate::isValid( y, m, d ) && d > 0 ) - --d; - - date.setYMD( y, m, d ); -} - -void subMonths( TQDate & date, int months ) -{ - int d = date.day(); - int m = date.month() - months; - int y = date.year(); - - while ( m < 1 ) - { - m += 12; - y -= 1; - } - - // e.g. 31 Feb: decrease day - while ( !TQDate::isValid( y, m, d ) && d > 0 ) - --d; - - date.setYMD( y, m, d ); -} - -*/ - -int KSpread::daysPerYear(TQDate const & date, int basis) -{ - switch( basis ) - { - case 0: - return 360; - - case 1: - if ( TQDate::leapYear( date.year() ) ) - return 366; - return 365; - - case 2: - return 360; - case 3: - return 365; - case 4: - return 360; - } - - return -1; -} - -int KSpread::daysBetweenDates(TQDate const & date1, TQDate const & date2, int basis) -{ - int day1, day2, month1, month2, year1, year2; - bool isLeapYear = false; - int days, months, years; - - day1 = date1.day(); - month1 = date1.month(); - year1 = date1.year(); - day2 = date2.day(); - month2 = date2.month(); - year2 = date2.year(); - - years = year2 - year1; - months = month2 - month1 + years * 12; - days = day2 - day1; - - isLeapYear = TQDate::leapYear( year1 ); - - switch (basis) - { - case 0: - if ( month1 == 2 && month2 != 2 && year1 == year2 ) - { - if ( isLeapYear ) - return months * 30 + days - 1; - else - return months * 30 + days - 2; - } - return months * 30 + days; - - case 1: // TODO: real days for difference between months! - // return ( month2 - month1 ) * 30 + years * 360 + days; - - case 2: // TODO: real days for difference between months! - // return ( month2 - month1 ) * 30 + years * 365 + days; - - case 3: - return date1.daysTo( date2 ); - - case 4: - return months * 30 + days; - } - - return -1; -} - diff --git a/kspread/kspread_functions_helper.cpp b/kspread/kspread_functions_helper.cpp new file mode 100644 index 00000000..92f7b1ae --- /dev/null +++ b/kspread/kspread_functions_helper.cpp @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include + +#include "kspread_functions_helper.h" + +/* DISABLED - we use KCalendarSystem instead +void addMonths( TQDate & date, int months ) +{ + int d = date.day(); + int m = date.month() + months; + int y = date.year(); + + if ( m > 12 ) + { + y += (int) ( m / 12 ); + m %= 12; + } + + // e.g. 31 Feb: decrease day... + while ( !TQDate::isValid( y, m, d ) && d > 0 ) + --d; + + date.setYMD( y, m, d ); +} + +void subMonths( TQDate & date, int months ) +{ + int d = date.day(); + int m = date.month() - months; + int y = date.year(); + + while ( m < 1 ) + { + m += 12; + y -= 1; + } + + // e.g. 31 Feb: decrease day + while ( !TQDate::isValid( y, m, d ) && d > 0 ) + --d; + + date.setYMD( y, m, d ); +} + +*/ + +int KSpread::daysPerYear(TQDate const & date, int basis) +{ + switch( basis ) + { + case 0: + return 360; + + case 1: + if ( TQDate::leapYear( date.year() ) ) + return 366; + return 365; + + case 2: + return 360; + case 3: + return 365; + case 4: + return 360; + } + + return -1; +} + +int KSpread::daysBetweenDates(TQDate const & date1, TQDate const & date2, int basis) +{ + int day1, day2, month1, month2, year1, year2; + bool isLeapYear = false; + int days, months, years; + + day1 = date1.day(); + month1 = date1.month(); + year1 = date1.year(); + day2 = date2.day(); + month2 = date2.month(); + year2 = date2.year(); + + years = year2 - year1; + months = month2 - month1 + years * 12; + days = day2 - day1; + + isLeapYear = TQDate::leapYear( year1 ); + + switch (basis) + { + case 0: + if ( month1 == 2 && month2 != 2 && year1 == year2 ) + { + if ( isLeapYear ) + return months * 30 + days - 1; + else + return months * 30 + days - 2; + } + return months * 30 + days; + + case 1: // TODO: real days for difference between months! + // return ( month2 - month1 ) * 30 + years * 360 + days; + + case 2: // TODO: real days for difference between months! + // return ( month2 - month1 ) * 30 + years * 365 + days; + + case 3: + return date1.daysTo( date2 ); + + case 4: + return months * 30 + days; + } + + return -1; +} + diff --git a/kspread/kspread_functions_information.cc b/kspread/kspread_functions_information.cc deleted file mode 100644 index 30d64263..00000000 --- a/kspread/kspread_functions_information.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in information functions - - -#include -#include - -#include -#include -#include - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -#include "kspread_doc.h" -#include "kspread_sheet.h" - -using namespace KSpread; - -// prototypes (sorted alphabetically) -Value func_filename (valVector args, ValueCalc *calc, FuncExtra *); -Value func_info (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isblank (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isdate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_iserr (valVector args, ValueCalc *calc, FuncExtra *); -Value func_iserror (valVector args, ValueCalc *calc, FuncExtra *); -Value func_iseven (valVector args, ValueCalc *calc, FuncExtra *); -Value func_islogical (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isna (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isnottext (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isnum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isodd (valVector args, ValueCalc *calc, FuncExtra *); -Value func_isref (valVector args, ValueCalc *calc, FuncExtra *); -Value func_istext (valVector args, ValueCalc *calc, FuncExtra *); -Value func_istime (valVector args, ValueCalc *calc, FuncExtra *); -Value func_n (valVector args, ValueCalc *calc, FuncExtra *); -Value func_type (valVector args, ValueCalc *calc, FuncExtra *); -Value func_version (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all information functions -void RegisterInformationFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("FILENAME", func_filename); - f->setParamCount (0); - repo->add (f); - f = new Function ("INFO", func_info); - repo->add (f); - f = new Function ("ISBLANK", func_isblank); - repo->add (f); - f = new Function ("ISDATE", func_isdate); - repo->add (f); - f = new Function ("ISERR", func_iserr); - repo->add (f); - f = new Function ("ISERROR", func_iserror); - repo->add (f); - f = new Function ("ISEVEN", func_iseven); - repo->add (f); - f = new Function ("ISLOGICAL", func_islogical); - repo->add (f); - f = new Function ("ISNA", func_isna); - repo->add (f); - f = new Function ("ISNONTEXT", func_isnottext); - repo->add (f); - f = new Function ("ISNOTTEXT", func_isnottext); - repo->add (f); - f = new Function ("ISNUM", func_isnum); - repo->add (f); - f = new Function ("ISNUMBER", func_isnum); - repo->add (f); - f = new Function ("ISODD", func_isodd); - repo->add (f); - f = new Function ("ISREF", func_isref); - f->setNeedsExtra (true); - repo->add (f); - f = new Function ("ISTEXT", func_istext); - repo->add (f); - f = new Function ("ISTIME", func_istime); - repo->add (f); - f = new Function ("N", func_n); - repo->add (f); - f = new Function ("TYPE", func_type); - f->setAcceptArray (); - repo->add (f); -} - -// Function: INFO -Value func_info (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString type = calc->conv()->asString (args[0]).asString().lower(); - - if (type == "directory") - return Value (TQDir::currentDirPath()); - - if (type == "release") - return Value (TQString (VERSION)); - - if ( type == "numfile" ) - return Value ((int) Doc::documents().count()); - - if (type == "recalc") - { - TQString result; - if (calc->doc()) { - if (calc->doc()->delayCalculation()) - result = i18n ("Manual"); - else - result = i18n ("Automatic"); - } - return Value (result); - } - - if (type == "memavail") - // not supported - return Value::errorVALUE(); - if (type == "memused") - // not supported - return Value::errorVALUE(); - if (type == "origin") - // not supported - return Value::errorVALUE(); - - if (type == "system") { - struct utsname name; - if (uname (&name) >= 0) - return Value (TQString (name.sysname)); - } - - if (type == "totmem") - // not supported - return Value::errorVALUE(); - - if (type == "osversion") - { - struct utsname name; - if (uname (&name) >= 0) - { - TQString os = TQString("%1 %2 (%3)").arg( name.sysname ). - arg( name.release ).arg( name.machine ); - return Value (os); - } - } - - return Value::errorVALUE(); -} - -// Function: ISBLANK -Value func_isblank (valVector args, ValueCalc *, FuncExtra *) -{ - return Value (args[0].isEmpty()); -} - -// Function: ISLOGICAL -Value func_islogical (valVector args, ValueCalc *, FuncExtra *) -{ - return Value (args[0].isBoolean()); -} - -// Function: ISTEXT -Value func_istext (valVector args, ValueCalc *, FuncExtra *) -{ - return Value (args[0].isString()); -} - -// Function: ISREF -Value func_isref (valVector, ValueCalc */*calc*/, FuncExtra *e) -{ - // no reference ? - if ((e == 0) || (e->ranges[0].col1 == -1) || (e->ranges[0].row1 == -1)) - return Value (false); - // if we are here, it is a reference (cell/range) - return Value (true); -} - -// Function: ISNOTTEXT -Value func_isnottext (valVector args, ValueCalc *, FuncExtra *) -{ - return Value (args[0].isString() ? false : true); -} - -// Function: ISNUM -Value func_isnum (valVector args, ValueCalc *, FuncExtra *) -{ - return Value (args[0].isNumber()); -} - -// Function: ISTIME -Value func_istime (valVector args, ValueCalc *, FuncExtra *) -{ - return Value ((args[0].format() == Value::fmt_Time) - || (args[0].format() == Value::fmt_DateTime)); -} - -// Function: ISDATE -Value func_isdate (valVector args, ValueCalc *, FuncExtra *) -{ - return Value ((args[0].format() == Value::fmt_Date) - || (args[0].format() == Value::fmt_DateTime)); -} - -// Function: ISODD -Value func_isodd (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->isEven(args[0]) ? false : true); -} - -// Function: ISEVEN -Value func_iseven (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->isEven(args[0])); -} - -// Function: ISERR -Value func_iserr (valVector args, ValueCalc *, FuncExtra *) -{ - return (args[0].isError() && - (args[0].errorMessage() != Value::errorNA().errorMessage())); -} - -// Function: ISERROR -Value func_iserror (valVector args, ValueCalc *, FuncExtra *) -{ - return args[0].isError(); -} - -// Function: ISNA -Value func_isna (valVector args, ValueCalc *, FuncExtra *) -{ - return (args[0].isError() && - (args[0].errorMessage() == Value::errorNA().errorMessage())); -} - -// Function: TYPE -Value func_type (valVector args, ValueCalc *, FuncExtra *) -{ - // Returns 1 for numbers, 2 for text, 4 for boolean, 16 for error, - // 64 for arrays - if (args[0].isArray()) - return Value (64); - if (args[0].isNumber()) - return Value (1); - if (args[0].isString()) - return Value (2); - if (args[0].isBoolean()) - return Value (4); - if (args[0].isError()) - return Value (16); - - // something else ? - return Value (0); -} - -Value func_filename (valVector, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->doc()->url().prettyURL()); -} - -// Function: N -Value func_n (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asFloat (args[0]); -} diff --git a/kspread/kspread_functions_information.cpp b/kspread/kspread_functions_information.cpp new file mode 100644 index 00000000..30d64263 --- /dev/null +++ b/kspread/kspread_functions_information.cpp @@ -0,0 +1,285 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in information functions + + +#include +#include + +#include +#include +#include + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +#include "kspread_doc.h" +#include "kspread_sheet.h" + +using namespace KSpread; + +// prototypes (sorted alphabetically) +Value func_filename (valVector args, ValueCalc *calc, FuncExtra *); +Value func_info (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isblank (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isdate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_iserr (valVector args, ValueCalc *calc, FuncExtra *); +Value func_iserror (valVector args, ValueCalc *calc, FuncExtra *); +Value func_iseven (valVector args, ValueCalc *calc, FuncExtra *); +Value func_islogical (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isna (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isnottext (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isnum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isodd (valVector args, ValueCalc *calc, FuncExtra *); +Value func_isref (valVector args, ValueCalc *calc, FuncExtra *); +Value func_istext (valVector args, ValueCalc *calc, FuncExtra *); +Value func_istime (valVector args, ValueCalc *calc, FuncExtra *); +Value func_n (valVector args, ValueCalc *calc, FuncExtra *); +Value func_type (valVector args, ValueCalc *calc, FuncExtra *); +Value func_version (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all information functions +void RegisterInformationFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("FILENAME", func_filename); + f->setParamCount (0); + repo->add (f); + f = new Function ("INFO", func_info); + repo->add (f); + f = new Function ("ISBLANK", func_isblank); + repo->add (f); + f = new Function ("ISDATE", func_isdate); + repo->add (f); + f = new Function ("ISERR", func_iserr); + repo->add (f); + f = new Function ("ISERROR", func_iserror); + repo->add (f); + f = new Function ("ISEVEN", func_iseven); + repo->add (f); + f = new Function ("ISLOGICAL", func_islogical); + repo->add (f); + f = new Function ("ISNA", func_isna); + repo->add (f); + f = new Function ("ISNONTEXT", func_isnottext); + repo->add (f); + f = new Function ("ISNOTTEXT", func_isnottext); + repo->add (f); + f = new Function ("ISNUM", func_isnum); + repo->add (f); + f = new Function ("ISNUMBER", func_isnum); + repo->add (f); + f = new Function ("ISODD", func_isodd); + repo->add (f); + f = new Function ("ISREF", func_isref); + f->setNeedsExtra (true); + repo->add (f); + f = new Function ("ISTEXT", func_istext); + repo->add (f); + f = new Function ("ISTIME", func_istime); + repo->add (f); + f = new Function ("N", func_n); + repo->add (f); + f = new Function ("TYPE", func_type); + f->setAcceptArray (); + repo->add (f); +} + +// Function: INFO +Value func_info (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString type = calc->conv()->asString (args[0]).asString().lower(); + + if (type == "directory") + return Value (TQDir::currentDirPath()); + + if (type == "release") + return Value (TQString (VERSION)); + + if ( type == "numfile" ) + return Value ((int) Doc::documents().count()); + + if (type == "recalc") + { + TQString result; + if (calc->doc()) { + if (calc->doc()->delayCalculation()) + result = i18n ("Manual"); + else + result = i18n ("Automatic"); + } + return Value (result); + } + + if (type == "memavail") + // not supported + return Value::errorVALUE(); + if (type == "memused") + // not supported + return Value::errorVALUE(); + if (type == "origin") + // not supported + return Value::errorVALUE(); + + if (type == "system") { + struct utsname name; + if (uname (&name) >= 0) + return Value (TQString (name.sysname)); + } + + if (type == "totmem") + // not supported + return Value::errorVALUE(); + + if (type == "osversion") + { + struct utsname name; + if (uname (&name) >= 0) + { + TQString os = TQString("%1 %2 (%3)").arg( name.sysname ). + arg( name.release ).arg( name.machine ); + return Value (os); + } + } + + return Value::errorVALUE(); +} + +// Function: ISBLANK +Value func_isblank (valVector args, ValueCalc *, FuncExtra *) +{ + return Value (args[0].isEmpty()); +} + +// Function: ISLOGICAL +Value func_islogical (valVector args, ValueCalc *, FuncExtra *) +{ + return Value (args[0].isBoolean()); +} + +// Function: ISTEXT +Value func_istext (valVector args, ValueCalc *, FuncExtra *) +{ + return Value (args[0].isString()); +} + +// Function: ISREF +Value func_isref (valVector, ValueCalc */*calc*/, FuncExtra *e) +{ + // no reference ? + if ((e == 0) || (e->ranges[0].col1 == -1) || (e->ranges[0].row1 == -1)) + return Value (false); + // if we are here, it is a reference (cell/range) + return Value (true); +} + +// Function: ISNOTTEXT +Value func_isnottext (valVector args, ValueCalc *, FuncExtra *) +{ + return Value (args[0].isString() ? false : true); +} + +// Function: ISNUM +Value func_isnum (valVector args, ValueCalc *, FuncExtra *) +{ + return Value (args[0].isNumber()); +} + +// Function: ISTIME +Value func_istime (valVector args, ValueCalc *, FuncExtra *) +{ + return Value ((args[0].format() == Value::fmt_Time) + || (args[0].format() == Value::fmt_DateTime)); +} + +// Function: ISDATE +Value func_isdate (valVector args, ValueCalc *, FuncExtra *) +{ + return Value ((args[0].format() == Value::fmt_Date) + || (args[0].format() == Value::fmt_DateTime)); +} + +// Function: ISODD +Value func_isodd (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->isEven(args[0]) ? false : true); +} + +// Function: ISEVEN +Value func_iseven (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->isEven(args[0])); +} + +// Function: ISERR +Value func_iserr (valVector args, ValueCalc *, FuncExtra *) +{ + return (args[0].isError() && + (args[0].errorMessage() != Value::errorNA().errorMessage())); +} + +// Function: ISERROR +Value func_iserror (valVector args, ValueCalc *, FuncExtra *) +{ + return args[0].isError(); +} + +// Function: ISNA +Value func_isna (valVector args, ValueCalc *, FuncExtra *) +{ + return (args[0].isError() && + (args[0].errorMessage() == Value::errorNA().errorMessage())); +} + +// Function: TYPE +Value func_type (valVector args, ValueCalc *, FuncExtra *) +{ + // Returns 1 for numbers, 2 for text, 4 for boolean, 16 for error, + // 64 for arrays + if (args[0].isArray()) + return Value (64); + if (args[0].isNumber()) + return Value (1); + if (args[0].isString()) + return Value (2); + if (args[0].isBoolean()) + return Value (4); + if (args[0].isError()) + return Value (16); + + // something else ? + return Value (0); +} + +Value func_filename (valVector, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->doc()->url().prettyURL()); +} + +// Function: N +Value func_n (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asFloat (args[0]); +} diff --git a/kspread/kspread_functions_logic.cc b/kspread/kspread_functions_logic.cc deleted file mode 100644 index 87dd26d4..00000000 --- a/kspread/kspread_functions_logic.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in logical functions - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -using namespace KSpread; - -// prototypes (sorted alphabetically) -Value func_and (valVector args, ValueCalc *calc, FuncExtra *); -Value func_false (valVector args, ValueCalc *calc, FuncExtra *); -Value func_if (valVector args, ValueCalc *calc, FuncExtra *); -Value func_nand (valVector args, ValueCalc *calc, FuncExtra *); -Value func_nor (valVector args, ValueCalc *calc, FuncExtra *); -Value func_not (valVector args, ValueCalc *calc, FuncExtra *); -Value func_or (valVector args, ValueCalc *calc, FuncExtra *); -Value func_true (valVector args, ValueCalc *calc, FuncExtra *); -Value func_xor (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all logic functions -void RegisterLogicFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("FALSE", func_false); - f->setParamCount (0); - repo->add (f); - f = new Function ("TRUE", func_true); - f->setParamCount (0); - repo->add (f); - f = new Function ("NOT", func_not); - f->setParamCount (1); - repo->add (f); - f = new Function ("AND", func_and); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("NAND", func_nand); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("NOR", func_nor); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("OR", func_or); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("XOR", func_xor); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("IF", func_if); - f->setParamCount (3); - repo->add (f); -} - -// Function: FALSE -Value func_false (valVector, ValueCalc *, FuncExtra *) -{ - return Value (false); -} - -// Function: TRUE -Value func_true (valVector, ValueCalc *, FuncExtra *) -{ - return Value (true); -} - -// helper for most logical functions -bool asBool (Value val, ValueCalc *calc) -{ - return calc->conv()->asBoolean (val).asBoolean (); -} - -// Function: NOT -Value func_not (valVector args, ValueCalc *calc, FuncExtra *) -{ - bool val = asBool (args[0], calc) ? false : true; - return Value (val); -} - -// Function: OR -void awOr (ValueCalc *calc, Value &res, Value value, Value) -{ - if (! res.asBoolean()) - res = Value ( asBool (value, calc) ); -} -Value func_or (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result(false); - int cnt = args.count(); - for (int i = 0; i < cnt; ++i) { - calc->arrayWalk (args[i], result, awOr, 0); - if (result.asBoolean()) - // if any value is true, return true - return result; - } - // nothing is true -> return false - return result; -} - -// Function: NOR -Value func_nor (valVector args, ValueCalc *calc, FuncExtra *extra) -{ - // OR in reverse - return Value(! func_or(args, calc, extra).asBoolean()); -} - -// Function: AND -void awAnd (ValueCalc *calc, Value &res, Value value, Value) -{ - if (res.asBoolean()) - res = Value ( asBool (value, calc) ); -} -Value func_and (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result(true); - int cnt = args.count(); - for (int i = 0; i < cnt; ++i) { - calc->arrayWalk (args[i], result, awAnd, 0); - if (! result.asBoolean()) - // if any value is false, return false - return result; - } - // nothing is false -> return true - return result; -} - -// Function: NAND -Value func_nand (valVector args, ValueCalc *calc, FuncExtra *extra) -{ - // AND in reverse - return Value(! func_and(args, calc, extra).asBoolean()); -} - -// Function: XOR -void awXor (ValueCalc *calc, Value &count, Value value, Value) -{ - if (asBool (value, calc)) - count = Value( count.asInteger() + 1 ); -} -Value func_xor (valVector args, ValueCalc *calc, FuncExtra *) -{ - // exclusive OR - exactly one value must be true - int cnt = args.count(); - Value count(0); - for (int i = 0; i < cnt; ++i) - calc->arrayWalk (args[i], count, awXor, 0); - return Value (count.asInteger() == 1); -} - -// Function: IF -Value func_if (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (asBool (args[0], calc)) - return args[1]; - else - return args[2]; -} diff --git a/kspread/kspread_functions_logic.cpp b/kspread/kspread_functions_logic.cpp new file mode 100644 index 00000000..87dd26d4 --- /dev/null +++ b/kspread/kspread_functions_logic.cpp @@ -0,0 +1,183 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in logical functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +using namespace KSpread; + +// prototypes (sorted alphabetically) +Value func_and (valVector args, ValueCalc *calc, FuncExtra *); +Value func_false (valVector args, ValueCalc *calc, FuncExtra *); +Value func_if (valVector args, ValueCalc *calc, FuncExtra *); +Value func_nand (valVector args, ValueCalc *calc, FuncExtra *); +Value func_nor (valVector args, ValueCalc *calc, FuncExtra *); +Value func_not (valVector args, ValueCalc *calc, FuncExtra *); +Value func_or (valVector args, ValueCalc *calc, FuncExtra *); +Value func_true (valVector args, ValueCalc *calc, FuncExtra *); +Value func_xor (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all logic functions +void RegisterLogicFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("FALSE", func_false); + f->setParamCount (0); + repo->add (f); + f = new Function ("TRUE", func_true); + f->setParamCount (0); + repo->add (f); + f = new Function ("NOT", func_not); + f->setParamCount (1); + repo->add (f); + f = new Function ("AND", func_and); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("NAND", func_nand); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("NOR", func_nor); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("OR", func_or); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("XOR", func_xor); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IF", func_if); + f->setParamCount (3); + repo->add (f); +} + +// Function: FALSE +Value func_false (valVector, ValueCalc *, FuncExtra *) +{ + return Value (false); +} + +// Function: TRUE +Value func_true (valVector, ValueCalc *, FuncExtra *) +{ + return Value (true); +} + +// helper for most logical functions +bool asBool (Value val, ValueCalc *calc) +{ + return calc->conv()->asBoolean (val).asBoolean (); +} + +// Function: NOT +Value func_not (valVector args, ValueCalc *calc, FuncExtra *) +{ + bool val = asBool (args[0], calc) ? false : true; + return Value (val); +} + +// Function: OR +void awOr (ValueCalc *calc, Value &res, Value value, Value) +{ + if (! res.asBoolean()) + res = Value ( asBool (value, calc) ); +} +Value func_or (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result(false); + int cnt = args.count(); + for (int i = 0; i < cnt; ++i) { + calc->arrayWalk (args[i], result, awOr, 0); + if (result.asBoolean()) + // if any value is true, return true + return result; + } + // nothing is true -> return false + return result; +} + +// Function: NOR +Value func_nor (valVector args, ValueCalc *calc, FuncExtra *extra) +{ + // OR in reverse + return Value(! func_or(args, calc, extra).asBoolean()); +} + +// Function: AND +void awAnd (ValueCalc *calc, Value &res, Value value, Value) +{ + if (res.asBoolean()) + res = Value ( asBool (value, calc) ); +} +Value func_and (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result(true); + int cnt = args.count(); + for (int i = 0; i < cnt; ++i) { + calc->arrayWalk (args[i], result, awAnd, 0); + if (! result.asBoolean()) + // if any value is false, return false + return result; + } + // nothing is false -> return true + return result; +} + +// Function: NAND +Value func_nand (valVector args, ValueCalc *calc, FuncExtra *extra) +{ + // AND in reverse + return Value(! func_and(args, calc, extra).asBoolean()); +} + +// Function: XOR +void awXor (ValueCalc *calc, Value &count, Value value, Value) +{ + if (asBool (value, calc)) + count = Value( count.asInteger() + 1 ); +} +Value func_xor (valVector args, ValueCalc *calc, FuncExtra *) +{ + // exclusive OR - exactly one value must be true + int cnt = args.count(); + Value count(0); + for (int i = 0; i < cnt; ++i) + calc->arrayWalk (args[i], count, awXor, 0); + return Value (count.asInteger() == 1); +} + +// Function: IF +Value func_if (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (asBool (args[0], calc)) + return args[1]; + else + return args[2]; +} diff --git a/kspread/kspread_functions_math.cc b/kspread/kspread_functions_math.cc deleted file mode 100644 index 06b6da2b..00000000 --- a/kspread/kspread_functions_math.cc +++ /dev/null @@ -1,1144 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in math functions - -#include -#include - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -// these two are needed for SUBTOTAL: -#include "kspread_cell.h" -#include "kspread_sheet.h" - -// needed for RANDBINOM and so -#include - -using namespace KSpread; - -// RANDBINOM and RANDNEGBINOM won't support arbitrary precision - -// prototypes -Value func_abs (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *); -Value func_count (valVector args, ValueCalc *calc, FuncExtra *); -Value func_counta (valVector args, ValueCalc *calc, FuncExtra *); -Value func_countblank (valVector args, ValueCalc *calc, FuncExtra *); -Value func_countif (valVector args, ValueCalc *calc, FuncExtra *); -Value func_cur (valVector args, ValueCalc *calc, FuncExtra *); -Value func_div (valVector args, ValueCalc *calc, FuncExtra *); -Value func_eps (valVector args, ValueCalc *calc, FuncExtra *); -Value func_even (valVector args, ValueCalc *calc, FuncExtra *); -Value func_exp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fact (valVector args, ValueCalc *calc, FuncExtra *); -Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fib (valVector args, ValueCalc *calc, FuncExtra *); -Value func_floor (valVector args, ValueCalc *calc, FuncExtra *); -Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *); -Value func_int (valVector args, ValueCalc *calc, FuncExtra *); -Value func_inv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *); -Value func_ln (valVector args, ValueCalc *calc, FuncExtra *); -Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_logn (valVector args, ValueCalc *calc, FuncExtra *); -Value func_max (valVector args, ValueCalc *calc, FuncExtra *); -Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *); -Value func_min (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mina (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mod (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mround (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mult (valVector args, ValueCalc *calc, FuncExtra *); -Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *); -Value func_odd (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pow (valVector args, ValueCalc *calc, FuncExtra *); -Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *); -Value func_product (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rand (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *); -Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *); -Value func_round (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *); -Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sign (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *); -Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sum (valVector args, ValueCalc *calc, FuncExtra *); -Value func_suma (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *); -Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *); - - -// Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all math functions -void RegisterMathFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - -/* - f = new Function ("MULTIPLEOPERATIONS", func_multipleOP); - repo->add (f); -*/ - - // functions that don't take array parameters - f = new Function ("ABS", func_abs); - repo->add (f); - f = new Function ("CEIL", func_ceil); - repo->add (f); - f = new Function ("CEILING", func_ceiling); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("CUR", func_cur); - repo->add (f); - f = new Function ("EPS", func_eps); - f->setParamCount (0); - repo->add (f); - f = new Function ("EVEN", func_even); - repo->add (f); - f = new Function ("EXP", func_exp); - repo->add (f); - f = new Function ("FACT", func_fact); - repo->add (f); - f = new Function ("FACTDOUBLE", func_factdouble); - repo->add (f); - f = new Function ("FIB", func_fib); // KSpread-specific, like Quattro-Pro's FIB - repo->add (f); - f = new Function ("FLOOR", func_floor); - repo->add (f); - f = new Function ("INT", func_int); - repo->add (f); - f = new Function ("INV", func_inv); - repo->add (f); - f = new Function ("LN", func_ln); - repo->add (f); - f = new Function ("LOG", func_log10); - repo->add (f); - f = new Function ("LOG2", func_log2); - repo->add (f); - f = new Function ("LOG10", func_log10); // same as LOG - repo->add (f); - f = new Function ("LOGN", func_logn); - f->setParamCount (2); - repo->add (f); - f = new Function ("MOD", func_mod); - f->setParamCount (2); - repo->add (f); - f = new Function ("MROUND", func_mround); - f->setParamCount (2); - repo->add (f); - f = new Function ("MULTINOMIAL", func_multinomial); - f->setParamCount (1, -1); - repo->add (f); - f = new Function ("ODD", func_odd); - repo->add (f); - f = new Function ("POW", func_pow); - f->setParamCount (2); - repo->add (f); - f = new Function ("POWER", func_pow); - f->setParamCount (2); - repo->add (f); - f = new Function ("QUOTIENT", func_quotient); - f->setParamCount (2); - repo->add (f); - f = new Function ("RAND", func_rand); - f->setParamCount (0); - repo->add (f); - f = new Function ("RANDBERNOULLI", func_randbernoulli); - repo->add (f); - f = new Function ("RANDBETWEEN", func_randbetween); - f->setParamCount (2); - repo->add (f); - f = new Function ("RANDBINOM", func_randbinom); - f->setParamCount (2); - repo->add (f); - f = new Function ("RANDEXP", func_randexp); - repo->add (f); - f = new Function ("RANDNEGBINOM", func_randnegbinom); - f->setParamCount (2); - repo->add (f); - f = new Function ("RANDNORM", func_randnorm); - f->setParamCount (2); - repo->add (f); - f = new Function ("RANDPOISSON", func_randpoisson); - repo->add (f); - f = new Function ("ROOTN", func_rootn); - f->setParamCount (2); - repo->add (f); - f = new Function ("ROUND", func_round); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("ROUNDDOWN", func_rounddown); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("ROUNDUP", func_roundup); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("SIGN", func_sign); - repo->add (f); - f = new Function ("SQRT", func_sqrt); - repo->add (f); - f = new Function ("SQRTPI", func_sqrtpi); - repo->add (f); - f = new Function ("TRUNC", func_trunc); - f->setParamCount (1, 2); - repo->add (f); - - // functions that operate over arrays - f = new Function ("COUNT", func_count); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("COUNTA", func_counta); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("COUNTBLANK", func_countblank); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("COUNTIF", func_countif); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DIV", func_div); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("G_PRODUCT", func_kproduct); // Gnumeric compatibility - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("GCD", func_gcd); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("KPRODUCT", func_kproduct); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("LCM", func_lcm); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MAX", func_max); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MAXA", func_maxa); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MDETERM", func_mdeterm); - f->setParamCount (1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MIN", func_min); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MINA", func_mina); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MMULT", func_mmult); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MULTIPLY", func_product); // same as PRODUCT - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("PRODUCT", func_product); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUM", func_sum); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUMA", func_suma); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUBTOTAL", func_subtotal); - f->setParamCount (2); - f->setAcceptArray (); - f->setNeedsExtra (true); - repo->add (f); - f = new Function ("SUMIF", func_sumif); - f->setParamCount (2, 3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUMSQ", func_sumsq); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); -} - -// Function: SQRT -Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->sqrt (args[0]); -} - -// Function: SQRTPI -Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *) -{ - // sqrt (val * PI) - return calc->sqrt (calc->mul (args[0], calc->pi())); -} - -// Function: ROOTN -Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->pow (args[0], calc->div (1, args[1])); -} - -// Function: CUR -Value func_cur (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->pow (args[0], 1.0/3.0); -} - -// Function: ABS -Value func_abs (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->abs (args[0]); -} - -// Function: exp -Value func_exp (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->exp (args[0]); -} - -// Function: ceil -Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->roundUp (args[0], 0); -} - -// Function: ceiling -Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value number = args[0]; - Value res; - if (args.count() == 2) - res = args[1]; - else - res = calc->gequal (number, 0.0) ? 1.0 : -1.0; - - if (calc->isZero(res)) - return Value::errorDIV0(); - - Value d = calc->div (number, res); - if (calc->greater (0, d)) - return Value::errorVALUE(); - - Value rud = calc->roundDown (d); - if (calc->approxEqual (rud, d)) - d = calc->mul (rud, res); - else - d = calc->mul (calc->roundUp (d), res); - - return d; -} - -// Function: floor -Value func_floor (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->roundDown (args[0], 0); -} - -// Function: ln -Value func_ln (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->ln (args[0]); -} - -// Function: LOGn -Value func_logn (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->log (args[0], args[1]); -} - -// Function: LOG2 -Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->log (args[0], 2.0); -} - -// Function: LOG10 -Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->log (args[0]); -} - -// Function: sum -Value func_sum (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->sum (args, false); -} - -// Function: suma -Value func_suma (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->sum (args, true); -} - -Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value checkRange = args[0]; - TQString condition = calc->conv()->asString (args[1]).asString(); - Value sumRange = checkRange; - if (args.count() == 3) - sumRange = args[2]; - - Condition cond; - calc->getCond (cond, condition); - - return calc->sumIf (sumRange, checkRange, cond); -} - -// Function: product -Value func_product (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->product (args, 0.0); -} - -// Function: kproduct -Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->product (args, 1.0); -} - -// Function: DIV -Value func_div (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value val = args[0]; - for (unsigned int i = 1; i < args.count(); ++i) - { - val = calc->div (val, args[i]); - if (val.isError()) - return val; - } - return val; -} - -// Function: SUMSQ -Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value res; - calc->arrayWalk (args, res, calc->awFunc ("sumsq"), 0); - return res; -} - -// Function: MAX -Value func_max (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m = calc->max (args, false); - return m.isEmpty() ? Value(0.0) : m; -} - -// Function: MAXA -Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m = calc->max (args); - return m.isEmpty() ? Value(0.0) : m; -} - -// Function: MIN -Value func_min (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m = calc->min (args, false); - return m.isEmpty() ? Value(0.0) : m; -} - -// Function: MINA -Value func_mina (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m = calc->min (args); - return m.isEmpty() ? Value(0.0) : m; -} - -// Function: INT -Value func_int (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asInteger (args[0]); -} - -// Function: QUOTIENT -Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (calc->isZero (args[1])) - return Value::errorDIV0(); - return calc->conv()->asInteger (calc->div (args[0], args[1])); -} - - -// Function: eps -Value func_eps (valVector, ValueCalc *calc, FuncExtra *) -{ - return calc->eps (); -} - -Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *) -{ - // -1 * d * log (random) - return calc->mul (calc->mul (args[0], -1), calc->random()); -} - -Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *) -{ - // this function will not support arbitrary precision - - double d = calc->conv()->asFloat (args[0]).asFloat(); - int tr = calc->conv()->asInteger (args[1]).asInteger(); - - if ( d < 0 || d > 1 ) - return Value::errorVALUE(); - - if ( tr < 0 ) - return Value::errorVALUE(); - - // taken from gnumeric - double x = pow(1 - d, tr); - double r = (double) rand() / ( RAND_MAX + 1.0 ); - double t = x; - int i = 0; - - while (r > t) - { - x *= (((tr - i) * d) / ((1 + i) * (1 - d))); - i++; - t += x; - } - - return Value (i); -} - -Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *) -{ - // this function will not support arbitrary precision - - double d = calc->conv()->asFloat (args[0]).asFloat(); - int f = calc->conv()->asInteger (args[1]).asInteger(); - - if ( d < 0 || d > 1 ) - return Value::errorVALUE(); - - if ( f < 0 ) - return Value::errorVALUE(); - - - // taken from Gnumeric - double x = pow(d, f); - double r = (double) rand() / ( RAND_MAX + 1.0 ); - double t = x; - int i = 0; - - while (r > t) - { - x *= ( ( ( f + i ) * ( 1 - d ) ) / (1 + i) ) ; - i++; - t += x; - } - - return Value (i); -} - -Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value rnd = calc->random (); - return Value (calc->greater (rnd, args[0]) ? 1.0 : 0.0); -} - -Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value mu = args[0]; - Value sigma = args[1]; - - //using polar form of the Box-Muller transformation - //refer to http://www.taygeta.com/random/gaussian.html for more info - - Value x1, x2, w; - do { - // x1,x2 = 2 * random() - 1 - x1 = calc->random (2.0); - x2 = calc->random (2.0); - x1 = calc->sub (x1, 1); - x1 = calc->sub (x2, 1); - w = calc->add (calc->sqr(x1), calc->sqr (x2)); - } while (calc->gequal (w, 1.0)); // w >= 1.0 - - //sqrt ((-2.0 * log (w)) / w) : - w = calc->sqrt (calc->div (calc->mul (-2.0, calc->ln (w)), w)); - Value res = calc->mul (x1, w); - - res = calc->add (calc->mul (res, sigma), mu); // res*sigma + mu - return res; -} - -Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (calc->lower (args[0], 0)) - return Value::errorVALUE(); - - // taken from Gnumeric... - Value x = calc->exp (calc->mul (-1, args[0])); // e^(-A) - Value r = calc->random (); - Value t = x; - int i = 0; - - while (calc->greater (r, t)) { // r > t - x = calc->mul (x, calc->div (args[0], i + 1)); // x *= (A/(i+1)) - t = calc->add (t, x); //t += x - i++; - } - - return Value (i); -} - -// Function: rand -Value func_rand (valVector, ValueCalc *calc, FuncExtra *) -{ - return calc->random (); -} - -// Function: RANDBETWEEN -Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value v1 = args[0]; - Value v2 = args[1]; - if (calc->greater (v2, v1)) { - v1 = args[1]; - v2 = args[0]; - } - return calc->add (v1, calc->random (calc->sub (v2, v1))); -} - -// Function: POW -Value func_pow (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->pow (args[0], args[1]); -} - -// Function: MOD -Value func_mod (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->mod (args[0], args[1]); -} - -// Function: fact -Value func_fact (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->fact (args[0]); -} - -// Function: FACTDOUBLE -Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->factDouble (args[0]); -} - -// Function: MULTINOMIAL -Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *) -{ - // (a+b+c)! / a!b!c! (any number of params possible) - Value num = 0, den = 1; - for (unsigned int i = 0; i < args.count(); ++i) { - num = calc->add (num, args[i]); - den = calc->mul (den, calc->fact (args[i])); - } - num = calc->fact (num); - return calc->div (num, den); -} - -// Function: sign -Value func_sign (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->sign (args[0])); -} - -// Function: INV -Value func_inv (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->mul (args[0], -1); -} - -Value func_mround (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value d = args[0]; - Value m = args[1]; - - // signs must be the same - if ((calc->greater (d, 0) && calc->lower (m, 0)) - || (calc->lower (d, 0) && calc->greater (m, 0))) - return Value::errorVALUE(); - - int sign = 1; - - if (calc->lower (d, 0)) - { - sign = -1; - d = calc->mul (d, -1); - m = calc->mul (m, -1); - } - - // from gnumeric: - Value mod = calc->mod (d, m); - Value div = calc->sub (d, mod); - - Value result = div; - if (calc->greater (mod, calc->div (m, 2))) // mod > m/2 - result = calc->add (result, m); // result += m - result = calc->mul (result, sign); // add the sign - - return result; -} - -// Function: ROUNDDOWN -Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 2) - return calc->roundDown (args[0], args[1]); - return calc->roundDown (args[0], 0); -} - -// Function: ROUNDUP -Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 2) - return calc->roundUp (args[0], args[1]); - return calc->roundUp (args[0], 0); -} - -// Function: ROUND -Value func_round (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 2) - return calc->round (args[0], args[1]); - return calc->round (args[0], 0); -} - -// Function: EVEN -Value func_even (valVector args, ValueCalc *calc, FuncExtra *) -{ - const Value value = calc->roundUp (args[0], 0); - return calc->isZero( calc->mod(value, 2) ) ? value : calc->add(value, 1); -} - -// Function: ODD -Value func_odd (valVector args, ValueCalc *calc, FuncExtra *) -{ - const Value value = calc->roundUp (args[0], 0); - return calc->isZero( calc->mod(value, 2) ) ? calc->add(value, 1) : value; -} - -Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (args.count() == 1) - return calc->roundDown (args[0]); - return calc->roundDown (args[0], args[1]); -} - -// Function: COUNT -Value func_count (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->count (args, false); -} - -// Function: COUNTA -Value func_counta (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->count (args); -} - -// Function: COUNTBLANK -Value func_countblank (valVector args, ValueCalc *, FuncExtra *) -{ - int cnt = 0; - for (unsigned int i = 0; i < args.count(); ++i) - if (args[i].isArray()) { - int rows = args[i].rows(); - int cols = args[i].columns(); - for (int r = 0; r < rows; ++r) - for (int c = 0; c < cols; ++c) - if (args[i].element (c, r).isEmpty()) - cnt++; - } else - if (args[i].isEmpty()) - cnt++; - return Value (cnt); -} - -// Function: COUNTIF -Value func_countif (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value range = args[0]; - TQString condition = calc->conv()->asString (args[1]).asString(); - - Condition cond; - calc->getCond (cond, condition); - - return calc->countIf (range, cond); -} - -// Function: FIB -Value func_fib (valVector args, ValueCalc *calc, FuncExtra *) -{ -/* -Lucas' formula for the nth Fibonacci number F(n) is given by - - ((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n - F(n) = ------------------------------------- . - sqrt(5) - -*/ - Value n = args[0]; - Value s = calc->sqrt (5.0); - // u1 = ((1+sqrt(5))/2)^n - Value u1 = calc->pow (calc->div (calc->add (1, s), 2), n); - // u2 = ((1-sqrt(5))/2)^n - Value u2 = calc->pow (calc->div (calc->sub (1, s), 2), n); - - Value result = calc->div (calc->sub (u1, u2), s); - return result; -} - -static Value func_gcd_helper(const Value &val, ValueCalc *calc) -{ - Value res = 0; - if (!val.isArray ()) - return val; - for (unsigned int row = 0; row < val.rows(); ++row) - for (unsigned int col = 0; col < val.columns(); ++col) - { - Value v = val.element (col, row); - if (v.isArray ()) - v = func_gcd_helper (v, calc); - res = calc->gcd (res, v); - } - return res; -} - -// Function: GCD -Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result = 0; - for (unsigned int i = 0; i < args.count(); ++i) - if (args[i].isArray()) - result = calc->gcd (result, func_gcd_helper (args[i], calc)); - else - result = calc->gcd (result, args[i]); - return result; -} - -static Value func_lcm_helper(const Value &val, ValueCalc *calc) -{ - Value res = 0; - if (!val.isArray ()) - return val; - for (unsigned int row = 0; row < val.rows(); ++row) - for (unsigned int col = 0; col < val.columns(); ++col) - { - Value v = val.element (col, row); - if (v.isArray ()) - v = func_lcm_helper (v, calc); - res = calc->lcm (res, v); - } - return res; -} - -// Function: lcm -Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result = 0; - for (unsigned int i = 0; i < args.count(); ++i) - if (args[i].isArray()) - result = calc->lcm (result, func_lcm_helper (args[i], calc)); - else - result = calc->lcm (result, args[i]); - return result; -} - -Value determinant (ValueCalc *calc, Value matrix) -{ - // this is a --- SLOOOW --- recursive function - // using this for something bigger than 10x10 or so = suicide :P - // but I'm too lazy to adjust gnumeric's code - remains as a TODO then - // as a note, gnumeric uses LUP decomposition to compute this - - // take first row, generate smaller matrices, recursion, multiply - Value res = 0.0; - int n = matrix.columns(); - if (n == 1) return matrix.element (0, 0); - if (n == 2) return calc->sub ( - calc->mul (matrix.element (1,1), matrix.element (0,0)), - calc->mul (matrix.element (1,0), matrix.element (0,1))); - - // n >= 3 - for (int i = 0; i < n; ++i) { - Value smaller (n-1, n-1); - int col = 0; - for (int c = 0; c < n; ++c) - if (c != i) { - // copy column c to column col in new matrix - for (int r = 1; r < n; r++) - smaller.setElement (col, r-1, matrix.element (c, r)); - col++; - } - Value minor = determinant (calc, smaller); - if (i % 2 == 1) minor = calc->mul (minor, -1); - res = calc->add (res, calc->mul (minor, matrix.element (i, 0))); - } - return res; -} - -// Function: mdeterm -Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m = args[0]; - unsigned r = m.rows (); - unsigned c = m.columns (); - if (r != c) // must be a square matrix - return Value::errorVALUE(); - - return determinant (calc, args[0]); -} - -// Function: mmult -Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value m1 = args[0]; - Value m2 = args[1]; - unsigned r1 = m1.rows (); - unsigned c1 = m1.columns (); - unsigned r2 = m2.rows (); - unsigned c2 = m2.columns (); - if (c1 != r2) // row/column counts must match - return Value::errorVALUE(); - - // create the resulting matrix - Value res (c2, r1); - - // perform the multiplication - O(n^3) algorithm - for (uint row = 0; row < r1; ++row) - for (uint col = 0; col < c2; ++col) { - Value val = 0.0; - for (uint pos = 0; pos < c1; ++pos) - val = calc->add (val, - calc->mul (m1.element (pos, row), m2.element (col, pos))); - res.setElement (col, row, val); - } - return res; -} - -// Function: SUBTOTAL -// This function requires access to the Sheet and so on, because -// it needs to check whether cells contain the SUBTOTAL formula or not ... -// Cells containing a SUBTOTAL formula must be ignored. -Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *e) -{ - int function = calc->conv()->asInteger (args[0]).asInteger(); - Value range = args[1]; - int r1 = -1, c1 = -1, r2 = -1, c2 = -1; - if (e) { - r1 = e->ranges[1].row1; - c1 = e->ranges[1].col1; - r2 = e->ranges[1].row2; - c2 = e->ranges[1].col2; - } - - // if we have a range, run through it, and put an empty value to the place - // of all occurences of the SUBTOTAL function - Value empty; - if ((r1 > 0) && (c1 > 0) && (r2 > 0) && (c2 > 0)) { - for (int r = r1; r <= r2; ++r) - for (int c = c1; c <= c2; ++c) { - Cell *cell = e->sheet->cellAt (c, r); - if (cell->isDefault()) - continue; - if (cell->isFormula() && cell->text().find ("SUBTOTAL", 0, false) != -1) - // cell contains the word SUBTOTAL - replace value with empty - range.setElement (c-c1, r-r1, empty); - } - } - - // Good. Now we can execute the necessary function on the range. - Value res; - Function *f; - valVector a; - switch (function) { - case 1: // Average - res = calc->avg (range, false); - break; - case 2: // Count - res = calc->count (range, false); - break; - case 3: // CountA - res = calc->count (range); - break; - case 4: // MAX - res = calc->max (range, false); - break; - case 5: // Min - res = calc->min (range, false); - break; - case 6: // Product - res = calc->product (range, 0.0, false); - break; - case 7: // StDev - res = calc->stddev (range, false); - break; - case 8: // StDevP - res = calc->stddevP (range, false); - break; - case 9: // Sum - res = calc->sum (range, false); - break; - case 10: // Var - f = FunctionRepository::self()->function ("VAR"); - if (!f) return Value::errorVALUE(); - a.reserve (1); - a[0] = range; - res = f->exec (a, calc, 0); - break; - case 11: // VarP - f = FunctionRepository::self()->function ("VARP"); - if (!f) return Value::errorVALUE(); - a.reserve (1); - a[0] = range; - res = f->exec (a, calc, 0); - break; - default: - return Value::errorVALUE(); - } - return res; -} - -/* -Commented out. -Absolutely no idea what this thing is supposed to do. -To anyone who would enable this code: it still uses koscript calls - you need -to convert it to the new style prior to uncommenting. - -// Function: MULTIPLEOPERATIONS -Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *) -{ - if (gCell) - { - context.setValue( new KSValue( ((Interpreter *) context.interpreter() )->cell()->value().asFloat() ) ); - return true; - } - - gCell = ((Interpreter *) context.interpreter() )->cell(); - - TQValueList& args = context.value()->listValue(); - TQValueList& extra = context.extraData()->listValue(); - - if ( !KSUtil::checkArgumentsCount( context, 5, "MULTIPLEOPERATIONS", true ) ) - { - gCell = 0; - return false; - } - - // 0: cell must contain formula with double/int result - // 0, 1, 2, 3, 4: must contain integer/double - for (int i = 0; i < 5; ++i) - { - if ( !KSUtil::checkType( context, args[i], KSValue::DoubleType, true ) ) - { - gCell = 0; - return false; - } - } - - // ((Interpreter *) context.interpreter() )->document()->emitBeginOperation(); - - double oldCol = args[1]->doubleValue(); - double oldRow = args[3]->doubleValue(); - kdDebug() << "Old values: Col: " << oldCol << ", Row: " << oldRow << endl; - - Cell * cell; - Sheet * sheet = ((Interpreter *) context.interpreter() )->sheet(); - - Point point( extra[1]->stringValue() ); - Point point2( extra[3]->stringValue() ); - Point point3( extra[0]->stringValue() ); - - if ( ( args[1]->doubleValue() != args[2]->doubleValue() ) - || ( args[3]->doubleValue() != args[4]->doubleValue() ) ) - { - cell = sheet->cellAt( point.pos.x(), point.pos.y() ); - cell->setValue( args[2]->doubleValue() ); - kdDebug() << "Setting value " << args[2]->doubleValue() << " on cell " << point.pos.x() - << ", " << point.pos.y() << endl; - - cell = sheet->cellAt( point2.pos.x(), point.pos.y() ); - cell->setValue( args[4]->doubleValue() ); - kdDebug() << "Setting value " << args[4]->doubleValue() << " on cell " << point2.pos.x() - << ", " << point2.pos.y() << endl; - } - - Cell * cell1 = sheet->cellAt( point3.pos.x(), point3.pos.y() ); - cell1->calc( false ); - - double d = cell1->value().asFloat(); - kdDebug() << "Cell: " << point3.pos.x() << "; " << point3.pos.y() << " with value " - << d << endl; - - kdDebug() << "Resetting old values" << endl; - - cell = sheet->cellAt( point.pos.x(), point.pos.y() ); - cell->setValue( oldCol ); - - cell = sheet->cellAt( point2.pos.x(), point2.pos.y() ); - cell->setValue( oldRow ); - - cell1->calc( false ); - - // ((Interpreter *) context.interpreter() )->document()->emitEndOperation(); - - context.setValue( new KSValue( (double) d ) ); - - gCell = 0; - return true; -} - -*/ diff --git a/kspread/kspread_functions_math.cpp b/kspread/kspread_functions_math.cpp new file mode 100644 index 00000000..06b6da2b --- /dev/null +++ b/kspread/kspread_functions_math.cpp @@ -0,0 +1,1144 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in math functions + +#include +#include + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +// these two are needed for SUBTOTAL: +#include "kspread_cell.h" +#include "kspread_sheet.h" + +// needed for RANDBINOM and so +#include + +using namespace KSpread; + +// RANDBINOM and RANDNEGBINOM won't support arbitrary precision + +// prototypes +Value func_abs (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *); +Value func_count (valVector args, ValueCalc *calc, FuncExtra *); +Value func_counta (valVector args, ValueCalc *calc, FuncExtra *); +Value func_countblank (valVector args, ValueCalc *calc, FuncExtra *); +Value func_countif (valVector args, ValueCalc *calc, FuncExtra *); +Value func_cur (valVector args, ValueCalc *calc, FuncExtra *); +Value func_div (valVector args, ValueCalc *calc, FuncExtra *); +Value func_eps (valVector args, ValueCalc *calc, FuncExtra *); +Value func_even (valVector args, ValueCalc *calc, FuncExtra *); +Value func_exp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fact (valVector args, ValueCalc *calc, FuncExtra *); +Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fib (valVector args, ValueCalc *calc, FuncExtra *); +Value func_floor (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *); +Value func_int (valVector args, ValueCalc *calc, FuncExtra *); +Value func_inv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *); +Value func_ln (valVector args, ValueCalc *calc, FuncExtra *); +Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_logn (valVector args, ValueCalc *calc, FuncExtra *); +Value func_max (valVector args, ValueCalc *calc, FuncExtra *); +Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *); +Value func_min (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mina (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mod (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mround (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mult (valVector args, ValueCalc *calc, FuncExtra *); +Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *); +Value func_odd (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pow (valVector args, ValueCalc *calc, FuncExtra *); +Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *); +Value func_product (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rand (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *); +Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *); +Value func_round (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *); +Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sign (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *); +Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_suma (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *); +Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *); + + +// Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all math functions +void RegisterMathFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + +/* + f = new Function ("MULTIPLEOPERATIONS", func_multipleOP); + repo->add (f); +*/ + + // functions that don't take array parameters + f = new Function ("ABS", func_abs); + repo->add (f); + f = new Function ("CEIL", func_ceil); + repo->add (f); + f = new Function ("CEILING", func_ceiling); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("CUR", func_cur); + repo->add (f); + f = new Function ("EPS", func_eps); + f->setParamCount (0); + repo->add (f); + f = new Function ("EVEN", func_even); + repo->add (f); + f = new Function ("EXP", func_exp); + repo->add (f); + f = new Function ("FACT", func_fact); + repo->add (f); + f = new Function ("FACTDOUBLE", func_factdouble); + repo->add (f); + f = new Function ("FIB", func_fib); // KSpread-specific, like Quattro-Pro's FIB + repo->add (f); + f = new Function ("FLOOR", func_floor); + repo->add (f); + f = new Function ("INT", func_int); + repo->add (f); + f = new Function ("INV", func_inv); + repo->add (f); + f = new Function ("LN", func_ln); + repo->add (f); + f = new Function ("LOG", func_log10); + repo->add (f); + f = new Function ("LOG2", func_log2); + repo->add (f); + f = new Function ("LOG10", func_log10); // same as LOG + repo->add (f); + f = new Function ("LOGN", func_logn); + f->setParamCount (2); + repo->add (f); + f = new Function ("MOD", func_mod); + f->setParamCount (2); + repo->add (f); + f = new Function ("MROUND", func_mround); + f->setParamCount (2); + repo->add (f); + f = new Function ("MULTINOMIAL", func_multinomial); + f->setParamCount (1, -1); + repo->add (f); + f = new Function ("ODD", func_odd); + repo->add (f); + f = new Function ("POW", func_pow); + f->setParamCount (2); + repo->add (f); + f = new Function ("POWER", func_pow); + f->setParamCount (2); + repo->add (f); + f = new Function ("QUOTIENT", func_quotient); + f->setParamCount (2); + repo->add (f); + f = new Function ("RAND", func_rand); + f->setParamCount (0); + repo->add (f); + f = new Function ("RANDBERNOULLI", func_randbernoulli); + repo->add (f); + f = new Function ("RANDBETWEEN", func_randbetween); + f->setParamCount (2); + repo->add (f); + f = new Function ("RANDBINOM", func_randbinom); + f->setParamCount (2); + repo->add (f); + f = new Function ("RANDEXP", func_randexp); + repo->add (f); + f = new Function ("RANDNEGBINOM", func_randnegbinom); + f->setParamCount (2); + repo->add (f); + f = new Function ("RANDNORM", func_randnorm); + f->setParamCount (2); + repo->add (f); + f = new Function ("RANDPOISSON", func_randpoisson); + repo->add (f); + f = new Function ("ROOTN", func_rootn); + f->setParamCount (2); + repo->add (f); + f = new Function ("ROUND", func_round); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("ROUNDDOWN", func_rounddown); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("ROUNDUP", func_roundup); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("SIGN", func_sign); + repo->add (f); + f = new Function ("SQRT", func_sqrt); + repo->add (f); + f = new Function ("SQRTPI", func_sqrtpi); + repo->add (f); + f = new Function ("TRUNC", func_trunc); + f->setParamCount (1, 2); + repo->add (f); + + // functions that operate over arrays + f = new Function ("COUNT", func_count); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("COUNTA", func_counta); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("COUNTBLANK", func_countblank); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("COUNTIF", func_countif); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DIV", func_div); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("G_PRODUCT", func_kproduct); // Gnumeric compatibility + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("GCD", func_gcd); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("KPRODUCT", func_kproduct); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("LCM", func_lcm); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MAX", func_max); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MAXA", func_maxa); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MDETERM", func_mdeterm); + f->setParamCount (1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MIN", func_min); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MINA", func_mina); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MMULT", func_mmult); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MULTIPLY", func_product); // same as PRODUCT + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("PRODUCT", func_product); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUM", func_sum); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUMA", func_suma); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUBTOTAL", func_subtotal); + f->setParamCount (2); + f->setAcceptArray (); + f->setNeedsExtra (true); + repo->add (f); + f = new Function ("SUMIF", func_sumif); + f->setParamCount (2, 3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUMSQ", func_sumsq); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); +} + +// Function: SQRT +Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->sqrt (args[0]); +} + +// Function: SQRTPI +Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *) +{ + // sqrt (val * PI) + return calc->sqrt (calc->mul (args[0], calc->pi())); +} + +// Function: ROOTN +Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->pow (args[0], calc->div (1, args[1])); +} + +// Function: CUR +Value func_cur (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->pow (args[0], 1.0/3.0); +} + +// Function: ABS +Value func_abs (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->abs (args[0]); +} + +// Function: exp +Value func_exp (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->exp (args[0]); +} + +// Function: ceil +Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->roundUp (args[0], 0); +} + +// Function: ceiling +Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value number = args[0]; + Value res; + if (args.count() == 2) + res = args[1]; + else + res = calc->gequal (number, 0.0) ? 1.0 : -1.0; + + if (calc->isZero(res)) + return Value::errorDIV0(); + + Value d = calc->div (number, res); + if (calc->greater (0, d)) + return Value::errorVALUE(); + + Value rud = calc->roundDown (d); + if (calc->approxEqual (rud, d)) + d = calc->mul (rud, res); + else + d = calc->mul (calc->roundUp (d), res); + + return d; +} + +// Function: floor +Value func_floor (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->roundDown (args[0], 0); +} + +// Function: ln +Value func_ln (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->ln (args[0]); +} + +// Function: LOGn +Value func_logn (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->log (args[0], args[1]); +} + +// Function: LOG2 +Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->log (args[0], 2.0); +} + +// Function: LOG10 +Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->log (args[0]); +} + +// Function: sum +Value func_sum (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->sum (args, false); +} + +// Function: suma +Value func_suma (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->sum (args, true); +} + +Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value checkRange = args[0]; + TQString condition = calc->conv()->asString (args[1]).asString(); + Value sumRange = checkRange; + if (args.count() == 3) + sumRange = args[2]; + + Condition cond; + calc->getCond (cond, condition); + + return calc->sumIf (sumRange, checkRange, cond); +} + +// Function: product +Value func_product (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->product (args, 0.0); +} + +// Function: kproduct +Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->product (args, 1.0); +} + +// Function: DIV +Value func_div (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value val = args[0]; + for (unsigned int i = 1; i < args.count(); ++i) + { + val = calc->div (val, args[i]); + if (val.isError()) + return val; + } + return val; +} + +// Function: SUMSQ +Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value res; + calc->arrayWalk (args, res, calc->awFunc ("sumsq"), 0); + return res; +} + +// Function: MAX +Value func_max (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m = calc->max (args, false); + return m.isEmpty() ? Value(0.0) : m; +} + +// Function: MAXA +Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m = calc->max (args); + return m.isEmpty() ? Value(0.0) : m; +} + +// Function: MIN +Value func_min (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m = calc->min (args, false); + return m.isEmpty() ? Value(0.0) : m; +} + +// Function: MINA +Value func_mina (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m = calc->min (args); + return m.isEmpty() ? Value(0.0) : m; +} + +// Function: INT +Value func_int (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asInteger (args[0]); +} + +// Function: QUOTIENT +Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (calc->isZero (args[1])) + return Value::errorDIV0(); + return calc->conv()->asInteger (calc->div (args[0], args[1])); +} + + +// Function: eps +Value func_eps (valVector, ValueCalc *calc, FuncExtra *) +{ + return calc->eps (); +} + +Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *) +{ + // -1 * d * log (random) + return calc->mul (calc->mul (args[0], -1), calc->random()); +} + +Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *) +{ + // this function will not support arbitrary precision + + double d = calc->conv()->asFloat (args[0]).asFloat(); + int tr = calc->conv()->asInteger (args[1]).asInteger(); + + if ( d < 0 || d > 1 ) + return Value::errorVALUE(); + + if ( tr < 0 ) + return Value::errorVALUE(); + + // taken from gnumeric + double x = pow(1 - d, tr); + double r = (double) rand() / ( RAND_MAX + 1.0 ); + double t = x; + int i = 0; + + while (r > t) + { + x *= (((tr - i) * d) / ((1 + i) * (1 - d))); + i++; + t += x; + } + + return Value (i); +} + +Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *) +{ + // this function will not support arbitrary precision + + double d = calc->conv()->asFloat (args[0]).asFloat(); + int f = calc->conv()->asInteger (args[1]).asInteger(); + + if ( d < 0 || d > 1 ) + return Value::errorVALUE(); + + if ( f < 0 ) + return Value::errorVALUE(); + + + // taken from Gnumeric + double x = pow(d, f); + double r = (double) rand() / ( RAND_MAX + 1.0 ); + double t = x; + int i = 0; + + while (r > t) + { + x *= ( ( ( f + i ) * ( 1 - d ) ) / (1 + i) ) ; + i++; + t += x; + } + + return Value (i); +} + +Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value rnd = calc->random (); + return Value (calc->greater (rnd, args[0]) ? 1.0 : 0.0); +} + +Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value mu = args[0]; + Value sigma = args[1]; + + //using polar form of the Box-Muller transformation + //refer to http://www.taygeta.com/random/gaussian.html for more info + + Value x1, x2, w; + do { + // x1,x2 = 2 * random() - 1 + x1 = calc->random (2.0); + x2 = calc->random (2.0); + x1 = calc->sub (x1, 1); + x1 = calc->sub (x2, 1); + w = calc->add (calc->sqr(x1), calc->sqr (x2)); + } while (calc->gequal (w, 1.0)); // w >= 1.0 + + //sqrt ((-2.0 * log (w)) / w) : + w = calc->sqrt (calc->div (calc->mul (-2.0, calc->ln (w)), w)); + Value res = calc->mul (x1, w); + + res = calc->add (calc->mul (res, sigma), mu); // res*sigma + mu + return res; +} + +Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (calc->lower (args[0], 0)) + return Value::errorVALUE(); + + // taken from Gnumeric... + Value x = calc->exp (calc->mul (-1, args[0])); // e^(-A) + Value r = calc->random (); + Value t = x; + int i = 0; + + while (calc->greater (r, t)) { // r > t + x = calc->mul (x, calc->div (args[0], i + 1)); // x *= (A/(i+1)) + t = calc->add (t, x); //t += x + i++; + } + + return Value (i); +} + +// Function: rand +Value func_rand (valVector, ValueCalc *calc, FuncExtra *) +{ + return calc->random (); +} + +// Function: RANDBETWEEN +Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value v1 = args[0]; + Value v2 = args[1]; + if (calc->greater (v2, v1)) { + v1 = args[1]; + v2 = args[0]; + } + return calc->add (v1, calc->random (calc->sub (v2, v1))); +} + +// Function: POW +Value func_pow (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->pow (args[0], args[1]); +} + +// Function: MOD +Value func_mod (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->mod (args[0], args[1]); +} + +// Function: fact +Value func_fact (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fact (args[0]); +} + +// Function: FACTDOUBLE +Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->factDouble (args[0]); +} + +// Function: MULTINOMIAL +Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *) +{ + // (a+b+c)! / a!b!c! (any number of params possible) + Value num = 0, den = 1; + for (unsigned int i = 0; i < args.count(); ++i) { + num = calc->add (num, args[i]); + den = calc->mul (den, calc->fact (args[i])); + } + num = calc->fact (num); + return calc->div (num, den); +} + +// Function: sign +Value func_sign (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->sign (args[0])); +} + +// Function: INV +Value func_inv (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->mul (args[0], -1); +} + +Value func_mround (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value d = args[0]; + Value m = args[1]; + + // signs must be the same + if ((calc->greater (d, 0) && calc->lower (m, 0)) + || (calc->lower (d, 0) && calc->greater (m, 0))) + return Value::errorVALUE(); + + int sign = 1; + + if (calc->lower (d, 0)) + { + sign = -1; + d = calc->mul (d, -1); + m = calc->mul (m, -1); + } + + // from gnumeric: + Value mod = calc->mod (d, m); + Value div = calc->sub (d, mod); + + Value result = div; + if (calc->greater (mod, calc->div (m, 2))) // mod > m/2 + result = calc->add (result, m); // result += m + result = calc->mul (result, sign); // add the sign + + return result; +} + +// Function: ROUNDDOWN +Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->roundDown (args[0], args[1]); + return calc->roundDown (args[0], 0); +} + +// Function: ROUNDUP +Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->roundUp (args[0], args[1]); + return calc->roundUp (args[0], 0); +} + +// Function: ROUND +Value func_round (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->round (args[0], args[1]); + return calc->round (args[0], 0); +} + +// Function: EVEN +Value func_even (valVector args, ValueCalc *calc, FuncExtra *) +{ + const Value value = calc->roundUp (args[0], 0); + return calc->isZero( calc->mod(value, 2) ) ? value : calc->add(value, 1); +} + +// Function: ODD +Value func_odd (valVector args, ValueCalc *calc, FuncExtra *) +{ + const Value value = calc->roundUp (args[0], 0); + return calc->isZero( calc->mod(value, 2) ) ? calc->add(value, 1) : value; +} + +Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 1) + return calc->roundDown (args[0]); + return calc->roundDown (args[0], args[1]); +} + +// Function: COUNT +Value func_count (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->count (args, false); +} + +// Function: COUNTA +Value func_counta (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->count (args); +} + +// Function: COUNTBLANK +Value func_countblank (valVector args, ValueCalc *, FuncExtra *) +{ + int cnt = 0; + for (unsigned int i = 0; i < args.count(); ++i) + if (args[i].isArray()) { + int rows = args[i].rows(); + int cols = args[i].columns(); + for (int r = 0; r < rows; ++r) + for (int c = 0; c < cols; ++c) + if (args[i].element (c, r).isEmpty()) + cnt++; + } else + if (args[i].isEmpty()) + cnt++; + return Value (cnt); +} + +// Function: COUNTIF +Value func_countif (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value range = args[0]; + TQString condition = calc->conv()->asString (args[1]).asString(); + + Condition cond; + calc->getCond (cond, condition); + + return calc->countIf (range, cond); +} + +// Function: FIB +Value func_fib (valVector args, ValueCalc *calc, FuncExtra *) +{ +/* +Lucas' formula for the nth Fibonacci number F(n) is given by + + ((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n + F(n) = ------------------------------------- . + sqrt(5) + +*/ + Value n = args[0]; + Value s = calc->sqrt (5.0); + // u1 = ((1+sqrt(5))/2)^n + Value u1 = calc->pow (calc->div (calc->add (1, s), 2), n); + // u2 = ((1-sqrt(5))/2)^n + Value u2 = calc->pow (calc->div (calc->sub (1, s), 2), n); + + Value result = calc->div (calc->sub (u1, u2), s); + return result; +} + +static Value func_gcd_helper(const Value &val, ValueCalc *calc) +{ + Value res = 0; + if (!val.isArray ()) + return val; + for (unsigned int row = 0; row < val.rows(); ++row) + for (unsigned int col = 0; col < val.columns(); ++col) + { + Value v = val.element (col, row); + if (v.isArray ()) + v = func_gcd_helper (v, calc); + res = calc->gcd (res, v); + } + return res; +} + +// Function: GCD +Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result = 0; + for (unsigned int i = 0; i < args.count(); ++i) + if (args[i].isArray()) + result = calc->gcd (result, func_gcd_helper (args[i], calc)); + else + result = calc->gcd (result, args[i]); + return result; +} + +static Value func_lcm_helper(const Value &val, ValueCalc *calc) +{ + Value res = 0; + if (!val.isArray ()) + return val; + for (unsigned int row = 0; row < val.rows(); ++row) + for (unsigned int col = 0; col < val.columns(); ++col) + { + Value v = val.element (col, row); + if (v.isArray ()) + v = func_lcm_helper (v, calc); + res = calc->lcm (res, v); + } + return res; +} + +// Function: lcm +Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result = 0; + for (unsigned int i = 0; i < args.count(); ++i) + if (args[i].isArray()) + result = calc->lcm (result, func_lcm_helper (args[i], calc)); + else + result = calc->lcm (result, args[i]); + return result; +} + +Value determinant (ValueCalc *calc, Value matrix) +{ + // this is a --- SLOOOW --- recursive function + // using this for something bigger than 10x10 or so = suicide :P + // but I'm too lazy to adjust gnumeric's code - remains as a TODO then + // as a note, gnumeric uses LUP decomposition to compute this + + // take first row, generate smaller matrices, recursion, multiply + Value res = 0.0; + int n = matrix.columns(); + if (n == 1) return matrix.element (0, 0); + if (n == 2) return calc->sub ( + calc->mul (matrix.element (1,1), matrix.element (0,0)), + calc->mul (matrix.element (1,0), matrix.element (0,1))); + + // n >= 3 + for (int i = 0; i < n; ++i) { + Value smaller (n-1, n-1); + int col = 0; + for (int c = 0; c < n; ++c) + if (c != i) { + // copy column c to column col in new matrix + for (int r = 1; r < n; r++) + smaller.setElement (col, r-1, matrix.element (c, r)); + col++; + } + Value minor = determinant (calc, smaller); + if (i % 2 == 1) minor = calc->mul (minor, -1); + res = calc->add (res, calc->mul (minor, matrix.element (i, 0))); + } + return res; +} + +// Function: mdeterm +Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m = args[0]; + unsigned r = m.rows (); + unsigned c = m.columns (); + if (r != c) // must be a square matrix + return Value::errorVALUE(); + + return determinant (calc, args[0]); +} + +// Function: mmult +Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value m1 = args[0]; + Value m2 = args[1]; + unsigned r1 = m1.rows (); + unsigned c1 = m1.columns (); + unsigned r2 = m2.rows (); + unsigned c2 = m2.columns (); + if (c1 != r2) // row/column counts must match + return Value::errorVALUE(); + + // create the resulting matrix + Value res (c2, r1); + + // perform the multiplication - O(n^3) algorithm + for (uint row = 0; row < r1; ++row) + for (uint col = 0; col < c2; ++col) { + Value val = 0.0; + for (uint pos = 0; pos < c1; ++pos) + val = calc->add (val, + calc->mul (m1.element (pos, row), m2.element (col, pos))); + res.setElement (col, row, val); + } + return res; +} + +// Function: SUBTOTAL +// This function requires access to the Sheet and so on, because +// it needs to check whether cells contain the SUBTOTAL formula or not ... +// Cells containing a SUBTOTAL formula must be ignored. +Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *e) +{ + int function = calc->conv()->asInteger (args[0]).asInteger(); + Value range = args[1]; + int r1 = -1, c1 = -1, r2 = -1, c2 = -1; + if (e) { + r1 = e->ranges[1].row1; + c1 = e->ranges[1].col1; + r2 = e->ranges[1].row2; + c2 = e->ranges[1].col2; + } + + // if we have a range, run through it, and put an empty value to the place + // of all occurences of the SUBTOTAL function + Value empty; + if ((r1 > 0) && (c1 > 0) && (r2 > 0) && (c2 > 0)) { + for (int r = r1; r <= r2; ++r) + for (int c = c1; c <= c2; ++c) { + Cell *cell = e->sheet->cellAt (c, r); + if (cell->isDefault()) + continue; + if (cell->isFormula() && cell->text().find ("SUBTOTAL", 0, false) != -1) + // cell contains the word SUBTOTAL - replace value with empty + range.setElement (c-c1, r-r1, empty); + } + } + + // Good. Now we can execute the necessary function on the range. + Value res; + Function *f; + valVector a; + switch (function) { + case 1: // Average + res = calc->avg (range, false); + break; + case 2: // Count + res = calc->count (range, false); + break; + case 3: // CountA + res = calc->count (range); + break; + case 4: // MAX + res = calc->max (range, false); + break; + case 5: // Min + res = calc->min (range, false); + break; + case 6: // Product + res = calc->product (range, 0.0, false); + break; + case 7: // StDev + res = calc->stddev (range, false); + break; + case 8: // StDevP + res = calc->stddevP (range, false); + break; + case 9: // Sum + res = calc->sum (range, false); + break; + case 10: // Var + f = FunctionRepository::self()->function ("VAR"); + if (!f) return Value::errorVALUE(); + a.reserve (1); + a[0] = range; + res = f->exec (a, calc, 0); + break; + case 11: // VarP + f = FunctionRepository::self()->function ("VARP"); + if (!f) return Value::errorVALUE(); + a.reserve (1); + a[0] = range; + res = f->exec (a, calc, 0); + break; + default: + return Value::errorVALUE(); + } + return res; +} + +/* +Commented out. +Absolutely no idea what this thing is supposed to do. +To anyone who would enable this code: it still uses koscript calls - you need +to convert it to the new style prior to uncommenting. + +// Function: MULTIPLEOPERATIONS +Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (gCell) + { + context.setValue( new KSValue( ((Interpreter *) context.interpreter() )->cell()->value().asFloat() ) ); + return true; + } + + gCell = ((Interpreter *) context.interpreter() )->cell(); + + TQValueList& args = context.value()->listValue(); + TQValueList& extra = context.extraData()->listValue(); + + if ( !KSUtil::checkArgumentsCount( context, 5, "MULTIPLEOPERATIONS", true ) ) + { + gCell = 0; + return false; + } + + // 0: cell must contain formula with double/int result + // 0, 1, 2, 3, 4: must contain integer/double + for (int i = 0; i < 5; ++i) + { + if ( !KSUtil::checkType( context, args[i], KSValue::DoubleType, true ) ) + { + gCell = 0; + return false; + } + } + + // ((Interpreter *) context.interpreter() )->document()->emitBeginOperation(); + + double oldCol = args[1]->doubleValue(); + double oldRow = args[3]->doubleValue(); + kdDebug() << "Old values: Col: " << oldCol << ", Row: " << oldRow << endl; + + Cell * cell; + Sheet * sheet = ((Interpreter *) context.interpreter() )->sheet(); + + Point point( extra[1]->stringValue() ); + Point point2( extra[3]->stringValue() ); + Point point3( extra[0]->stringValue() ); + + if ( ( args[1]->doubleValue() != args[2]->doubleValue() ) + || ( args[3]->doubleValue() != args[4]->doubleValue() ) ) + { + cell = sheet->cellAt( point.pos.x(), point.pos.y() ); + cell->setValue( args[2]->doubleValue() ); + kdDebug() << "Setting value " << args[2]->doubleValue() << " on cell " << point.pos.x() + << ", " << point.pos.y() << endl; + + cell = sheet->cellAt( point2.pos.x(), point.pos.y() ); + cell->setValue( args[4]->doubleValue() ); + kdDebug() << "Setting value " << args[4]->doubleValue() << " on cell " << point2.pos.x() + << ", " << point2.pos.y() << endl; + } + + Cell * cell1 = sheet->cellAt( point3.pos.x(), point3.pos.y() ); + cell1->calc( false ); + + double d = cell1->value().asFloat(); + kdDebug() << "Cell: " << point3.pos.x() << "; " << point3.pos.y() << " with value " + << d << endl; + + kdDebug() << "Resetting old values" << endl; + + cell = sheet->cellAt( point.pos.x(), point.pos.y() ); + cell->setValue( oldCol ); + + cell = sheet->cellAt( point2.pos.x(), point2.pos.y() ); + cell->setValue( oldRow ); + + cell1->calc( false ); + + // ((Interpreter *) context.interpreter() )->document()->emitEndOperation(); + + context.setValue( new KSValue( (double) d ) ); + + gCell = 0; + return true; +} + +*/ diff --git a/kspread/kspread_functions_reference.cc b/kspread/kspread_functions_reference.cc deleted file mode 100644 index 7dacb054..00000000 --- a/kspread/kspread_functions_reference.cc +++ /dev/null @@ -1,342 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in reference functions - -#include "kspread_cell.h" -#include "kspread_sheet.h" -#include "kspread_util.h" -#include "kspread_value.h" - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -using namespace KSpread; - -// prototypes (sorted alphabetically) -Value func_address (valVector args, ValueCalc *calc, FuncExtra *); -Value func_areas (valVector args, ValueCalc *calc, FuncExtra *); -Value func_choose (valVector args, ValueCalc *calc, FuncExtra *); -Value func_column (valVector args, ValueCalc *calc, FuncExtra *); -Value func_columns (valVector args, ValueCalc *calc, FuncExtra *); -Value func_index (valVector args, ValueCalc *calc, FuncExtra *); -Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *); -Value func_lookup (valVector args, ValueCalc *calc, FuncExtra *); -Value func_row (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rows (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all reference functions -void RegisterReferenceFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("ADDRESS", func_address); - f->setParamCount (2, 5); - repo->add (f); - f = new Function ("AREAS", func_areas); - f->setParamCount (1); - f->setNeedsExtra (true); - repo->add (f); - f = new Function ("CHOOSE", func_choose); - f->setParamCount (2, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("COLUMN", func_column); - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("COLUMNS", func_columns); - f->setParamCount (1); - f->setAcceptArray (); - f->setNeedsExtra (true); - repo->add (f); - f = new Function ("INDEX", func_index); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("INDIRECT", func_indirect); - f->setParamCount (1, 2); - f->setNeedsExtra (true); - repo->add (f); - f = new Function ("LOOKUP", func_lookup); - f->setParamCount (3); - f->setAcceptArray (); - repo->add (f); - f = new Function ("ROW", func_row); - f->setParamCount (0, 1); - repo->add (f); - f = new Function ("ROWS", func_rows); - f->setParamCount (1); - f->setAcceptArray (); - f->setNeedsExtra (true); - repo->add (f); -} - -// Function: ADDRESS -Value func_address (valVector args, ValueCalc *calc, FuncExtra *) -{ - bool r1c1 = false; - TQString sheetName; - int absNum = 1; - if (args.count() > 2) - absNum = calc->conv()->asInteger (args[2]).asInteger(); - if (args.count() > 3) - r1c1 = !(calc->conv()->asBoolean (args[3]).asBoolean()); - if (args.count() == 5) - sheetName = calc->conv()->asString (args[4]).asString(); - - TQString result; - int row = calc->conv()->asInteger (args[0]).asInteger(); - int col = calc->conv()->asInteger (args[1]).asInteger(); - - if ( !sheetName.isEmpty() ) - { - result += sheetName; - result += "!"; - } - - if ( r1c1 ) - { - // row first - bool abs = false; - if ( absNum == 1 || absNum == 2 ) - abs = true; - - result += 'R'; - if ( !abs ) - result += '['; - result += TQString::number( row ); - - if ( !abs ) - result += ']'; - - // column - abs = false; - if ( absNum == 1 || absNum == 3 ) - abs = true; - - result += 'C'; - if ( !abs ) - result += '['; - result += TQString::number( col ); - - if ( !abs ) - result += ']'; - } - else - { - bool abs = false; - if ( absNum == 1 || absNum == 3 ) - abs = true; - - if ( abs ) - result += '$'; - - result += Cell::columnName( col ); - - abs = false; - if ( absNum == 1 || absNum == 2 ) - abs = true; - - if ( abs ) - result += '$'; - - result += TQString::number( row ); - } - - return Value (result); -} - -bool checkRef( TQString const & ref ) -{ - Range r( ref ); - if ( !r.isValid() ) - { - Point p( ref ); - if ( !p.isValid() ) - return false; - } - return true; -} - -// Function: AREAS -Value func_areas (valVector args, ValueCalc *calc, FuncExtra *e) -{ - if (e) { - if ((e->ranges[0].col1 != -1) && (e->ranges[0].row1 != -1) && - (e->ranges[0].col2 != -1) && (e->ranges[0].row2 != -1)) - // we have a range reference - return 1 - return 1; - } - - TQString s = calc->conv()->asString (args[0]).asString(); - if ( s[0] != '(' || s[s.length() - 1] != ')' ) - return Value::errorVALUE(); - - int l = s.length(); - - int num = 0; - TQString ref; - for ( int i = 1; i < l; ++i ) - { - if ( s[i] == ',' || s[i] == ')' ) - { - if ( !checkRef( ref ) ) - return Value::errorVALUE(); - else - { - ++num; - ref = ""; - } - } - else - ref += s[i]; - } - - return Value (num); -} - -// Function: CHOOSE -Value func_choose (valVector args, ValueCalc *calc, FuncExtra *) -{ - int cnt = args.count () - 1; - int num = calc->conv()->asInteger (args[0]).asInteger(); - if ((num <= 0) || (num > cnt)) - return Value::errorVALUE(); - return args[num]; -} - -// Function: INDEX -Value func_index (valVector args, ValueCalc *calc, FuncExtra *) -{ - // first argument can be either a range, then we return a given cell's - // value, or a single cell containing an array - then we return the array - // element. In any case, this function can assume that the given value - // is the same. Because it is. - - Value val = args[0]; - unsigned row = calc->conv()->asInteger (args[1]).asInteger() - 1; - unsigned col = calc->conv()->asInteger (args[2]).asInteger() - 1; - if ((row >= val.rows()) || (col >= val.columns())) - return Value::errorREF(); - return val.element (col, row); -} - -// Function: LOOKUP -Value func_lookup (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value num = calc->conv()->asNumeric (args[0]); - if (num.isArray()) - return Value::errorVALUE(); - Value lookup = args[1]; - Value rr = args[2]; - unsigned cols = lookup.columns(); - unsigned rows = lookup.rows(); - if ((cols != rr.columns()) || (rows != rr.rows())) - return Value::errorVALUE(); - Value res = Value::errorNA(); - - // now traverse the array and perform comparison - for (unsigned r = 0; r < rows; ++r) - for (unsigned c = 0; c < cols; ++c) - { - // update the result, return if we cross the line - Value le = lookup.element (c, r); - if (calc->lower (le, num) || calc->equal (num, le)) - res = rr.element (c, r); - else - return res; - } - return res; -} - -// Function: COLUMN -Value func_column (valVector args, ValueCalc *, FuncExtra *e) -{ - int col = e ? e->mycol : 0; - if (e && args.count()) - col = e->ranges[0].col1; - if (col > 0) - return Value (col); - return Value::errorVALUE(); -} - -// Function: ROW -Value func_row (valVector args, ValueCalc *, FuncExtra *e) -{ - int row = e ? e->myrow : 0; - if (e && args.count()) - row = e->ranges[0].row1; - if (row > 0) - return Value (row); - return Value::errorVALUE(); -} - -// Function: COLUMNS -Value func_columns (valVector, ValueCalc *, FuncExtra *e) -{ - int col1 = e->ranges[0].col1; - int col2 = e->ranges[0].col2; - if ((col1 == -1) || (col2 == -1)) - return Value::errorVALUE(); - return Value (col2 - col1 + 1); -} - -// Function: ROWS -Value func_rows (valVector, ValueCalc *, FuncExtra *e) -{ - int row1 = e->ranges[0].row1; - int row2 = e->ranges[0].row2; - if ((row1 == -1) || (row2 == -1)) - return Value::errorVALUE(); - return Value (row2 - row1 + 1); -} - - -// Function: INDIRECT -Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *e) -{ - bool r1c1 = false; - TQString ref = calc->conv()->asString (args[0]).asString(); - if (args.count() == 2) - r1c1 = !(calc->conv()->asBoolean (args[1]).asBoolean()); - - if (ref.isEmpty()) - return Value::errorVALUE(); - - if ( r1c1 ) - { - // TODO: translate the r1c1 style to a1 style - ref = ref; - } - - Point p (ref, e->sheet->workbook(), e->sheet); - - if ( !p.isValid() ) - return Value::errorVALUE(); - - Cell * cell = p.cell(); - if (cell) - return cell->value(); - return Value::errorVALUE(); -} - diff --git a/kspread/kspread_functions_reference.cpp b/kspread/kspread_functions_reference.cpp new file mode 100644 index 00000000..7dacb054 --- /dev/null +++ b/kspread/kspread_functions_reference.cpp @@ -0,0 +1,342 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in reference functions + +#include "kspread_cell.h" +#include "kspread_sheet.h" +#include "kspread_util.h" +#include "kspread_value.h" + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +using namespace KSpread; + +// prototypes (sorted alphabetically) +Value func_address (valVector args, ValueCalc *calc, FuncExtra *); +Value func_areas (valVector args, ValueCalc *calc, FuncExtra *); +Value func_choose (valVector args, ValueCalc *calc, FuncExtra *); +Value func_column (valVector args, ValueCalc *calc, FuncExtra *); +Value func_columns (valVector args, ValueCalc *calc, FuncExtra *); +Value func_index (valVector args, ValueCalc *calc, FuncExtra *); +Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *); +Value func_lookup (valVector args, ValueCalc *calc, FuncExtra *); +Value func_row (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rows (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all reference functions +void RegisterReferenceFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("ADDRESS", func_address); + f->setParamCount (2, 5); + repo->add (f); + f = new Function ("AREAS", func_areas); + f->setParamCount (1); + f->setNeedsExtra (true); + repo->add (f); + f = new Function ("CHOOSE", func_choose); + f->setParamCount (2, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("COLUMN", func_column); + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("COLUMNS", func_columns); + f->setParamCount (1); + f->setAcceptArray (); + f->setNeedsExtra (true); + repo->add (f); + f = new Function ("INDEX", func_index); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("INDIRECT", func_indirect); + f->setParamCount (1, 2); + f->setNeedsExtra (true); + repo->add (f); + f = new Function ("LOOKUP", func_lookup); + f->setParamCount (3); + f->setAcceptArray (); + repo->add (f); + f = new Function ("ROW", func_row); + f->setParamCount (0, 1); + repo->add (f); + f = new Function ("ROWS", func_rows); + f->setParamCount (1); + f->setAcceptArray (); + f->setNeedsExtra (true); + repo->add (f); +} + +// Function: ADDRESS +Value func_address (valVector args, ValueCalc *calc, FuncExtra *) +{ + bool r1c1 = false; + TQString sheetName; + int absNum = 1; + if (args.count() > 2) + absNum = calc->conv()->asInteger (args[2]).asInteger(); + if (args.count() > 3) + r1c1 = !(calc->conv()->asBoolean (args[3]).asBoolean()); + if (args.count() == 5) + sheetName = calc->conv()->asString (args[4]).asString(); + + TQString result; + int row = calc->conv()->asInteger (args[0]).asInteger(); + int col = calc->conv()->asInteger (args[1]).asInteger(); + + if ( !sheetName.isEmpty() ) + { + result += sheetName; + result += "!"; + } + + if ( r1c1 ) + { + // row first + bool abs = false; + if ( absNum == 1 || absNum == 2 ) + abs = true; + + result += 'R'; + if ( !abs ) + result += '['; + result += TQString::number( row ); + + if ( !abs ) + result += ']'; + + // column + abs = false; + if ( absNum == 1 || absNum == 3 ) + abs = true; + + result += 'C'; + if ( !abs ) + result += '['; + result += TQString::number( col ); + + if ( !abs ) + result += ']'; + } + else + { + bool abs = false; + if ( absNum == 1 || absNum == 3 ) + abs = true; + + if ( abs ) + result += '$'; + + result += Cell::columnName( col ); + + abs = false; + if ( absNum == 1 || absNum == 2 ) + abs = true; + + if ( abs ) + result += '$'; + + result += TQString::number( row ); + } + + return Value (result); +} + +bool checkRef( TQString const & ref ) +{ + Range r( ref ); + if ( !r.isValid() ) + { + Point p( ref ); + if ( !p.isValid() ) + return false; + } + return true; +} + +// Function: AREAS +Value func_areas (valVector args, ValueCalc *calc, FuncExtra *e) +{ + if (e) { + if ((e->ranges[0].col1 != -1) && (e->ranges[0].row1 != -1) && + (e->ranges[0].col2 != -1) && (e->ranges[0].row2 != -1)) + // we have a range reference - return 1 + return 1; + } + + TQString s = calc->conv()->asString (args[0]).asString(); + if ( s[0] != '(' || s[s.length() - 1] != ')' ) + return Value::errorVALUE(); + + int l = s.length(); + + int num = 0; + TQString ref; + for ( int i = 1; i < l; ++i ) + { + if ( s[i] == ',' || s[i] == ')' ) + { + if ( !checkRef( ref ) ) + return Value::errorVALUE(); + else + { + ++num; + ref = ""; + } + } + else + ref += s[i]; + } + + return Value (num); +} + +// Function: CHOOSE +Value func_choose (valVector args, ValueCalc *calc, FuncExtra *) +{ + int cnt = args.count () - 1; + int num = calc->conv()->asInteger (args[0]).asInteger(); + if ((num <= 0) || (num > cnt)) + return Value::errorVALUE(); + return args[num]; +} + +// Function: INDEX +Value func_index (valVector args, ValueCalc *calc, FuncExtra *) +{ + // first argument can be either a range, then we return a given cell's + // value, or a single cell containing an array - then we return the array + // element. In any case, this function can assume that the given value + // is the same. Because it is. + + Value val = args[0]; + unsigned row = calc->conv()->asInteger (args[1]).asInteger() - 1; + unsigned col = calc->conv()->asInteger (args[2]).asInteger() - 1; + if ((row >= val.rows()) || (col >= val.columns())) + return Value::errorREF(); + return val.element (col, row); +} + +// Function: LOOKUP +Value func_lookup (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value num = calc->conv()->asNumeric (args[0]); + if (num.isArray()) + return Value::errorVALUE(); + Value lookup = args[1]; + Value rr = args[2]; + unsigned cols = lookup.columns(); + unsigned rows = lookup.rows(); + if ((cols != rr.columns()) || (rows != rr.rows())) + return Value::errorVALUE(); + Value res = Value::errorNA(); + + // now traverse the array and perform comparison + for (unsigned r = 0; r < rows; ++r) + for (unsigned c = 0; c < cols; ++c) + { + // update the result, return if we cross the line + Value le = lookup.element (c, r); + if (calc->lower (le, num) || calc->equal (num, le)) + res = rr.element (c, r); + else + return res; + } + return res; +} + +// Function: COLUMN +Value func_column (valVector args, ValueCalc *, FuncExtra *e) +{ + int col = e ? e->mycol : 0; + if (e && args.count()) + col = e->ranges[0].col1; + if (col > 0) + return Value (col); + return Value::errorVALUE(); +} + +// Function: ROW +Value func_row (valVector args, ValueCalc *, FuncExtra *e) +{ + int row = e ? e->myrow : 0; + if (e && args.count()) + row = e->ranges[0].row1; + if (row > 0) + return Value (row); + return Value::errorVALUE(); +} + +// Function: COLUMNS +Value func_columns (valVector, ValueCalc *, FuncExtra *e) +{ + int col1 = e->ranges[0].col1; + int col2 = e->ranges[0].col2; + if ((col1 == -1) || (col2 == -1)) + return Value::errorVALUE(); + return Value (col2 - col1 + 1); +} + +// Function: ROWS +Value func_rows (valVector, ValueCalc *, FuncExtra *e) +{ + int row1 = e->ranges[0].row1; + int row2 = e->ranges[0].row2; + if ((row1 == -1) || (row2 == -1)) + return Value::errorVALUE(); + return Value (row2 - row1 + 1); +} + + +// Function: INDIRECT +Value func_indirect (valVector args, ValueCalc *calc, FuncExtra *e) +{ + bool r1c1 = false; + TQString ref = calc->conv()->asString (args[0]).asString(); + if (args.count() == 2) + r1c1 = !(calc->conv()->asBoolean (args[1]).asBoolean()); + + if (ref.isEmpty()) + return Value::errorVALUE(); + + if ( r1c1 ) + { + // TODO: translate the r1c1 style to a1 style + ref = ref; + } + + Point p (ref, e->sheet->workbook(), e->sheet); + + if ( !p.isValid() ) + return Value::errorVALUE(); + + Cell * cell = p.cell(); + if (cell) + return cell->value(); + return Value::errorVALUE(); +} + diff --git a/kspread/kspread_functions_statistical.cc b/kspread/kspread_functions_statistical.cc deleted file mode 100644 index 26c9d483..00000000 --- a/kspread/kspread_functions_statistical.cc +++ /dev/null @@ -1,1243 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in statistical functions - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -// needed for MODE -#include - -using namespace KSpread; - -// prototypes (sorted!) -Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *); -Value func_average (valVector args, ValueCalc *calc, FuncExtra *); -Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *); -Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *); -Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_bino (valVector args, ValueCalc *calc, FuncExtra *); -Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_combin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *); -Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *); -Value func_covar (valVector args, ValueCalc *calc, FuncExtra *); -Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *); -Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *); -Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *); -Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *); -Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *); -Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *); -Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *); -Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *); -Value func_large (valVector args, ValueCalc *calc, FuncExtra *); -Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_median (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mode (valVector args, ValueCalc *calc, FuncExtra *); -Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *); -Value func_phi (valVector args, ValueCalc *calc, FuncExtra *); -Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *); -Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *); -Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *); -Value func_small (valVector args, ValueCalc *calc, FuncExtra *); -Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *); -Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *); -Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *); -Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *); -Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *); -Value func_variance (valVector args, ValueCalc *calc, FuncExtra *); -Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *); -Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *); -Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *); -Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *); - -typedef TQValueList List; - -// registers all statistical functions -void RegisterStatisticalFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("AVEDEV", func_avedev); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("AVERAGE", func_average); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("AVERAGEA", func_averagea); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("BETADIST", func_betadist); - f->setParamCount (3, 5); - repo->add (f); - f = new Function ("BINO", func_bino); - f->setParamCount (3); - repo->add (f); - f = new Function ("CHIDIST", func_chidist); - f->setParamCount (2); - repo->add (f); - f = new Function ("COMBIN", func_combin); - f->setParamCount (2); - repo->add (f); - f = new Function ("CONFIDENCE", func_confidence); - f->setParamCount (3); - repo->add (f); - f = new Function ("CORREL", func_correl_pop); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("COVAR", func_covar); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DEVSQ", func_devsq); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DEVSQA", func_devsqa); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("EXPONDIST", func_expondist); - f->setParamCount (3); - repo->add (f); - f = new Function ("FDIST", func_fdist); - f->setParamCount (3); - repo->add (f); - f = new Function ("FISHER", func_fisher); - repo->add (f); - f = new Function ("FISHERINV", func_fisherinv); - repo->add (f); - f = new Function ("GAMMADIST", func_gammadist); - f->setParamCount (4); - repo->add (f); - f = new Function ("GAMMALN", func_gammaln); - repo->add (f); - f = new Function ("GAUSS", func_gauss); - repo->add (f); - f = new Function ("GEOMEAN", func_geomean); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("HARMEAN", func_harmean); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("HYPGEOMDIST", func_hypgeomdist); - f->setParamCount (4); - repo->add (f); - f = new Function ("INVBINO", func_bino); // same as BINO, for 1.4 compat - repo->add (f); - f = new Function ("KURT", func_kurtosis_est); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("KURTP", func_kurtosis_pop); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("LARGE", func_large); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("LOGINV", func_loginv); - f->setParamCount (3); - repo->add (f); - f = new Function ("LOGNORMDIST", func_lognormdist); - f->setParamCount (3); - repo->add (f); - f = new Function ("MEDIAN", func_median); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("MODE", func_mode); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("NEGBINOMDIST", func_negbinomdist); - f->setParamCount (3); - repo->add (f); - f = new Function ("NORMDIST", func_normdist); - f->setParamCount (4); - repo->add (f); - f = new Function ("NORMINV", func_norminv); - f->setParamCount (3); - repo->add (f); - f = new Function ("NORMSDIST", func_stdnormdist); - repo->add (f); - f = new Function ("NORMSINV", func_normsinv); - repo->add (f); - f = new Function ("PEARSON", func_correl_pop); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("PERMUT", func_arrang); - f->setParamCount (2); - repo->add (f); - f = new Function ("PHI", func_phi); - repo->add (f); - f = new Function ("POISSON", func_poisson); - f->setParamCount (3); - repo->add (f); - f = new Function ("SKEW", func_skew_est); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SKEWP", func_skew_pop); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SMALL", func_small); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("STANDARDIZE", func_standardize); - f->setParamCount (3); - repo->add (f); - f = new Function ("STDEV", func_stddev); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("STDEVA", func_stddeva); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("STDEVP", func_stddevp); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("STDEVPA", func_stddevpa); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUM2XMY", func_sumxmy2); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUMPRODUCT", func_sumproduct); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUMX2PY2", func_sumx2py2); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("SUMX2MY2", func_sumx2my2); - f->setParamCount (2); - f->setAcceptArray (); - repo->add (f); - f = new Function ("TDIST", func_tdist); - f->setParamCount (3); - repo->add (f); - f = new Function ("VARIANCE", func_variance); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("VAR", func_variance); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("VARP", func_variancep); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("VARA", func_variancea); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("VARPA", func_variancepa); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("WEIBULL", func_weibull); - f->setParamCount (4); - repo->add (f); -} - -// array-walk functions used in this file - -void awSkew (ValueCalc *c, Value &res, Value val, Value p) -{ - Value avg = p.element (0, 0); - Value stdev = p.element (1, 0); - // (val - avg) / stddev - Value d = c->div (c->sub (val, avg), stdev); - // res += d*d*d - res = c->add (res, c->mul (d, c->mul (d, d))); -} - -void awSumInv (ValueCalc *c, Value &res, Value val, Value) -{ - // res += 1/value - res = c->add (res, c->div (1.0, val)); -} - -void awAveDev (ValueCalc *c, Value &res, Value val, - Value p) -{ - // res += abs (val - p) - res = c->add (res, c->abs (c->sub (val, p))); -} - -void awKurtosis (ValueCalc *c, Value &res, Value val, - Value p) -{ - Value avg = p.element (0, 0); - Value stdev = p.element (1, 0); - //d = (val - avg ) / stdev - Value d = c->div (c->sub (val, avg), stdev); - // res += d^4 - res = c->add (res, c->pow (d, 4)); -} - - -Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *) -{ - int number = calc->count (args); - Value avg = calc->avg (args); - if (number < 3) - return Value::errorVALUE(); - - Value res = calc->stddev (args, avg); - if (res.isZero()) - return Value::errorVALUE(); - - Value params (2, 1); - params.setElement (0, 0, avg); - params.setElement (1, 0, res); - Value tskew; - calc->arrayWalk (args, tskew, awSkew, params); - - // ((tskew * number) / (number-1)) / (number-2) - return calc->div (calc->div (calc->mul (tskew, number), number-1), number-2); -} - -Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *) -{ - int number = calc->count (args); - Value avg = calc->avg (args); - if (number < 1) - return Value::errorVALUE(); - - Value res = calc->stddevP (args, avg); - if (res.isZero()) - return Value::errorVALUE(); - - Value params (2, 1); - params.setElement (0, 0, avg); - params.setElement (1, 0, res); - Value tskew; - calc->arrayWalk (args, tskew, awSkew, params); - - // tskew / number - return calc->div (tskew, number); -} - -class ContentSheet : public TQMap {}; - -void func_mode_helper (Value range, ValueCalc *calc, ContentSheet &sh) -{ - if (!range.isArray()) - { - double d = calc->conv()->asFloat (range).asFloat(); - sh[d]++; - return; - } - - for (unsigned int row = 0; row < range.rows(); ++row) - for (unsigned int col = 0; col < range.columns(); ++col) { - Value v = range.element (col, row); - if (v.isArray()) - func_mode_helper (v, calc, sh); - else { - double d = calc->conv()->asFloat (v).asFloat(); - sh[d]++; - } - } -} - -Value func_mode (valVector args, ValueCalc *calc, FuncExtra *) -{ - // does NOT support anything other than doubles !!! - ContentSheet sh; - for (unsigned int i = 0; i < args.count(); ++i) - func_mode_helper (args[i], calc, sh); - - // retrieve value with max.count - int maxcount = 0; - double max = 0.0; - ContentSheet::iterator it; - for (it = sh.begin(); it != sh.end(); ++it) - if (it.data() > maxcount) { - max = it.key(); - maxcount = it.data(); - } - return Value (max); -} - -Value func_covar_helper (Value range1, Value range2, - ValueCalc *calc, Value avg1, Value avg2) -{ - // two arrays -> cannot use arrayWalk - if ((!range1.isArray()) && (!range2.isArray())) - // (v1-E1)*(v2-E2) - return calc->mul (calc->sub (range1, avg1), calc->sub (range2, avg2)); - - int rows = range1.rows(); - int cols = range1.columns(); - int rows2 = range2.rows(); - int cols2 = range2.columns(); - if ((rows != rows2) || (cols != cols2)) - return Value::errorVALUE(); - - Value result = 0.0; - for (int row = 0; row < rows; ++row) - for (int col = 0; col < cols; ++col) { - Value v1 = range1.element (col, row); - Value v2 = range2.element (col, row); - if (v1.isArray() || v2.isArray()) - result = calc->add (result, - func_covar_helper (v1, v2, calc, avg1, avg2)); - else - // result += (v1-E1)*(v2-E2) - result = calc->add (result, calc->mul (calc->sub (v1, avg1), - calc->sub (v2, avg2))); - } - - return result; -} - -Value func_covar (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value avg1 = calc->avg (args[0]); - Value avg2 = calc->avg (args[1]); - int number = calc->count (args[0]); - int number2 = calc->count (args[1]); - - if (number2 <= 0 || number2 != number) - return Value::errorVALUE(); - - Value covar = func_covar_helper (args[0], args[1], calc, avg1, avg2); - return calc->div (covar, number); -} - -Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value covar = func_covar (args, calc, 0); - Value stdevp1 = calc->stddevP (args[0]); - Value stdevp2 = calc->stddevP (args[1]); - - if (calc->isZero (stdevp1) || calc->isZero (stdevp2)) - return Value::errorDIV0(); - - // covar / (stdevp1 * stdevp2) - return calc->div (covar, calc->mul (stdevp1, stdevp2)); -} - -void func_array_helper (Value range, ValueCalc *calc, - List &array, int &number) -{ - if (!range.isArray()) - { - array << calc->conv()->asFloat (range).asFloat(); - ++number; - return; - } - - for (unsigned int row = 0; row < range.rows(); ++row) - for (unsigned int col = 0; col < range.columns(); ++col) { - Value v = range.element (col, row); - if (v.isArray ()) - func_array_helper (v, calc, array, number); - else { - array << calc->conv()->asFloat (v).asFloat(); - ++number; - } - } -} - -Value func_large (valVector args, ValueCalc *calc, FuncExtra *) -{ - // does NOT support anything other than doubles !!! - int k = calc->conv()->asInteger (args[1]).asInteger(); - if ( k < 1 ) - return false; - - List array; - int number = 1; - - func_array_helper (args[0], calc, array, number); - - if ( k > number ) - return Value::errorVALUE(); - - qHeapSort (array); - double d = *array.at (number - k - 1); - return Value (d); -} - -Value func_small (valVector args, ValueCalc *calc, FuncExtra *) -{ - // does NOT support anything other than doubles !!! - int k = calc->conv()->asInteger (args[1]).asInteger(); - if ( k < 1 ) - return false; - - List array; - int number = 1; - - func_array_helper (args[0], calc, array, number); - - if ( k > number ) - return Value::errorVALUE(); - - qHeapSort (array); - double d = *array.at (k - 1); - return Value (d); -} - -Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value count = calc->count (args); - Value prod = calc->product (args, 1.0); - if (calc->isZero (count)) - return Value::errorDIV0(); - return calc->pow (prod, calc->div (1.0, count)); -} - -Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value count = calc->count (args); - if (calc->isZero (count)) - return Value::errorDIV0(); - Value suminv; - calc->arrayWalk (args, suminv, awSumInv, 0); - return calc->div (suminv, count); -} - -Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value p = args[0]; - Value m = args[1]; - Value s = args[2]; - - if (calc->lower (p, 0) || calc->greater (p, 1)) - return Value::errorVALUE(); - - if (!calc->greater (s, 0)) - return Value::errorVALUE(); - - Value result = 0.0; - if (calc->equal (p, 1)) //p==1 - result = Value::errorVALUE(); - else if (calc->greater (p, 0)) { //p>0 - Value gaussInv = calc->gaussinv (p); - // exp (gaussInv * s + m) - result = calc->exp (calc->add (calc->mul (s, gaussInv), m)); - } - - return result; -} - -Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value res; - calc->arrayWalk (args, res, calc->awFunc ("devsq"), calc->avg (args, false)); - return res; -} - -Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value res; - calc->arrayWalk (args, res, calc->awFunc ("devsqa"), calc->avg (args)); - return res; -} - -Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args); - if (count < 4) - return Value::errorVALUE(); - - Value avg = calc->avg (args); - Value devsq; - calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg); - - if (devsq.isZero ()) - return Value::errorDIV0(); - - Value params (2, 1); - params.setElement (0, 0, avg); - params.setElement (1, 0, devsq); - Value x4; - calc->arrayWalk (args, x4, awKurtosis, params); - - double den = (double) (count - 2) * (count - 3); - double nth = (double) count * (count + 1) / ((count - 1) * den); - double t = 3.0 * (count - 1) * (count - 1) / den; - - // res = x4 * nth - t - return calc->sub (calc->mul (x4, nth), t); -} - -Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args); - if (count < 4) - return Value::errorVALUE(); - - Value avg = calc->avg (args); - Value devsq; - calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg); - - if (devsq.isZero ()) - return Value::errorDIV0(); - - Value params (2, 1); - params.setElement (0, 0, avg); - params.setElement (1, 0, devsq); - Value x4; - calc->arrayWalk (args, x4, awKurtosis, params); - - // x4 / count - 3 - return calc->sub (calc->div (x4, count), 3); -} - -Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value m = args[1]; - Value s = args[2]; - - if (!calc->greater (s, 0)) // s must be >0 - return Value::errorVALUE(); - - // (x - m) / s - return calc->div (calc->sub (x, m), s); -} - -Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *) -{ - int x = calc->conv()->asInteger (args[0]).asInteger(); - int n = calc->conv()->asInteger (args[1]).asInteger(); - int M = calc->conv()->asInteger (args[2]).asInteger(); - int N = calc->conv()->asInteger (args[3]).asInteger(); - - if ( x < 0 || n < 0 || M < 0 || N < 0 ) - return Value::errorVALUE(); - - if ( x > M || n > N ) - return Value::errorVALUE(); - - Value d1 = calc->combin (M, x); - Value d2 = calc->combin (N - M, n - x); - Value d3 = calc->combin (N, n); - - // d1 * d2 / d3 - return calc->div (calc->mul (d1, d2), d3); -} - -Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *) -{ - int x = calc->conv()->asInteger (args[0]).asInteger(); - int r = calc->conv()->asInteger (args[1]).asInteger(); - Value p = args[2]; - - if ((x + r - 1) <= 0) - return Value::errorVALUE(); - if (calc->lower (p, 0) || calc->greater (p, 1)) - return Value::errorVALUE(); - - Value d1 = calc->combin (x + r - 1, r - 1); - // d2 = pow (p, r) * pow (1 - p, x) - Value d2 = calc->mul (calc->pow (p, r), - calc->pow (calc->sub (1, p), x)); - - return calc->mul (d1, d2); -} - -// Function: permut -Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value n = args[0]; - Value m = args[1]; - if (calc->lower (n, m)) // problem if nlower (m, 0)) // problem if m<0 (n>=m so that's okay) - return Value::errorVALUE(); - - // fact(n) / (fact(n-m) - return calc->fact (n, calc->sub (n, m)); -} - -// Function: average -Value func_average (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->avg (args, false); -} - -// Function: averagea -Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->avg (args); -} - -// Function: avedev -Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->arrayWalk (args, result, awAveDev, calc->avg (args)); - return result; -} - -// Function: median -Value func_median (valVector args, ValueCalc *calc, FuncExtra *) -{ - // does NOT support anything other than doubles !!! - List array; - int number = 1; - - for (unsigned int i = 0; i < args.count(); ++i) - func_array_helper (args[i], calc, array, number); - - qHeapSort (array); - double d = *array.at (number / 2 + number % 2); - return Value (d); -} - -// Function: variance -Value func_variance (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args, false); - if (count < 2) - return Value::errorVALUE(); - - Value result = func_devsq (args, calc, 0); - return calc->div (result, count-1); -} - -// Function: vara -Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args); - if (count < 2) - return Value::errorVALUE(); - - Value result = func_devsqa (args, calc, 0); - return calc->div (result, count-1); -} - -// Function: varp -Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args, false); - if (count == 0) - return Value::errorVALUE(); - - Value result = func_devsq (args, calc, 0); - return calc->div (result, count); -} - -// Function: varpa -Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *) -{ - int count = calc->count (args); - if (count == 0) - return Value::errorVALUE(); - - Value result = func_devsqa (args, calc, 0); - return calc->div (result, count); -} - -// Function: stddev -Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->stddev (args, false); -} - -// Function: stddeva -Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->stddev (args); -} - -// Function: stddevp -Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->stddevP (args, false); -} - -// Function: stddevpa -Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->stddevP (args); -} - -// Function: combin -Value func_combin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->combin (args[0], args[1]); -} - -// Function: bino -Value func_bino (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value n = args[0]; - Value m = args[1]; - Value comb = calc->combin (n, m); - Value prob = args[2]; - - if (calc->lower (prob,0) || calc->greater (prob,1)) - return Value::errorVALUE(); - - // result = comb * pow (prob, m) * pow (1 - prob, n - m) - Value pow1 = calc->pow (prob, m); - Value pow2 = calc->pow (calc->sub (1, prob), calc->sub (n, m)); - return calc->mul (comb, calc->mul (pow1, pow2)); -} - -// Function: phi -Value func_phi (valVector args, ValueCalc *calc, FuncExtra *) -//distribution function for a standard normal distribution -{ - return calc->phi (args[0]); -} - -// Function: gauss -Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *) -{ - //returns the integral values of the standard normal cumulative distribution - return calc->gauss (args[0]); -} - -// Function: gammadist -Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value alpha = args[1]; - Value beta = args[2]; - int kum = calc->conv()->asInteger (args[3]).asInteger(); // 0 or 1 - - Value result; - - if (calc->lower (x, 0.0) || (!calc->greater (alpha, 0.0)) || - (!calc->greater (beta, 0.0))) - return Value::errorVALUE(); - - if (kum == 0) { //density - Value G = calc->GetGamma (alpha); - // result = pow (x, alpha - 1.0) / exp (x / beta) / pow (beta, alpha) / G - Value pow1 = calc->pow (x, calc->sub (alpha, 1.0)); - Value pow2 = calc->exp (calc->div (x, beta)); - Value pow3 = calc->pow (beta, alpha); - result = calc->div (calc->div (calc->div (pow1, pow2), pow3), G); - } - else - result = calc->GetGammaDist (x, alpha, beta); - - return Value (result); -} - -// Function: betadist -Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value x = args[0]; - Value alpha = args[1]; - Value beta = args[2]; - - Value fA = 0.0; - Value fB = 1.0; - if (args.count() > 3) fA = args[3]; - if (args.count() == 5) fB = args[4]; - - //x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0 - if (calc->lower (x, fA) || calc->greater (x, fB) || calc->equal (fA, fB) || - (!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0))) - return Value::errorVALUE(); - - // xx = (x - fA) / (fB - fA) // scaling - Value xx = calc->div (calc->sub (x, fA), calc->sub (fB, fA)); - - return calc->GetBeta (xx, alpha, beta); -} - -// Function: fisher -Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the Fisher transformation for x - - // 0.5 * ln ((1.0 + fVal) / (1.0 - fVal)) - Value fVal = args[0]; - Value num = calc->div (calc->add (fVal, 1.0), calc->sub (1.0, fVal)); - return calc->mul (calc->ln (num), 0.5); -} - -// Function: fisherinv -Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the inverse of the Fisher transformation for x - - Value fVal = args[0]; - // (exp (2.0 * fVal) - 1.0) / (exp (2.0 * fVal) + 1.0) - Value ex = calc->exp (calc->mul (fVal, 2.0)); - return calc->div (calc->sub (ex, 1.0), calc->add (ex, 1.0)); -} - -// Function: normdist -Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the normal cumulative distribution - Value x = args[0]; - Value mue = args[1]; - Value sigma = args[2]; - Value k = args[3]; - - if (!calc->greater (sigma, 0.0)) - return Value::errorVALUE(); - - // (x - mue) / sigma - Value Y = calc->div (calc->sub (x, mue), sigma); - if (calc->isZero (k)) // density - return calc->div (calc->phi (Y), sigma); - else // distribution - return calc->add (calc->gauss (Y), 0.5); -} - -// Function: lognormdist -Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the cumulative lognormal distribution - Value x = args[0]; - Value mue = args[1]; - Value sigma = args[2]; - - if (!calc->greater (sigma, 0.0) || (!calc->greater (x, 0.0))) - return Value::errorVALUE(); - - // (ln(x) - mue) / sigma - Value Y = calc->div (calc->sub (calc->ln (x), mue), sigma); - return calc->add (calc->gauss (Y), 0.5); -} - -// Function: normsdist -Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *) -{ - //returns the cumulative lognormal distribution, mue=0, sigma=1 - return calc->add (calc->gauss (args[0]), 0.5); -} - -// Function: expondist -Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the exponential distribution - Value x = args[0]; - Value lambda = args[1]; - Value kum = args[2]; - - Value result = 0.0; - - if (!calc->greater (lambda, 0.0)) - return Value::errorVALUE(); - - // ex = exp (-lambda * x) - Value ex = calc->exp (calc->mul (calc->mul (lambda, -1), x)); - if (calc->isZero (kum)) { //density - if (!calc->lower (x, 0.0)) - // lambda * ex - result = calc->mul (lambda, ex); - } - else { //distribution - if (calc->greater (x, 0.0)) - // 1.0 - ex - result = calc->sub (1.0, ex); - } - return result; -} - -// Function: weibull -Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the Weibull distribution - - Value x = args[0]; - Value alpha = args[1]; - Value beta = args[2]; - Value kum = args[3]; - - Value result; - - if ((!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0)) || - calc->lower (x, 0.0)) - return Value::errorVALUE(); - - // ex = exp (-pow (x / beta, alpha)) - Value ex; - ex = calc->exp (calc->mul (calc->pow (calc->div (x, beta), alpha), -1)); - if (calc->isZero (kum)) // density - { - // result = alpha / pow(beta,alpha) * pow(x,alpha-1.0) * ex - result = calc->div (alpha, calc->pow (beta, alpha)); - result = calc->mul (result, calc->mul (calc->pow (x, - calc->sub (alpha, 1)), ex)); - } - else // distribution - result = calc->sub (1.0, ex); - - return result; -} - -// Function: normsinv -Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the inverse of the standard normal cumulative distribution - - Value x = args[0]; - if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0))) - return Value::errorVALUE(); - - return calc->gaussinv (x); -} - -// Function: norminv -Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the inverse of the normal cumulative distribution - Value x = args[0]; - Value mue = args[1]; - Value sigma = args[2]; - - if (!calc->greater (sigma, 0.0)) - return Value::errorVALUE(); - if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0))) - return Value::errorVALUE(); - - // gaussinv (x)*sigma + mue - return calc->add (calc->mul (calc->gaussinv (x), sigma), mue); -} - -// Function: gammaln -Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the natural logarithm of the gamma function - - if (calc->greater (args[0], 0.0)) - return calc->GetLogGamma (args[0]); - return Value::errorVALUE(); -} - -// Function: poisson -Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the Poisson distribution - - Value x = args[0]; - Value lambda = args[1]; - Value kum = args[2]; - - // lambda < 0.0 || x < 0.0 - if (calc->lower (lambda, 0.0) || calc->lower (x, 0.0)) - return Value::errorVALUE(); - - Value result; - - // ex = exp (-lambda) - Value ex = calc->exp (calc->mul (lambda, -1)); - - if (calc->isZero (kum)) { // density - if (calc->isZero (lambda)) - result = 0; - else - // ex * pow (lambda, x) / fact (x) - result = calc->div (calc->mul (ex, calc->pow (lambda, x)), calc->fact (x)); - } - else { // distribution - if (calc->isZero (lambda)) - result = 1; - else - { - result = 1.0; - Value fFak = 1.0; - unsigned long nEnd = calc->conv()->asInteger (x).asInteger(); - for (unsigned long i = 1; i <= nEnd; i++) - { - // fFak *= i - fFak = calc->mul (fFak, i); - // result += pow (lambda, i) / fFak - result = calc->add (result, calc->div (calc->pow (lambda, i), fFak)); - } - result = calc->mul (result, ex); - } - } - - return result; -} - -// Function: confidence -Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the confidence interval for a population mean - Value alpha = args[0]; - Value sigma = args[1]; - Value n = args[2]; - - // sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1 - if ((!calc->greater (sigma, 0.0)) || (!calc->greater (alpha, 0.0)) || - (!calc->lower (alpha, 1.0)) || calc->lower (n, 1)) - return Value::errorVALUE(); - - // g = gaussinv (1.0 - alpha / 2.0) - Value g = calc->gaussinv (calc->sub (1.0, calc->div (alpha, 2.0))); - // g * sigma / sqrt (n) - return calc->div (calc->mul (g, sigma), calc->sqrt (n)); -} - -// Function: tdist -Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the t-distribution - - Value T = args[0]; - Value fDF = args[1]; - int flag = calc->conv()->asInteger (args[2]).asInteger(); - - if (calc->lower (fDF, 1) || calc->lower (T, 0.0) || (flag != 1 && flag != 2)) - return Value::errorVALUE(); - - // arg = fDF / (fDF + T * T) - Value arg = calc->div (fDF, calc->add (fDF, calc->sqr (T))); - - Value R; - R = calc->mul (calc->GetBeta (arg, calc->div (fDF, 2.0), 0.5), 0.5); - - if (flag == 1) - return R; - return calc->mul (R, 2); // flag is 2 here -} - -// Function: fdist -Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the f-distribution - - Value x = args[0]; - Value fF1 = args[1]; - Value fF2 = args[2]; - - // x < 0.0 || fF1 < 1 || fF2 < 1 || fF1 >= 1.0E10 || fF2 >= 1.0E10 - if (calc->lower (x, 0.0) || calc->lower (fF1, 1) || calc->lower (fF2, 1) || - (!calc->lower (fF1, 1.0E10)) || (!calc->lower (fF2, 1.0E10))) - return Value::errorVALUE(); - - // arg = fF2 / (fF2 + fF1 * x) - Value arg = calc->div (fF2, calc->add (fF2, calc->mul (fF1, x))); - // alpha = fF2/2.0 - Value alpha = calc->div (fF2, 2.0); - // beta = fF1/2.0 - Value beta = calc->div (fF1, 2.0); - return calc->GetBeta (arg, alpha, beta); -} - -// Function: chidist -Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *) { - //returns the chi-distribution - - Value fChi = args[0]; - Value fDF = args[1]; - - // fDF < 1 || fDF >= 1.0E5 || fChi < 0.0 - if (calc->lower (fDF, 1) || (!calc->lower (fDF, 1.0E5)) || - calc->lower (fChi, 0.0)) - return Value::errorVALUE(); - - // 1.0 - GetGammaDist (fChi / 2.0, fDF / 2.0, 1.0) - return calc->sub (1.0, calc->GetGammaDist (calc->div (fChi, 2.0), - calc->div (fDF, 2.0), 1.0)); -} - - -// two-array-walk functions used in the two-sum functions - -void tawSumproduct (ValueCalc *c, Value &res, Value v1, - Value v2) { - // res += v1*v2 - res = c->add (res, c->mul (v1, v2)); -} - -void tawSumx2py2 (ValueCalc *c, Value &res, Value v1, - Value v2) { - // res += sqr(v1)+sqr(v2) - res = c->add (res, c->add (c->sqr (v1), c->sqr (v2))); -} - -void tawSumx2my2 (ValueCalc *c, Value &res, Value v1, - Value v2) { - // res += sqr(v1)-sqr(v2) - res = c->add (res, c->sub (c->sqr (v1), c->sqr (v2))); -} - -void tawSumxmy2 (ValueCalc *c, Value &res, Value v1, - Value v2) { - // res += sqr(v1-v2) - res = c->add (res, c->sqr (c->sub (v1, v2))); - -} - -// Function: sumproduct -Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->twoArrayWalk (args[0], args[1], result, tawSumproduct); - return result; -} - -// Function: sumx2py2 -Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->twoArrayWalk (args[0], args[1], result, tawSumx2py2); - return result; -} - -// Function: sumx2my2 -Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->twoArrayWalk (args[0], args[1], result, tawSumx2my2); - return result; -} - -// Function: sum2xmy -Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *) -{ - Value result; - calc->twoArrayWalk (args[0], args[1], result, tawSumxmy2); - return result; -} diff --git a/kspread/kspread_functions_statistical.cpp b/kspread/kspread_functions_statistical.cpp new file mode 100644 index 00000000..26c9d483 --- /dev/null +++ b/kspread/kspread_functions_statistical.cpp @@ -0,0 +1,1243 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in statistical functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +// needed for MODE +#include + +using namespace KSpread; + +// prototypes (sorted!) +Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *); +Value func_average (valVector args, ValueCalc *calc, FuncExtra *); +Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *); +Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *); +Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bino (valVector args, ValueCalc *calc, FuncExtra *); +Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_combin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *); +Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *); +Value func_covar (valVector args, ValueCalc *calc, FuncExtra *); +Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *); +Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *); +Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *); +Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *); +Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *); +Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *); +Value func_large (valVector args, ValueCalc *calc, FuncExtra *); +Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_median (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mode (valVector args, ValueCalc *calc, FuncExtra *); +Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_phi (valVector args, ValueCalc *calc, FuncExtra *); +Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *); +Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *); +Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *); +Value func_small (valVector args, ValueCalc *calc, FuncExtra *); +Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *); +Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *); +Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *); +Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *); +Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *); +Value func_variance (valVector args, ValueCalc *calc, FuncExtra *); +Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *); +Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *); +Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *); +Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *); + +typedef TQValueList List; + +// registers all statistical functions +void RegisterStatisticalFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("AVEDEV", func_avedev); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("AVERAGE", func_average); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("AVERAGEA", func_averagea); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("BETADIST", func_betadist); + f->setParamCount (3, 5); + repo->add (f); + f = new Function ("BINO", func_bino); + f->setParamCount (3); + repo->add (f); + f = new Function ("CHIDIST", func_chidist); + f->setParamCount (2); + repo->add (f); + f = new Function ("COMBIN", func_combin); + f->setParamCount (2); + repo->add (f); + f = new Function ("CONFIDENCE", func_confidence); + f->setParamCount (3); + repo->add (f); + f = new Function ("CORREL", func_correl_pop); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("COVAR", func_covar); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DEVSQ", func_devsq); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DEVSQA", func_devsqa); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("EXPONDIST", func_expondist); + f->setParamCount (3); + repo->add (f); + f = new Function ("FDIST", func_fdist); + f->setParamCount (3); + repo->add (f); + f = new Function ("FISHER", func_fisher); + repo->add (f); + f = new Function ("FISHERINV", func_fisherinv); + repo->add (f); + f = new Function ("GAMMADIST", func_gammadist); + f->setParamCount (4); + repo->add (f); + f = new Function ("GAMMALN", func_gammaln); + repo->add (f); + f = new Function ("GAUSS", func_gauss); + repo->add (f); + f = new Function ("GEOMEAN", func_geomean); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("HARMEAN", func_harmean); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("HYPGEOMDIST", func_hypgeomdist); + f->setParamCount (4); + repo->add (f); + f = new Function ("INVBINO", func_bino); // same as BINO, for 1.4 compat + repo->add (f); + f = new Function ("KURT", func_kurtosis_est); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("KURTP", func_kurtosis_pop); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("LARGE", func_large); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("LOGINV", func_loginv); + f->setParamCount (3); + repo->add (f); + f = new Function ("LOGNORMDIST", func_lognormdist); + f->setParamCount (3); + repo->add (f); + f = new Function ("MEDIAN", func_median); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("MODE", func_mode); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("NEGBINOMDIST", func_negbinomdist); + f->setParamCount (3); + repo->add (f); + f = new Function ("NORMDIST", func_normdist); + f->setParamCount (4); + repo->add (f); + f = new Function ("NORMINV", func_norminv); + f->setParamCount (3); + repo->add (f); + f = new Function ("NORMSDIST", func_stdnormdist); + repo->add (f); + f = new Function ("NORMSINV", func_normsinv); + repo->add (f); + f = new Function ("PEARSON", func_correl_pop); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("PERMUT", func_arrang); + f->setParamCount (2); + repo->add (f); + f = new Function ("PHI", func_phi); + repo->add (f); + f = new Function ("POISSON", func_poisson); + f->setParamCount (3); + repo->add (f); + f = new Function ("SKEW", func_skew_est); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SKEWP", func_skew_pop); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SMALL", func_small); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("STANDARDIZE", func_standardize); + f->setParamCount (3); + repo->add (f); + f = new Function ("STDEV", func_stddev); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("STDEVA", func_stddeva); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("STDEVP", func_stddevp); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("STDEVPA", func_stddevpa); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUM2XMY", func_sumxmy2); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUMPRODUCT", func_sumproduct); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUMX2PY2", func_sumx2py2); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("SUMX2MY2", func_sumx2my2); + f->setParamCount (2); + f->setAcceptArray (); + repo->add (f); + f = new Function ("TDIST", func_tdist); + f->setParamCount (3); + repo->add (f); + f = new Function ("VARIANCE", func_variance); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("VAR", func_variance); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("VARP", func_variancep); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("VARA", func_variancea); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("VARPA", func_variancepa); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("WEIBULL", func_weibull); + f->setParamCount (4); + repo->add (f); +} + +// array-walk functions used in this file + +void awSkew (ValueCalc *c, Value &res, Value val, Value p) +{ + Value avg = p.element (0, 0); + Value stdev = p.element (1, 0); + // (val - avg) / stddev + Value d = c->div (c->sub (val, avg), stdev); + // res += d*d*d + res = c->add (res, c->mul (d, c->mul (d, d))); +} + +void awSumInv (ValueCalc *c, Value &res, Value val, Value) +{ + // res += 1/value + res = c->add (res, c->div (1.0, val)); +} + +void awAveDev (ValueCalc *c, Value &res, Value val, + Value p) +{ + // res += abs (val - p) + res = c->add (res, c->abs (c->sub (val, p))); +} + +void awKurtosis (ValueCalc *c, Value &res, Value val, + Value p) +{ + Value avg = p.element (0, 0); + Value stdev = p.element (1, 0); + //d = (val - avg ) / stdev + Value d = c->div (c->sub (val, avg), stdev); + // res += d^4 + res = c->add (res, c->pow (d, 4)); +} + + +Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *) +{ + int number = calc->count (args); + Value avg = calc->avg (args); + if (number < 3) + return Value::errorVALUE(); + + Value res = calc->stddev (args, avg); + if (res.isZero()) + return Value::errorVALUE(); + + Value params (2, 1); + params.setElement (0, 0, avg); + params.setElement (1, 0, res); + Value tskew; + calc->arrayWalk (args, tskew, awSkew, params); + + // ((tskew * number) / (number-1)) / (number-2) + return calc->div (calc->div (calc->mul (tskew, number), number-1), number-2); +} + +Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *) +{ + int number = calc->count (args); + Value avg = calc->avg (args); + if (number < 1) + return Value::errorVALUE(); + + Value res = calc->stddevP (args, avg); + if (res.isZero()) + return Value::errorVALUE(); + + Value params (2, 1); + params.setElement (0, 0, avg); + params.setElement (1, 0, res); + Value tskew; + calc->arrayWalk (args, tskew, awSkew, params); + + // tskew / number + return calc->div (tskew, number); +} + +class ContentSheet : public TQMap {}; + +void func_mode_helper (Value range, ValueCalc *calc, ContentSheet &sh) +{ + if (!range.isArray()) + { + double d = calc->conv()->asFloat (range).asFloat(); + sh[d]++; + return; + } + + for (unsigned int row = 0; row < range.rows(); ++row) + for (unsigned int col = 0; col < range.columns(); ++col) { + Value v = range.element (col, row); + if (v.isArray()) + func_mode_helper (v, calc, sh); + else { + double d = calc->conv()->asFloat (v).asFloat(); + sh[d]++; + } + } +} + +Value func_mode (valVector args, ValueCalc *calc, FuncExtra *) +{ + // does NOT support anything other than doubles !!! + ContentSheet sh; + for (unsigned int i = 0; i < args.count(); ++i) + func_mode_helper (args[i], calc, sh); + + // retrieve value with max.count + int maxcount = 0; + double max = 0.0; + ContentSheet::iterator it; + for (it = sh.begin(); it != sh.end(); ++it) + if (it.data() > maxcount) { + max = it.key(); + maxcount = it.data(); + } + return Value (max); +} + +Value func_covar_helper (Value range1, Value range2, + ValueCalc *calc, Value avg1, Value avg2) +{ + // two arrays -> cannot use arrayWalk + if ((!range1.isArray()) && (!range2.isArray())) + // (v1-E1)*(v2-E2) + return calc->mul (calc->sub (range1, avg1), calc->sub (range2, avg2)); + + int rows = range1.rows(); + int cols = range1.columns(); + int rows2 = range2.rows(); + int cols2 = range2.columns(); + if ((rows != rows2) || (cols != cols2)) + return Value::errorVALUE(); + + Value result = 0.0; + for (int row = 0; row < rows; ++row) + for (int col = 0; col < cols; ++col) { + Value v1 = range1.element (col, row); + Value v2 = range2.element (col, row); + if (v1.isArray() || v2.isArray()) + result = calc->add (result, + func_covar_helper (v1, v2, calc, avg1, avg2)); + else + // result += (v1-E1)*(v2-E2) + result = calc->add (result, calc->mul (calc->sub (v1, avg1), + calc->sub (v2, avg2))); + } + + return result; +} + +Value func_covar (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value avg1 = calc->avg (args[0]); + Value avg2 = calc->avg (args[1]); + int number = calc->count (args[0]); + int number2 = calc->count (args[1]); + + if (number2 <= 0 || number2 != number) + return Value::errorVALUE(); + + Value covar = func_covar_helper (args[0], args[1], calc, avg1, avg2); + return calc->div (covar, number); +} + +Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value covar = func_covar (args, calc, 0); + Value stdevp1 = calc->stddevP (args[0]); + Value stdevp2 = calc->stddevP (args[1]); + + if (calc->isZero (stdevp1) || calc->isZero (stdevp2)) + return Value::errorDIV0(); + + // covar / (stdevp1 * stdevp2) + return calc->div (covar, calc->mul (stdevp1, stdevp2)); +} + +void func_array_helper (Value range, ValueCalc *calc, + List &array, int &number) +{ + if (!range.isArray()) + { + array << calc->conv()->asFloat (range).asFloat(); + ++number; + return; + } + + for (unsigned int row = 0; row < range.rows(); ++row) + for (unsigned int col = 0; col < range.columns(); ++col) { + Value v = range.element (col, row); + if (v.isArray ()) + func_array_helper (v, calc, array, number); + else { + array << calc->conv()->asFloat (v).asFloat(); + ++number; + } + } +} + +Value func_large (valVector args, ValueCalc *calc, FuncExtra *) +{ + // does NOT support anything other than doubles !!! + int k = calc->conv()->asInteger (args[1]).asInteger(); + if ( k < 1 ) + return false; + + List array; + int number = 1; + + func_array_helper (args[0], calc, array, number); + + if ( k > number ) + return Value::errorVALUE(); + + qHeapSort (array); + double d = *array.at (number - k - 1); + return Value (d); +} + +Value func_small (valVector args, ValueCalc *calc, FuncExtra *) +{ + // does NOT support anything other than doubles !!! + int k = calc->conv()->asInteger (args[1]).asInteger(); + if ( k < 1 ) + return false; + + List array; + int number = 1; + + func_array_helper (args[0], calc, array, number); + + if ( k > number ) + return Value::errorVALUE(); + + qHeapSort (array); + double d = *array.at (k - 1); + return Value (d); +} + +Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value count = calc->count (args); + Value prod = calc->product (args, 1.0); + if (calc->isZero (count)) + return Value::errorDIV0(); + return calc->pow (prod, calc->div (1.0, count)); +} + +Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value count = calc->count (args); + if (calc->isZero (count)) + return Value::errorDIV0(); + Value suminv; + calc->arrayWalk (args, suminv, awSumInv, 0); + return calc->div (suminv, count); +} + +Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value p = args[0]; + Value m = args[1]; + Value s = args[2]; + + if (calc->lower (p, 0) || calc->greater (p, 1)) + return Value::errorVALUE(); + + if (!calc->greater (s, 0)) + return Value::errorVALUE(); + + Value result = 0.0; + if (calc->equal (p, 1)) //p==1 + result = Value::errorVALUE(); + else if (calc->greater (p, 0)) { //p>0 + Value gaussInv = calc->gaussinv (p); + // exp (gaussInv * s + m) + result = calc->exp (calc->add (calc->mul (s, gaussInv), m)); + } + + return result; +} + +Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value res; + calc->arrayWalk (args, res, calc->awFunc ("devsq"), calc->avg (args, false)); + return res; +} + +Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value res; + calc->arrayWalk (args, res, calc->awFunc ("devsqa"), calc->avg (args)); + return res; +} + +Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args); + if (count < 4) + return Value::errorVALUE(); + + Value avg = calc->avg (args); + Value devsq; + calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg); + + if (devsq.isZero ()) + return Value::errorDIV0(); + + Value params (2, 1); + params.setElement (0, 0, avg); + params.setElement (1, 0, devsq); + Value x4; + calc->arrayWalk (args, x4, awKurtosis, params); + + double den = (double) (count - 2) * (count - 3); + double nth = (double) count * (count + 1) / ((count - 1) * den); + double t = 3.0 * (count - 1) * (count - 1) / den; + + // res = x4 * nth - t + return calc->sub (calc->mul (x4, nth), t); +} + +Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args); + if (count < 4) + return Value::errorVALUE(); + + Value avg = calc->avg (args); + Value devsq; + calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg); + + if (devsq.isZero ()) + return Value::errorDIV0(); + + Value params (2, 1); + params.setElement (0, 0, avg); + params.setElement (1, 0, devsq); + Value x4; + calc->arrayWalk (args, x4, awKurtosis, params); + + // x4 / count - 3 + return calc->sub (calc->div (x4, count), 3); +} + +Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value m = args[1]; + Value s = args[2]; + + if (!calc->greater (s, 0)) // s must be >0 + return Value::errorVALUE(); + + // (x - m) / s + return calc->div (calc->sub (x, m), s); +} + +Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *) +{ + int x = calc->conv()->asInteger (args[0]).asInteger(); + int n = calc->conv()->asInteger (args[1]).asInteger(); + int M = calc->conv()->asInteger (args[2]).asInteger(); + int N = calc->conv()->asInteger (args[3]).asInteger(); + + if ( x < 0 || n < 0 || M < 0 || N < 0 ) + return Value::errorVALUE(); + + if ( x > M || n > N ) + return Value::errorVALUE(); + + Value d1 = calc->combin (M, x); + Value d2 = calc->combin (N - M, n - x); + Value d3 = calc->combin (N, n); + + // d1 * d2 / d3 + return calc->div (calc->mul (d1, d2), d3); +} + +Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *) +{ + int x = calc->conv()->asInteger (args[0]).asInteger(); + int r = calc->conv()->asInteger (args[1]).asInteger(); + Value p = args[2]; + + if ((x + r - 1) <= 0) + return Value::errorVALUE(); + if (calc->lower (p, 0) || calc->greater (p, 1)) + return Value::errorVALUE(); + + Value d1 = calc->combin (x + r - 1, r - 1); + // d2 = pow (p, r) * pow (1 - p, x) + Value d2 = calc->mul (calc->pow (p, r), + calc->pow (calc->sub (1, p), x)); + + return calc->mul (d1, d2); +} + +// Function: permut +Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value n = args[0]; + Value m = args[1]; + if (calc->lower (n, m)) // problem if nlower (m, 0)) // problem if m<0 (n>=m so that's okay) + return Value::errorVALUE(); + + // fact(n) / (fact(n-m) + return calc->fact (n, calc->sub (n, m)); +} + +// Function: average +Value func_average (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->avg (args, false); +} + +// Function: averagea +Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->avg (args); +} + +// Function: avedev +Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awAveDev, calc->avg (args)); + return result; +} + +// Function: median +Value func_median (valVector args, ValueCalc *calc, FuncExtra *) +{ + // does NOT support anything other than doubles !!! + List array; + int number = 1; + + for (unsigned int i = 0; i < args.count(); ++i) + func_array_helper (args[i], calc, array, number); + + qHeapSort (array); + double d = *array.at (number / 2 + number % 2); + return Value (d); +} + +// Function: variance +Value func_variance (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args, false); + if (count < 2) + return Value::errorVALUE(); + + Value result = func_devsq (args, calc, 0); + return calc->div (result, count-1); +} + +// Function: vara +Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args); + if (count < 2) + return Value::errorVALUE(); + + Value result = func_devsqa (args, calc, 0); + return calc->div (result, count-1); +} + +// Function: varp +Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args, false); + if (count == 0) + return Value::errorVALUE(); + + Value result = func_devsq (args, calc, 0); + return calc->div (result, count); +} + +// Function: varpa +Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *) +{ + int count = calc->count (args); + if (count == 0) + return Value::errorVALUE(); + + Value result = func_devsqa (args, calc, 0); + return calc->div (result, count); +} + +// Function: stddev +Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->stddev (args, false); +} + +// Function: stddeva +Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->stddev (args); +} + +// Function: stddevp +Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->stddevP (args, false); +} + +// Function: stddevpa +Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->stddevP (args); +} + +// Function: combin +Value func_combin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->combin (args[0], args[1]); +} + +// Function: bino +Value func_bino (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value n = args[0]; + Value m = args[1]; + Value comb = calc->combin (n, m); + Value prob = args[2]; + + if (calc->lower (prob,0) || calc->greater (prob,1)) + return Value::errorVALUE(); + + // result = comb * pow (prob, m) * pow (1 - prob, n - m) + Value pow1 = calc->pow (prob, m); + Value pow2 = calc->pow (calc->sub (1, prob), calc->sub (n, m)); + return calc->mul (comb, calc->mul (pow1, pow2)); +} + +// Function: phi +Value func_phi (valVector args, ValueCalc *calc, FuncExtra *) +//distribution function for a standard normal distribution +{ + return calc->phi (args[0]); +} + +// Function: gauss +Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *) +{ + //returns the integral values of the standard normal cumulative distribution + return calc->gauss (args[0]); +} + +// Function: gammadist +Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value alpha = args[1]; + Value beta = args[2]; + int kum = calc->conv()->asInteger (args[3]).asInteger(); // 0 or 1 + + Value result; + + if (calc->lower (x, 0.0) || (!calc->greater (alpha, 0.0)) || + (!calc->greater (beta, 0.0))) + return Value::errorVALUE(); + + if (kum == 0) { //density + Value G = calc->GetGamma (alpha); + // result = pow (x, alpha - 1.0) / exp (x / beta) / pow (beta, alpha) / G + Value pow1 = calc->pow (x, calc->sub (alpha, 1.0)); + Value pow2 = calc->exp (calc->div (x, beta)); + Value pow3 = calc->pow (beta, alpha); + result = calc->div (calc->div (calc->div (pow1, pow2), pow3), G); + } + else + result = calc->GetGammaDist (x, alpha, beta); + + return Value (result); +} + +// Function: betadist +Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value alpha = args[1]; + Value beta = args[2]; + + Value fA = 0.0; + Value fB = 1.0; + if (args.count() > 3) fA = args[3]; + if (args.count() == 5) fB = args[4]; + + //x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0 + if (calc->lower (x, fA) || calc->greater (x, fB) || calc->equal (fA, fB) || + (!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0))) + return Value::errorVALUE(); + + // xx = (x - fA) / (fB - fA) // scaling + Value xx = calc->div (calc->sub (x, fA), calc->sub (fB, fA)); + + return calc->GetBeta (xx, alpha, beta); +} + +// Function: fisher +Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the Fisher transformation for x + + // 0.5 * ln ((1.0 + fVal) / (1.0 - fVal)) + Value fVal = args[0]; + Value num = calc->div (calc->add (fVal, 1.0), calc->sub (1.0, fVal)); + return calc->mul (calc->ln (num), 0.5); +} + +// Function: fisherinv +Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the inverse of the Fisher transformation for x + + Value fVal = args[0]; + // (exp (2.0 * fVal) - 1.0) / (exp (2.0 * fVal) + 1.0) + Value ex = calc->exp (calc->mul (fVal, 2.0)); + return calc->div (calc->sub (ex, 1.0), calc->add (ex, 1.0)); +} + +// Function: normdist +Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the normal cumulative distribution + Value x = args[0]; + Value mue = args[1]; + Value sigma = args[2]; + Value k = args[3]; + + if (!calc->greater (sigma, 0.0)) + return Value::errorVALUE(); + + // (x - mue) / sigma + Value Y = calc->div (calc->sub (x, mue), sigma); + if (calc->isZero (k)) // density + return calc->div (calc->phi (Y), sigma); + else // distribution + return calc->add (calc->gauss (Y), 0.5); +} + +// Function: lognormdist +Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the cumulative lognormal distribution + Value x = args[0]; + Value mue = args[1]; + Value sigma = args[2]; + + if (!calc->greater (sigma, 0.0) || (!calc->greater (x, 0.0))) + return Value::errorVALUE(); + + // (ln(x) - mue) / sigma + Value Y = calc->div (calc->sub (calc->ln (x), mue), sigma); + return calc->add (calc->gauss (Y), 0.5); +} + +// Function: normsdist +Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *) +{ + //returns the cumulative lognormal distribution, mue=0, sigma=1 + return calc->add (calc->gauss (args[0]), 0.5); +} + +// Function: expondist +Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the exponential distribution + Value x = args[0]; + Value lambda = args[1]; + Value kum = args[2]; + + Value result = 0.0; + + if (!calc->greater (lambda, 0.0)) + return Value::errorVALUE(); + + // ex = exp (-lambda * x) + Value ex = calc->exp (calc->mul (calc->mul (lambda, -1), x)); + if (calc->isZero (kum)) { //density + if (!calc->lower (x, 0.0)) + // lambda * ex + result = calc->mul (lambda, ex); + } + else { //distribution + if (calc->greater (x, 0.0)) + // 1.0 - ex + result = calc->sub (1.0, ex); + } + return result; +} + +// Function: weibull +Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the Weibull distribution + + Value x = args[0]; + Value alpha = args[1]; + Value beta = args[2]; + Value kum = args[3]; + + Value result; + + if ((!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0)) || + calc->lower (x, 0.0)) + return Value::errorVALUE(); + + // ex = exp (-pow (x / beta, alpha)) + Value ex; + ex = calc->exp (calc->mul (calc->pow (calc->div (x, beta), alpha), -1)); + if (calc->isZero (kum)) // density + { + // result = alpha / pow(beta,alpha) * pow(x,alpha-1.0) * ex + result = calc->div (alpha, calc->pow (beta, alpha)); + result = calc->mul (result, calc->mul (calc->pow (x, + calc->sub (alpha, 1)), ex)); + } + else // distribution + result = calc->sub (1.0, ex); + + return result; +} + +// Function: normsinv +Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the inverse of the standard normal cumulative distribution + + Value x = args[0]; + if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0))) + return Value::errorVALUE(); + + return calc->gaussinv (x); +} + +// Function: norminv +Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the inverse of the normal cumulative distribution + Value x = args[0]; + Value mue = args[1]; + Value sigma = args[2]; + + if (!calc->greater (sigma, 0.0)) + return Value::errorVALUE(); + if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0))) + return Value::errorVALUE(); + + // gaussinv (x)*sigma + mue + return calc->add (calc->mul (calc->gaussinv (x), sigma), mue); +} + +// Function: gammaln +Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the natural logarithm of the gamma function + + if (calc->greater (args[0], 0.0)) + return calc->GetLogGamma (args[0]); + return Value::errorVALUE(); +} + +// Function: poisson +Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the Poisson distribution + + Value x = args[0]; + Value lambda = args[1]; + Value kum = args[2]; + + // lambda < 0.0 || x < 0.0 + if (calc->lower (lambda, 0.0) || calc->lower (x, 0.0)) + return Value::errorVALUE(); + + Value result; + + // ex = exp (-lambda) + Value ex = calc->exp (calc->mul (lambda, -1)); + + if (calc->isZero (kum)) { // density + if (calc->isZero (lambda)) + result = 0; + else + // ex * pow (lambda, x) / fact (x) + result = calc->div (calc->mul (ex, calc->pow (lambda, x)), calc->fact (x)); + } + else { // distribution + if (calc->isZero (lambda)) + result = 1; + else + { + result = 1.0; + Value fFak = 1.0; + unsigned long nEnd = calc->conv()->asInteger (x).asInteger(); + for (unsigned long i = 1; i <= nEnd; i++) + { + // fFak *= i + fFak = calc->mul (fFak, i); + // result += pow (lambda, i) / fFak + result = calc->add (result, calc->div (calc->pow (lambda, i), fFak)); + } + result = calc->mul (result, ex); + } + } + + return result; +} + +// Function: confidence +Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the confidence interval for a population mean + Value alpha = args[0]; + Value sigma = args[1]; + Value n = args[2]; + + // sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1 + if ((!calc->greater (sigma, 0.0)) || (!calc->greater (alpha, 0.0)) || + (!calc->lower (alpha, 1.0)) || calc->lower (n, 1)) + return Value::errorVALUE(); + + // g = gaussinv (1.0 - alpha / 2.0) + Value g = calc->gaussinv (calc->sub (1.0, calc->div (alpha, 2.0))); + // g * sigma / sqrt (n) + return calc->div (calc->mul (g, sigma), calc->sqrt (n)); +} + +// Function: tdist +Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the t-distribution + + Value T = args[0]; + Value fDF = args[1]; + int flag = calc->conv()->asInteger (args[2]).asInteger(); + + if (calc->lower (fDF, 1) || calc->lower (T, 0.0) || (flag != 1 && flag != 2)) + return Value::errorVALUE(); + + // arg = fDF / (fDF + T * T) + Value arg = calc->div (fDF, calc->add (fDF, calc->sqr (T))); + + Value R; + R = calc->mul (calc->GetBeta (arg, calc->div (fDF, 2.0), 0.5), 0.5); + + if (flag == 1) + return R; + return calc->mul (R, 2); // flag is 2 here +} + +// Function: fdist +Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the f-distribution + + Value x = args[0]; + Value fF1 = args[1]; + Value fF2 = args[2]; + + // x < 0.0 || fF1 < 1 || fF2 < 1 || fF1 >= 1.0E10 || fF2 >= 1.0E10 + if (calc->lower (x, 0.0) || calc->lower (fF1, 1) || calc->lower (fF2, 1) || + (!calc->lower (fF1, 1.0E10)) || (!calc->lower (fF2, 1.0E10))) + return Value::errorVALUE(); + + // arg = fF2 / (fF2 + fF1 * x) + Value arg = calc->div (fF2, calc->add (fF2, calc->mul (fF1, x))); + // alpha = fF2/2.0 + Value alpha = calc->div (fF2, 2.0); + // beta = fF1/2.0 + Value beta = calc->div (fF1, 2.0); + return calc->GetBeta (arg, alpha, beta); +} + +// Function: chidist +Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *) { + //returns the chi-distribution + + Value fChi = args[0]; + Value fDF = args[1]; + + // fDF < 1 || fDF >= 1.0E5 || fChi < 0.0 + if (calc->lower (fDF, 1) || (!calc->lower (fDF, 1.0E5)) || + calc->lower (fChi, 0.0)) + return Value::errorVALUE(); + + // 1.0 - GetGammaDist (fChi / 2.0, fDF / 2.0, 1.0) + return calc->sub (1.0, calc->GetGammaDist (calc->div (fChi, 2.0), + calc->div (fDF, 2.0), 1.0)); +} + + +// two-array-walk functions used in the two-sum functions + +void tawSumproduct (ValueCalc *c, Value &res, Value v1, + Value v2) { + // res += v1*v2 + res = c->add (res, c->mul (v1, v2)); +} + +void tawSumx2py2 (ValueCalc *c, Value &res, Value v1, + Value v2) { + // res += sqr(v1)+sqr(v2) + res = c->add (res, c->add (c->sqr (v1), c->sqr (v2))); +} + +void tawSumx2my2 (ValueCalc *c, Value &res, Value v1, + Value v2) { + // res += sqr(v1)-sqr(v2) + res = c->add (res, c->sub (c->sqr (v1), c->sqr (v2))); +} + +void tawSumxmy2 (ValueCalc *c, Value &res, Value v1, + Value v2) { + // res += sqr(v1-v2) + res = c->add (res, c->sqr (c->sub (v1, v2))); + +} + +// Function: sumproduct +Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->twoArrayWalk (args[0], args[1], result, tawSumproduct); + return result; +} + +// Function: sumx2py2 +Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->twoArrayWalk (args[0], args[1], result, tawSumx2py2); + return result; +} + +// Function: sumx2my2 +Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->twoArrayWalk (args[0], args[1], result, tawSumx2my2); + return result; +} + +// Function: sum2xmy +Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->twoArrayWalk (args[0], args[1], result, tawSumxmy2); + return result; +} diff --git a/kspread/kspread_functions_text.cc b/kspread/kspread_functions_text.cc deleted file mode 100644 index 5a8dccf6..00000000 --- a/kspread/kspread_functions_text.cc +++ /dev/null @@ -1,636 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - - -// built-in text functions -// please keep it in alphabetical order - -#include -#include -#include -#include - -#include "functions.h" -#include "valuecalc.h" -#include "valueconverter.h" - -using namespace KSpread; - -// Functions DOLLAR and FIXED convert data to double, hence they will not -// support arbitrary precision, when it will be introduced. - -// prototypes -Value func_char (valVector args, ValueCalc *calc, FuncExtra *); -Value func_clean (valVector args, ValueCalc *calc, FuncExtra *); -Value func_code (valVector args, ValueCalc *calc, FuncExtra *); -Value func_compare (valVector args, ValueCalc *calc, FuncExtra *); -Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *); -Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *); -Value func_exact (valVector args, ValueCalc *calc, FuncExtra *); -Value func_find (valVector args, ValueCalc *calc, FuncExtra *); -Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *); -Value func_left (valVector args, ValueCalc *calc, FuncExtra *); -Value func_len (valVector args, ValueCalc *calc, FuncExtra *); -Value func_lower (valVector args, ValueCalc *calc, FuncExtra *); -Value func_mid (valVector args, ValueCalc *calc, FuncExtra *); -Value func_proper (valVector args, ValueCalc *calc, FuncExtra *); -Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *); -Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *); -Value func_replace (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rept (valVector args, ValueCalc *calc, FuncExtra *); -Value func_rot (valVector args, ValueCalc *calc, FuncExtra *); -Value func_right (valVector args, ValueCalc *calc, FuncExtra *); -Value func_search (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *); -Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *); -Value func_t (valVector args, ValueCalc *calc, FuncExtra *); -Value func_text (valVector args, ValueCalc *calc, FuncExtra *); -Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *); -Value func_trim (valVector args, ValueCalc *calc, FuncExtra *); -Value func_upper (valVector args, ValueCalc *calc, FuncExtra *); -Value func_value (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all text functions -void RegisterTextFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - // one-parameter functions - f = new Function ("CHAR", func_char); - repo->add (f); - f = new Function ("CLEAN", func_clean); - repo->add (f); - f = new Function ("CODE", func_code); - repo->add (f); - f = new Function ("LEN", func_len); - repo->add (f); - f = new Function ("LOWER", func_lower); - repo->add (f); - f = new Function ("PROPER", func_proper); - repo->add (f); - f = new Function ("ROT", func_rot); - repo->add (f); - f = new Function ("SLEEK", func_sleek); - repo->add (f); - f = new Function ("T", func_t); - repo->add (f); - f = new Function ("TOGGLE", func_toggle); - repo->add (f); - f = new Function ("TRIM", func_trim); - repo->add (f); - f = new Function ("UPPER", func_upper); - repo->add (f); - f = new Function ("VALUE", func_value); - repo->add (f); - - // other functions - f = new Function ("COMPARE", func_compare); - f->setParamCount (3); - repo->add (f); - f = new Function ("CONCATENATE", func_concatenate); - f->setParamCount (1, -1); - f->setAcceptArray (); - repo->add (f); - f = new Function ("DOLLAR", func_dollar); - f->setParamCount (1, 2); - repo->add (f); - f = new Function ("EXACT", func_exact); - f->setParamCount (2); - repo->add (f); - f = new Function ("FIND", func_find); - f->setParamCount (2, 3); - repo->add (f); - f = new Function ("FIXED", func_fixed); - f->setParamCount (1, 3); - repo->add (f); - f = new Function ("LEFT", func_left); - f->setParamCount (2); - repo->add (f); - f = new Function ("MID", func_mid); - f->setParamCount (2, 3); - repo->add (f); - f = new Function ("REGEXP", func_regexp); - f->setParamCount (2, 4); - repo->add (f); - f = new Function ("REGEXPRE", func_regexpre); - f->setParamCount (3); - repo->add (f); - f = new Function ("REPLACE", func_replace); - f->setParamCount (4); - repo->add (f); - f = new Function ("REPT", func_rept); - f->setParamCount (2); - repo->add (f); - f = new Function ("RIGHT", func_right); - f->setParamCount (2); - repo->add (f); - f = new Function ("SEARCH", func_search); - f->setParamCount (2, 3); - repo->add (f); - f = new Function ("SUBSTITUTE", func_substitute); - f->setParamCount (3, 4); - repo->add (f); - f = new Function ("TEXT", func_text); - f->setParamCount (1, 2); - repo->add (f); -} - - -// Function: CHAR -Value func_char (valVector args, ValueCalc *calc, FuncExtra *) -{ - int val = calc->conv()->asInteger (args[0]).asInteger (); - return Value (TQString (TQChar (val))); -} - -// Function: CLEAN -Value func_clean (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str (calc->conv()->asString (args[0]).asString()); - TQString result; - TQChar c; - int i; - int l = str.length(); - - for (i = 0; i < l; ++i) - { - c = str[i]; - if (c.isPrint()) - result += c; - } - - return Value (result); -} - -// Function: CODE -Value func_code (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str (calc->conv()->asString (args[0]).asString()); - if (str.length() <= 0) - return Value::errorVALUE(); - - return Value (str[0].unicode()); -} - -// Function: COMPARE -Value func_compare (valVector args, ValueCalc *calc, FuncExtra *) -{ - int result = 0; - bool exact = calc->conv()->asBoolean (args[2]).asBoolean(); - - TQString s1 = calc->conv()->asString (args[0]).asString(); - TQString s2 = calc->conv()->asString (args[1]).asString(); - - if (!exact) - result = s1.lower().localeAwareCompare(s2.lower()); - else - result = s1.localeAwareCompare(s2); - - if (result < 0) - result = -1; - else if (result > 0) - result = 1; - - return Value (result); -} - -void func_concatenate_helper (Value val, ValueCalc *calc, - TQString& tmp) -{ - if (val.isArray()) { - for (unsigned int row = 0; row < val.rows(); ++row) - for (unsigned int col = 0; col < val.columns(); ++col) - func_concatenate_helper (val.element (col, row), calc, tmp); - } else - tmp += calc->conv()->asString (val).asString(); -} - -// Function: CONCATENATE -Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString tmp; - for (unsigned int i = 0; i < args.count(); ++i) - func_concatenate_helper (args[i], calc, tmp); - - return Value (tmp); -} - -// Function: DOLLAR -Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *) -{ - // ValueConverter doesn't support money directly, hence we need to - // use the locale. This code has the same effect as the output - // of ValueFormatter for money format. - - // This function converts data to double/int, hence it won't support - // larger precision. - - double value = calc->conv()->asFloat (args[0]).asFloat(); - int precision = 2; - if (args.count() == 2) - precision = calc->conv()->asInteger (args[1]).asInteger(); - - // do round, because formatMoney doesn't - value = floor (value * pow (10.0, precision) + 0.5) / pow (10.0, precision); - - TDELocale *locale = calc->conv()->locale(); - TQString s = locale->formatMoney (value, locale->currencySymbol(), precision); - - return Value (s); -} - -// Function: EXACT -Value func_exact (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString s1 = calc->conv()->asString (args[0]).asString(); - TQString s2 = calc->conv()->asString (args[1]).asString(); - bool exact = (s1 == s2); - return Value (exact); -} - -// Function: FIND -Value func_find (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString find_text, within_text; - int start_num = 1; - - find_text = calc->conv()->asString (args[0]).asString(); - within_text = calc->conv()->asString (args[1]).asString(); - if (args.count() == 3) - start_num = calc->conv()->asInteger (args[2]).asInteger(); - - // conforms to Excel behaviour - if (start_num <= 0) return Value::errorVALUE(); - if (start_num > (int)within_text.length()) return Value::errorVALUE(); - - int pos = within_text.find (find_text, start_num - 1); - if( pos < 0 ) return Value::errorNA(); - - return Value (pos + 1); -} - -// Function: FIXED -Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *) -{ - // uses double, hence won't support big precision - - int decimals = 2; - bool no_commas = false; - - double number = calc->conv()->asFloat (args[0]).asFloat(); - if (args.count() > 1) - decimals = calc->conv()->asInteger (args[1]).asInteger(); - if (args.count() == 3) - no_commas = calc->conv()->asBoolean (args[2]).asBoolean(); - - TQString result; - TDELocale *locale = calc->conv()->locale(); - - // unfortunately, we can't just use TDELocale::formatNumber because - // * if decimals < 0, number is rounded - // * if no_commas is true, thousand separators shouldn't show up - - if( decimals < 0 ) - { - decimals = -decimals; - number = floor( number/pow(10.0,decimals)+0.5 ) * pow(10.0,decimals); - decimals = 0; - } - - bool neg = number < 0; - result = TQString::number( neg ? -number:number, 'f', decimals ); - - int pos = result.find('.'); - if (pos == -1) pos = result.length(); - else result.replace(pos, 1, locale->decimalSymbol()); - if( !no_commas ) - while (0 < (pos -= 3)) - result.insert(pos, locale->thousandsSeparator()); - - result.prepend( neg ? locale->negativeSign(): - locale->positiveSign() ); - - return Value (result); -} - -// Function: LEFT -Value func_left (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString(); - int nb = 1; - if (args.count() == 2) - nb = calc->conv()->asInteger (args[1]).asInteger(); - - return Value (str.left (nb)); -} - -// Function: LEN -Value func_len (valVector args, ValueCalc *calc, FuncExtra *) -{ - int nb = calc->conv()->asString (args[0]).asString().length(); - return Value (nb); -} - -// Function: LOWER -Value func_lower (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->conv()->asString (args[0]).asString().lower()); -} - -// Function: MID -Value func_mid (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString(); - int pos = calc->conv()->asInteger (args[1]).asInteger(); - uint len = 0xffffffff; - if (args.count() == 3) - len = (uint) calc->conv()->asInteger (args[2]).asInteger(); - - // Excel compatible - pos--; - - return Value (str.mid (pos, len)); -} - -// Function: PROPER -Value func_proper (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString().lower(); - - TQChar f; - bool first = true; - - for (unsigned int i = 0; i < str.length(); ++i) - { - if (first) - { - f = str[i]; - if (f.isNumber()) - continue; - - f = f.upper(); - - str[i] = f; - first = false; - - continue; - } - - if (str[i] == ' ' || str[i] == '-') - first = true; - } - - return Value (str); -} - -// Function: REGEXP -Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *) -{ - // ensure that we got a valid regular expression - TQRegExp exp (calc->conv()->asString (args[1]).asString()); - if (!exp.isValid ()) - return Value::errorVALUE(); - - TQString s = calc->conv()->asString (args[0]).asString(); - TQString defText; - if (args.count() > 2) - defText = calc->conv()->asString (args[2]).asString(); - int bkref = 0; - if (args.count() == 4) - bkref = calc->conv()->asInteger (args[3]).asInteger(); - if (bkref < 0) // strange back-reference - return Value::errorVALUE(); - - TQString returnValue; - - int pos = exp.search (s); - if (pos == -1) - returnValue = defText; - else - returnValue = exp.cap (bkref); - - return Value (returnValue); -} - -// Function: REGEXPRE -Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *) -{ - // ensure that we got a valid regular expression - TQRegExp exp (calc->conv()->asString (args[1]).asString()); - if (!exp.isValid ()) - return Value::errorVALUE(); - - TQString s = calc->conv()->asString (args[0]).asString(); - TQString str = calc->conv()->asString (args[2]).asString(); - - int pos = 0; - while ((pos = exp.search (s, pos)) != -1) - { - int i = exp.matchedLength(); - s = s.replace (pos, i, str); - pos += str.length(); - } - - return Value (s); -} - -// Function: REPLACE -Value func_replace (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString text = calc->conv()->asString (args[0]).asString(); - int pos = calc->conv()->asInteger (args[1]).asInteger(); - int len = calc->conv()->asInteger (args[2]).asInteger(); - TQString new_text = calc->conv()->asString (args[3]).asString(); - - if (pos < 0) pos = 0; - - TQString result = text.replace (pos-1, len, new_text); - return Value (result); -} - -// Function: REPT -Value func_rept (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString s = calc->conv()->asString (args[0]).asString(); - int nb = calc->conv()->asInteger (args[1]).asInteger(); - - TQString result; - for (int i = 0; i < nb; i++) result += s; - return Value (result); -} - -// Function: RIGHT -Value func_right (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString(); - int nb = 1; - if (args.count() == 2) - nb = calc->conv()->asInteger (args[1]).asInteger(); - - return Value (str.right (nb)); -} - -// Function: ROT -Value func_rot (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString text = calc->conv()->asString (args[0]).asString(); - - for( unsigned i=0; i= 'A' ) && ( c <= 'M' ) ) - text[i] = TQChar( text[i].unicode() + 13); - if( ( c >= 'N' ) && ( c <= 'Z' ) ) - text[i] = TQChar( text[i].unicode() - 13); - } - - return Value (text); -} - -// Function: SEARCH -Value func_search (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString find_text = calc->conv()->asString (args[0]).asString(); - TQString within_text = calc->conv()->asString (args[1]).asString(); - int start_num = 1; - if (args.count() == 3) - start_num = calc->conv()->asInteger (args[2]).asInteger(); - - // conforms to Excel behaviour - if (start_num <= 0) return Value::errorVALUE(); - if (start_num > (int)within_text.length()) return Value::errorVALUE(); - - // use globbing feature of TQRegExp - TQRegExp regex( find_text, false, true ); - int pos = within_text.find( regex, start_num-1 ); - if( pos < 0 ) return Value::errorNA(); - - return Value (pos + 1); -} - -// Function: SLEEK -Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString(); - TQString result; - TQChar c; - int i; - int l = str.length(); - - for (i = 0; i < l; ++i) - { - c = str[i]; - if (!c.isSpace()) - result += c; - } - - return Value (result); -} - -// Function: SUBSTITUTE -Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *) -{ - int num = 1; - bool all = true; - - if (args.count() == 4) - { - num = calc->conv()->asInteger (args[3]).asInteger(); - all = false; - } - - TQString text = calc->conv()->asString (args[0]).asString(); - TQString old_text = calc->conv()->asString (args[1]).asString(); - TQString new_text = calc->conv()->asString (args[2]).asString(); - - if( num <= 0 ) return Value::errorVALUE(); - if (old_text.length() == 0) return Value (text); - - TQString result = text; - - int p = result.find (old_text); - while ((p != -1) && (num > 0)) - { - result.replace( p, old_text.length(), new_text ); - // find another location, starting straight after the replaced text - p = result.find (old_text, p + new_text.length()); - if( !all ) num--; - } - - return Value (result); -} - -// Function: T -Value func_t (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->conv()->asString (args[0]); -} - -// Function: TEXT -Value func_text (valVector args, ValueCalc *calc, FuncExtra *) -{ - //Currently the same as the T function ... - //Second parameter is format_text. It is currently ignored. - return calc->conv()->asString (args[0]); -} - -// Function: TOGGLE -Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *) -{ - TQString str = calc->conv()->asString (args[0]).asString(); - int i; - int l = str.length(); - - for (i = 0; i < l; ++i) - { - TQChar c = str[i]; - TQChar lc = c.lower(); - TQChar uc = c.upper(); - - if (c == lc) // it is in lowercase - str[i] = c.upper(); - else if (c == uc) // it is in uppercase - str[i] = c.lower(); - } - - return Value (str); -} - -// Function: TRIM -Value func_trim (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value ( - calc->conv()->asString (args[0]).asString().simplifyWhiteSpace()); -} - -// Function: UPPER -Value func_upper (valVector args, ValueCalc *calc, FuncExtra *) -{ - return Value (calc->conv()->asString (args[0]).asString().upper()); -} - -// Function: VALUE -Value func_value (valVector args, ValueCalc *calc, FuncExtra *) -{ - // same as the N function - return calc->conv()->asFloat (args[0]); -} diff --git a/kspread/kspread_functions_text.cpp b/kspread/kspread_functions_text.cpp new file mode 100644 index 00000000..5a8dccf6 --- /dev/null +++ b/kspread/kspread_functions_text.cpp @@ -0,0 +1,636 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +// built-in text functions +// please keep it in alphabetical order + +#include +#include +#include +#include + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +using namespace KSpread; + +// Functions DOLLAR and FIXED convert data to double, hence they will not +// support arbitrary precision, when it will be introduced. + +// prototypes +Value func_char (valVector args, ValueCalc *calc, FuncExtra *); +Value func_clean (valVector args, ValueCalc *calc, FuncExtra *); +Value func_code (valVector args, ValueCalc *calc, FuncExtra *); +Value func_compare (valVector args, ValueCalc *calc, FuncExtra *); +Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *); +Value func_exact (valVector args, ValueCalc *calc, FuncExtra *); +Value func_find (valVector args, ValueCalc *calc, FuncExtra *); +Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *); +Value func_left (valVector args, ValueCalc *calc, FuncExtra *); +Value func_len (valVector args, ValueCalc *calc, FuncExtra *); +Value func_lower (valVector args, ValueCalc *calc, FuncExtra *); +Value func_mid (valVector args, ValueCalc *calc, FuncExtra *); +Value func_proper (valVector args, ValueCalc *calc, FuncExtra *); +Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *); +Value func_replace (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rept (valVector args, ValueCalc *calc, FuncExtra *); +Value func_rot (valVector args, ValueCalc *calc, FuncExtra *); +Value func_right (valVector args, ValueCalc *calc, FuncExtra *); +Value func_search (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *); +Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *); +Value func_t (valVector args, ValueCalc *calc, FuncExtra *); +Value func_text (valVector args, ValueCalc *calc, FuncExtra *); +Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *); +Value func_trim (valVector args, ValueCalc *calc, FuncExtra *); +Value func_upper (valVector args, ValueCalc *calc, FuncExtra *); +Value func_value (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all text functions +void RegisterTextFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + // one-parameter functions + f = new Function ("CHAR", func_char); + repo->add (f); + f = new Function ("CLEAN", func_clean); + repo->add (f); + f = new Function ("CODE", func_code); + repo->add (f); + f = new Function ("LEN", func_len); + repo->add (f); + f = new Function ("LOWER", func_lower); + repo->add (f); + f = new Function ("PROPER", func_proper); + repo->add (f); + f = new Function ("ROT", func_rot); + repo->add (f); + f = new Function ("SLEEK", func_sleek); + repo->add (f); + f = new Function ("T", func_t); + repo->add (f); + f = new Function ("TOGGLE", func_toggle); + repo->add (f); + f = new Function ("TRIM", func_trim); + repo->add (f); + f = new Function ("UPPER", func_upper); + repo->add (f); + f = new Function ("VALUE", func_value); + repo->add (f); + + // other functions + f = new Function ("COMPARE", func_compare); + f->setParamCount (3); + repo->add (f); + f = new Function ("CONCATENATE", func_concatenate); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("DOLLAR", func_dollar); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("EXACT", func_exact); + f->setParamCount (2); + repo->add (f); + f = new Function ("FIND", func_find); + f->setParamCount (2, 3); + repo->add (f); + f = new Function ("FIXED", func_fixed); + f->setParamCount (1, 3); + repo->add (f); + f = new Function ("LEFT", func_left); + f->setParamCount (2); + repo->add (f); + f = new Function ("MID", func_mid); + f->setParamCount (2, 3); + repo->add (f); + f = new Function ("REGEXP", func_regexp); + f->setParamCount (2, 4); + repo->add (f); + f = new Function ("REGEXPRE", func_regexpre); + f->setParamCount (3); + repo->add (f); + f = new Function ("REPLACE", func_replace); + f->setParamCount (4); + repo->add (f); + f = new Function ("REPT", func_rept); + f->setParamCount (2); + repo->add (f); + f = new Function ("RIGHT", func_right); + f->setParamCount (2); + repo->add (f); + f = new Function ("SEARCH", func_search); + f->setParamCount (2, 3); + repo->add (f); + f = new Function ("SUBSTITUTE", func_substitute); + f->setParamCount (3, 4); + repo->add (f); + f = new Function ("TEXT", func_text); + f->setParamCount (1, 2); + repo->add (f); +} + + +// Function: CHAR +Value func_char (valVector args, ValueCalc *calc, FuncExtra *) +{ + int val = calc->conv()->asInteger (args[0]).asInteger (); + return Value (TQString (TQChar (val))); +} + +// Function: CLEAN +Value func_clean (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str (calc->conv()->asString (args[0]).asString()); + TQString result; + TQChar c; + int i; + int l = str.length(); + + for (i = 0; i < l; ++i) + { + c = str[i]; + if (c.isPrint()) + result += c; + } + + return Value (result); +} + +// Function: CODE +Value func_code (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str (calc->conv()->asString (args[0]).asString()); + if (str.length() <= 0) + return Value::errorVALUE(); + + return Value (str[0].unicode()); +} + +// Function: COMPARE +Value func_compare (valVector args, ValueCalc *calc, FuncExtra *) +{ + int result = 0; + bool exact = calc->conv()->asBoolean (args[2]).asBoolean(); + + TQString s1 = calc->conv()->asString (args[0]).asString(); + TQString s2 = calc->conv()->asString (args[1]).asString(); + + if (!exact) + result = s1.lower().localeAwareCompare(s2.lower()); + else + result = s1.localeAwareCompare(s2); + + if (result < 0) + result = -1; + else if (result > 0) + result = 1; + + return Value (result); +} + +void func_concatenate_helper (Value val, ValueCalc *calc, + TQString& tmp) +{ + if (val.isArray()) { + for (unsigned int row = 0; row < val.rows(); ++row) + for (unsigned int col = 0; col < val.columns(); ++col) + func_concatenate_helper (val.element (col, row), calc, tmp); + } else + tmp += calc->conv()->asString (val).asString(); +} + +// Function: CONCATENATE +Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString tmp; + for (unsigned int i = 0; i < args.count(); ++i) + func_concatenate_helper (args[i], calc, tmp); + + return Value (tmp); +} + +// Function: DOLLAR +Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *) +{ + // ValueConverter doesn't support money directly, hence we need to + // use the locale. This code has the same effect as the output + // of ValueFormatter for money format. + + // This function converts data to double/int, hence it won't support + // larger precision. + + double value = calc->conv()->asFloat (args[0]).asFloat(); + int precision = 2; + if (args.count() == 2) + precision = calc->conv()->asInteger (args[1]).asInteger(); + + // do round, because formatMoney doesn't + value = floor (value * pow (10.0, precision) + 0.5) / pow (10.0, precision); + + TDELocale *locale = calc->conv()->locale(); + TQString s = locale->formatMoney (value, locale->currencySymbol(), precision); + + return Value (s); +} + +// Function: EXACT +Value func_exact (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString s1 = calc->conv()->asString (args[0]).asString(); + TQString s2 = calc->conv()->asString (args[1]).asString(); + bool exact = (s1 == s2); + return Value (exact); +} + +// Function: FIND +Value func_find (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString find_text, within_text; + int start_num = 1; + + find_text = calc->conv()->asString (args[0]).asString(); + within_text = calc->conv()->asString (args[1]).asString(); + if (args.count() == 3) + start_num = calc->conv()->asInteger (args[2]).asInteger(); + + // conforms to Excel behaviour + if (start_num <= 0) return Value::errorVALUE(); + if (start_num > (int)within_text.length()) return Value::errorVALUE(); + + int pos = within_text.find (find_text, start_num - 1); + if( pos < 0 ) return Value::errorNA(); + + return Value (pos + 1); +} + +// Function: FIXED +Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *) +{ + // uses double, hence won't support big precision + + int decimals = 2; + bool no_commas = false; + + double number = calc->conv()->asFloat (args[0]).asFloat(); + if (args.count() > 1) + decimals = calc->conv()->asInteger (args[1]).asInteger(); + if (args.count() == 3) + no_commas = calc->conv()->asBoolean (args[2]).asBoolean(); + + TQString result; + TDELocale *locale = calc->conv()->locale(); + + // unfortunately, we can't just use TDELocale::formatNumber because + // * if decimals < 0, number is rounded + // * if no_commas is true, thousand separators shouldn't show up + + if( decimals < 0 ) + { + decimals = -decimals; + number = floor( number/pow(10.0,decimals)+0.5 ) * pow(10.0,decimals); + decimals = 0; + } + + bool neg = number < 0; + result = TQString::number( neg ? -number:number, 'f', decimals ); + + int pos = result.find('.'); + if (pos == -1) pos = result.length(); + else result.replace(pos, 1, locale->decimalSymbol()); + if( !no_commas ) + while (0 < (pos -= 3)) + result.insert(pos, locale->thousandsSeparator()); + + result.prepend( neg ? locale->negativeSign(): + locale->positiveSign() ); + + return Value (result); +} + +// Function: LEFT +Value func_left (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString(); + int nb = 1; + if (args.count() == 2) + nb = calc->conv()->asInteger (args[1]).asInteger(); + + return Value (str.left (nb)); +} + +// Function: LEN +Value func_len (valVector args, ValueCalc *calc, FuncExtra *) +{ + int nb = calc->conv()->asString (args[0]).asString().length(); + return Value (nb); +} + +// Function: LOWER +Value func_lower (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->conv()->asString (args[0]).asString().lower()); +} + +// Function: MID +Value func_mid (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString(); + int pos = calc->conv()->asInteger (args[1]).asInteger(); + uint len = 0xffffffff; + if (args.count() == 3) + len = (uint) calc->conv()->asInteger (args[2]).asInteger(); + + // Excel compatible + pos--; + + return Value (str.mid (pos, len)); +} + +// Function: PROPER +Value func_proper (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString().lower(); + + TQChar f; + bool first = true; + + for (unsigned int i = 0; i < str.length(); ++i) + { + if (first) + { + f = str[i]; + if (f.isNumber()) + continue; + + f = f.upper(); + + str[i] = f; + first = false; + + continue; + } + + if (str[i] == ' ' || str[i] == '-') + first = true; + } + + return Value (str); +} + +// Function: REGEXP +Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *) +{ + // ensure that we got a valid regular expression + TQRegExp exp (calc->conv()->asString (args[1]).asString()); + if (!exp.isValid ()) + return Value::errorVALUE(); + + TQString s = calc->conv()->asString (args[0]).asString(); + TQString defText; + if (args.count() > 2) + defText = calc->conv()->asString (args[2]).asString(); + int bkref = 0; + if (args.count() == 4) + bkref = calc->conv()->asInteger (args[3]).asInteger(); + if (bkref < 0) // strange back-reference + return Value::errorVALUE(); + + TQString returnValue; + + int pos = exp.search (s); + if (pos == -1) + returnValue = defText; + else + returnValue = exp.cap (bkref); + + return Value (returnValue); +} + +// Function: REGEXPRE +Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *) +{ + // ensure that we got a valid regular expression + TQRegExp exp (calc->conv()->asString (args[1]).asString()); + if (!exp.isValid ()) + return Value::errorVALUE(); + + TQString s = calc->conv()->asString (args[0]).asString(); + TQString str = calc->conv()->asString (args[2]).asString(); + + int pos = 0; + while ((pos = exp.search (s, pos)) != -1) + { + int i = exp.matchedLength(); + s = s.replace (pos, i, str); + pos += str.length(); + } + + return Value (s); +} + +// Function: REPLACE +Value func_replace (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString text = calc->conv()->asString (args[0]).asString(); + int pos = calc->conv()->asInteger (args[1]).asInteger(); + int len = calc->conv()->asInteger (args[2]).asInteger(); + TQString new_text = calc->conv()->asString (args[3]).asString(); + + if (pos < 0) pos = 0; + + TQString result = text.replace (pos-1, len, new_text); + return Value (result); +} + +// Function: REPT +Value func_rept (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString s = calc->conv()->asString (args[0]).asString(); + int nb = calc->conv()->asInteger (args[1]).asInteger(); + + TQString result; + for (int i = 0; i < nb; i++) result += s; + return Value (result); +} + +// Function: RIGHT +Value func_right (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString(); + int nb = 1; + if (args.count() == 2) + nb = calc->conv()->asInteger (args[1]).asInteger(); + + return Value (str.right (nb)); +} + +// Function: ROT +Value func_rot (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString text = calc->conv()->asString (args[0]).asString(); + + for( unsigned i=0; i= 'A' ) && ( c <= 'M' ) ) + text[i] = TQChar( text[i].unicode() + 13); + if( ( c >= 'N' ) && ( c <= 'Z' ) ) + text[i] = TQChar( text[i].unicode() - 13); + } + + return Value (text); +} + +// Function: SEARCH +Value func_search (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString find_text = calc->conv()->asString (args[0]).asString(); + TQString within_text = calc->conv()->asString (args[1]).asString(); + int start_num = 1; + if (args.count() == 3) + start_num = calc->conv()->asInteger (args[2]).asInteger(); + + // conforms to Excel behaviour + if (start_num <= 0) return Value::errorVALUE(); + if (start_num > (int)within_text.length()) return Value::errorVALUE(); + + // use globbing feature of TQRegExp + TQRegExp regex( find_text, false, true ); + int pos = within_text.find( regex, start_num-1 ); + if( pos < 0 ) return Value::errorNA(); + + return Value (pos + 1); +} + +// Function: SLEEK +Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString(); + TQString result; + TQChar c; + int i; + int l = str.length(); + + for (i = 0; i < l; ++i) + { + c = str[i]; + if (!c.isSpace()) + result += c; + } + + return Value (result); +} + +// Function: SUBSTITUTE +Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *) +{ + int num = 1; + bool all = true; + + if (args.count() == 4) + { + num = calc->conv()->asInteger (args[3]).asInteger(); + all = false; + } + + TQString text = calc->conv()->asString (args[0]).asString(); + TQString old_text = calc->conv()->asString (args[1]).asString(); + TQString new_text = calc->conv()->asString (args[2]).asString(); + + if( num <= 0 ) return Value::errorVALUE(); + if (old_text.length() == 0) return Value (text); + + TQString result = text; + + int p = result.find (old_text); + while ((p != -1) && (num > 0)) + { + result.replace( p, old_text.length(), new_text ); + // find another location, starting straight after the replaced text + p = result.find (old_text, p + new_text.length()); + if( !all ) num--; + } + + return Value (result); +} + +// Function: T +Value func_t (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->conv()->asString (args[0]); +} + +// Function: TEXT +Value func_text (valVector args, ValueCalc *calc, FuncExtra *) +{ + //Currently the same as the T function ... + //Second parameter is format_text. It is currently ignored. + return calc->conv()->asString (args[0]); +} + +// Function: TOGGLE +Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *) +{ + TQString str = calc->conv()->asString (args[0]).asString(); + int i; + int l = str.length(); + + for (i = 0; i < l; ++i) + { + TQChar c = str[i]; + TQChar lc = c.lower(); + TQChar uc = c.upper(); + + if (c == lc) // it is in lowercase + str[i] = c.upper(); + else if (c == uc) // it is in uppercase + str[i] = c.lower(); + } + + return Value (str); +} + +// Function: TRIM +Value func_trim (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value ( + calc->conv()->asString (args[0]).asString().simplifyWhiteSpace()); +} + +// Function: UPPER +Value func_upper (valVector args, ValueCalc *calc, FuncExtra *) +{ + return Value (calc->conv()->asString (args[0]).asString().upper()); +} + +// Function: VALUE +Value func_value (valVector args, ValueCalc *calc, FuncExtra *) +{ + // same as the N function + return calc->conv()->asFloat (args[0]); +} diff --git a/kspread/kspread_functions_trig.cc b/kspread/kspread_functions_trig.cc deleted file mode 100644 index f79d7f81..00000000 --- a/kspread/kspread_functions_trig.cc +++ /dev/null @@ -1,194 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998-2002 The KSpread Team - www.koffice.org/kspread - Copyright (C) 2005 Tomas Mecir - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -// built-in trigonometric functions - -#include "functions.h" -#include "valuecalc.h" - -using namespace KSpread; - -// prototypes (sort alphabetically) -Value func_acos (valVector args, ValueCalc *calc, FuncExtra *); -Value func_acosh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_acot (valVector args, ValueCalc *calc, FuncExtra *); -Value func_asinh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_asin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_atan (valVector args, ValueCalc *calc, FuncExtra *); -Value func_atan2 (valVector args, ValueCalc *calc, FuncExtra *); -Value func_atanh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_cos (valVector args, ValueCalc *calc, FuncExtra *); -Value func_cosh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_degrees (valVector args, ValueCalc *calc, FuncExtra *); -Value func_radians (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sin (valVector args, ValueCalc *calc, FuncExtra *); -Value func_sinh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tan (valVector args, ValueCalc *calc, FuncExtra *); -Value func_tanh (valVector args, ValueCalc *calc, FuncExtra *); -Value func_pi (valVector args, ValueCalc *calc, FuncExtra *); - -// registers all trigonometric functions -void RegisterTrigFunctions() -{ - FunctionRepository* repo = FunctionRepository::self(); - Function *f; - - f = new Function ("ACOS", func_acos); - repo->add (f); - f = new Function ("ACOSH", func_acosh); - repo->add (f); - f = new Function ("ACOT", func_acot); - repo->add (f); - f = new Function ("ASIN", func_asin); - repo->add (f); - f = new Function ("ASINH", func_asinh); - repo->add (f); - f = new Function ("ATAN", func_atan); - repo->add (f); - f = new Function ("ATAN2", func_atan2); - f->setParamCount (2); - repo->add (f); - f = new Function ("ATANH", func_atanh); - repo->add (f); - f = new Function ("COS", func_cos); - repo->add (f); - f = new Function ("COSH", func_cosh); - repo->add (f); - f = new Function ("DEGREES",func_degrees); - repo->add (f); - f = new Function ("RADIANS",func_radians); - repo->add (f); - f = new Function ("SIN", func_sin); - repo->add (f); - f = new Function ("SINH", func_sinh); - repo->add (f); - f = new Function ("TAN", func_tan); - repo->add (f); - f = new Function ("TANH", func_tanh); - repo->add (f); - f = new Function ("PI", func_pi); - f->setParamCount (0); - repo->add (f); -} - -// Function: sin -Value func_sin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->sin (args[0]); -} - -// Function: cos -Value func_cos (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->cos (args[0]); -} - -// Function: tan -Value func_tan (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->tg (args[0]); -} - -// Function: atan -Value func_atan (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->atg (args[0]); -} - -// Function: asin -Value func_asin (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->asin (args[0]); -} - -// Function: acos -Value func_acos (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->acos (args[0]); -} - -Value func_acot (valVector args, ValueCalc *calc, FuncExtra *) -{ - // PI/2 - atg (val) - return calc->sub (calc->div (calc->pi(), 2), calc->atg (args[0])); -} - -// Function: asinh -Value func_asinh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->asinh (args[0]); -} - -// Function: acosh -Value func_acosh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->acosh (args[0]); -} - -// Function: atanh -Value func_atanh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->atgh (args[0]); -} - -// Function: tanh -Value func_tanh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->tgh (args[0]); -} - -// Function: sinh -Value func_sinh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->sinh (args[0]); -} - -// Function: cosh -Value func_cosh (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->cosh (args[0]); -} - -// Function: DEGREES -Value func_degrees (valVector args, ValueCalc *calc, FuncExtra *) -{ - // val * 180 / pi - return calc->div (calc->mul (args[0], 180.0), calc->pi()); -} - -// Function: RADIANS -Value func_radians (valVector args, ValueCalc *calc, FuncExtra *) -{ - // val * pi / 180 - return calc->mul (calc->div (args[0], 180.0), calc->pi()); -} - -// Function: PI -Value func_pi (valVector, ValueCalc *calc, FuncExtra *) -{ - return calc->pi(); -} - -// Function: atan2 -Value func_atan2 (valVector args, ValueCalc *calc, FuncExtra *) -{ - return calc->atan2 (args[1], args[0]); -} diff --git a/kspread/kspread_functions_trig.cpp b/kspread/kspread_functions_trig.cpp new file mode 100644 index 00000000..f79d7f81 --- /dev/null +++ b/kspread/kspread_functions_trig.cpp @@ -0,0 +1,194 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in trigonometric functions + +#include "functions.h" +#include "valuecalc.h" + +using namespace KSpread; + +// prototypes (sort alphabetically) +Value func_acos (valVector args, ValueCalc *calc, FuncExtra *); +Value func_acosh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_acot (valVector args, ValueCalc *calc, FuncExtra *); +Value func_asinh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_asin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_atan (valVector args, ValueCalc *calc, FuncExtra *); +Value func_atan2 (valVector args, ValueCalc *calc, FuncExtra *); +Value func_atanh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_cos (valVector args, ValueCalc *calc, FuncExtra *); +Value func_cosh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_degrees (valVector args, ValueCalc *calc, FuncExtra *); +Value func_radians (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_sinh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tan (valVector args, ValueCalc *calc, FuncExtra *); +Value func_tanh (valVector args, ValueCalc *calc, FuncExtra *); +Value func_pi (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all trigonometric functions +void RegisterTrigFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("ACOS", func_acos); + repo->add (f); + f = new Function ("ACOSH", func_acosh); + repo->add (f); + f = new Function ("ACOT", func_acot); + repo->add (f); + f = new Function ("ASIN", func_asin); + repo->add (f); + f = new Function ("ASINH", func_asinh); + repo->add (f); + f = new Function ("ATAN", func_atan); + repo->add (f); + f = new Function ("ATAN2", func_atan2); + f->setParamCount (2); + repo->add (f); + f = new Function ("ATANH", func_atanh); + repo->add (f); + f = new Function ("COS", func_cos); + repo->add (f); + f = new Function ("COSH", func_cosh); + repo->add (f); + f = new Function ("DEGREES",func_degrees); + repo->add (f); + f = new Function ("RADIANS",func_radians); + repo->add (f); + f = new Function ("SIN", func_sin); + repo->add (f); + f = new Function ("SINH", func_sinh); + repo->add (f); + f = new Function ("TAN", func_tan); + repo->add (f); + f = new Function ("TANH", func_tanh); + repo->add (f); + f = new Function ("PI", func_pi); + f->setParamCount (0); + repo->add (f); +} + +// Function: sin +Value func_sin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->sin (args[0]); +} + +// Function: cos +Value func_cos (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->cos (args[0]); +} + +// Function: tan +Value func_tan (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->tg (args[0]); +} + +// Function: atan +Value func_atan (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->atg (args[0]); +} + +// Function: asin +Value func_asin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->asin (args[0]); +} + +// Function: acos +Value func_acos (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->acos (args[0]); +} + +Value func_acot (valVector args, ValueCalc *calc, FuncExtra *) +{ + // PI/2 - atg (val) + return calc->sub (calc->div (calc->pi(), 2), calc->atg (args[0])); +} + +// Function: asinh +Value func_asinh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->asinh (args[0]); +} + +// Function: acosh +Value func_acosh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->acosh (args[0]); +} + +// Function: atanh +Value func_atanh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->atgh (args[0]); +} + +// Function: tanh +Value func_tanh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->tgh (args[0]); +} + +// Function: sinh +Value func_sinh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->sinh (args[0]); +} + +// Function: cosh +Value func_cosh (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->cosh (args[0]); +} + +// Function: DEGREES +Value func_degrees (valVector args, ValueCalc *calc, FuncExtra *) +{ + // val * 180 / pi + return calc->div (calc->mul (args[0], 180.0), calc->pi()); +} + +// Function: RADIANS +Value func_radians (valVector args, ValueCalc *calc, FuncExtra *) +{ + // val * pi / 180 + return calc->mul (calc->div (args[0], 180.0), calc->pi()); +} + +// Function: PI +Value func_pi (valVector, ValueCalc *calc, FuncExtra *) +{ + return calc->pi(); +} + +// Function: atan2 +Value func_atan2 (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->atan2 (args[1], args[0]); +} diff --git a/kspread/kspread_genvalidationstyle.cc b/kspread/kspread_genvalidationstyle.cc deleted file mode 100644 index 613be176..00000000 --- a/kspread/kspread_genvalidationstyle.cc +++ /dev/null @@ -1,401 +0,0 @@ -/* This file is part of the KDE project - - Copyright 2004 Laurent Montel - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include "kspread_genvalidationstyle.h" -#include "kspread_cell.h" -#include - -using namespace KSpread; - -GenValidationStyles::GenValidationStyles() -{ - -} - -GenValidationStyles::~GenValidationStyles() -{ - -} - -TQString GenValidationStyles::lookup( const GenValidationStyle& style ) -{ - StyleMap::iterator it = m_styles.find( style ); - if ( it == m_styles.end() ) { - - TQString styleName( "val" ); - styleName = makeUniqueName( styleName ); - m_names.insert( styleName, true ); - it = m_styles.insert( style, styleName ); - } - return it.data(); -} - -TQString GenValidationStyles::makeUniqueName( const TQString& base ) const -{ - int num = 1; - TQString name; - do { - name = base; - name += TQString::number( num++ ); - } while ( m_names.find( name ) != m_names.end() ); - return name; -} - -void GenValidationStyles::writeStyle( KoXmlWriter& writer ) -{ - if ( m_styles.count()>0 ) - { - writer.startElement( "table:content-validations" ); - StyleMap::Iterator it; - for ( it = m_styles.begin(); it != m_styles.end(); ++it ) - { - writer.startElement( "table:content-validation" ); - writer.addAttribute( "table:name", it.data() ); - writer.addAttribute( "table:allow-empty-cell", it.key().allowEmptyCell ); - writer.addAttribute( "table:condition", it.key().condition ); - - writer.startElement( "table:help-message" ); - writer.addAttribute( "table:title", it.key().title ); - writer.addAttribute( "table:display", it.key().displayValidationInformation ); - - TQStringList text = TQStringList::split( "\n", it.key().messageInfo ); - for ( TQStringList::Iterator it2 = text.begin(); it2 != text.end(); ++it2 ) { - writer.startElement( "text:p" ); - writer.addTextNode( *it2 ); - writer.endElement(); - } - writer.endElement(); - - writer.startElement( "table:error-message" ); - writer.addAttribute( "table:message-type", it.key().messageType ); - - writer.addAttribute("table:title", it.key().titleInfo); - writer.addAttribute("table:display", it.key().displayMessage); - text = TQStringList::split( "\n", it.key().message ); - for ( TQStringList::Iterator it3 = text.begin(); it3 != text.end(); ++it3 ) { - writer.startElement( "text:p" ); - writer.addTextNode( *it3 ); - writer.endElement(); - } - writer.endElement(); - - writer.endElement(); - } - writer.endElement();//close sheet:content-validation - } -} - -void GenValidationStyle::initVal( Validity *_val ) -{ - if ( _val ) - { - allowEmptyCell = ( _val->allowEmptyCell ? "true" : "false" ); - condition = createValidationCondition( _val ); - title = _val->title; - displayValidationInformation = ( _val->displayValidationInformation ? "true" : "false" ); - messageInfo = _val->messageInfo; - - switch( _val->m_action ) - { - case Action::Warning: - messageType = "warning"; - break; - case Action::Information: - messageType = "information"; - break; - case Action::Stop: - messageType = "stop"; - break; - } - - titleInfo = _val->titleInfo; - displayMessage = ( _val->displayMessage ? "true" : "false" ); - message = _val->message; - } -} - -TQString GenValidationStyle::createValidationCondition( Validity* _val ) -{ - TQString result; - switch( _val->m_restriction ) - { - case Restriction::None: - //nothing - break; - case Restriction::Text: - //doesn't exist into oo spec - result = "cell-content-is-text()"; - break; - case Restriction::Time: - result = createTimeValidationCondition( _val ); - break; - case Restriction::Date: - result = createDateValidationCondition( _val ); - break; - case Restriction::Integer: - case Restriction::Number: - result = createNumberValidationCondition( _val ); - break; - case Restriction::TextLength: - result = createTextValidationCondition( _val ); - break; - case Restriction::List: - result = createListValidationCondition( _val ); - break; - } - return result; -} - -TQString GenValidationStyle::createListValidationCondition( Validity* _val ) -{ - TQString result = "oooc:cell-content-is-in-list("; - result = _val->listValidity.join( ";" ); - result +=")"; - return result; -} - -TQString GenValidationStyle::createNumberValidationCondition( Validity* _val ) -{ - TQString result; - if ( _val->m_restriction == Restriction::Number ) - result = "oooc:cell-content-is-whole-number() and "; - else if ( _val->m_restriction == Restriction::Integer ) - result = "oooc:cell-content-is-decimal-number() and "; - switch( _val->m_cond ) - { - case Conditional::None: - //nothing - break; - case Conditional::Equal: - result+="cell-content()"; - result+="="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Superior: - result+="cell-content()"; - result+=">"; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Inferior: - result+="cell-content()"; - result+="<"; - result+=TQString::number( _val->valMin ); - break; - case Conditional::SuperiorEqual: - result+="cell-content()"; - result+=">="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::InferiorEqual: - result+="cell-content()"; - result+="<="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Different: - result+="cell-content()"; - result+="!="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Between: - result+="cell-content-is-between("; - result+=TQString::number( _val->valMin ); - result+=","; - result+=TQString::number( _val->valMax ); - result+=")"; - break; - case Conditional::DifferentTo: - result+="cell-content-is-not-between("; - result+=TQString::number( _val->valMin ); - result+=","; - result+=TQString::number( _val->valMax ); - result+=")"; - break; - } - return result; -} - - -TQString GenValidationStyle::createTimeValidationCondition( Validity* _val ) -{ - TQString result( "oooc:cell-content-is-time() and " ); - switch( _val->m_cond ) - { - case Conditional::None: - //nothing - break; - case Conditional::Equal: - result+="cell-content()"; - result+="="; - result+=_val->timeMin.toString( ); - break; - case Conditional::Superior: - result+="cell-content()"; - result+=">"; - result+=_val->timeMin.toString( ); - break; - case Conditional::Inferior: - result+="cell-content()"; - result+="<"; - result+=_val->timeMin.toString( ); - break; - case Conditional::SuperiorEqual: - result+="cell-content()"; - result+=">="; - result+=_val->timeMin.toString( ); - break; - case Conditional::InferiorEqual: - result+="cell-content()"; - result+="<="; - result+=_val->timeMin.toString( ); - break; - case Conditional::Different: - result+="cell-content()"; - result+="!="; - result+=_val->timeMin.toString( ); - break; - case Conditional::Between: - result+="cell-content-is-between("; - result+=_val->timeMin.toString( ); - result+=","; - result+=_val->timeMax.toString( ); - result+=")"; - break; - case Conditional::DifferentTo: - result+="cell-content-is-not-between("; - result+=_val->timeMin.toString( ); - result+=","; - result+=_val->timeMax.toString( ); - result+=")"; - break; - } - return result; -} - -TQString GenValidationStyle::createDateValidationCondition( Validity* _val ) -{ - TQString result( "oooc:cell-content-is-date() and " ); - switch( _val->m_cond ) - { - case Conditional::None: - //nothing - break; - case Conditional::Equal: - result+="cell-content()"; - result+="="; - result+=_val->dateMin.toString(); - break; - case Conditional::Superior: - result+="cell-content()"; - result+=">"; - result+=_val->dateMin.toString(); - break; - case Conditional::Inferior: - result+="cell-content()"; - result+="<"; - result+=_val->dateMin.toString(); - break; - case Conditional::SuperiorEqual: - result+="cell-content()"; - result+=">="; - result+=_val->dateMin.toString(); - break; - case Conditional::InferiorEqual: - result+="cell-content()"; - result+="<="; - result+=_val->dateMin.toString(); - break; - case Conditional::Different: - result+="cell-content()"; - result+="!="; - result+=_val->dateMin.toString(); - break; - case Conditional::Between: - result+="cell-content-is-between("; - result+=_val->dateMin.toString(); - result+=","; - result+=_val->dateMax.toString(); - result+=")"; - break; - case Conditional::DifferentTo: - result+="cell-content-is-not-between("; - result+=_val->dateMin.toString(); - result+=","; - result+=_val->dateMax.toString(); - result+=")"; - break; - } - return result; -} - -TQString GenValidationStyle::createTextValidationCondition( Validity* _val ) -{ - TQString result; - switch( _val->m_cond ) - { - case Conditional::None: - //nothing - break; - case Conditional::Equal: - result+="oooc:cell-content-text-length()"; - result+="="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Superior: - result+="oooc:cell-content-text-length()"; - result+=">"; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Inferior: - result+="oooc:cell-content-text-length()"; - result+="<"; - result+=TQString::number( _val->valMin ); - break; - case Conditional::SuperiorEqual: - result+="oooc:cell-content-text-length()"; - result+=">="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::InferiorEqual: - result+="oooc:cell-content-text-length()"; - result+="<="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Different: - result+="oooc:cell-content-text-length()"; - result+="!="; - result+=TQString::number( _val->valMin ); - break; - case Conditional::Between: - result+="oooc:cell-content-text-length-is-between("; - result+=TQString::number( _val->valMin ); - result+=","; - result+=TQString::number( _val->valMax ); - result+=")"; - break; - case Conditional::DifferentTo: - result+="oooc:cell-content-text-length-is-not-between("; - result+=TQString::number( _val->valMin ); - result+=","; - result+=TQString::number( _val->valMax ); - result+=")"; - break; - } - return result; -} diff --git a/kspread/kspread_genvalidationstyle.cpp b/kspread/kspread_genvalidationstyle.cpp new file mode 100644 index 00000000..613be176 --- /dev/null +++ b/kspread/kspread_genvalidationstyle.cpp @@ -0,0 +1,401 @@ +/* This file is part of the KDE project + + Copyright 2004 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kspread_genvalidationstyle.h" +#include "kspread_cell.h" +#include + +using namespace KSpread; + +GenValidationStyles::GenValidationStyles() +{ + +} + +GenValidationStyles::~GenValidationStyles() +{ + +} + +TQString GenValidationStyles::lookup( const GenValidationStyle& style ) +{ + StyleMap::iterator it = m_styles.find( style ); + if ( it == m_styles.end() ) { + + TQString styleName( "val" ); + styleName = makeUniqueName( styleName ); + m_names.insert( styleName, true ); + it = m_styles.insert( style, styleName ); + } + return it.data(); +} + +TQString GenValidationStyles::makeUniqueName( const TQString& base ) const +{ + int num = 1; + TQString name; + do { + name = base; + name += TQString::number( num++ ); + } while ( m_names.find( name ) != m_names.end() ); + return name; +} + +void GenValidationStyles::writeStyle( KoXmlWriter& writer ) +{ + if ( m_styles.count()>0 ) + { + writer.startElement( "table:content-validations" ); + StyleMap::Iterator it; + for ( it = m_styles.begin(); it != m_styles.end(); ++it ) + { + writer.startElement( "table:content-validation" ); + writer.addAttribute( "table:name", it.data() ); + writer.addAttribute( "table:allow-empty-cell", it.key().allowEmptyCell ); + writer.addAttribute( "table:condition", it.key().condition ); + + writer.startElement( "table:help-message" ); + writer.addAttribute( "table:title", it.key().title ); + writer.addAttribute( "table:display", it.key().displayValidationInformation ); + + TQStringList text = TQStringList::split( "\n", it.key().messageInfo ); + for ( TQStringList::Iterator it2 = text.begin(); it2 != text.end(); ++it2 ) { + writer.startElement( "text:p" ); + writer.addTextNode( *it2 ); + writer.endElement(); + } + writer.endElement(); + + writer.startElement( "table:error-message" ); + writer.addAttribute( "table:message-type", it.key().messageType ); + + writer.addAttribute("table:title", it.key().titleInfo); + writer.addAttribute("table:display", it.key().displayMessage); + text = TQStringList::split( "\n", it.key().message ); + for ( TQStringList::Iterator it3 = text.begin(); it3 != text.end(); ++it3 ) { + writer.startElement( "text:p" ); + writer.addTextNode( *it3 ); + writer.endElement(); + } + writer.endElement(); + + writer.endElement(); + } + writer.endElement();//close sheet:content-validation + } +} + +void GenValidationStyle::initVal( Validity *_val ) +{ + if ( _val ) + { + allowEmptyCell = ( _val->allowEmptyCell ? "true" : "false" ); + condition = createValidationCondition( _val ); + title = _val->title; + displayValidationInformation = ( _val->displayValidationInformation ? "true" : "false" ); + messageInfo = _val->messageInfo; + + switch( _val->m_action ) + { + case Action::Warning: + messageType = "warning"; + break; + case Action::Information: + messageType = "information"; + break; + case Action::Stop: + messageType = "stop"; + break; + } + + titleInfo = _val->titleInfo; + displayMessage = ( _val->displayMessage ? "true" : "false" ); + message = _val->message; + } +} + +TQString GenValidationStyle::createValidationCondition( Validity* _val ) +{ + TQString result; + switch( _val->m_restriction ) + { + case Restriction::None: + //nothing + break; + case Restriction::Text: + //doesn't exist into oo spec + result = "cell-content-is-text()"; + break; + case Restriction::Time: + result = createTimeValidationCondition( _val ); + break; + case Restriction::Date: + result = createDateValidationCondition( _val ); + break; + case Restriction::Integer: + case Restriction::Number: + result = createNumberValidationCondition( _val ); + break; + case Restriction::TextLength: + result = createTextValidationCondition( _val ); + break; + case Restriction::List: + result = createListValidationCondition( _val ); + break; + } + return result; +} + +TQString GenValidationStyle::createListValidationCondition( Validity* _val ) +{ + TQString result = "oooc:cell-content-is-in-list("; + result = _val->listValidity.join( ";" ); + result +=")"; + return result; +} + +TQString GenValidationStyle::createNumberValidationCondition( Validity* _val ) +{ + TQString result; + if ( _val->m_restriction == Restriction::Number ) + result = "oooc:cell-content-is-whole-number() and "; + else if ( _val->m_restriction == Restriction::Integer ) + result = "oooc:cell-content-is-decimal-number() and "; + switch( _val->m_cond ) + { + case Conditional::None: + //nothing + break; + case Conditional::Equal: + result+="cell-content()"; + result+="="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Superior: + result+="cell-content()"; + result+=">"; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Inferior: + result+="cell-content()"; + result+="<"; + result+=TQString::number( _val->valMin ); + break; + case Conditional::SuperiorEqual: + result+="cell-content()"; + result+=">="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::InferiorEqual: + result+="cell-content()"; + result+="<="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Different: + result+="cell-content()"; + result+="!="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Between: + result+="cell-content-is-between("; + result+=TQString::number( _val->valMin ); + result+=","; + result+=TQString::number( _val->valMax ); + result+=")"; + break; + case Conditional::DifferentTo: + result+="cell-content-is-not-between("; + result+=TQString::number( _val->valMin ); + result+=","; + result+=TQString::number( _val->valMax ); + result+=")"; + break; + } + return result; +} + + +TQString GenValidationStyle::createTimeValidationCondition( Validity* _val ) +{ + TQString result( "oooc:cell-content-is-time() and " ); + switch( _val->m_cond ) + { + case Conditional::None: + //nothing + break; + case Conditional::Equal: + result+="cell-content()"; + result+="="; + result+=_val->timeMin.toString( ); + break; + case Conditional::Superior: + result+="cell-content()"; + result+=">"; + result+=_val->timeMin.toString( ); + break; + case Conditional::Inferior: + result+="cell-content()"; + result+="<"; + result+=_val->timeMin.toString( ); + break; + case Conditional::SuperiorEqual: + result+="cell-content()"; + result+=">="; + result+=_val->timeMin.toString( ); + break; + case Conditional::InferiorEqual: + result+="cell-content()"; + result+="<="; + result+=_val->timeMin.toString( ); + break; + case Conditional::Different: + result+="cell-content()"; + result+="!="; + result+=_val->timeMin.toString( ); + break; + case Conditional::Between: + result+="cell-content-is-between("; + result+=_val->timeMin.toString( ); + result+=","; + result+=_val->timeMax.toString( ); + result+=")"; + break; + case Conditional::DifferentTo: + result+="cell-content-is-not-between("; + result+=_val->timeMin.toString( ); + result+=","; + result+=_val->timeMax.toString( ); + result+=")"; + break; + } + return result; +} + +TQString GenValidationStyle::createDateValidationCondition( Validity* _val ) +{ + TQString result( "oooc:cell-content-is-date() and " ); + switch( _val->m_cond ) + { + case Conditional::None: + //nothing + break; + case Conditional::Equal: + result+="cell-content()"; + result+="="; + result+=_val->dateMin.toString(); + break; + case Conditional::Superior: + result+="cell-content()"; + result+=">"; + result+=_val->dateMin.toString(); + break; + case Conditional::Inferior: + result+="cell-content()"; + result+="<"; + result+=_val->dateMin.toString(); + break; + case Conditional::SuperiorEqual: + result+="cell-content()"; + result+=">="; + result+=_val->dateMin.toString(); + break; + case Conditional::InferiorEqual: + result+="cell-content()"; + result+="<="; + result+=_val->dateMin.toString(); + break; + case Conditional::Different: + result+="cell-content()"; + result+="!="; + result+=_val->dateMin.toString(); + break; + case Conditional::Between: + result+="cell-content-is-between("; + result+=_val->dateMin.toString(); + result+=","; + result+=_val->dateMax.toString(); + result+=")"; + break; + case Conditional::DifferentTo: + result+="cell-content-is-not-between("; + result+=_val->dateMin.toString(); + result+=","; + result+=_val->dateMax.toString(); + result+=")"; + break; + } + return result; +} + +TQString GenValidationStyle::createTextValidationCondition( Validity* _val ) +{ + TQString result; + switch( _val->m_cond ) + { + case Conditional::None: + //nothing + break; + case Conditional::Equal: + result+="oooc:cell-content-text-length()"; + result+="="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Superior: + result+="oooc:cell-content-text-length()"; + result+=">"; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Inferior: + result+="oooc:cell-content-text-length()"; + result+="<"; + result+=TQString::number( _val->valMin ); + break; + case Conditional::SuperiorEqual: + result+="oooc:cell-content-text-length()"; + result+=">="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::InferiorEqual: + result+="oooc:cell-content-text-length()"; + result+="<="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Different: + result+="oooc:cell-content-text-length()"; + result+="!="; + result+=TQString::number( _val->valMin ); + break; + case Conditional::Between: + result+="oooc:cell-content-text-length-is-between("; + result+=TQString::number( _val->valMin ); + result+=","; + result+=TQString::number( _val->valMax ); + result+=")"; + break; + case Conditional::DifferentTo: + result+="oooc:cell-content-text-length-is-not-between("; + result+=TQString::number( _val->valMin ); + result+=","; + result+=TQString::number( _val->valMax ); + result+=")"; + break; + } + return result; +} diff --git a/kspread/kspread_handler.cc b/kspread/kspread_handler.cc deleted file mode 100644 index 262774ff..00000000 --- a/kspread/kspread_handler.cc +++ /dev/null @@ -1,194 +0,0 @@ -// -// TODO: insert copyright header -// - -#include - -#include "kspread_view.h" - -#include "kspread_handler.h" - -#define KS_MIN_RECTSIZE 3 - -using namespace KSpread; - -InsertHandler::InsertHandler( View* view, TQWidget* widget ) - : KoEventHandler( TQT_TQOBJECT(widget) ) -{ - m_view = view; - m_started = false; - m_clicked = false; - - widget->setCursor( crossCursor ); -} - -InsertHandler::~InsertHandler() -{ - ((TQWidget*)target())->setCursor( arrowCursor ); - m_view->resetInsertHandle(); -} - -bool InsertHandler::eventFilter( TQObject*, TQEvent* ev ) -{ - if ( ev->type() == TQEvent::MouseButtonPress ) - { - TQMouseEvent* e = (TQMouseEvent*)ev; - - m_geometryStart = e->pos(); - m_geometryEnd = e->pos(); - m_started = false; - m_clicked = true; - - return true; - } - else if ( ev->type() == TQEvent::MouseMove ) - { - if ( !m_clicked ) - return true; - - TQMouseEvent* e = (TQMouseEvent*)ev; - - TQPainter painter; - painter.begin( (TQWidget*)target() ); - painter.setRasterOp( NotROP ); - - TQPen pen; - pen.setStyle( Qt::DashLine ); - painter.setPen( pen ); - - if ( m_started ) - { - int x = m_geometryStart.x(); - int y = m_geometryStart.y(); - if ( x > m_geometryEnd.x() ) - x = m_geometryEnd.x(); - if ( y > m_geometryEnd.y() ) - y = m_geometryEnd.y(); - int w = m_geometryEnd.x() - m_geometryStart.x(); - if ( w < 0 ) w *= -1; - int h = m_geometryEnd.y() - m_geometryStart.y(); - if ( h < 0 ) h *= -1; - - if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; - if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; - - painter.drawRect( x, y, w, h ); - } - else - m_started = true; - - m_geometryEnd = e->pos(); - - int x = m_geometryStart.x(); - int y = m_geometryStart.y(); - if ( x > m_geometryEnd.x() ) - x = m_geometryEnd.x(); - if ( y > m_geometryEnd.y() ) - y = m_geometryEnd.y(); - int w = m_geometryEnd.x() - m_geometryStart.x(); - if ( w < 0 ) w *= -1; - int h = m_geometryEnd.y() - m_geometryStart.y(); - if ( h < 0 ) h *= -1; - - if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; - if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; - - painter.drawRect( x, y, w, h ); - painter.end(); - - return true; - } - else if ( ev->type() == TQEvent::MouseButtonRelease ) - { - TQMouseEvent* e = (TQMouseEvent*)ev; - - if ( !m_started ) - { - delete this; - return true; - } - - m_geometryEnd = e->pos(); - - int x = m_geometryStart.x(); - int y = m_geometryStart.y(); - if ( x > m_geometryEnd.x() ) - x = m_geometryEnd.x(); - if ( y > m_geometryEnd.y() ) - y = m_geometryEnd.y(); - int w = m_geometryEnd.x() - m_geometryStart.x(); - if ( w < 0 ) w *= -1; - int h = m_geometryEnd.y() - m_geometryStart.y(); - if ( h < 0 ) h *= -1; - - if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; - if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; - - TQPainter painter; - painter.begin( (TQWidget*)target() ); - - TQPen pen; - pen.setStyle( Qt::DashLine ); - painter.setPen( pen ); - - painter.setRasterOp( NotROP ); - painter.drawRect( x, y, w, h ); - painter.end(); - - insertObject( TQRect( x, y, w, h) ); - - delete this; - return true; - } - else if ( ev->type() == TQEvent::KeyPress ) - { - TQKeyEvent* e = (TQKeyEvent*)ev; - if ( e->key() != Key_Escape ) - return false; - - delete this; - return true; - } - - return false; -} - -InsertPartHandler::InsertPartHandler( View* view, TQWidget* widget, const KoDocumentEntry& entry ) - : InsertHandler( view, widget ), m_entry( entry ) -{ -} -InsertPartHandler::~InsertPartHandler() -{ -} -void InsertPartHandler::insertObject( TQRect r) -{ - m_view->insertChild( r, m_entry ); -} - - -InsertChartHandler::InsertChartHandler( View* view, TQWidget* widget, const KoDocumentEntry& entry ) - : InsertHandler( view, widget ), m_entry( entry ) -{ -} -InsertChartHandler::~InsertChartHandler() -{ -} -void InsertChartHandler::insertObject( TQRect r) -{ - m_view->insertChart( r, m_entry ); -} - -InsertPictureHandler::InsertPictureHandler( View* view, TQWidget* widget, const KURL &file ) - : InsertHandler( view, widget ) -{ - m_file = file; -} -InsertPictureHandler::~InsertPictureHandler() -{ -} -void InsertPictureHandler::insertObject( TQRect r) -{ - //m_view->insertPicture(/* r,*/ m_file ); -} - -#include "kspread_handler.moc" diff --git a/kspread/kspread_handler.cpp b/kspread/kspread_handler.cpp new file mode 100644 index 00000000..262774ff --- /dev/null +++ b/kspread/kspread_handler.cpp @@ -0,0 +1,194 @@ +// +// TODO: insert copyright header +// + +#include + +#include "kspread_view.h" + +#include "kspread_handler.h" + +#define KS_MIN_RECTSIZE 3 + +using namespace KSpread; + +InsertHandler::InsertHandler( View* view, TQWidget* widget ) + : KoEventHandler( TQT_TQOBJECT(widget) ) +{ + m_view = view; + m_started = false; + m_clicked = false; + + widget->setCursor( crossCursor ); +} + +InsertHandler::~InsertHandler() +{ + ((TQWidget*)target())->setCursor( arrowCursor ); + m_view->resetInsertHandle(); +} + +bool InsertHandler::eventFilter( TQObject*, TQEvent* ev ) +{ + if ( ev->type() == TQEvent::MouseButtonPress ) + { + TQMouseEvent* e = (TQMouseEvent*)ev; + + m_geometryStart = e->pos(); + m_geometryEnd = e->pos(); + m_started = false; + m_clicked = true; + + return true; + } + else if ( ev->type() == TQEvent::MouseMove ) + { + if ( !m_clicked ) + return true; + + TQMouseEvent* e = (TQMouseEvent*)ev; + + TQPainter painter; + painter.begin( (TQWidget*)target() ); + painter.setRasterOp( NotROP ); + + TQPen pen; + pen.setStyle( Qt::DashLine ); + painter.setPen( pen ); + + if ( m_started ) + { + int x = m_geometryStart.x(); + int y = m_geometryStart.y(); + if ( x > m_geometryEnd.x() ) + x = m_geometryEnd.x(); + if ( y > m_geometryEnd.y() ) + y = m_geometryEnd.y(); + int w = m_geometryEnd.x() - m_geometryStart.x(); + if ( w < 0 ) w *= -1; + int h = m_geometryEnd.y() - m_geometryStart.y(); + if ( h < 0 ) h *= -1; + + if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; + if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; + + painter.drawRect( x, y, w, h ); + } + else + m_started = true; + + m_geometryEnd = e->pos(); + + int x = m_geometryStart.x(); + int y = m_geometryStart.y(); + if ( x > m_geometryEnd.x() ) + x = m_geometryEnd.x(); + if ( y > m_geometryEnd.y() ) + y = m_geometryEnd.y(); + int w = m_geometryEnd.x() - m_geometryStart.x(); + if ( w < 0 ) w *= -1; + int h = m_geometryEnd.y() - m_geometryStart.y(); + if ( h < 0 ) h *= -1; + + if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; + if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; + + painter.drawRect( x, y, w, h ); + painter.end(); + + return true; + } + else if ( ev->type() == TQEvent::MouseButtonRelease ) + { + TQMouseEvent* e = (TQMouseEvent*)ev; + + if ( !m_started ) + { + delete this; + return true; + } + + m_geometryEnd = e->pos(); + + int x = m_geometryStart.x(); + int y = m_geometryStart.y(); + if ( x > m_geometryEnd.x() ) + x = m_geometryEnd.x(); + if ( y > m_geometryEnd.y() ) + y = m_geometryEnd.y(); + int w = m_geometryEnd.x() - m_geometryStart.x(); + if ( w < 0 ) w *= -1; + int h = m_geometryEnd.y() - m_geometryStart.y(); + if ( h < 0 ) h *= -1; + + if ( w < KS_MIN_RECTSIZE ) w = KS_MIN_RECTSIZE; + if ( h < KS_MIN_RECTSIZE ) h = KS_MIN_RECTSIZE; + + TQPainter painter; + painter.begin( (TQWidget*)target() ); + + TQPen pen; + pen.setStyle( Qt::DashLine ); + painter.setPen( pen ); + + painter.setRasterOp( NotROP ); + painter.drawRect( x, y, w, h ); + painter.end(); + + insertObject( TQRect( x, y, w, h) ); + + delete this; + return true; + } + else if ( ev->type() == TQEvent::KeyPress ) + { + TQKeyEvent* e = (TQKeyEvent*)ev; + if ( e->key() != Key_Escape ) + return false; + + delete this; + return true; + } + + return false; +} + +InsertPartHandler::InsertPartHandler( View* view, TQWidget* widget, const KoDocumentEntry& entry ) + : InsertHandler( view, widget ), m_entry( entry ) +{ +} +InsertPartHandler::~InsertPartHandler() +{ +} +void InsertPartHandler::insertObject( TQRect r) +{ + m_view->insertChild( r, m_entry ); +} + + +InsertChartHandler::InsertChartHandler( View* view, TQWidget* widget, const KoDocumentEntry& entry ) + : InsertHandler( view, widget ), m_entry( entry ) +{ +} +InsertChartHandler::~InsertChartHandler() +{ +} +void InsertChartHandler::insertObject( TQRect r) +{ + m_view->insertChart( r, m_entry ); +} + +InsertPictureHandler::InsertPictureHandler( View* view, TQWidget* widget, const KURL &file ) + : InsertHandler( view, widget ) +{ + m_file = file; +} +InsertPictureHandler::~InsertPictureHandler() +{ +} +void InsertPictureHandler::insertObject( TQRect r) +{ + //m_view->insertPicture(/* r,*/ m_file ); +} + +#include "kspread_handler.moc" diff --git a/kspread/kspread_locale.cc b/kspread/kspread_locale.cc deleted file mode 100644 index fc665f0a..00000000 --- a/kspread/kspread_locale.cc +++ /dev/null @@ -1,106 +0,0 @@ -#include "kspread_locale.h" - -#include - -using namespace KSpread; - -Locale::Locale() - : TDELocale("kspread") -{ - insertCatalogue("koffice"); -} - -void Locale::load( const TQDomElement& element ) -{ - if ( element.hasAttribute( "weekStartsMonday" ) ) - { - TQString c = element.attribute( "weekStartsMonday" ); - if ( c != "False") - { - setWeekStartDay( 1 /*Monday*/ ); - } - } - if ( element.hasAttribute( "decimalSymbol" ) ) - setDecimalSymbol( element.attribute( "decimalSymbol" ) ); - if ( element.hasAttribute( "thousandsSeparator" ) ) - setThousandsSeparator( element.attribute( "thousandsSeparator" ) ); - if ( element.hasAttribute( "currencySymbol" ) ) - setCurrencySymbol( element.attribute( "currencySymbol" ) ); - if ( element.hasAttribute( "monetaryDecimalSymbol" ) ) - setMonetaryDecimalSymbol( element.attribute( "monetaryDecimalSymbol" ) ); - if ( element.hasAttribute( "monetaryThousandsSeparator" ) ) - setMonetaryThousandsSeparator( element.attribute( "monetaryThousandsSeparator" ) ); - if ( element.hasAttribute( "positiveSign" ) ) - setPositiveSign( element.attribute( "positiveSign" ) ); - if ( element.hasAttribute( "negativeSign" ) ) - setNegativeSign( element.attribute( "negativeSign" ) ); - if ( element.hasAttribute( "fracDigits" ) ) - setFracDigits( element.attribute( "fracDigits" ).toInt() ); - if ( element.hasAttribute( "positivePrefixCurrencySymbol" ) ) - { - TQString c = element.attribute( "positivePrefixCurrencySymbol" ); - setPositivePrefixCurrencySymbol( c == "True" ); - } - if ( element.hasAttribute( "negativePrefixCurrencySymbol" ) ) - { - TQString c = element.attribute( "negativePrefixCurrencySymbol" ); - setNegativePrefixCurrencySymbol( c == "True" ); - } - if ( element.hasAttribute( "positiveMonetarySignPosition" ) ) - setPositiveMonetarySignPosition( (SignPosition)element.attribute( "positiveMonetarySignPosition" ).toInt() ); - if ( element.hasAttribute( "negativeMonetarySignPosition" ) ) - setNegativeMonetarySignPosition( (SignPosition)element.attribute( "negativeMonetarySignPosition" ).toInt() ); - if ( element.hasAttribute( "timeFormat" ) ) - setTimeFormat( element.attribute( "timeFormat" ) ); - if ( element.hasAttribute( "dateFormat" ) ) - setDateFormat( element.attribute( "dateFormat" ) ); - if ( element.hasAttribute( "dateFormatShort" ) ) - setDateFormatShort( element.attribute( "dateFormatShort" ) ); -} - -TQDomElement Locale::save( TQDomDocument& doc ) const -{ - TQDomElement element = doc.createElement( "locale" ); - - element.setAttribute( "weekStartsMonday", (weekStartDay() == 1) ? "True" : "False" ); - element.setAttribute( "decimalSymbol", decimalSymbol() ); - element.setAttribute( "thousandsSeparator", thousandsSeparator() ); - element.setAttribute( "currencySymbol", currencySymbol() ); - element.setAttribute( "monetaryDecimalSymbol", monetaryDecimalSymbol() ); - element.setAttribute( "monetaryThousandsSeparator", monetaryThousandsSeparator() ); - element.setAttribute( "positiveSign", positiveSign() ); - element.setAttribute( "negativeSign", negativeSign() ); - element.setAttribute( "fracDigits", fracDigits() ); - element.setAttribute( "positivePrefixCurrencySymbol", positivePrefixCurrencySymbol() ? "True" : "False"); - element.setAttribute( "negativePrefixCurrencySymbol", negativePrefixCurrencySymbol() ? "True" : "False"); - element.setAttribute( "positiveMonetarySignPosition", (int)positiveMonetarySignPosition() ); - element.setAttribute( "negativeMonetarySignPosition", (int)negativeMonetarySignPosition() ); - element.setAttribute( "timeFormat", timeFormat() ); - element.setAttribute( "dateFormat", dateFormat() ); - element.setAttribute( "dateFormatShort", dateFormatShort() ); - - return element; -} - -void Locale::defaultSystemConfig( ) -{ - TDELocale locale("kspread"); - setWeekStartDay( locale.weekStartDay() ); - setDecimalSymbol( locale.decimalSymbol()); - setThousandsSeparator( locale.thousandsSeparator() ); - setCurrencySymbol( locale.currencySymbol() ); - setMonetaryDecimalSymbol( locale.monetaryDecimalSymbol() ); - setMonetaryThousandsSeparator( locale.monetaryThousandsSeparator()); - setPositiveSign( locale.positiveSign() ); - setNegativeSign( locale.negativeSign() ); - setFracDigits( locale.fracDigits() ); - setPositivePrefixCurrencySymbol( locale.positivePrefixCurrencySymbol() ); - setNegativePrefixCurrencySymbol( locale.negativePrefixCurrencySymbol() ); - setPositiveMonetarySignPosition( locale.positiveMonetarySignPosition() ); - setNegativeMonetarySignPosition( locale.negativeMonetarySignPosition() ); - setTimeFormat( locale.timeFormat() ); - setDateFormat( locale.dateFormat() ); - setDateFormatShort( locale.dateFormatShort() ); - -} - diff --git a/kspread/kspread_locale.cpp b/kspread/kspread_locale.cpp new file mode 100644 index 00000000..fc665f0a --- /dev/null +++ b/kspread/kspread_locale.cpp @@ -0,0 +1,106 @@ +#include "kspread_locale.h" + +#include + +using namespace KSpread; + +Locale::Locale() + : TDELocale("kspread") +{ + insertCatalogue("koffice"); +} + +void Locale::load( const TQDomElement& element ) +{ + if ( element.hasAttribute( "weekStartsMonday" ) ) + { + TQString c = element.attribute( "weekStartsMonday" ); + if ( c != "False") + { + setWeekStartDay( 1 /*Monday*/ ); + } + } + if ( element.hasAttribute( "decimalSymbol" ) ) + setDecimalSymbol( element.attribute( "decimalSymbol" ) ); + if ( element.hasAttribute( "thousandsSeparator" ) ) + setThousandsSeparator( element.attribute( "thousandsSeparator" ) ); + if ( element.hasAttribute( "currencySymbol" ) ) + setCurrencySymbol( element.attribute( "currencySymbol" ) ); + if ( element.hasAttribute( "monetaryDecimalSymbol" ) ) + setMonetaryDecimalSymbol( element.attribute( "monetaryDecimalSymbol" ) ); + if ( element.hasAttribute( "monetaryThousandsSeparator" ) ) + setMonetaryThousandsSeparator( element.attribute( "monetaryThousandsSeparator" ) ); + if ( element.hasAttribute( "positiveSign" ) ) + setPositiveSign( element.attribute( "positiveSign" ) ); + if ( element.hasAttribute( "negativeSign" ) ) + setNegativeSign( element.attribute( "negativeSign" ) ); + if ( element.hasAttribute( "fracDigits" ) ) + setFracDigits( element.attribute( "fracDigits" ).toInt() ); + if ( element.hasAttribute( "positivePrefixCurrencySymbol" ) ) + { + TQString c = element.attribute( "positivePrefixCurrencySymbol" ); + setPositivePrefixCurrencySymbol( c == "True" ); + } + if ( element.hasAttribute( "negativePrefixCurrencySymbol" ) ) + { + TQString c = element.attribute( "negativePrefixCurrencySymbol" ); + setNegativePrefixCurrencySymbol( c == "True" ); + } + if ( element.hasAttribute( "positiveMonetarySignPosition" ) ) + setPositiveMonetarySignPosition( (SignPosition)element.attribute( "positiveMonetarySignPosition" ).toInt() ); + if ( element.hasAttribute( "negativeMonetarySignPosition" ) ) + setNegativeMonetarySignPosition( (SignPosition)element.attribute( "negativeMonetarySignPosition" ).toInt() ); + if ( element.hasAttribute( "timeFormat" ) ) + setTimeFormat( element.attribute( "timeFormat" ) ); + if ( element.hasAttribute( "dateFormat" ) ) + setDateFormat( element.attribute( "dateFormat" ) ); + if ( element.hasAttribute( "dateFormatShort" ) ) + setDateFormatShort( element.attribute( "dateFormatShort" ) ); +} + +TQDomElement Locale::save( TQDomDocument& doc ) const +{ + TQDomElement element = doc.createElement( "locale" ); + + element.setAttribute( "weekStartsMonday", (weekStartDay() == 1) ? "True" : "False" ); + element.setAttribute( "decimalSymbol", decimalSymbol() ); + element.setAttribute( "thousandsSeparator", thousandsSeparator() ); + element.setAttribute( "currencySymbol", currencySymbol() ); + element.setAttribute( "monetaryDecimalSymbol", monetaryDecimalSymbol() ); + element.setAttribute( "monetaryThousandsSeparator", monetaryThousandsSeparator() ); + element.setAttribute( "positiveSign", positiveSign() ); + element.setAttribute( "negativeSign", negativeSign() ); + element.setAttribute( "fracDigits", fracDigits() ); + element.setAttribute( "positivePrefixCurrencySymbol", positivePrefixCurrencySymbol() ? "True" : "False"); + element.setAttribute( "negativePrefixCurrencySymbol", negativePrefixCurrencySymbol() ? "True" : "False"); + element.setAttribute( "positiveMonetarySignPosition", (int)positiveMonetarySignPosition() ); + element.setAttribute( "negativeMonetarySignPosition", (int)negativeMonetarySignPosition() ); + element.setAttribute( "timeFormat", timeFormat() ); + element.setAttribute( "dateFormat", dateFormat() ); + element.setAttribute( "dateFormatShort", dateFormatShort() ); + + return element; +} + +void Locale::defaultSystemConfig( ) +{ + TDELocale locale("kspread"); + setWeekStartDay( locale.weekStartDay() ); + setDecimalSymbol( locale.decimalSymbol()); + setThousandsSeparator( locale.thousandsSeparator() ); + setCurrencySymbol( locale.currencySymbol() ); + setMonetaryDecimalSymbol( locale.monetaryDecimalSymbol() ); + setMonetaryThousandsSeparator( locale.monetaryThousandsSeparator()); + setPositiveSign( locale.positiveSign() ); + setNegativeSign( locale.negativeSign() ); + setFracDigits( locale.fracDigits() ); + setPositivePrefixCurrencySymbol( locale.positivePrefixCurrencySymbol() ); + setNegativePrefixCurrencySymbol( locale.negativePrefixCurrencySymbol() ); + setPositiveMonetarySignPosition( locale.positiveMonetarySignPosition() ); + setNegativeMonetarySignPosition( locale.negativeMonetarySignPosition() ); + setTimeFormat( locale.timeFormat() ); + setDateFormat( locale.dateFormat() ); + setDateFormatShort( locale.dateFormatShort() ); + +} + diff --git a/kspread/kspread_map.cc b/kspread/kspread_map.cc deleted file mode 100644 index d54c340a..00000000 --- a/kspread/kspread_map.cc +++ /dev/null @@ -1,524 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998, 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "kspread_canvas.h" -#include "kspread_doc.h" -#include "kspread_genvalidationstyle.h" -#include "kspread_locale.h" -#include "kspread_sheet.h" -#include "kspread_style.h" -#include "kspread_style_manager.h" -#include "kspread_view.h" -#include "KSpreadMapIface.h" - -#include "kspread_map.h" - -using namespace KSpread; - -bool Map::respectCase = true; - -Map::Map ( Doc* doc, const char* name) - : TQObject( doc, name ), - m_doc( doc ), - m_initialActiveSheet( 0 ), - m_initialMarkerColumn( 0 ), - m_initialMarkerRow( 0 ), - m_initialXOffset(0.0), - m_initialYOffset(0.0), - tableId (1), - m_dcop( 0 ) -{ - m_lstSheets.setAutoDelete( true ); -} - -Map::~Map() -{ - delete m_dcop; -} - -Doc* Map::doc() const -{ - return m_doc; -} - -void Map::setProtected( TQCString const & passwd ) -{ - m_strPassword = passwd; -} - -Sheet* Map::createSheet() -{ - TQString s( i18n("Sheet%1") ); - s = s.arg( tableId++ ); - Sheet *t = new Sheet ( this, s , s.utf8()); - t->setSheetName( s, true ); // huh? (Werner) - return t; -} - -void Map::addSheet( Sheet *_sheet ) -{ - m_lstSheets.append( _sheet ); - - m_doc->setModified( true ); - - emit sig_addSheet( _sheet ); -} - -Sheet *Map::addNewSheet () -{ - Sheet *t = createSheet (); - addSheet (t); - return t; -} - -void Map::moveSheet( const TQString & _from, const TQString & _to, bool _before ) -{ - Sheet* sheetfrom = findSheet( _from ); - Sheet* sheetto = findSheet( _to ); - - int from = m_lstSheets.find( sheetfrom ) ; - int to = m_lstSheets.find( sheetto ) ; - if ( !_before ) - ++to; - - if ( to > (int)m_lstSheets.count() ) - { - m_lstSheets.append( sheetfrom ); - m_lstSheets.take( from ); - } - else if ( from < to ) - { - m_lstSheets.insert( to, sheetfrom ); - m_lstSheets.take( from ); - } - else - { - m_lstSheets.take( from ); - m_lstSheets.insert( to, sheetfrom ); - } -} - -void Map::loadOasisSettings( KoOasisSettings &settings ) -{ - KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); - KoOasisSettings::IndexedMap viewMap = viewSettings.indexedMap( "Views" ); - KoOasisSettings::Items firstView = viewMap.entry( 0 ); - - KoOasisSettings::NamedMap sheetsMap = firstView.namedMap( "Tables" ); - kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) exist : "<< !sheetsMap.isNull() < it( m_lstSheets ); - for( ; it.current(); ++it ) - { - it.current()->loadOasisSettings( sheetsMap ); - } - } - - TQString activeSheet = firstView.parseConfigItemString( "ActiveTable" ); - kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) activeSheet :"<views().isEmpty() ? 0 : dynamic_cast(m_doc->views().getFirst()); - if ( view ) // no view if embedded document - { - // save current sheet selection before to save marker, otherwise current pos is not saved - view->saveCurrentSheetSelection(); - //Feuille1 - settingsWriter.addConfigItem( "ActiveTable", view->activeSheet()->sheetName() ); - } - - // - settingsWriter.startElement("config:config-item-map-named" ); - settingsWriter.addAttribute("config:name","Tables" ); - TQPtrListIterator it( m_lstSheets ); - for( ; it.current(); ++it ) - { - settingsWriter.startElement( "config:config-item-map-entry" ); - settingsWriter.addAttribute( "config:name", ( *it )->sheetName() ); - if ( view ) - { - TQPoint marker = view->markerFromSheet( *it ); - KoPoint offset = view->offsetFromSheet( *it ); - settingsWriter.addConfigItem( "CursorPositionX", marker.x() ); - settingsWriter.addConfigItem( "CursorPositionY", marker.y() ); - settingsWriter.addConfigItem( "xOffset", offset.x() ); - settingsWriter.addConfigItem( "yOffset", offset.y() ); - } - it.current()->saveOasisSettings( settingsWriter ); - settingsWriter.endElement(); - } - settingsWriter.endElement(); -} - - -bool Map::saveOasis( KoXmlWriter & xmlWriter, KoGenStyles & mainStyles, KoStore *store, KoXmlWriter* manifestWriter, int &_indexObj, int &_partIndexObj ) -{ - if ( !m_strPassword.isEmpty() ) - { - xmlWriter.addAttribute("table:structure-protected", "true" ); - TQCString str = KCodecs::base64Encode( m_strPassword ); - xmlWriter.addAttribute("table:protection-key", TQString( str.data() ) );/* FIXME !!!!*/ - } - - GenValidationStyles valStyle; - - KTempFile bodyTmpFile; - //Check that creation of temp file was successful - if (bodyTmpFile.status() != 0) - { - tqWarning("Creation of temporary file to store document body failed."); - return false; - } - - bodyTmpFile.setAutoDelete( true ); - TQFile* tmpFile = bodyTmpFile.file(); - KoXmlWriter bodyTmpWriter( TQT_TQIODEVICE(tmpFile) ); - - - TQPtrListIterator it( m_lstSheets ); - for( ; it.current(); ++it ) - { - it.current()->saveOasis( bodyTmpWriter, mainStyles, valStyle, store, manifestWriter, _indexObj, _partIndexObj ); - } - - valStyle.writeStyle( xmlWriter ); - - - tmpFile->close(); - xmlWriter.addCompleteElement( TQT_TQIODEVICE(tmpFile) ); - bodyTmpFile.close(); - - return true; -} - -TQDomElement Map::save( TQDomDocument& doc ) -{ - TQDomElement mymap = doc.createElement( "map" ); - // Save visual info for the first view, such as active sheet and active cell - // It looks like a hack, but reopening a document creates only one view anyway (David) - View * view = static_cast(m_doc->views().getFirst()); - if ( view ) // no view if embedded document - { - Canvas * canvas = view->canvasWidget(); - mymap.setAttribute( "activeTable", canvas->activeSheet()->sheetName() ); - mymap.setAttribute( "markerColumn", canvas->markerColumn() ); - mymap.setAttribute( "markerRow", canvas->markerRow() ); - mymap.setAttribute( "xOffset", canvas->xOffset() ); - mymap.setAttribute( "yOffset", canvas->yOffset() ); - } - - if ( !m_strPassword.isNull() ) - { - if ( m_strPassword.size() > 0 ) - { - TQCString str = KCodecs::base64Encode( m_strPassword ); - mymap.setAttribute( "protected", TQString( str.data() ) ); - } - else - mymap.setAttribute( "protected", "" ); - } - - TQPtrListIterator it( m_lstSheets ); - for( ; it.current(); ++it ) - { - TQDomElement e = it.current()->saveXML( doc ); - if ( e.isNull() ) - return e; - mymap.appendChild( e ); - } - return mymap; -} - -bool Map::loadOasis( const TQDomElement& body, KoOasisLoadingContext& oasisContext ) -{ - if ( body.hasAttributeNS( KoXmlNS::table, "structure-protected" ) ) - { - TQCString passwd( "" ); - if ( body.hasAttributeNS( KoXmlNS::table, "protection-key" ) ) - { - TQString p = body.attributeNS( KoXmlNS::table, "protection-key", TQString() ); - TQCString str( p.latin1() ); - passwd = KCodecs::base64Decode( str ); - } - m_strPassword = passwd; - } - TQDomNode sheetNode = KoDom::namedItemNS( body, KoXmlNS::table, "table" ); - - // sanity check - if ( sheetNode.isNull() ) return false; - - while ( !sheetNode.isNull() ) - { - TQDomElement sheetElement = sheetNode.toElement(); - if( !sheetElement.isNull() ) - { - //kdDebug()<<" Map::loadOasis tableElement is not null \n"; - //kdDebug()<<"tableElement.nodeName() :"<setSheetName( sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ), true, false ); - } - } - } - sheetNode = sheetNode.nextSibling(); - } - - //pre-load auto styles - TQDict