/***************************************************************************
 *   Copyright (C) 2005-2007 by Niklas Knutsson                            *
 *   nq@altern.org                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef KQALCULATE_H
#define KQALCULATE_H

#include <tqvariant.h>
#include <tdemainwindow.h>
#include <tqvaluevector.h>
#include <tqlabel.h>
#include <tqpushbutton.h>
#include <tqstylesheet.h>
#include <ktextbrowser.h>
#include <tdelistview.h>
#include <kdialogbase.h>
#include <tdeshortcut.h>

class Prefix;
class QalculatePrecisionDialog;
class Variable;
class MathFunction;
class Unit;
class QalculateDecimalsDialog;
class QalculateEditVariableDialog;
class QalculateEditMatrixVectorDialog;
class QalculateEditUnitDialog;
class QalculateEditFunctionDialog;
class QalculateEditDataSetDialog;
class QalculateEditUnknownVariableDialog;
class QalculateVariablesDialog;
class QalculateFunctionsDialog;
class QalculateUnitsDialog;
class QalculateDataSetsDialog;
class QalculateConvertUnitsDialog;
class TDEAction;
class TDERadioAction;
class TDEToggleAction;
class TQToolBar;
class TQPopupMenu;
class KPushButton;
class QalculateExpressionEdit;
class QalculateResultDisplay;
class TQFrame;
class TQWidgetStack;
class TQWidget;
class TQComboBox;
class QalculateHistoryBrowser;
class QalculateConvertNumberBasesDialog;
class QalculatePeriodicTableDialog;
class QalculatePlotDialog;
class QalculateSetBaseDialog;
class KLineEdit;
class MathStructure;
class QalculateImportCSVDialog;
class QalculateExportCSVDialog;
class QalculatePreferencesDialog;
class QalculateInsertMatrixVectorDialog;
class KSystemTray;
class QalculateParseLabel;
class TQButtonGroup;
class TQRadioButton;
class QalculateButton;
class TQVBoxLayout;
class KSeparator;
class TDEUniqueApplication;
class TDEConfig;
class TQListViewItem;
class QalculateRPNStackListView;
class TDEGlobalAccel;
class KKeyButton;

void *view_proc(void *pipe);
void *command_proc(void *pipe);

enum {
	COMMAND_FACTORIZE,
	COMMAND_SIMPLIFY
};


class ModeObject : public TQObject {

	TQ_OBJECT
	
	public:

		ModeObject(int mode);
		int i_mode;

	public slots:

		void loadMode();
		
};

class KQalculate : public TDEMainWindow {
	
	TQ_OBJECT

public:

	KQalculate(TDEUniqueApplication *parent = 0, const char* name = 0, WFlags fl = WType_TopLevel | WDestructiveClose);
	virtual ~KQalculate();

	void setupActions();
	void setAssumptionsMenu();
	void setModeActions();
	void execute_expression(bool force = true);
	void setResult(Prefix *prefix = NULL, bool update_history = true, bool update_parse = false, bool force = false, TQString transformation = "", size_t stack_index = 0, bool register_moved = false);
	void executeCommand(int command_type);
	void result_display_updated();
	void result_format_updated();
	void result_action_executed();
	void result_prefix_changed(Prefix *prefix = NULL);
	void expression_calculation_updated();
	void expression_format_updated(bool recalculate = false);
	void display_errors(TQString *new_text = NULL, int *inhistory_index = NULL);
	void update_status_text();
	void display_function_hint(MathFunction *f, int arg_index = 1);
	void clearresult();
	void create_fmenu();
	void create_vmenu();
	void create_umenu();
	void create_toumenu();
	void create_setpmenu();
	void recreate_recent_functions();
	void recreate_recent_variables();
	void recreate_recent_units();
	void function_inserted(MathFunction *object);
	void variable_inserted(Variable *object);
	void unit_inserted(Unit *object);
	void updateStatusLabelFonts();
	void set_unicode_buttons();
	void insertButtonFunction(TQString text, bool append_space = true);
	void insertButtonFunction(MathFunction *f);
	const MathStructure *getResultPart(int);
	void insertMatrixVector(const MathStructure *m = NULL, bool do_vector = false, bool is_text_struct = false, bool is_result = false);

	void calculateRPN(int op);
	void calculateRPN(MathFunction *f);
	void RPNStackEnter(Variable *v);
	void RPNRegisterAdded(const TQString &text, size_t index = 0);
	void RPNRegisterRemoved(size_t index);
	void RPNRegisterChanged(const TQString &text, size_t index = 0);

	QalculateInsertMatrixVectorDialog *insert_matrix_dialog;
	QalculatePrecisionDialog *precisionDialog;
	QalculateDecimalsDialog *decimalsDialog;
	QalculateConvertUnitsDialog *convert_to_unit_expression_dialog;
	QalculateEditVariableDialog *variable_edit_dialog, *store_dialog;
	QalculateEditMatrixVectorDialog *matrix_edit_dialog;
	QalculateEditUnitDialog *unit_edit_dialog;
	QalculateEditFunctionDialog *function_edit_dialog;
	QalculateEditDataSetDialog *dataset_edit_dialog;
	QalculateEditUnknownVariableDialog *unknown_edit_dialog;
	QalculateVariablesDialog *variables_dialog;
	QalculateFunctionsDialog *functions_dialog;
	QalculateUnitsDialog *units_dialog;
	QalculateDataSetsDialog *datasets_dialog;
	QalculateConvertNumberBasesDialog *convert_number_bases_dialog;
	QalculatePeriodicTableDialog *periodic_table_dialog;
	QalculateImportCSVDialog *import_csv_dialog;
	QalculateExportCSVDialog *export_csv_dialog;
	QalculatePlotDialog *plot_dialog;
	QalculateSetBaseDialog *set_base_dialog;
	QalculatePreferencesDialog *preferences_dialog;
	TQMap <int, Variable*> menu_variables_ids;
	TQMap <int, MathFunction*> menu_functions_ids;
	TQMap <int, Unit*> menu_units_ids, menu_to_unit_ids;
	TQMap <int, Prefix*> menu_units_prefixes_ids, menu_set_prefix_ids;
	TQValueVector<int> recent_function_ids;
	TQValueVector<int> recent_variable_ids;
	TQValueVector<int> recent_unit_ids;

	QalculateRPNStackListView *stackList;
	TQVBoxLayout *stackPageButtonsLayout;
	QalculateButton *registerUpButton, *registerDownButton, *deleteRegisterButton, *editRegisterButton, *clearStackButton;
	TQPopupMenu *stackMenu;
	TDEUniqueApplication *m_parent;
	KSystemTray *trayicon;
	QalculateButton *executeButton, *storeButton, *convertButton;
	QalculateButton *functionsButton;
	TQVBoxLayout *leftButtonsLayout;
	KSeparator *leftButtonsSeparator;
	QalculateExpressionEdit* expressionEdit;
	TQLabel *statusLabel_r;
	QalculateParseLabel *statusLabel_l;
	QalculateResultDisplay* resultLabel;
	TQWidgetStack* mainStack;
	TQFrame *bottomLine;
	TQWidget *keypadPage, *historyPage, *stackPage;
	TQComboBox* kpNumericCombo, *kpBaseCombo;
	TQRadioButton *kpDegreesButton, *kpRadiansButton, *kpGradiansButton, *kpNoAngleUnitButton;
	TQButtonGroup *kpAngleGroup;
	TQPushButton *kpExact, *kpFraction;
	QalculateButton *kpSquare, *kpLog, *kpHyp, *kpSqrt, *kpCos, *kpRaise, *kpInv, *kpSin;
	QalculateButton *kpTan, *kpLn, *kpFactorial, *kpMod, *kpAns, *kp8, *kp0, *kp7, *kpDel, *kpDot, *kp5, *kpEquals, *kpClear;
	QalculateButton *kp3, *kp1, *kp4, *kp9, *kpDivision, *kpExp, *kp6, *kp2, *kpMinus, *kpTimes, *kpPlus;
	QalculateHistoryBrowser *historyBrowser;
	TQPushButton *historyButton, *keypadButton, *stackButton;
	KMenuBar *menubar;
	TQPopupMenu *menu_functions, *menu_variables, *menu_units, *menu_to_unit, *menu_set_prefix, *menu_modes;
	TDEToggleAction *ActionAbbreviateNames, *ActionReadPrecision, *ActionNonZeroDenominators, *ActionWarnAboutDenominatorsAssumedNonZero;
	TDEToggleAction *ActionLimitImplicitMultiplication, *ActionRPNMode, *ActionRPNSyntax, *ActionIndicateInfiniteSeries, *ActionNegativeExponents, *ActionSortMinusLast;
	TDEToggleAction *ActionShowEndingZeroes, *ActionRoundHalfwayNumbersToEven, *ActionEnablePrefixes;
	TDEToggleAction *ActionEnableUseOfAllPrefixes, *ActionEnableDenominatorPrefixes, *ActionPlaceUnitsSeparately;
	TDEToggleAction *ActionEnableVariables, *ActionEnableFunctions, *ActionEnableUnits, *ActionEnableUnknowns;
	TDEToggleAction *ActionCalculateVariables, *ActionAllowComplexResult, *ActionAllowInfiniteResult;
	TDERadioAction *ActionApproximationAlwaysExact, *ActionApproximationTryExact, *ActionApproximationApproximate;
	TDERadioAction *ActionAlgebraicModeSimplify, *ActionAlgebraicModeFactorize, *ActionAlgebraicModeNone;
	TDERadioAction *ActionFractionalDisplayDecimal, *ActionFractionalDisplayDecimalTryExact;
	TDERadioAction *ActionFractionalDisplayFraction, *ActionFractionalDisplayCombined;
	TDERadioAction *ActionNumericalDisplayEngineering, *ActionNumericalDisplayScientific, *ActionNumericalDisplayPurelyScientific, *ActionNumericalDisplaySimple, *ActionNumericalDisplayNormal;
	TDERadioAction *ActionNumberBaseBinary, *ActionNumberBaseOctal, *ActionNumberBaseDecimal, *ActionNumberBaseHexadecimal, *ActionNumberBaseOther;
	TDERadioAction *ActionNumberBaseSexagesimal, *ActionNumberBaseTimeFormat, *ActionNumberBaseRomanNumerals;
	TDERadioAction *ActionAssumptionTypeUnknown, *ActionAssumptionTypeNonMatrix, *ActionAssumptionTypeNumber, *ActionAssumptionTypeComplex, *ActionAssumptionTypeReal;
	TDERadioAction *ActionAssumptionTypeRational, *ActionAssumptionTypeInteger, *ActionAssumptionSignUnknown, *ActionAssumptionSignNonZero;
	TDERadioAction *ActionAssumptionSignPositive, *ActionAssumptionSignNonNegative, *ActionAssumptionSignNegative;
	TDERadioAction *ActionAssumptionSignNonPositive, *ActionAngleUnitDegrees, *ActionAngleUnitRadians, *ActionAngleUnitGradians;
	TDERadioAction *ActionAngleUnitNone, *ActionAutoNoConversion, *ActionAutoConvertToBaseUnits, *ActionAutoConvertToBestUnit;
	TDEAction *ActionSetBase, *ActionPrecision, *ActionDecimals, *ActionSaveModeAs, *ActionDeleteMode, *ActionSaveMode, *ActionQuit;
	TDEAction *ActionUpdateExchangeRates, *ActionManageVariables, *ActionConvertToUnitExpression, *ActionStoreResult, *ActionClose;
	TDEAction *ActionConvertNumberBases, *ActionManageFunctions, *ActionConvertToBaseUnits, *ActionConvertToBestUnit;
	TDEAction *ActionManageUnits, *ActionManageDataSets, *ActionFactorize, *ActionSimplify, *ActionSetUnknowns, *ActionCopyResult;
	TDEAction *ActionPreferences, *ActionSaveAsImage, *ActionImportCSVFile, *ActionExportCSVFile, *ActionPeriodicTable;
	TDEAction *ActionPlotFunctionsData, *ActionSaveDefinitions, *ActionNewVariable, *ActionNewMatrix, *ActionNewVector;
	TDEAction *ActionNewUnknownVariable, *ActionNewFunction, *ActionNewUnit, *ActionNewDataSet;
	TDEAction *ActionInsertMatrix, *ActionInsertVector;
	TDEAction *ActionClearHistory;
	TDEAction *ActionHideSystemTrayIcon, *ActionHide;
	TDEAction *ActionClearStack, *ActionDeleteRegister, *ActionEditRegister;
	TDEAction *ActionConfigureGlobalShortcuts;

	TDEGlobalAccel *globalAccel;

	TQValueVector<int>::size_type current_history_index;
	TQValueVector<ModeObject*> mode_objects;

public slots:

	void executeCommand2();
	void setResult2();
	void execute_expression2();

	void showHide();
	void configureGlobalShortcuts();

	void update_fmenu();
	void update_vmenu();	
	void update_umenus();
	void insertVariable(Variable*);
	void insertFunction(MathFunction*, TQWidget *parent);
	void applyFunction(MathFunction*, TQWidget *parent);
	void onExpressionChanged();
	void onErrorTimeout();
	bool fetch_exchange_rates(int);
	void update_completion();
	void insert_text(TQString);
	void aboutToQuit();
	void onVariableMenuItemActivated(int);
	void onFunctionMenuItemActivated(int);
	void onUnitMenuItemActivated(int);
	void onUnitsPrefixMenuItemActivated(int);
	void precisionRecalculate();
	void setMaxDecimals(int);
	void setMinDecimals(int);
	void execute();
	void toggleHistory(bool);
	void toggleStack(bool);
	void toggleKeypad(bool);
	void showEndingZeroes(bool);
	void approximationTryExact();
	void approximationAlwaysExact();
	void approximationApproximate();
	void fractionalDisplayDecimal();
	void fractionalDisplayDecimalTryExact();
	void fractionalDisplayFraction();
	void fractionalDisplayCombined();
	void numericalDisplayNormal();
	void numericalDisplayEngineering();
	void numericalDisplayScientific();
	void numericalDisplayPurelyScientific();
	void numericalDisplaySimple();
	void indicateInfiniteSeries(bool);
	void sortMinusLast(bool);
	void negativeExponents(bool);
	void roundHalfwayNumbersToEven(bool);
	void abbreviateNames(bool);
	void updateBaseOther();
	void numberBaseBinary();
	void numberBaseOctal();
	void numberBaseDecimal();
	void numberBaseOther();
	void numberBaseHexadecimal();
	void numberBaseSexagesimal();
	void numberBaseTimeFormat();
	void numberBaseRomanNumerals();
	void setBaseInResultFromDialogGroup(int);
	void setBaseInResultFromDialogBox(int);
	void setBaseInExpressionFromDialogGroup(int);
	void setBaseInExpressionFromDialogBox(int);
	void setBase();
	void nonZeroDenominators(bool);
	void warnAboutDenominatorsAssumedNonZero(bool);
	void algebraicModeSimplify();
	void algebraicModeFactorize();
	void algebraicModeNone();
	void readPrecision(bool);
	void limitImplicitMultiplication(bool);
	void setPrecision(int);
	void precision();
	void decimals();
	void rpnMode(bool);
	void rpnSyntax(bool);
	void assumptionSignUnknown();
	void assumptionSignNonZero();
	void assumptionSignPositive();
	void assumptionSignNonNegative();
	void assumptionSignNegative();
	void assumptionSignNonPositive();
	void assumptionTypeUnknown();
	void assumptionTypeNonMatrix();
	void assumptionTypeNumber();
	void assumptionTypeComplex();
	void assumptionTypeReal();
	void assumptionTypeRational();
	void assumptionTypeInteger();
	void loadMode(int);
	void onModesMenuItemActivated(int);
	void saveModeAs();
	void deleteMode();
	void saveMode();
	void angleUnitDegrees();
	void angleUnitRadians();
	void angleUnitGradians();
	void angleUnitNone();
	void autoNoConversion();
	void autoConvertToBaseUnits();
	void autoConvertToBestUnit();
	void enablePrefixes(bool);
	void enableUseOfAllPrefixes(bool);
	void enableDenominatorPrefixes(bool);
	void placeUnitsSeparately(bool);
	void enableVariables(bool);
	void enableFunctions(bool);
	void enableUnits(bool);
	void enableUnknowns(bool);
	void calculateVariables(bool);
	void allowComplexResult(bool);
	void allowInfiniteResult(bool);
	void updateExchangeRates();
	void insertKP1();
	void insertKP2();
	void insertKP3();
	void insertKP4();
	void insertKP5();
	void insertKP6();
	void insertKP7();
	void insertKP8();
	void insertKP9();
	void insertKP0();
	void insertDot();
	void insertExp();
	void insertAns();
	void insertMinus();
	void insertPlus();
	void insertTimes();
	void insertDivision();
	void insertCos();
	void insertSin();
	void insertTan();
	void insertSqrt();
	void insertLog();
	void insertLn();
	void insertRaise();
	void clearExpression();
	void expressionDel();
	void insertSquare();
	void setExactMode(bool);
	void setFractionMode(bool);
	void kpSetAngleUnit(int);
	void kpSetBaseSelected(int);
	void kpSetBase(int);
	void kpSetNumericalMode(int);
	void insertFactorial();
	void insertMod();
	void storeResult();
	void manageVariables();
	void convertToUnitConvertToDialogExpression();
	void convertToUnitExpression();
	void convertNumberBases();
	void insertManagedFunction(MathFunction*);
	void applyManagedFunction(MathFunction*);
	void manageFunctions();
	void manageUnits();
	void insertUnit(Unit *u);
	void convertResult(Unit *u);
	void factorize();
	void simplify();
	void manageDataSets();
	void setUnknownsApplyClicked();
	void setUnknowns();
	void convertToBaseUnits();
	void convertToBestUnit();
	void copyResult();
	void clearHistory();
	void preferences();
	void applyPreferences();
	void onConvertToUnitMenuItemActivated(int);
	void onSetPrefixMenuItemActivated(int);
	void periodicTable();
	void plotFunctionsData();
	void saveDefinitions();
	void saveAsImage();
	void importCSVFile();
	void exportCSVFile();
	void newVariable();
	void newMatrix();
	void newVector();
	void newUnknownVariable();
	void newFunction();
	void newDataSet();
	void newUnit();
	void insertMatrix();
	void insertVector();
	void showSystemTrayIcon(bool);
	void hideSystemTrayIcon();
	void displayParseStatus();
	void registerUp();
	void registerDown();
	void clearStack();
	void deleteRegister();
	void editRegister();
	void updateRPNIndexes();
	TQListViewItem *getRPNRegister(size_t index);
	void stackRegisterMoved();
	void stackRegisterSet(TQListViewItem*);
	void popupStackMenu(TDEListView*, TQListViewItem*, const TQPoint&);
	void registerSelected();
	void editHistoryExpression();
	void editHistoryParse();
	void editHistoryResult();
	void insertHistoryResultVariable();

protected:

	void updateButtonWidths();
	void applySetUnknowns(bool okclicked);
	bool b_unknowns_changed;
	TQValueVector<bool> unknown_changed;
	MathStructure *mstruct_before_unknowns, *unknowns_mstruct;
	TQValueVector<KLineEdit*> unknowns_entries;
	bool queryClose();
	TQString parsed_expression;
	void keyPressEvent(TQKeyEvent *e);
	void fontChange(const TQFont &old_font);
	void saveProperties(TDEConfig *cfg);
	void readProperties(TDEConfig *cfg);
	
private:

	bool close_to_systray_was;
	bool display_expression_status_was;
	int history_height;

};

class QalculateHistoryBrowser : public KTextBrowser {

	TQ_OBJECT
	
public:

	QalculateHistoryBrowser(TQWidget *parent, const char *name);
	~QalculateHistoryBrowser();

protected:

	TQPopupMenu *createPopupMenu(const TQPoint &pos);

};

class QalculateParseLabel : public TQLabel {

	TQ_OBJECT

public:

	QalculateParseLabel(TQWidget *parent = 0, const char *name = 0);
	virtual ~QalculateParseLabel();
	
	void setText(TQString text, bool break_begin, bool error_color, bool warning_color);
	
protected:

	TQString parsetext;
	bool bb, ec, wc;
	void drawContents(TQPainter *p);

};

class QalculateButton : public TQPushButton {

	TQ_OBJECT

public:

	QalculateButton(TQWidget *parent = 0, const char *name = 0);
	QalculateButton(const TQString &text, TQWidget *parent = 0, const char *name = 0);
	QalculateButton(const TQIconSet &icon, const TQString &text, TQWidget *parent = 0, const char *name = 0);
	virtual ~QalculateButton();
	
	void setUseMinThreeCharWidth(bool b);
	void setMarkup(const TQString &str);
	TQSize sizeHint() const;
	
private:

	bool umtcw;

};

class QalculateStyleSheet : public TQStyleSheet {

	TQ_OBJECT

public:

	QalculateStyleSheet(TQObject *parent = 0, const char *name = 0);
	virtual ~QalculateStyleSheet();
	
	void scaleFont(TQFont &font, int logicalSize) const;

};

class QalculateRPNStackListView : public TDEListView {

	TQ_OBJECT

public:

	QalculateRPNStackListView(TQWidget *parent = 0, const char *name = 0);
	virtual ~QalculateRPNStackListView();

protected:

	void keyPressEvent(TQKeyEvent *e);

};

class QalculateModeDialog : public KDialogBase {
	
	TQ_OBJECT
	
	protected:

		KKeyButton *keyButton;
		KComboBox *modeCombo;
		
	public:
		
		QalculateModeDialog(TQWidget *parent);
		virtual ~QalculateModeDialog();

		TQString modeName();
		const TDEShortcut &modeShortcut();

	public slots:
		
		void slotOk();
		void updateShortcut(const TDEShortcut&);
		void modeSelected(int);
		
};

#endif // QALCULATE_KWINDOW_H
