// XDrawChem
// Copyright (C) 2004-2005  Bryan Herger <bherger@users.sourceforge.net>
// Copyright (C) 2020  Yaman Qalieh <ybq987@gmail.com>

// 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 3 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, see <https://www.gnu.org/licenses/>.

#include <QApplication>
#include <QBitmap>
#include <QCloseEvent>
#include <QColorDialog>
#include <QDateTime>
#include <QDesktopWidget>
#include <QFontComboBox>
#include <QFontDialog>
#include <QGridLayout>
#include <QLineEdit>
#include <QMenuBar>
#include <QMessageBox>
#include <QStatusBar>
#include <QTemporaryDir>
#include <QWhatsThis>
#include <qfontdatabase.h>
#include <qkeysequence.h>
#include <qnamespace.h>
#include <qvalidator.h>
#include <unistd.h>

#include "application.h"
#include "charsel.h"
#include "chemdata.h"
#include "colorbutton.h"
#include "crings_dialog.h"
#include "defs.h"
#include "drawable.h"
#include "dyk.h"
#include "fixeddialog.h"
#include "helpwindow.h"
#include "myfiledialog.h"
#include "netaccess.h"
#include "netchoosedialog.h"
#include "netdialog.h"
#include "pagesetupdialog.h"
#include "peptidebuilder.h"
#include "render2d.h"
#include "renderarea.h"
#include "ringdialog.h"
#include "xdc_event.h"
#include "xdc_toolbutton.h"
#include "xruler.h"

// Brackets
#include "brackets.h"
// end brackets

// Symbols
#include "newman-anti.xpm"
#include "newman-eclipse.xpm"
#include "newman.xpm"
#include "symbol_xpm.h"
// end symbols

// Arrows
#include "arrows.h"
#include "ccw180.xpm"
#include "ccw270.xpm"
#include "ccw90.xpm"
#include "cubicbezier.h"
#include "cw180.xpm"
#include "cw270.xpm"
#include "cw90.xpm"
// end Arrows

// defined in main.cpp
// extern QString RingDir, HomeDir;

ApplicationWindow::ApplicationWindow() : QMainWindow() {
    setFont(preferences.getMainFont());

    // new, fancy PNG icon
    setWindowIcon(QIcon(":/icons/xdrawchem-icon.png"));

    OBGetFilters();

    // What's This? text for top toolbar
    QString fileOpenText = tr("Click this button to open a file.<br><br>You can also select the "
                              "Open command from the File menu.");
    QString fileSaveText = tr("Click this button to save the file you are editing.<br><br>You can "
                              "also select the Save command from the File menu.<br><br>");
    QString filePrintText = tr("Click this button to print the file you are editing.<br><br>You "
                               "can also select the Print command from the File menu.");
    QString editCutText = tr("Click this button to cut a selection.<br><br>You can also select "
                             "the Cut command from the Edit menu, or press Ctrl+X.");
    QString editCopyText = tr("Click this button to copy a selection.<br><br>You can also select "
                              "the Copy command from the Edit menu, or press Ctrl+C.");
    QString editPasteText = tr("Click this button to paste a selection.<br><br>You can also select "
                               "the Paste command from the Edit menu, or press Ctrl+V.");
    QString editMPText = tr("Click this button to zoom in.");
    QString editMMText = tr("Click this button to zoom out.");

    // What's This? text for left side toolbar
    QString selectToolText = tr("Select tool<br><br>Use the Select tool to select and move items "
                                "inside a box.<br><br>You can select multiple items and cut, copy, "
                                "move and rotate them.");
    QString lassoToolText = tr("Lasso tool<br><br>Use the Lasso tool to select and move items by "
                               "drawing a loop around them.<br><br>You can select multiple items "
                               "and cut, copy, move and rotate them.");
    QString eraseToolText = tr("Erase tool<br><br>Use the Erase tool to erase individual items.");
    QString lineToolText = tr("Line tool<br><br>Use the Line tool to draw bonds.  Draw over "
                              "existing bonds to create double and triple bonds.");
    QString dashLineToolText =
        tr("Dashed Line tool<br><br>Use the Dashed Line tool to draw dashed "
           "lines.  Draw over existing bonds to add dashed lines (to indicate "
           "resonance, etc.).");
    QString chainToolText = tr("Chain tool<br><br>Use the Chain tool to draw aliphatic chains.  "
                               "The length of each segment is the current bond length.");
    QString upLineToolText = tr("Stereo Up Line tool<br><br>Use the Line tool to draw stereo-up "
                                "lines, as shown on the button.");
    QString downLineToolText =
        tr("Stereo Down Line tool<br><br>Use the Line tool to draw stereo-down "
           "lines, as shown on the button.");
    QString wavyLineToolText =
        tr("Wavy Line tool<br><br>Use the Wavy Line tool to draw wavy lines, "
           "as shown on the button.");
    QString arrowToolText = tr("Arrow tool<br><br>Use the Arrow tool to draw straight "
                               "arrows.<br><br>Click to draw a straight arrow.<br><br>Click and "
                               "hold to pick from a list of available arrows.");
    QString cArrowToolText =
        tr("Curved Arrow tool<br><br>Use the Curved Arrow tool to insert "
           "curved arrows.<br><br>Click and hold to select from a picture menu "
           "of arrows.");
    QString bracketToolText = tr("Bracket tool<br><br>Use the Bracket tool to draw brackets and "
                                 "parentheses.<br><br>Click to draw square brackets.<br><br>Click "
                                 "and hold to select from a picture menu of brackets.");
    QString textToolText = tr("Text tool<br><br>Use the Text tool to add text and label atoms and "
                              "points.<br>(See manual for info on formatting text)");
    QString ringToolText = tr("Ring tool<br><br>Use the Ring tool to insert ready-made rings and "
                              "structures.<br><br>Click to open the ring dialog, which allows "
                              "selection from a list of all built-in rings and "
                              "structures.<br><br>Click and hold to select from a picture menu of "
                              "select rings.<br>(See manual for more info on modifying this menu)");
    QString symbolToolText = tr("Symbol tool<br><br>Use the Symbol tool to "
                                "insert symbols.<br><br>Click and hold to "
                                "select from a picture menu of symbols.<br>");

    printer = new QPrinter;

    m_centralWidget = new QWidget(this);
    setCentralWidget(m_centralWidget);

    /// create scrolling viewport and render widget
    m_renderArea = new RenderArea(m_centralWidget);
    m_renderer = new Render2D(m_renderArea);
    m_renderArea->setWidget(m_renderer);
    m_renderArea->setAlignment(Qt::AlignCenter);
    connect(m_renderArea, SIGNAL(scrolled(int, int)), SLOT(svXY(int, int)));
    m_renderArea->viewport()->installEventFilter(this);

    /// create grid layout
    QGridLayout *glo = new QGridLayout(m_centralWidget);

    m_rulerUnitLabel = new QLabel(m_centralWidget);
    m_rulerUnitLabel->setText(QString::fromLatin1("px"));
    glo->addWidget(m_rulerUnitLabel, 0, 0);
    vruler = new XRuler(m_centralWidget);
    vruler->setHV(2);
    vruler->setFixedWidth(20);
    glo->addWidget(vruler, 1, 0);
    hruler = new XRuler(m_centralWidget);
    hruler->setHV(1);
    hruler->setFixedHeight(20);
    glo->addWidget(hruler, 0, 1);
    glo->addWidget(m_renderArea, 1, 1);

    /**
     * top toolbar
     */
    fileTools = new QToolBar(tr("File Operations"), this);
    addToolBar(fileTools);

    QAction *fileOpenAction =
        fileTools->addAction(QIcon(":/icons/fileopen.png"), tr("Open file"), this, SLOT(load()));

    fileOpenAction->setWhatsThis(fileOpenText);

    QAction *fileSaveAction =
        fileTools->addAction(QIcon(":/icons/filesave.png"), tr("Save file"), this, SLOT(save()));

    fileSaveAction->setWhatsThis(fileSaveText);

    QAction *filePrintAction =
        fileTools->addAction(QIcon(":/icons/fileprint.png"), tr("Print file"), this, SLOT(print()));

    filePrintAction->setWhatsThis(filePrintText);

    QAction *cutAction =
        fileTools->addAction(QIcon(":/icons/cuttool.png"), tr("Cut"), this, SLOT(Cut()));

    cutAction->setWhatsThis(editCutText);

    QAction *copyAction =
        fileTools->addAction(QIcon(":/icons/copytool.png"), tr("Copy"), this, SLOT(Copy()));

    copyAction->setWhatsThis(editCopyText);

    QAction *pasteAction =
        fileTools->addAction(QIcon(":/icons/pastetool.png"), tr("Paste"), this, SLOT(Paste()));

    pasteAction->setWhatsThis(editPasteText);

    QAction *magPlusAction = fileTools->addAction(QIcon(":/icons/mag_plus.png"), tr("Zoom In"), this,
                                                  SLOT(MagnifyPlus()));

    magPlusAction->setWhatsThis(editMPText);

    QAction *magMinusAction = fileTools->addAction(QIcon(":/icons/mag_minus.png"), tr("Zoom Out"),
                                                   this, SLOT(MagnifyMinus()));

    magMinusAction->setWhatsThis(editMMText);

    //     QPixmap tmp_pm = QPixmap( 32, 20 );
    //
    //     tmp_pm.fill( QColor( 210, 210, 210 ) );
    //     QPainter pixpaint( &tmp_pm );
    //
    //     pixpaint.fillRect( 2, 3, 14, 14, QColor( 0, 0, 0 ) );
    //     pixpaint.setPen( QColor( 0, 0, 0 ) );
    //     pixpaint.drawLine( 24, 2, 24, 16 );
    //     pixpaint.drawLine( 24, 16, 20, 12 );
    //     pixpaint.drawLine( 24, 16, 28, 12 );
    //     setColorAction = fileTools->addAction( QIcon( tmp_pm ), tr( "Color"
    //     ), this, SLOT( NewColor() ) );

    colorBtn = new ColorButton(m_renderer->GetColor());
    connect(colorBtn, SIGNAL(pressed()), SLOT(NewColor()));
    fileTools->addWidget(colorBtn);

    ltList = new QComboBox(fileTools);
    ltList->setToolTip(tr("Set line thickness"));
    ltList->setWhatsThis(tr("Set Line Thickness"));

    ltList->addItem(QIcon(":/icons/line1.png"), "1");
    ltList->addItem(QIcon(":/icons/line2.png"), "2");
    ltList->addItem(QIcon(":/icons/line3.png"), "3");
    ltList->addItem(QIcon(":/icons/line4.png"), "4");
    ltList->addItem(QIcon(":/icons/line5.png"), "5");
    connect(ltList, SIGNAL(activated(int)), SLOT(SetThick(int)));

    fileTools->addWidget(ltList);

    QFontComboBox *fonts = new QFontComboBox;
    fonts->setFontFilters(QFontComboBox::ScalableFonts);
    fonts->setWritingSystem(QFontDatabase::Latin);
    connect(fonts, SIGNAL(currentFontChanged(const QFont &)), SLOT(setFontFace(const QFont &)));
    fileTools->addWidget(fonts);

    // TODO GitLab Issue #32
    fontSizeList = new QComboBox(fileTools);
    fontSizeList->setToolTip(tr("Set font size"));
    fontSizeList->setWhatsThis(tr("Set Font Size"));

    fontSizeList->setEditable(true);
    fontSizeList->setInsertPolicy(QComboBox::InsertAtBottom);
    QDoubleValidator *double_validator = new QDoubleValidator;
    double_validator->setBottom(0.05);
    double_validator->setNotation(QDoubleValidator::StandardNotation);
    fontSizeList->setValidator(double_validator);
    fontSizeList->addItem("8");
    fontSizeList->addItem("9");
    fontSizeList->addItem("10");
    fontSizeList->addItem("11");
    fontSizeList->addItem("12");
    fontSizeList->addItem("13");
    fontSizeList->addItem("14");
    fontSizeList->addItem("16");
    fontSizeList->addItem("18");
    fontSizeList->addItem("24");
    fontSizeList->addItem("32");
    fontSizeList->setCurrentIndex(2);
    connect(fontSizeList, SIGNAL(textActivated(const QString &)), this,
            SLOT(setFontPoints(const QString &)));

    fileTools->addWidget(fontSizeList);

    justifyLeftAction =
        fileTools->addAction(QIcon(":/icons/justifylefttool.png"), tr("Left-justify selected text"),
                             m_renderer, SLOT(JustifyLeft()));
    justifyLeftAction->setVisible(false);

    justifyCenterAction =
        fileTools->addAction(QIcon(":/icons/justifycentertool.png"), tr("Center selected text"),
                             m_renderer, SLOT(JustifyCenter()));
    justifyCenterAction->setVisible(false);

    justifyRightAction =
        fileTools->addAction(QIcon(":/icons/justifyrighttool.png"),
                             tr("Right-justify selected text"), m_renderer, SLOT(JustifyRight()));
    justifyRightAction->setVisible(false);

    boldAction =
        fileTools->addAction(QIcon(":/icons/boldtool.png"), tr("Make selected text <b>bold</b>"),
                             m_renderer, SLOT(Bold()));
    boldAction->setVisible(false);

    italicAction =
        fileTools->addAction(QIcon(":/icons/italictool.png"), tr("<i>Italicize</i> selected text"),
                             m_renderer, SLOT(Italic()));
    italicAction->setVisible(false);

    underlineAction =
        fileTools->addAction(QIcon(":/icons/underlinetool.png"), tr("Underline selected text"),
                             m_renderer, SLOT(Underline()));
    underlineAction->setVisible(false);

    superscriptAction =
        fileTools->addAction(QIcon(":/icons/superscript.png"), tr("Superscript selected text"),
                             m_renderer, SLOT(Superscript()));
    superscriptAction->setVisible(false);

    subscriptAction =
        fileTools->addAction(QIcon(":/icons/subscript.png"), tr("Subscript selected text"),
                             m_renderer, SLOT(Subscript()));
    subscriptAction->setVisible(false);

    QAction *whatsThisAction = QWhatsThis::createAction(fileTools);

    fileTools->addAction(whatsThisAction);

    /**
     * left side toolbar
     */
    drawTools = new QToolBar(tr("Tools"), this);
    addToolBar(Qt::LeftToolBarArea, drawTools);

    QAction *selectAction = drawTools->addAction(QIcon(":/icons/selecttool.svg"), tr("Select"),
                                                 m_renderer, SLOT(setMode_Select()));
    selectAction->setShortcut(QKeySequence(tr("s")));
    selectAction->setWhatsThis(selectToolText);

    QAction *lassoAction = drawTools->addAction(QIcon(":/icons/lassotool.svg"), tr("Lasso"),
                                                m_renderer, SLOT(setMode_Lasso()));
    lassoAction->setShortcut(QKeySequence(tr("l")));
    lassoAction->setWhatsThis(lassoToolText);

    QAction *eraseAction = drawTools->addAction(QIcon(":/icons/erasetool.svg"), tr("Erase"),
                                                m_renderer, SLOT(setMode_Erase()));
    eraseAction->setShortcut(QKeySequence(tr("e")));
    eraseAction->setWhatsThis(eraseToolText);

    QAction *drawLineAction = drawTools->addAction(QIcon(":/icons/linetool.svg"), tr("Draw Line"),
                                                   m_renderer, SLOT(setMode_DrawLine()));
    drawLineAction->setShortcut(QKeySequence(tr("d")));
    drawLineAction->setWhatsThis(lineToolText);

    QAction *drawDashLineAction =
        drawTools->addAction(QIcon(":/icons/dashtool.svg"), tr("Draw dashed line"), m_renderer,
                             SLOT(setMode_DrawDashLine()));

    drawDashLineAction->setWhatsThis(dashLineToolText);

    QAction *drawChainAction =
        drawTools->addAction(QIcon(":/icons/chaintool.svg"), tr("Draw aliphatic chain"), m_renderer,
                             SLOT(setMode_DrawChain()));
    drawChainAction->setShortcut(QKeySequence(tr("c")));
    drawChainAction->setWhatsThis(chainToolText);

    QAction *drawUpLineAction =
        drawTools->addAction(QIcon(":/icons/uptool.svg"), tr("Draw stereo-up line"), m_renderer,
                             SLOT(setMode_DrawUpLine()));

    drawUpLineAction->setWhatsThis(upLineToolText);

    QAction *drawDownLineAction =
        drawTools->addAction(QIcon(":/icons/downtool.svg"), tr("Draw stereo-down line"), m_renderer,
                             SLOT(setMode_DrawDownLine()));

    drawDownLineAction->setWhatsThis(downLineToolText);

    QAction *drawWavyLineAction =
        drawTools->addAction(QIcon(":/icons/wavytool.svg"), tr("Draw wavy bond"), m_renderer,
                             SLOT(setMode_DrawWavyLine()));

    drawWavyLineAction->setWhatsThis(wavyLineToolText);

    /// textbutton
    QAction *drawTextAction =
        drawTools->addAction(QIcon(":/icons/texttool.svg"), tr("Draw or edit text"), m_renderer,
                             SLOT(setMode_DrawText()));
    drawTextAction->setShortcut(QKeySequence(tr("t")));
    drawTextAction->setWhatsThis(textToolText);

    /// arrowbutton
    drawArrowButton = new QToolButton();
    regularArrowMenu = BuildArrowMenu();
    drawArrowButton->setMenu(regularArrowMenu);
    drawArrowButton->setPopupMode(QToolButton::MenuButtonPopup);
    drawArrowButton->setDefaultAction(regularArrowAction);
    drawArrowButton->setWhatsThis(arrowToolText);
    drawArrowButton->setIcon(QIcon(":/icons/regulararrow.svg"));
    drawArrowButton->setShortcut(QKeySequence(tr("a")));
    connect(drawArrowButton, SIGNAL(triggered(QAction *)), SLOT(FromArrowMenu(QAction *)));
    connect(regularArrowMenu, SIGNAL(triggered(QAction *)), SLOT(setRegularArrowAction(QAction *)));
    drawTools->addWidget(drawArrowButton);

    /// curvearrowbutton
    drawCurveArrowButton = new QToolButton();
    curveArrowMenu = BuildCurveArrowMenu();
    drawCurveArrowButton->setMenu(curveArrowMenu);
    drawCurveArrowButton->setPopupMode(QToolButton::MenuButtonPopup);
    drawCurveArrowButton->setDefaultAction(carrowCW90Action);
    drawCurveArrowButton->setWhatsThis(cArrowToolText);
    drawCurveArrowButton->setIcon(QIcon(":/icons/clockwise90arrow.svg"));
    drawCurveArrowButton->setShortcut(QKeySequence(tr("Shift+A")));
    connect(drawCurveArrowButton, SIGNAL(triggered(QAction *)),
            SLOT(FromCurveArrowMenu(QAction *)));
    connect(curveArrowMenu, SIGNAL(triggered(QAction *)), SLOT(setCurveArrowAction(QAction *)));
    drawTools->addWidget(drawCurveArrowButton);

    /// bracketbutton
    drawBracketButton = new QToolButton();
    bracketMenu = BuildBracketMenu();
    drawBracketButton->setMenu(bracketMenu);
    drawBracketButton->setPopupMode(QToolButton::MenuButtonPopup);
    drawBracketButton->setDefaultAction(squareBracketAction);
    drawBracketButton->setWhatsThis(bracketToolText);
    drawBracketButton->setIcon(QIcon(QPixmap(squarebracket_xpm)));
    drawBracketButton->setShortcut(QKeySequence(tr("b")));
    connect(drawBracketButton, SIGNAL(triggered(QAction *)), SLOT(FromBracketMenu(QAction *)));
    connect(bracketMenu, SIGNAL(triggered(QAction *)), SLOT(setBracketAction(QAction *)));
    drawTools->addWidget(drawBracketButton);

    // QAction *drawRingAction = new QAction( QIcon( ":/icons/ringtool.png" ),
    // tr( "Draw ring" ), this );

    drawRingButton = new QToolButton();
    ringMenu = BuildNewRingMenu();
    drawRingButton->setMenu(ringMenu);
    drawRingButton->setPopupMode(QToolButton::MenuButtonPopup);
    drawRingButton->setDefaultAction(ring5Action);
    drawRingButton->setWhatsThis(ringToolText);
    drawRingButton->setShortcut(QKeySequence(tr("r")));
    connect(drawRingButton, SIGNAL(triggered(QAction *)), SLOT(setRingAction(QAction *)));
    drawTools->addWidget(drawRingButton);

    /// symbolbutton
    drawSymbolButton = new QToolButton(this);
    QMenu *symbolMenu = BuildSymbolMenu();
    drawSymbolButton->setMenu(symbolMenu);
    drawSymbolButton->setPopupMode(QToolButton::MenuButtonPopup);
    drawSymbolButton->setWhatsThis(symbolToolText);
    connect(symbolMenu, SIGNAL(triggered(QAction *)), SLOT(setSymbolAction(QAction *)));
    drawTools->addWidget(drawSymbolButton);

    addToolBarBreak(Qt::LeftToolBarArea);

    /**
     * second (left? right?) toolbar - predefined rings
     */
    ringTools = new QToolBar(tr("Common Rings"), this);
    addToolBar(Qt::LeftToolBarArea, ringTools);

    XDC_ToolButton *b1;
    b1 = new XDC_ToolButton(ringTools, "cyclopropane.cml");
    b1->setIcon(QIcon(":/icons/cyclopropane.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    b1 = new XDC_ToolButton(ringTools, "cyclobutane.cml");
    b1->setIcon(QIcon(":/icons/cyclobutane.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    b1 = new XDC_ToolButton(ringTools, "cyclopentane.cml");
    b1->setIcon(QIcon(":/icons/cyclopentane.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    b1 = new XDC_ToolButton(ringTools, "cyclopentadiene.cml");
    b1->setIcon(QIcon(":/icons/cyclopentadiene.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    b1 = new XDC_ToolButton(ringTools, "cyclohexane.cml");
    b1->setIcon(QIcon(":/icons/cyclohexane.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    b1 = new XDC_ToolButton(ringTools, "benzene.cml");
    b1->setIcon(QIcon(":/icons/benzene.svg"));
    connect(b1, SIGNAL(pressed()), b1, SLOT(trigger()));
    connect(b1, SIGNAL(IncludeFile(QString)), this, SLOT(FromRingToolbar(QString)));
    ringTools->addWidget(b1);

    /* may have to use these for Qt 4...
    QAction *cyclopropaneAction = ringTools->addAction( QIcon(
    ":/icons/cyclopropane.png" ), tr( "Cyclopropane" ), this, SLOT(
    FromRingToolbar( QString("cyclopropane.cml") ) ) );

    QAction *cyclobutaneAction = ringTools->addAction( QIcon(
    ":/icons/cyclobutane.png" ), tr( "Cyclobutane" ), this, SLOT(
    FromRingToolbar( QString("cyclobutane.cml") ) ) );

    QAction *cyclopentaneAction = ringTools->addAction( QIcon(
    ":/icons/cyclopentane.png" ), tr( "Cyclopentane" ), this, SLOT(
    FromRingToolbar( QString("cyclopentane.cml") ) ) );

    QAction *cyclopentadieneAction = ringTools->addAction( QIcon(
    ":/icons/cyclopentadiene.png" ), tr( "Cyclopentadiene" ), this, SLOT(
    FromRingToolbar( QString("cyclopentadiene.cml") ) ) );

    QAction *cyclohexaneAction = ringTools->addAction( QIcon(
    ":/icons/cyclohexane.png" ), tr( "Cyclohexane" ), this, SLOT(
    FromRingToolbar( QString("cyclohexane.cml") ) ) );

    QAction *ring_chairAction = ringTools->addAction( QIcon(
    ":/icons/6ring_chair.png" ), tr( "Cyclohexane - chair conformation" ), this,
    SLOT( FromRingToolbar( QString("6ring_chair.cml") ) ) );

    QAction *ring_boatAction = ringTools->addAction( QIcon(
    ":/icons/6ring_boat.png" ), tr( "Cyclohexane - boat conformation" ), this,
    SLOT( FromRingToolbar( QString("6ring_boat.cml") ) ) );

    QAction *benzeneAction = ringTools->addAction( QIcon( ":/icons/benzene.png"
    ), tr( "Benzene" ), this, SLOT( FromRingToolbar( QString("benzene.cml") ) )
    );
    */

    /**
     * BioTools toolbar
     */
    // bioTools = BuildBioTools();
    // addToolBar(Qt::RightToolBarArea, bioTools);

    /**
     * menus
     *
     * file menu
     */
    QMenu *file = menuBar()->addMenu(tr("&File"));

    file->addAction(tr("&New"), this, SLOT(newDoc()), QKeySequence::New);
    file->addAction(tr("&Open"), this, SLOT(load()), QKeySequence::Open);
    file->addAction(tr("&Find on Internet"), this, SLOT(MakeNetDialog()), QKeySequence::Find);
    file->addAction(tr("&Save"), this, SLOT(save()), QKeySequence::Save);
    file->addAction(tr("Save &as..."), this, SLOT(saveAs()), QKeySequence::SaveAs);
    file->addAction(tr("Save picture..."), this, SLOT(savePicture()));

    // TODO GitLab Issue #59
    /*
    file->addSeparator();

    file->addAction(tr("Send to &external program..."), this, SLOT(externalProgram()));
     */

    // TODO GitLab Issue #25
    /*
    file->addSeparator();

    file->addAction(tr("Pa&ge setup"), this, SLOT(pageSetup()));
     */

    file->addAction(tr("&Print"), this, SLOT(print()), QKeySequence::Print);

    file->addSeparator();

    file->addAction(tr("Close"), this, SLOT(close()), QKeySequence::Close);
    file->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence::Quit);

    /**
     * edit menu
     */
    edit = menuBar()->addMenu(tr("&Edit"));

    edit->addAction(tr("&Undo"), this, SLOT(Undo()), QKeySequence::Undo);
    edit->addAction(tr("&Redo"), this, SLOT(Redo()), QKeySequence::Redo);
    insertSymbolAction = edit->addAction(tr("Insert s&ymbol"), this, SLOT(InsertSymbol()));
    insertSymbolAction->setVisible(false);

    edit->addSeparator();

    edit->addAction(tr("Cu&t"), this, SLOT(Cut()), QKeySequence::Cut);
    edit->addAction(tr("&Copy"), this, SLOT(Copy()), QKeySequence::Copy);
    edit->addAction(tr("&Paste"), this, SLOT(Paste()), QKeySequence::Paste);
    edit->addAction(tr("Clear"), this, SLOT(Clear()), QKeySequence::Delete);

    edit->addSeparator();

    edit->addAction(tr("Select &All"), this, SLOT(SelectAll()), QKeySequence::SelectAll);
    edit->addAction(tr("&Deselect All"), this, SLOT(DeselectAll()), QKeySequence::Deselect);

    QMenu *rotateSub = new QMenu(tr("&Rotate"), this);

    rotateSub->addAction(tr("Rotate 90 degrees clockwise"), this, SLOT(Rotate90()));
    rotateSub->addAction(tr("Rotate 180 degrees"), this, SLOT(Rotate180()));
    rotateSub->addAction(tr("Rotate 90 degrees counterclockwise"), this, SLOT(Rotate270()));

    QMenu *flipSub = new QMenu(tr("&Flip"), this);

    flipSub->addAction(tr("Flip &horizontal"), this, SLOT(FlipH()));
    flipSub->addAction(tr("Flip &vertical"), this, SLOT(FlipV()));

    QMenu *zoomSub = new QMenu(tr("&Zoom"), this);

    zoomSub->addAction(tr("Normal (100%)"), this, SLOT(Magnify100()), Qt::CTRL + Qt::Key_0);
    zoomSub->addAction(tr("Zoom out"), this, SLOT(MagnifyMinus()), QKeySequence::ZoomOut);
    zoomSub->addAction(tr("Zoom in"), this, SLOT(MagnifyPlus()), QKeySequence::ZoomIn);

    edit->addMenu(rotateSub);
    edit->addMenu(flipSub);

    edit->addSeparator();

    edit->addMenu(zoomSub);

    /**
     * group menu
     */
    QMenu *groupmenu = menuBar()->addMenu(tr("&Group"));

    groupmenu->addAction(tr("Select &Reactant"), this, SLOT(setGroup_Reactant()));
    groupmenu->addAction(tr("Select &Product"), this, SLOT(setGroup_Product()));
    groupmenu->addAction(tr("Clear &group"), this, SLOT(clearGroup()));
    groupmenu->addAction(tr("Clear all &groups"), this, SLOT(clearAllGroups()));

    /**
     * format menu
     */
    format = menuBar()->addMenu(tr("Forma&t"));

    fixedBondAction =
        format->addAction(tr("&Bond - Fixed length and angle"), this, SLOT(setFixed_bond()));
    fixedBondAction->setCheckable(true);
    fixedBondAction->setChecked(preferences.getBond_fixed());

    fixedArrowAction =
        format->addAction(tr("&Arrow - Fixed length and angle"), this, SLOT(setFixed_arrow()));
    fixedArrowAction->setCheckable(true);
    fixedArrowAction->setChecked(preferences.getArrow_fixed());

    format->addSeparator();

    format->addAction(tr("Set background &color"), this, SLOT(BackgroundColor()));
    format->addAction(tr("Toggle &grid"), this, SLOT(toggleGrid()), Qt::CTRL + Qt::Key_G);

    format->addSeparator();

    format->addAction(tr("&Drawing settings..."), this, SLOT(ShowFixedDialog()));
    format->addAction(tr("&XDC settings..."), this, SLOT(XDCSettings()));

    /**
     * tools menu
     */
    QMenu *tools = menuBar()->addMenu(tr("T&ools"));

    tools->addAction(tr("Clean up molecule"), this, SLOT(CleanUpMolecule()));
    tools->addAction(tr("Auto &layout"), this, SLOT(AutoLayout()), Qt::CTRL + Qt::Key_L);
    tools->addAction(tr("Create custom ring"), this, SLOT(saveCustomRing()));

    tools->addSeparator();

    tools->addAction(tr("Molecule information..."), this, SLOT(MoleculeInfo()),
                     Qt::CTRL + Qt::Key_I);
    tools->addAction(tr("Predict 1H NMR"), this, SLOT(Calc1HNMR()));
    tools->addAction(tr("Predict 13C NMR"), this, SLOT(Calc13CNMR()));
    tools->addAction(tr("Predict IR"), this, SLOT(CalcIR()));
    tools->addAction(tr("Predict pKa"), this, SLOT(CalcpKa()));
    tools->addAction(tr("Predict octanol-water partition (Kow)"), this, SLOT(CalcKOW()));

    QMenu *reactionSub = new QMenu(tr("Reaction"), this);

    reactionSub->addAction(tr("Estimate gas-phase enthalphy change"), this,
                           SLOT(reactionAnalysisEnthalpy()));
    reactionSub->addAction(tr("Compare 1H NMR"), this, SLOT(reactionAnalysis1HNMR()));
    reactionSub->addAction(tr("Compare 13C NMR"), this, SLOT(reactionAnalysis13CNMR()));

    reactionSub->addSeparator();

    reactionSub->addAction(tr("Reverse reactions"), this, SLOT(reactivityRetro()));
    reactionSub->addAction(tr("Get bond identifier"), this, SLOT(RetroBondName()));

    tools->addMenu(reactionSub);

    tools->addSeparator();

    tools->addAction(tr("Input InChI or SMILES"), this, SLOT(FromSMILES()));
    tools->addAction(tr("Output SMILES"), this, SLOT(ToSMILES()));
    tools->addAction(tr("Output InChI"), this, SLOT(ToInChI()));

    // TODO GitLab Issue #58
    // tools->addSeparator();
    // tools->addAction(tr("Build 3D model of molecule"), this, SLOT(To3D()));

    /**
     * help menu
     */
    QMenu *help = menuBar()->addMenu(tr("&Help"));

    help->addAction(tr("&Manual"), this, SLOT(NewManual()), QKeySequence::HelpContents);
    help->addAction(tr("&Did You Know?"), this, SLOT(showDYK()));
    help->addAction(tr("&About"), this, SLOT(about()));
    help->addAction(tr("&Support"), this, SLOT(support()));
    help->addAction(tr("&References"), this, SLOT(Refs()));

    help->addSeparator();

    help->addAction(tr("What's &This"), this, SLOT(whatsThis()), QKeySequence::WhatsThis);

    /**
     * create data system
     */
    m_chemData = new ChemData;

    /// connect (non-Qt) data center and render widget
    m_renderer->setChemData(m_chemData);
    m_chemData->setRender2D(m_renderer);
    connect(m_renderer, SIGNAL(XDCEventSignal(XDC_Event *)), m_chemData,
            SLOT(XDCEventHandler(XDC_Event *)));
    // connect m_renderer to application window
    connect(m_renderer, SIGNAL(textOn(QFont)), SLOT(showTextButtons(QFont)));
    connect(m_renderer, SIGNAL(TextOff()), SLOT(HideTextButtons()));
    connect(m_renderer, SIGNAL(SignalSetStatusBar(QString)), SLOT(SetStatusBar(QString)));
    connect(m_chemData, SIGNAL(SignalSetStatusBar(QString)), SLOT(SetStatusBar(QString)));
    connect(m_renderer, SIGNAL(SignalHelpTopic(QString)), SLOT(HelpTopic(QString)));
    connect(m_chemData, SIGNAL(SignalHelpTopic(QString)), SLOT(HelpTopic(QString)));
    connect(m_chemData, SIGNAL(SignalUpdateCustomRingMenu()), SLOT(updateCustomRingMenu()));

    statusBar()->showMessage("Ready");
    showMaximized();
}

// externalProgram() sends to an external program
void ApplicationWindow::externalProgram() {
    // supported programs
#define PROGRAM_KRYOMOL 1
#define PROGRAM_GHEMICAL 2

    int sendto = 0, qbox, passfail = 0;

    qbox = QMessageBox::question(this, tr("Send to external program"),
                                 tr("This function will open a 3-D version of one molecule\nin an "
                                    "external modelling program.\n\nSend to program:"),
                                 tr("Ghemical"), tr("KryoMol"), tr("Cancel"), 2);

    sendto = (qbox + 1) % 3;

    if (sendto > 0) {
        QTemporaryDir dir;
        if (!dir.isValid()) {
            QMessageBox::critical(this, tr("Send to external program failed"),
                                  tr("Could not create temporary directory."));
            return;
        }
        Molecule *mol = m_chemData->firstMolecule();
        if (!mol) {
            QMessageBox::critical(this, tr("Send to external program failed"),
                                  tr("Could not find molecule to send."));
            return;
        }

        QString exportName = QDateTime::currentDateTime().toString("yyyyMMddhhmm.'m'ol");
        exportName = dir.filePath(exportName);
        qDebug() << "export " << exportName;

        mol->Make3DVersion(exportName);
        if (!QFile::exists(exportName)) {
            QMessageBox::critical(this, tr("Send to external program failed"),
                                  tr("Could not save file for external program."));
            return;
        }
        if (sendto == 1) {
            qDebug() << "Ghemical: ";
            exportName.prepend("ghemical ");
            passfail = system(exportName.toLatin1());
            qDebug() << passfail;
        }
        if (sendto == 2) {
            qDebug() << "KryoMol: ";
            exportName.prepend("kryomol ");
            passfail = system(exportName.toLatin1());
            qDebug() << passfail;
        }
        if (passfail != 0) {
            QMessageBox::critical(this, tr("Send to external program failed"),
                                  tr("Could not execute the external program.\nPlease verify "
                                     "that it is installed correctly."));
            return;
        }
    }
}

QMenu *ApplicationWindow::BuildSymbolMenu() {
    QMenu *symbolSub = new QMenu(this);

    QAction *defaultaction = symbolSub->addAction(QIcon(":/icons/sym_plus.png"), tr("Plus sign"));
    defaultaction->setData("sym_plus");
    drawSymbolButton->setDefaultAction(defaultaction);

    symbolSub->addAction(QIcon(":/icons/sym_minus.png"), tr("Minus sign"))->setData("sym_minus");
    symbolSub->addAction(QIcon(":/icons/sym_delta_plus.png"), tr("Delta plus"))
        ->setData("sym_delta_plus");
    symbolSub->addAction(QIcon(":/icons/sym_minus.png"), tr("Delta minus"))
        ->setData("sym_delta_minus");
    symbolSub->addAction(QIcon(":/icons/sym_1e.png"), tr("1e symbol"))->setData("sym_1e");
    symbolSub->addAction(QIcon(":/icons/sym_2e.png"), tr("2e symbol"))->setData("sym_2e");
    symbolSub->addAction(QIcon(":/icons/sym_2e_line.png"), tr("2e line"))->setData("sym_2e_line");
    symbolSub->addAction(QIcon(QPixmap(sym_ring_up_xpm)), tr("Ring up"))->setData("sym_ring_up");
    symbolSub->addAction(QIcon(QPixmap(p_orbital_xpm)), tr("Orbital"))->setData("p_orbital");
    symbolSub->addAction(QIcon(QPixmap(p_double_xpm)), tr("Double orbital"))
        ->setData("p_double_orbital");
    symbolSub->addAction(QIcon(QPixmap(bead_xpm)), tr("Bead"))->setData("bead");
    symbolSub->addAction(QIcon(QPixmap(sym_antibody)), tr("Antibody"))->setData("antibody");
    symbolSub->addAction(QIcon(QPixmap(newman_xpm)), tr("Newman projection symbol"))
        ->setData("newman");
    symbolSub
        ->addAction(QIcon(QPixmap(newman_anti_xpm)), tr("Newman projection - staggered (anti)"))
        ->setData("newman_anti");
    symbolSub->addAction(QIcon(QPixmap(newman_eclipse_xpm)), tr("Newman projection - eclipsed"))
        ->setData("newman_gauche");

    return symbolSub;
}

QMenu *ApplicationWindow::BuildArrowMenu() {
    QMenu *arrowSub = new QMenu(this);

    regularArrowAction =
        arrowSub->addAction(QIcon(":/icons/regulararrow.svg"), tr("Regular Arrow"));
    topharpoonArrowAction =
        arrowSub->addAction(QIcon(":/icons/upharpoonarrow.svg"), tr("Top harpoon"));
    bottomharpoonAction =
        arrowSub->addAction(QIcon(":/icons/downharpoonarrow.svg"), tr("Bottom harpoon"));
    middleArrowAction = arrowSub->addAction(QIcon(":/icons/middlearrow.svg"), tr("Middle"));
    didntworkArrowAction =
        arrowSub->addAction(QIcon(":/icons/negationarrow.svg"), tr("Did not work"));
    dashedArrowAction = arrowSub->addAction(QIcon(":/icons/dashedarrow.svg"), tr("Dashed arrow"));
    bi1ArrowAction = arrowSub->addAction(QIcon(":/icons/bidirectionalarrow1.svg"), tr("BI1 arrow"));
    bi2ArrowAction = arrowSub->addAction(QIcon(":/icons/bidirectionalarrow2.svg"), tr("BI2 arrow"));
    retroArrowAction =
        arrowSub->addAction(QIcon(":/icons/retrosynthesisarrow.svg"), tr("Retro arrow"));

    return arrowSub;
}

QMenu *ApplicationWindow::BuildCurveArrowMenu() {
    QMenu *arrowSub = new QMenu(this);

    carrowCW90Action = arrowSub->addAction(QIcon(":/icons/clockwise90arrow.svg"), tr("90° cw"));
    carrowCCW90Action =
        arrowSub->addAction(QIcon(":/icons/counterclockwise90arrow.svg"), tr("90° ccw"));
    carrowCW180Action = arrowSub->addAction(QIcon(":/icons/clockwise180arrow.svg"), tr("180° cw"));
    carrowCCW180Action =
        arrowSub->addAction(QIcon(":/icons/counterclockwise180arrow.svg"), tr("180° ccw"));
    carrowCW270Action = arrowSub->addAction(QIcon(":/icons/clockwise270arrow.svg"), tr("270° cw"));
    carrowCCW270Action =
        arrowSub->addAction(QIcon(":/icons/counterclockwise270arrow.svg"), tr("270° ccw"));
    // TODO Implement these actions (GitLab Issue #27)
    // carrowBezierAction = arrowSub->addAction(QIcon(QPixmap(cbezier_xpm)), tr("Cubic bezier"));
    // carrowBezierhalfAction =
    //     arrowSub->addAction(QIcon(QPixmap(cbezierhalf_xpm)), tr("Cubic bezier - half arrow"));
    // carrowBezierfullAction =
    //     arrowSub->addAction(QIcon(QPixmap(cbezierfull_xpm)), tr("Cubic bezier - full arrow"));

    return arrowSub;
}

QMenu *ApplicationWindow::BuildBracketMenu() {
    QMenu *bracketSub = new QMenu(this);

    squareBracketAction =
        bracketSub->addAction(QIcon(QPixmap(squarebracket_xpm)), tr("Square bracket"));
    curveBracketAction =
        bracketSub->addAction(QIcon(QPixmap(curvebracket_xpm)), tr("Curve bracket"));
    braceBracketAction =
        bracketSub->addAction(QIcon(QPixmap(bracebracket_xpm)), tr("Brace bracket"));
    boxBracketAction = bracketSub->addAction(QIcon(QPixmap(boxbracket_xpm)), tr("Box bracket"));
    ellipseBracketAction =
        bracketSub->addAction(QIcon(QPixmap(ellipsebracket_xpm)), tr("Ellipse bracket"));
    closedsquareBracketAction =
        bracketSub->addAction(QIcon(QPixmap(closedsquarebracket_xpm)), tr("Closed square bracket"));
    circleBracketAction =
        bracketSub->addAction(QIcon(QPixmap(circlebracket_xpm)), tr("Circle bracket"));

    return bracketSub;
}

// loads custom rings.
void ApplicationWindow::FromRingMenu(int x) {
    m_chemData->StartUndo(0, 0);
    m_chemData->DeselectAll();
    /// TODO  m_chemData->SetTopLeft(sa->viewportToContents(QPoint(0,0)));
    QString fname(ringlist[x]);

    fname.replace(fname.length() - 3, 3, QString("cml"));
    m_chemData->load(preferences.getCustomRingDir() + fname);
    m_renderer->Inserted();
}

void ApplicationWindow::updateCustomRingMenu() {
    ringMenu->removeAction(customRingMenuAction);
    QMenu *customMenu = BuildCustomRingMenu();
    ringMenu->addMenu(customMenu);
    customRingMenuAction = customMenu->menuAction();
}

void ApplicationWindow::FromRingToolbar(QString fi) {
    qDebug() << QString("FromRingToolbar:") << fi;
    m_chemData->DeselectAll();
    if (fi.contains("6ring") > 0) {
        m_renderer->setMode_DrawRing(":/ring_cml/" + fi, fi.left(fi.length() - 4));
        return;
    }
    m_renderer->setMode_DrawRing(":/ring_cml/" + fi, fi.left(fi.length() - 4), 1);
}

void ApplicationWindow::setSymbolAction(QAction *action) {
    drawSymbolButton->setDefaultAction(action);
    m_renderer->setMode_DrawSymbol(action->data().toString());
}

void ApplicationWindow::FromArrowMenu(QAction *action) {
    if (action == regularArrowAction) {
        m_renderer->setMode_DrawArrow(regularArrow);
    } else if (action == topharpoonArrowAction) {
        m_renderer->setMode_DrawArrow(topharpoonArrow);
    } else if (action == bottomharpoonAction) {
        m_renderer->setMode_DrawArrow(bottomharpoonArrow);
    } else if (action == middleArrowAction) {
        m_renderer->setMode_DrawArrow(middleArrow);
    } else if (action == didntworkArrowAction) {
        m_renderer->setMode_DrawArrow(didntworkArrow);
    } else if (action == dashedArrowAction) {
        m_renderer->setMode_DrawArrow(dashedArrow);
    } else if (action == bi1ArrowAction) {
        m_renderer->setMode_DrawArrow(bi1Arrow);
    } else if (action == bi2ArrowAction) {
        m_renderer->setMode_DrawArrow(bi2Arrow);
    } else if (action == retroArrowAction) {
        m_renderer->setMode_DrawArrow(retroArrow);
    } else {
        qDebug() << "unknown action";
    }
}

void ApplicationWindow::setRegularArrowAction(QAction *action) {
    drawArrowButton->setDefaultAction(action);
    FromArrowMenu(action);
}

void ApplicationWindow::FromCurveArrowMenu(QAction *action) {
    if (action == carrowCW90Action) {
        m_renderer->setMode_DrawCurveArrow(cw90Arrow);
    } else if (action == carrowCCW90Action) {
        m_renderer->setMode_DrawCurveArrow(ccw90Arrow);
    } else if (action == carrowCW180Action) {
        m_renderer->setMode_DrawCurveArrow(cw180Arrow);
    } else if (action == carrowCCW180Action) {
        m_renderer->setMode_DrawCurveArrow(ccw180Arrow);
    } else if (action == carrowCW270Action) {
        m_renderer->setMode_DrawCurveArrow(cw270Arrow);
    } else if (action == carrowCCW270Action) {
        m_renderer->setMode_DrawCurveArrow(ccw270Arrow);
    } else if (action == carrowBezierAction) {
        m_renderer->setMode_DrawGraphicObject(TYPE_BEZIER, 0);
    } else if (action == carrowBezierhalfAction) {
        m_renderer->setMode_DrawGraphicObject(TYPE_BEZIER, 1);
    } else if (action == carrowBezierfullAction) {
        m_renderer->setMode_DrawGraphicObject(TYPE_BEZIER, 2);
    } else {
        qDebug() << "unknown action";
    }
}

void ApplicationWindow::setCurveArrowAction(QAction *action) {
    drawCurveArrowButton->setDefaultAction(action);
    FromCurveArrowMenu(action);
}

void ApplicationWindow::FromBracketMenu(QAction *action) {
    if (action == squareBracketAction) {
        m_renderer->setMode_DrawBracket(squareBracket);
    } else if (action == curveBracketAction) {
        m_renderer->setMode_DrawBracket(curveBracket);
    } else if (action == braceBracketAction) {
        m_renderer->setMode_DrawBracket(braceBracket);
    } else if (action == boxBracketAction) {
        m_renderer->setMode_DrawBracket(boxBracket);
    } else if (action == ellipseBracketAction) {
        m_renderer->setMode_DrawBracket(ellipseBracket);
    } else if (action == closedsquareBracketAction) {
        m_renderer->setMode_DrawBracket(closedsquareBracket);
    } else if (action == circleBracketAction) {
        m_renderer->setMode_DrawBracket(circleBracket);
    } else {
        qDebug() << "unknown Action";
    }
}

void ApplicationWindow::setBracketAction(QAction *action) {
    if (action == squareBracketAction) {
        m_renderer->setMode_DrawBracket(squareBracket);
        drawBracketButton->setDefaultAction(squareBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(squarebracket_xpm)));
    } else if (action == curveBracketAction) {
        m_renderer->setMode_DrawBracket(curveBracket);
        drawBracketButton->setDefaultAction(curveBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(curvebracket_xpm)));
    } else if (action == braceBracketAction) {
        m_renderer->setMode_DrawBracket(braceBracket);
        drawBracketButton->setDefaultAction(braceBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(bracebracket_xpm)));
    } else if (action == boxBracketAction) {
        m_renderer->setMode_DrawBracket(boxBracket);
        drawBracketButton->setDefaultAction(boxBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(boxbracket_xpm)));
    } else if (action == ellipseBracketAction) {
        m_renderer->setMode_DrawBracket(ellipseBracket);
        drawBracketButton->setDefaultAction(ellipseBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(ellipsebracket_xpm)));
    } else if (action == closedsquareBracketAction) {
        m_renderer->setMode_DrawBracket(closedsquareBracket);
        drawBracketButton->setDefaultAction(closedsquareBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(closedsquarebracket_xpm)));
    } else if (action == circleBracketAction) {
        m_renderer->setMode_DrawBracket(circleBracket);
        drawBracketButton->setDefaultAction(circleBracketAction);
        drawBracketButton->setIcon(QIcon(QPixmap(circlebracket_xpm)));
    } else {
        qDebug() << "unknown Action";
    }
}

void ApplicationWindow::setFixed_arrow() {
    if (fixedArrowAction->isChecked()) {
        fixedArrowAction->setChecked(false);
        preferences.setArrow_fixed(false);
    } else {
        fixedArrowAction->setChecked(true);
        preferences.setArrow_fixed(true);
    }
}

void ApplicationWindow::setFixed_bond() {
    if (fixedBondAction->isChecked()) {
        fixedBondAction->setChecked(false);
        preferences.setBond_fixed(false);
    } else {
        fixedBondAction->setChecked(true);
        preferences.setBond_fixed(true);
    }
}

/*
void ApplicationWindow::setFix_Hydrogens()
{
    if ( format->isItemChecked( fix_hydrogens ) ) {
        format->setItemChecked( fix_hydrogens, false );
        preferences.setFixHydrogens( false );
    } else {
        format->setItemChecked( fix_hydrogens, true );
        preferences.setFixHydrogens( true );
    }
}
*/

ApplicationWindow::~ApplicationWindow() {
    delete printer;
    delete m_chemData;
}

void ApplicationWindow::SetColor(int m) {
    if (m == 0)
        m_renderer->SetColor(QColor(0, 0, 0));
    if (m == 1)
        m_renderer->SetColor(QColor(127, 0, 0));
    if (m == 2)
        m_renderer->SetColor(QColor(0, 127, 0));
    if (m == 3)
        m_renderer->SetColor(QColor(0, 0, 127));
}

void ApplicationWindow::SetThick(int t) { m_renderer->SetThick(t + 1); }

void ApplicationWindow::showTextButtons(QFont infont) {
    insertSymbolAction->setVisible(true);
    justifyLeftAction->setVisible(true);
    justifyCenterAction->setVisible(true);
    justifyRightAction->setVisible(true);
    boldAction->setVisible(true);
    italicAction->setVisible(true);
    underlineAction->setVisible(true);
    superscriptAction->setVisible(true);
    subscriptAction->setVisible(true);

    fontSizeList->setEditText(QString::number(infont.pointSize()));
}

void ApplicationWindow::HideTextButtons() {
    insertSymbolAction->setVisible(false);
    justifyLeftAction->setVisible(false);
    justifyCenterAction->setVisible(false);
    justifyRightAction->setVisible(false);
    boldAction->setVisible(false);
    italicAction->setVisible(false);
    underlineAction->setVisible(false);
    superscriptAction->setVisible(false);
    subscriptAction->setVisible(false);
    // set font combo boxes to object font (passed as infont)
    // set font combo boxes to current font
    QFont infont = m_renderer->GetFont();
    fontSizeList->setEditText(QString::number(infont.pointSize()));
}

void ApplicationWindow::newDoc() {
    ApplicationWindow *ed = new ApplicationWindow;

    // Share clipboard
    ed->setClipboard(m_renderer->getClipboard());
    ed->show();
    ed->HideTextButtons();
}

void ApplicationWindow::load() {
    OBImport();
    return;

    /* DELETE ME
       QFileDialog fd(QString(), QString(), 0, 0, TRUE);
       fd.setWindowTitle("Load file");
       fd.setMode(QFileDialog::ExistingFile);
       QStringList filters;
       filters.append("All files (*)");
       filters.append("XDrawChem native (*.xdc)");
       filters.append("MDL Molfile (*.mol)");
       filters.append("CML - Chemical Markup Language (*.cml)");
       fd.setFilters(filters);
       if ( fd.exec() == QDialog::Accepted )
       load( fd.selectedFile() );
     */
}

void ApplicationWindow::load(QString fileName) {
    OBNewLoad(fileName, "--Select a filter-- (*)");
    return;

    //
    // fix me
    // to use OpenBabel
    //
    /*
       QString realFileName = fileName;

       QFile f(fileName);
       if ( !f.open(IO_ReadOnly) ) {
       QMessageBox::warning(0, tr("Couldn't open file"), tr("Could not open the
       file: ") + fileName); statusBar()->showMessage(tr("Unable to load ") +
       fileName); return;
       }
       f.close();
       SelectAll();
       Clear();

       if ( !m_chemData->load(fileName) ) {
       statusBar()->showMessage(tr("Unable to load ") + fileName);
       return;
       }

       fileName = realFileName;
       setWindowTitle( QString(XDC_VERSION) + QString(" - ") + fileName );
       statusBar()->showMessage( tr("Loaded document ") + fileName );
       filename = fileName;
       m_chemData->DeselectAll();
       m_renderer->update();
     */
}

void ApplicationWindow::save() {
    if (filename.isEmpty()) {
        OBExport();

    } else {
        OBNewSave();
    }
}

void ApplicationWindow::saveAs() {
    OBExport();
    return;
}

void ApplicationWindow::savePicture() {
    int pm = 0;
    bool was_saved = false;
    QStringList picFiles;
    QString selectedFile;

    MyFileDialog fd(0);

    fd.setWindowTitle(tr("Save as picture..."));
    fd.setFileMode(QFileDialog::AnyFile);
    QStringList picfilters;

    picfilters.append("Portable Network Graphic (*.png)");
    picfilters.append("Windows Bitmap (*.bmp)");
    picfilters.append("Encapsulated PostScript (*.eps)");
    picfilters.append("Scalable Vector Graphics (*.svg)");
    fd.setNameFilters(picfilters);
    if (fd.exec() == QDialog::Accepted) {
        picFiles = fd.selectedFiles();
        if (!picFiles.isEmpty())
            selectedFile = picFiles.at(0);
        QString tmpx = selectedFile.right(4).toLower();

        if (tmpx == QString(".png"))
            pm = 1;
        if (tmpx == QString(".bmp"))
            pm = 2;
        if (tmpx == QString(".svg"))
            pm = 3;
        if ((tmpx != QString(".png")) && (tmpx != QString(".bmp")) && (tmpx != QString(".svg")) &&
            (tmpx != QString(".eps"))) {
            if (fd.selectedNameFilter().left(3) == QString("Por")) {
                selectedFile.append(".png");
                pm = 1;
            }
            if (fd.selectedNameFilter().left(3) == QString("Win")) {
                selectedFile.append(".bmp");
                pm = 2;
            }
            if (fd.selectedNameFilter().left(3) == QString("Enc")) {
                selectedFile.append(".eps");
            }
            if (fd.selectedNameFilter().left(3) == QString("Sca")) {
                selectedFile.append(".svg");
                pm = 3;
            }
        }
        if (pm == 3) {
            // save as Scalable Vector Graphics
            was_saved = m_renderer->SaveSVG(selectedFile);
            if (was_saved)
                statusBar()->showMessage(tr("Saved picture file ") + selectedFile);
            else
                statusBar()->showMessage(tr("Unable to save picture!"));
            return;
        }
        if (pm != 0) {
            QPixmap tosave = m_renderer->MakePixmap(fd.isTransparent());
            if (pm == 1) // PNG
                was_saved = tosave.save(selectedFile, "PNG");
            if (pm == 2) // BMP
                was_saved = tosave.save(selectedFile, "BMP");
            if (was_saved)
                statusBar()->showMessage(tr("Saved picture file ") + selectedFile);
            else
                statusBar()->showMessage(tr("Unable to save picture!"));
        } else {
            statusBar()->showMessage(tr("Unable to save picture!"));
        }
    }
}

void ApplicationWindow::savePNG() {
    bool was_saved;

    QPixmap tosave;

    tosave = m_renderer->MakePixmap(ni_tflag);
    was_saved = tosave.save(ni_savefile, "PNG");
    // QPixmap tosave = m_renderer->MakePixmap( ni_tflag );
    // was_saved = tosave.save(ni_savefile, "PNG");
    if (was_saved == false) {
        qWarning() << "save PNG failed for " << ni_savefile;
    }
    close(); // this function is only used in non-interactive mode
}

void ApplicationWindow::save3D() {
    //    bool was_saved;

    m_chemData->Save3D(ni_savefile);
    close(); // this function is only used in non-interactive mode
}

void ApplicationWindow::print() { m_renderer->Print(); }

void ApplicationWindow::closeEvent(QCloseEvent *ce) {
    if (!m_chemData->edited()) {
        ce->accept();
        return;
    }

    switch (QMessageBox::information(this, tr("Save before closing?"),
                                     tr("The document has been changed since the last save."),
                                     "Save Now", "Cancel", "Leave Anyway", 0, 1)) {
    case 0:
        save();
        ce->accept();
        break;
    case 1:
    default: // just for sanity
        ce->ignore();
        break;
    case 2:
        ce->accept();
        break;
    }
}

void ApplicationWindow::about() {
    QMessageBox::about(this, XDC_VERSION,
                       QString(XDC_VERSION) +
                           tr("\nBryan Herger\nbherger@users.sourceforge.net\n\nPlease "
                              "subscribe to the mailing list for information about future "
                              "releases.\nSend a message to "
                              "xdrawchem-announce-request@lists.sourceforge.net with "
                              "'subscribe' as the subject.\n\nXDrawChem is copyright (C) 2004 "
                              "Bryan Herger.\nPortions copyright (C) 1997-2000 Dr. Christoph "
                              "Steinbeck and the JChemPaint project\nOpenBabel code copyright "
                              "(C) 2003 by the OpenBabel project team.\nSee file "
                              "COPYRIGHT.txt for more details"));
}

void ApplicationWindow::support() {
    QMessageBox::information(
        0, tr("How to get help"),
        tr("Current information on XDrawChem can always be found "
           "at\nhttp://xdrawchem.sourceforge.net/\nThe latest release will be "
           "posted here, as well as links to mailing lists and the bug "
           "tracker.\n\nPlease submit bugs using the SourceForge tracker: "
           "http://www.sourceforge.net/tracker/?group_id=34518\n\nThere are "
           "two mailing lists:  xdrawchem-announce, where new releases will be "
           "announced,\nand xdrawchem-user, for open discussion among "
           "XDrawChem users.\nSubscribe by sending a blank e-mail with subject "
           "\"subscribe\" to "
           "\n\"xdrawchem-announce-request@lists.sourceforge.net\" "
           "or\n\"xdrawchem-user-request@lists.sourceforge.net\"\n\nYou can "
           "contact the author directly at\nbherger@users.sourceforge.net"));
}

void ApplicationWindow::whatsThis() { QWhatsThis::enterWhatsThisMode(); }

const char *reflist = "Krause S, Willighagen E, Steinbeck C, "
                      "\"JChemPaint - Using the Collaborative Forces of the Internet\nto Develop "
                      "a Free Editor for 2D Chemical Structures\", Molecules 5:93-98\n\n"
                      "Bremser W, \"HOSE - A Novel Substructure Code\", Anal. Chim. Acta 103:"
                      "355-365\n\n"
                      "Bremser W, \"Expectation Ranges of 13C NMR Chemical Shifts\", "
                      "Mag. Res. Chem. 23(4):271-275\n\n"
                      "Weininger D, \"SMILES, a Chemical Language and Information System.  1. "
                      "Introduction to Methodology and Encoding Rules\",\nJ. Chem. Inf. Comput. "
                      "Sci. 28:31-36\n\n"
                      "Figueras J, \"Ring Perception Using Breadth-First Search\", J. Chem. Inf. "
                      "Comput Sci. 36:986-991\n\n"
                      "Ugi I et al., Journal of Chemical research (M), 1991, 2601-2689\n\n"
                      "Pauling, L. \"The Nature of the Chemical Bond\", 3ed., 1960, Cornell "
                      "University Press\n\n"
                      "Pretsch, Clerc, Seibl, Simon. \"Tables of Spectral Data for Structure "
                      "Determination of Organic Compounds\", 2ed., 1989, Springer-Verlag\n\n"
                      "Lin S and Sandler SI, J. Phys. Chem. A, 2000, vol. 104, 7099-7105\n\n"
                      "Steinbeck C, JMDraw (software), http://jmdraw.sourceforge.net/\n\n"
                      "Molecules in the XDrawChem database are from the NCI Open Database, "
                      "October 1999 release:  http://cactvs.cit.nih.gov/";

void ApplicationWindow::Refs() { QMessageBox::about(this, "XDrawChem References", reflist); }

void ApplicationWindow::SetStatusBar(const QString &s) { statusBar()->showMessage(s); }

/* obsolete.
void ApplicationWindow::MakeRingDialog() {
  RingDialog t(this, "ring dialog");
  if ( !t.exec() ) return;

  m_chemData->StartUndo(0,0);
  m_chemData->DeselectAll();
  m_chemData->SetTopLeft(sv->viewportToContents(QPoint(0,0)));
  m_chemData->load( RingDir + t.getFile() );
  m_renderer->Inserted();
}
*/

void ApplicationWindow::ShowFixedDialog() {
    FixedDialog fixedDialog(this);

    if (!fixedDialog.exec())
        return;
    hruler->update();
    vruler->update();
    /*
       na = i.getAngle_arrow();
       nl = i.getLength_arrow();
       if (na < 0.0) return;
       if (nl < 0.0) return;
       preferences.setArrow_fixedangle(na);
       preferences.setArrow_fixedlength(nl);
       na = i.getAngle_bond();
       nl = i.getLength_bond();
       if (na < 0.0) return;
       if (nl < 0.0) return;
       preferences.setBond_fixedangle(na);
       preferences.setBond_fixedlength(nl);
       na = i.getDoubleBondOffset();
       if (na < 0.0) return;
       preferences.setDoubleBondOffset(na);
     */
}

/*
void ApplicationWindow::MakeNetDialog()
{
    netDlg = new NetDialog( this );
    if ( !netDlg->exec() )
        return;
    qDebug() << "Server:" << netDlg->getServer();
    qDebug() << "Key   :" << netDlg->getKey();
    qDebug() << "Value :" << netDlg->getValue();
    NetAccess *na = new NetAccess();
    connect( na, SIGNAL( choicesFinished( const QStringList & ) ), this, SLOT(
slotChoicesFinished( const QStringList & ) ) );

    setCursor( Qt::WaitCursor );
    m_renderer->setWaitCursor();
    na->getChoices( netDlg->getServer(), netDlg->getKey(), netDlg->getValue(),
netDlg->getExact() );
}
*/

void ApplicationWindow::MakeNetDialog() {
    NetDialog n(this);
    if (!n.exec())
        return;
    // cout << "Server:" << n.getServer() << Qt::endl;
    // cout << "Key   :" << n.getKey() << Qt::endl;
    // cout << "Value :" << n.getValue() << Qt::endl;
    NetAccess na;
    setCursor(Qt::WaitCursor);
    m_renderer->setWaitCursor();
    QStringList choices = na.getChoices(n.getServer(), n.getKey(), n.getValue(), n.getExact());
    setCursor(Qt::ArrowCursor);
    m_renderer->setArrowCursor();
    if (choices.count() == 0) {
        QMessageBox::warning(this, tr("Database query failed"),
                             tr("No molecules in the database match the query."));
        return;
    }
    /*
    if (choices.count() == 1) {
      int i1 = choices[0].find("|");
      QString subfile = choices[0].left(i1) + ".mol";
      QString wf = na.getFile(n.getServer(), subfile);
      c->DeselectAll();
      c->SetTopLeft(sv->viewportToContents(QPoint(0,0)));
      c->ProcessMDL(wf);
      r->Inserted();
      return;
    }
    */
    NetChooseDialog nc(this, choices);
    if (!nc.exec())
        return;
    // cout << nc.getFile() << Qt::endl;
    // TODO: insert SMILES string returned by database
    m_chemData->fromSMILES(nc.getFile());
    m_renderer->Inserted();
    m_renderer->update();

    /*
    if (nc.getFile().contains(".mol")) {
      c->DeselectAll();
      c->SetTopLeft(sv->viewportToContents(QPoint(0,0)));
      c->ProcessMDL(wf);
      r->Inserted();
     return;
    }
    */
}

void ApplicationWindow::slotChoicesFinished(const QStringList &choices) {
    qDebug() << "slotChoicesFinished";
    setCursor(Qt::ArrowCursor);
    m_renderer->setArrowCursor();
    if (choices.count() == 0) {
        QMessageBox::warning(this, tr("Database query failed"),
                             tr("No molecules in the database match the query."));
        return;
    }
    /*
       if (choices.count() == 1) {
       int i1 = choices[0].find("|");
       QString subfile = choices[0].left(i1) + ".mol";
       QString wf = na.getFile(n.getServer(), subfile);
       m_chemData->DeselectAll();
       m_chemData->SetTopLeft(sv->viewportToContents(QPoint(0,0)));
       m_chemData->ProcessMDL(wf);
       m_renderer->Inserted();
       return;
       }
     */
    NetChooseDialog nc(this, choices);

    if (!nc.exec())
        return;
    qDebug() << nc.getFile();
    // TODO: insert SMILES string returned by database
    m_chemData->fromSMILES(nc.getFile());
    m_renderer->Inserted();
    m_renderer->update();

    /*
       if (nc.getFile().contains(".mol")) {
       m_chemData->DeselectAll();
       m_chemData->SetTopLeft(sv->viewportToContents(QPoint(0,0)));
       m_chemData->ProcessMDL(wf);
       m_renderer->Inserted();
       return;
       }
     */
}

void ApplicationWindow::pageSetup() {
    PageSetupDialog p(this);

    // p.setPageSize(preferences.getPageSize());
    // p.setOrientation(preferences.getPageOrientation());
    if (!p.exec())
        return;
    // preferences.setPageSize(p.getPageSize());
    // preferences.setPageOrientation(p.getOrientation());
    m_renderer->UpdatePageGeometry();
}

void ApplicationWindow::NewColor() {
    QColor newColor = QColorDialog::getColor(m_renderer->GetColor());

    if (newColor.isValid()) {
        m_renderer->SetColor(newColor);
        colorBtn->setColor(newColor);
    }
}

void ApplicationWindow::BackgroundColor() {
    QColor nc1 = QColorDialog::getColor(m_renderer->getBGColor());

    if (nc1.isValid()) {
        m_renderer->setBGColor(nc1);
        m_renderer->update();
    }
}

// peptide builder
void ApplicationWindow::PeptideBuilder() {
    PeptDialog p1(this);

    if (!p1.exec())
        return;
    QString seq1 = p1.getPeptide();

    qDebug() << "peptide: " << seq1;
}

// help from help menu
void ApplicationWindow::NewManual() {
    QString home;

#ifdef UNIX
    home = QDir(RINGHOME).filePath("doc/index.html");
#else
    home = QDir(RINGHOME).filePath("doc\\index.html");
#endif
    HelpBrowser(QString(home));
}

// invoke context-sensitive help
void ApplicationWindow::HelpTopic(QString topic) {
    QString home;

#ifdef UNIX
    home = QDir(RINGHOME).filePath("doc/" + topic);
#else
    home = QDir(RINGHOME).filePath("doc\\" + topic);
#endif
    HelpBrowser(QString(home));
}

// new manual (based on QTextBrowser) -- derived from Qt example "helpviewer"
// Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
void ApplicationWindow::HelpBrowser(QString home) {
    HelpWindow *help = new HelpWindow(home, ".", 0);

    help->setWindowTitle(QString(XDC_VERSION) + " - Help viewer");
    if (QApplication::desktop()->width() > 400 && QApplication::desktop()->height() > 500)
        help->show();
    else
        help->showMaximized();
}
// end code covered by "helpviewer" example copyright

// pass thru to Render2D
void ApplicationWindow::Cut() { m_renderer->Cut(); }

void ApplicationWindow::Copy() { m_renderer->Copy(); }

void ApplicationWindow::Paste() { m_renderer->Paste(); }

void ApplicationWindow::Undo() { m_renderer->Undo(); }

void ApplicationWindow::Redo() { m_renderer->Redo(); }

void ApplicationWindow::FlipH() { m_renderer->Flip(FLIP_H); }

void ApplicationWindow::FlipV() { m_renderer->Flip(FLIP_V); }

void ApplicationWindow::Rotate90() { m_renderer->Rotate90(); }

void ApplicationWindow::Rotate180() { m_renderer->Rotate180(); }

void ApplicationWindow::Rotate270() { m_renderer->Rotate270(); }

void ApplicationWindow::Clear() { m_renderer->EraseSelected(); }

void ApplicationWindow::MoleculeInfo() { m_renderer->Tool(MODE_TOOL_MOLECULE_INFO); }

void ApplicationWindow::CalcEA() { m_renderer->Tool(MODE_TOOL_CALCEA); }

void ApplicationWindow::CalcEF() { m_renderer->Tool(MODE_TOOL_CALCEF); }

void ApplicationWindow::CalcMW() { m_renderer->Tool(MODE_TOOL_CALCMW); }

void ApplicationWindow::Calc13CNMR() { m_renderer->Tool(MODE_TOOL_13CNMR); }

void ApplicationWindow::Calc1HNMR() { m_renderer->Tool(MODE_TOOL_1HNMR); }

void ApplicationWindow::CalcIR() { m_renderer->Tool(MODE_TOOL_IR); }

void ApplicationWindow::CalcpKa() { m_renderer->Tool(MODE_TOOL_PKA); }

void ApplicationWindow::CalcKOW() { m_renderer->Tool(MODE_TOOL_KOW); }

void ApplicationWindow::CalcName() { m_renderer->Tool(MODE_TOOL_NAME); }

void ApplicationWindow::ToSMILES() { m_renderer->Tool(MODE_TOOL_TOSMILES); }

void ApplicationWindow::ToInChI() { m_renderer->Tool(MODE_TOOL_TOINCHI); }

void ApplicationWindow::To3D() { m_renderer->Tool(MODE_TOOL_2D3D); }

void ApplicationWindow::CleanUpMolecule() { m_renderer->Tool(MODE_TOOL_CLEANUPMOL); }

void ApplicationWindow::saveCustomRing() { m_renderer->Tool(MODE_TOOL_CUSTOMRING); }

void ApplicationWindow::SelectAll() { m_renderer->SelectAll(); }

void ApplicationWindow::DeselectAll() { m_renderer->DeselectAll(); }

void ApplicationWindow::AutoLayout() { m_renderer->AutoLayout(); }

void ApplicationWindow::DrawRegularArrow() { m_renderer->setMode_DrawArrow(regularArrow); }

void ApplicationWindow::DrawSquareBracket() { m_renderer->setMode_DrawBracket(squareBracket); }
void ApplicationWindow::CubicBezierTool(int x) {
    qDebug() << "Bezier:" << x - 6;
    m_renderer->setMode_DrawGraphicObject(TYPE_BEZIER, x - 6);
}

void ApplicationWindow::setClipboard(Clipboard *clip1) { m_renderer->setClipboard(clip1); }

void ApplicationWindow::setGroup_Reactant() { m_renderer->Tool(MODE_TOOL_GROUP_REACTANT); }

void ApplicationWindow::setGroup_Product() { m_renderer->Tool(MODE_TOOL_GROUP_PRODUCT); }

void ApplicationWindow::clearGroup() { m_renderer->Tool(MODE_TOOL_GROUP_CLEAR); }

void ApplicationWindow::Retro() { m_renderer->Tool(MODE_TOOL_RETRO); }

void ApplicationWindow::RetroAtomName() { m_renderer->Tool(MODE_TOOL_RETRO_ATOMNAME); }

void ApplicationWindow::RetroBondName() { m_renderer->Tool(MODE_TOOL_RETRO_BONDNAME); }

void ApplicationWindow::InsertSymbol() { m_renderer->InsertSymbol(); }

void ApplicationWindow::Test() {
    CharSelDialog cd1(this);

    cd1.exec();
    // m_renderer->Tool(MODE_TOOL_TEST);
}

void ApplicationWindow::clearAllGroups() { m_renderer->clearAllGroups(); }

void ApplicationWindow::reactionAnalysisTest() { m_renderer->ReactionAnalysis(RXN_TEST); }

void ApplicationWindow::reactionAnalysisEnthalpy() {
    m_renderer->ReactionAnalysis(RXN_ENTHALPY_ESTIMATE);
}

void ApplicationWindow::reactionAnalysis1HNMR() { m_renderer->ReactionAnalysis(RXN_1HNMR); }

void ApplicationWindow::reactionAnalysis13CNMR() { m_renderer->ReactionAnalysis(RXN_13CNMR); }

void ApplicationWindow::reactivityForward() { m_renderer->Tool(MODE_TOOL_REACTIVITY_FORWARD); }

void ApplicationWindow::reactivityRetro() { m_renderer->Tool(MODE_TOOL_REACTIVITY_RETRO); }

void ApplicationWindow::reactivityPC() { m_renderer->Tool(MODE_TOOL_CHARGES); }

void ApplicationWindow::toggleGrid() {
    int i1;

    i1 = preferences.getDrawGrid();
    i1++;
    if (i1 > 2)
        i1 = 0;
    preferences.setDrawGrid(i1);
    m_renderer->createGrid();
    m_renderer->update();
}

void ApplicationWindow::svXY(int x1, int y1) {
    hruler->setRange(x1, x1 + m_centralWidget->width());
    hruler->update();
    vruler->setRange(y1, y1 + m_centralWidget->height());
    vruler->update();
}

void ApplicationWindow::zoomEvent(QWheelEvent *e) {
    if (e->angleDelta().y() > 0) {
        MagnifyPlus();
    } else {
        MagnifyMinus();
    }
}

bool ApplicationWindow::eventFilter(QObject * /*obj*/, QEvent *e) {
    if (e->type() == QEvent::Wheel && (QApplication::keyboardModifiers() & Qt::ControlModifier)) {
        zoomEvent(static_cast<QWheelEvent *>(e));
        e->accept();
        return true;
    }
    return false;
}

void ApplicationWindow::showDYK() {
    DYKDialog dyk1;

    dyk1.exec();
}

void ApplicationWindow::MagnifyPlus() { Zoom(std::min(preferences.getZoom() + 25, 500)); }

void ApplicationWindow::MagnifyMinus() { Zoom(std::max(preferences.getZoom() - 25, 25)); }

void ApplicationWindow::Magnify100() { Zoom(100); }
void ApplicationWindow::Zoom(int zoom_level) {
    preferences.setZoom(zoom_level);
    m_renderer->zoomEvent();
    hruler->zoomEvent();
    vruler->zoomEvent();
    SetStatusBar(tr("Zoom = %1 %").arg(preferences.getZoom()));
}

void ApplicationWindow::XDCSettings() {
    bool ok;
    QFont font;

    switch (QMessageBox::information(this, tr("XDC Settings"), tr("Change XDrawChem settings:"),
                                     tr("&Main font"), tr("&Ruler font"), tr("Cancel"),
                                     2,    // Enter == button 2
                                     2)) { // Escape == button 2
    case 0:
        font = QFontDialog::getFont(&ok, preferences.getMainFont(), this);
        if (ok) {
            preferences.setMainFont(font);
            setFont(font);
            update();
        } else {
            return;
        }
        break;
    case 1:
        font = QFontDialog::getFont(&ok, preferences.getRulerFont(), this);
        if (ok) {
            preferences.setRulerFont(font);
            // setFont(font);
            hruler->update();
            vruler->update();
            update();
        } else {
            return;
        }
        break;
    case 2:
        return;
        break;
    }
}

void ApplicationWindow::setFontFace(const QFont &newfont) {
    qDebug() << "FontFace: " << newfont;
    m_renderer->SetFont(newfont);
}

void ApplicationWindow::setFontPoints(const QString &fn1) {
    qDebug() << "FontPoints: " << fn1;
    fontSizeList->removeItem(11); // 7 default options so delete anything more than that
    fontSizeList->setEditText(fn1);

    QFont newfont = m_renderer->GetFont();
    newfont.setPointSizeF(fn1.toDouble());
    m_renderer->SetFont(newfont);
}

// cmake#include "application.moc"
