#include "spreadsheet.h"
#ifdef CREATE_OBJS_WITH_QICSTABLE
#include <QPrintDialog>
#include <QPrinter>
#endif
#ifdef QSA
#include <qsproject.h>
#include <qsscript.h>
#include <qsworkbench.h>
#include <qsinterpreter.h>
#endif
#include <QicsDataModelDefault.h>
#include <QicsTable.h>
#include <QicsRowHeader.h>
#include <QicsColumnHeader.h>
#include <QicsColumn.h>
#include <QicsSelection.h>
#include <QicsMainGrid.h>
#include <QicsCellRegion.h>
#include <QicsCell.h>
#include <QicsRegionalAttributeController.h>
#include "QicsDataItemCurrencyFormatter.h"
#include "editcopy.xpm"
#include "editcut.xpm"
#include "editpaste.xpm"
#include "filenew.xpm"
#include "fileopen.xpm"
#include "filesave.xpm"
#include "fontcolor.xpm"
#include "sortasc.xpm"
#include "sortdesc.xpm"
#include "textbold.xpm"
#include "textitalic.xpm"
#include "textunder.xpm"
#include "textleft.xpm"
#include "textcenter.xpm"
#include "textright.xpm"
Spreadsheet::Spreadsheet(QWidget* parent) :
QMainWindow(parent)
{
setWindowTitle("Excellent Spreadsheet Demo");
QMenuBar *mainMenu = menuBar();
QMenu* file = mainMenu->addMenu("&File");
file->addAction("&New", this, SLOT(fileNew()), QKeySequence("Ctrl+N"));
file->addAction("&Open", this, SLOT(openFile()), QKeySequence("Ctrl+O"));
file->addAction("&Save", this, SLOT(saveFile()), QKeySequence("Ctrl+S"));
file->addAction("S&ave As ...", this, SLOT(saveFileAs()));
file->addSeparator();
#ifdef CREATE_OBJS_WITH_QICSTABLE
file->addAction("P&rint", this, SLOT(print()), QKeySequence("Ctrl+P"));
file->addSeparator();
#endif
file->addAction("E&xit", qApp, SLOT(closeAllWindows()), QKeySequence("Ctrl+x"));
QMenu* edit = mainMenu->addMenu("&Edit");
edit->addAction("&Copy", this, SLOT(copy()),QKeySequence("Ctrl+C"));
edit->addAction("&Paste", this, SLOT(paste()),QKeySequence("Ctrl+V"));
QMenu* view = mainMenu->addMenu("&View");
QMenu* tablem = mainMenu->addMenu("&Table");
tablem->addAction("Insert &Row", this, SLOT(insertRow()));
tablem->addAction("Insert &Column", this, SLOT(insertColumn()));
tablem->addSeparator();
tablem->addAction("Delete Row(s)", this, SLOT(deleteRow()));
tablem->addAction("Delete Column(s)", this, SLOT(deleteColumn()));
QMenu* format = mainMenu->addMenu("F&ormat");
QMenu* rowFormat = format->addMenu("&Row");
format->addSeparator();
format->addAction("&Font...", this, SLOT(formatFont()));
format->addAction("Fore&ground...", this,
SLOT(formatForegroundColor()));
format->addAction("&Background...", this,
SLOT(formatBackgroundColor()));
QMenu* tools = mainMenu->addMenu("Tools");
tools->addAction("&Script Editor", this, SLOT(showQSAWorkbench()));
tools->addAction("Script &Test", this, SLOT(testScripts()));
tools->addAction("Save Scripts", this, SLOT(saveScripts()));
QMenu* data = mainMenu->addMenu("&Data");
data->addAction("Sort &Ascending", this, SLOT(sortAscending()));
data->addAction("Sort &Descending", this, SLOT(sortDescending()));
QMenu* spans = mainMenu->addMenu("&Spans");
spans->addAction("Add Span", this, SLOT(addSpan()));
spans->addAction("Remove Span", this, SLOT(removeSpan()));
QToolBar* fileTools = new QToolBar("File tools",this);
fileTools->addAction(QIcon(filenew),"&New", this, SLOT(fileNew()));
fileTools->addAction(QIcon(fileopen),"&Open", this, SLOT(openFile()));
fileTools->addAction(QIcon(filesave),"&Save", this, SLOT(saveFile()));
fileTools->addSeparator();
fileTools->addAction(QIcon(editcut),"&Cut", this, SLOT(cut()));
fileTools->addAction(QIcon(editcopy),"&Copy", this, SLOT(copy()));
fileTools->addAction(QIcon(editpaste),"Paste", this, SLOT(paste()));
fileTools->addSeparator();
fileTools->addAction(QIcon(sortasc_xpm),"Sort Ascending", this, SLOT(sortAscending()));
fileTools->addAction(QIcon(sortdesc_xpm),"Sort Descending", this, SLOT(sortDescending()));
fileTools->addSeparator();
addToolBar(fileTools);
QToolBar* fontTools = new QToolBar("Font tools",this);
fontFamilyCombo = new QComboBox(fontTools);
fontSizeCombo = new QComboBox(fontTools);
fontTools->addWidget(fontFamilyCombo);
fontTools->addWidget(fontSizeCombo);
connect(fontFamilyCombo, SIGNAL(activated(int)),
this, SLOT(selectFont(int)));
connect(fontSizeCombo, SIGNAL(activated(int)),
this, SLOT(selectFontSize(int)));
QFontDatabase fdb;
QStringList families = fdb.families();
fontFamilyCombo->addItems(families);
boldAction = new QAction(QIcon(textbold),"Bold", this);
fontTools->addAction(boldAction);
boldAction->setCheckable(true);
connect(boldAction,SIGNAL(triggered()),this,SLOT(textBold()));
italicAction = new QAction(QIcon(textitalic),"Italic", this);
fontTools->addAction(italicAction);
italicAction->setCheckable(true);
connect(italicAction,SIGNAL(triggered()),this,SLOT(textItalic()));
underlineAction = new QAction(QIcon(textunder),"Underline", this);
fontTools->addAction(underlineAction);
underlineAction->setCheckable(true);
connect(underlineAction,SIGNAL(triggered()),this,SLOT(textUnderline()));
fontTools->addSeparator();
textLeftAction = new QAction(QIcon(textleft),"Align Left", this);
fontTools->addAction(textLeftAction);
textLeftAction->setCheckable(true);
connect(textLeftAction,SIGNAL(triggered()),this,SLOT(textAlignLeft()));
textCenterAction = new QAction(QIcon(textcenter),"Align Center", this);
fontTools->addAction(textCenterAction);
textCenterAction->setCheckable(true);
connect(textCenterAction,SIGNAL(triggered()),this,SLOT(textAlignCenter()));
textRightAction = new QAction(QIcon(textright),"Align Right", this);
fontTools->addAction(textRightAction);
textRightAction->setCheckable(true);
connect(textRightAction,SIGNAL(triggered()),this,SLOT(textAlignRight()));
fontTools->addSeparator();
QToolButton* currencyTB =
new QToolButton(fontTools);
currencyTB->setText("$");
connect(currencyTB, SIGNAL(clicked()),
this, SLOT(setCurrencyFormatter()));
fontTools->addWidget(currencyTB);
fontTools->addSeparator();
fontTools->addAction(
QPixmap(fontcolor_xpm), "Font Color",
this, SLOT(formatForegroundColor()));
fontTools->addAction(
QIcon("./images/fillcolor.png"), "Fill Color",
this, SLOT(formatBackgroundColor()));
addToolBar(fontTools);
QWidget *vbox = new QWidget(this);
QVBoxLayout *vboxLayout = new QVBoxLayout();
QWidget *cellrow = new QWidget(vbox);
QHBoxLayout *cellrowLayout = new QHBoxLayout();
cellrowLayout->setMargin(2);
cellrowLayout->addWidget(new QLabel("Cell Value = "));
cellLineEdit = new QLineEdit();
cellrowLayout->addWidget(cellLineEdit);
cellrow->setLayout(cellrowLayout);
connect(cellLineEdit, SIGNAL(returnPressed()),
this, SLOT(cellLineUpdate()));
int lastRow = 1000;
int lastCol = 1000;
dm = new QicsDataModelDefault(lastRow, lastCol);
table = new QicsTable(dm);
QicsRegionalAttributeController controller;
table->setExternalAttributeController(controller);
vboxLayout->addWidget(cellrow);
vboxLayout->addWidget(table);
vbox->setLayout(vboxLayout);
connect(table, SIGNAL(selectionListChanged(bool)),
this, SLOT(updateSelection(bool)));
table->rowHeader()->setAlignment(Qt::AlignHCenter);
table->columnHeader()->setAlignment(Qt::AlignHCenter);
table->rowHeader()->column(0)->setWidthInChars(3);
table->mainGridRef().setBackgroundColor(Qt::white);
table->setRowsSortingMode( Qics::QicsStableSort );
table->setNavigatorAllowed(true);
table->setWideKeyActions();
table->columnHeaderRef().setAllowUserMove(true);
table->rowHeaderRef().setAllowUserMove(true);
table->show();
setFontCombos(table->font());
setCentralWidget(vbox);
statusBar()->showMessage("Ready", -1);
fileName = QString::null;
#ifdef QSA
project = new QSProject( this, "spreadsheet_project" );
project->addObject(this);
QSInterpreter* interpreter = project->interpreter();
project->load( "Spreadsheet.qsa" );
#endif
connect(table,SIGNAL(rowResized(int,int,int)),this,SLOT(resized()));
connect(table,SIGNAL(columnResized(int,int,int)),this,SLOT(resized()));
}
#ifdef QSA
void Spreadsheet::saveScripts()
{
project->save("Spreadsheet.qsa");
}
void Spreadsheet::testScripts()
{
QStringList list = project->interpreter()->functions();
for (QStringList::Iterator it = list.begin();
it != list.end(); ++it)
{
cout << *it << endl;
}
QList<QVariant> args;
args.append(1);
args.append(1);
project->interpreter()->call("sum", args);
QSScript* script = project->script("Spreadsheet.qs");
if (script)
cout << script->code() << endl;
else
cout << "No script by that name" << endl;
}
static QSWorkbench *spreadsheet_ide = 0;
void Spreadsheet::showQSAWorkbench()
{
if (!spreadsheet_ide )
{
spreadsheet_ide = new QSWorkbench( project, this, "qside" );
}
spreadsheet_ide->open();
}
#else
void Spreadsheet::showQSAWorkbench()
{
QMessageBox::warning(0, tr("No QSA support!"),
tr("Sorry, no QSA support compiled in"),
QMessageBox::Ok, QMessageBox::NoButton);
}
void Spreadsheet::testScripts()
{
QMessageBox::warning(0, tr("No QSA support!"),
tr("Sorry, no QSA support compiled in"),
QMessageBox::Ok, QMessageBox::NoButton);
}
void Spreadsheet::saveScripts()
{
QMessageBox::warning(0, tr("No QSA support!"),
tr("Sorry, no QSA support compiled in"),
QMessageBox::Ok, QMessageBox::NoButton);
}
#endif
void Spreadsheet::setCurrencyFormatter()
{
this->getSelectedRegion();
if ( (startSelectedRow > -1 ) && (startSelectedColumn > -1) )
{
int i, j;
QicsDataItemCurrencyFormatter* currency =
new QicsDataItemCurrencyFormatter();
for (i = startSelectedRow; i < endSelectedRow; i++)
for (j = startSelectedColumn; j < endSelectedColumn; j++)
table->cellRef(i,j).setFormatter(currency);
}
}
QString Spreadsheet::getCellValue(int row, int col)
{
return dm->itemString(row, col);
}
void Spreadsheet::setCellValue(int row, int col, int value)
{
dm->setItem(row, col, value);
}
void Spreadsheet::cellLineUpdate()
{
this->getSelectedRegion();
if ( (startSelectedRow > -1 ) && (startSelectedColumn > -1) )
{
int row = startSelectedRow;
int col = startSelectedColumn;
bool ok;
int i = cellLineEdit->text().toInt(&ok);
if (ok)
{
dm->setItem(row, col, i);
return;
}
float f = cellLineEdit->text().toFloat(&ok);
if (ok)
{
dm->setItem(row, col, f);
return;
}
dm->setItem(row, col, cellLineEdit->text());
}
}
void Spreadsheet::selectFont(int combo)
{
Q_UNUSED(combo);
QString family = fontFamilyCombo->currentText();
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFontFamily(family, true);
}
}
void Spreadsheet::selectFontSize(int combo)
{
Q_UNUSED(combo);
int size = fontSizeCombo->currentText().toInt();
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFontSize(size, true);
}
}
void Spreadsheet::formatBackgroundColor()
{
QColor color = QColorDialog::getColor();
if (! color.isValid())
{
return;
}
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setBackgroundColor(color);
}
}
void Spreadsheet::formatForegroundColor()
{
QColor color = QColorDialog::getColor();
if (! color.isValid())
{
return;
}
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setForegroundColor(color);
}
}
void Spreadsheet::formatFont()
{
bool ok;
QFont font = QFontDialog::getFont(&ok, QFont("Helvetica", 10), this);
if (!ok )
{
return;
}
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFont(font);
}
}
void Spreadsheet::updateSelection(bool in_progress)
{
if (in_progress)
{
return;
}
this->getSelectedRegion();
if ( (startSelectedRow > -1 ) && (startSelectedColumn > -1) )
{
QFont font = table->cellRef(startSelectedRow, startSelectedColumn).font();
setFontCombos(font);
if (font.bold())
{
boldAction->setChecked(true);
}
else
{
boldAction->setChecked(false);
}
if (font.italic())
{
italicAction->setChecked(true);
}
else
{
italicAction->setChecked(false);
}
if (font.underline())
{
underlineAction->setChecked(true);
}
else
{
underlineAction->setChecked(false);
}
int alignment = table->cellRef(startSelectedRow, startSelectedColumn).alignment();
switch (alignment)
{
case Qt::AlignLeft:
textLeftAction->setChecked(true);
textRightAction->setChecked(false);
textCenterAction->setChecked(false);
break;
case Qt::AlignRight:
textLeftAction->setChecked(false);
textRightAction->setChecked(true);
textCenterAction->setChecked(false);
break;
case Qt::AlignHCenter:
textLeftAction->setChecked(false);
textRightAction->setChecked(false);
textCenterAction->setChecked(true);
break;
default:
textLeftAction->setChecked(false);
textRightAction->setChecked(false);
textCenterAction->setChecked(false);
break;
}
if (dm->item(startSelectedRow, startSelectedColumn) == NULL)
{
cellLineEdit->setText("");
return;
}
QicsCell* cell = table->cell(startSelectedRow, startSelectedColumn, true);
if (cell->dataValue())
{
QString cellval = cell->dataValue()->string();
cellLineEdit->setText(cellval);
}
}
}
void Spreadsheet::insertColumn()
{
this->getSelectedRegion();
if (startSelectedColumn > -1)
{
table->insertColumn(startSelectedColumn);
}
}
void Spreadsheet::insertRow()
{
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->insertRow(startSelectedRow);
}
}
void Spreadsheet::deleteRow()
{
this->getSelectedRegion();
if (startSelectedRow > -1)
{
table->deleteRow(startSelectedRow);
}
}
void Spreadsheet::deleteColumn()
{
this->getSelectedRegion();
if (startSelectedColumn > -1)
{
table->deleteColumn(startSelectedColumn);
}
}
void Spreadsheet::setFontCombos(const QFont& font)
{
fontFamilyCombo->setEditText(font.family());
QFontDatabase fdb;
QList<int> sizes = fdb.pointSizes(font.family());
fontSizeCombo->clear();
if (sizes.begin() != sizes.end())
{
for (QList<int>::Iterator pts = sizes.begin(); pts != sizes.end(); ++pts)
{
fontSizeCombo->addItem(QString::number(*pts));
}
fontSizeCombo->setEditText(QString::number(font.pointSize()));
}
}
void Spreadsheet::textAlignLeft()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setAlignment(Qt::AlignLeft);
}
textRightAction->setChecked(false);
textCenterAction->setChecked(false);
}
void Spreadsheet::textAlignCenter()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setAlignment(Qt::AlignHCenter);
}
textLeftAction->setChecked(false);
textRightAction->setChecked(false);
}
void Spreadsheet::textAlignRight()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setAlignment(Qt::AlignRight);
}
textLeftAction->setChecked(false);
textCenterAction->setChecked(false);
}
void Spreadsheet::textBold()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
bool on = boldAction->isChecked();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFontAttribute(QicsCellStyle::FontBold, on);
}
}
void Spreadsheet::textItalic()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
bool on = italicAction->isChecked();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFontAttribute(QicsCellStyle::FontItalic, on);
}
}
void Spreadsheet::textUnderline()
{
if ( (startSelectedRow < 0) && (startSelectedColumn < 0))
{
return;
}
bool on = underlineAction->isChecked();
if (startSelectedRow > -1)
{
table->cellRegion(selectedRegion)->setFontAttribute(QicsCellStyle::FontUnderline, on);
}
}
void Spreadsheet::openFile()
{
QString fname =
QFileDialog::getOpenFileName();
if (fname != QString::null)
{
fileName = fname;
loadFile(fileName);
}
}
void Spreadsheet::loadFile(QString fname)
{
QFile file(fname);
if (file.open(QIODevice::ReadOnly))
{
QTextStream stream(&file);
dm->readASCII(stream, ',');
}
}
void Spreadsheet::saveFile()
{
if (fileName != QString::null)
{
writeFile(fileName);
}
}
void Spreadsheet::saveFileAs()
{
QString fname =
QFileDialog::getSaveFileName();
if (fname != QString::null)
{
fileName = fname;
writeFile(fileName);
}
}
void Spreadsheet::writeFile(QString fname)
{
QFile file(fname);
if (file.open(QIODevice::WriteOnly))
{
QTextStream stream(&file);
dm->writeASCII(stream, ',', 0, 0, 10, 10);
}
}
void Spreadsheet::fileNew()
{
qDebug("To be implemented");
}
void Spreadsheet::copy()
{
table->copy();
}
void Spreadsheet::cut()
{
table->cut();
}
void Spreadsheet::paste()
{
table->paste();
}
void Spreadsheet::getSelectedRegion()
{
QicsSelection selection;
QicsSelectionList *list = table->selectionList();
if (list != NULL)
{
if (list->begin() != list->end())
{
selection = *(list->begin());
startSelectedRow = selection.anchorRow();
startSelectedColumn = selection.anchorColumn();
}
}
else
{
startSelectedRow = startSelectedColumn = -1;
}
delete list;
int row = selection.endRow();
if (row > dm->lastRow())
row = dm->lastRow() + 1;
else
row++;
int col = selection.endColumn();
if (col > dm->lastColumn())
col = dm->lastColumn() + 1;
else
col++;
endSelectedRow = row;
endSelectedColumn = col;
selectedRegion = QicsRegion(startSelectedRow, startSelectedColumn, endSelectedRow-1, endSelectedColumn-1);
selectedRegion.normalize();
}
void Spreadsheet::sortAscending()
{
QicsSelectionList *list = table->selectionList();
if(!list)
return;
QicsSelectionList::const_iterator iter;
QVector<int> selectedCols;
for (iter = list->begin(); iter < list->end(); ++iter)
selectedCols << (*iter).anchorColumn();
if (selectedCols.size() <= 0) selectedCols << 0;
table->sortRows(selectedCols, Qics::Ascending);
}
void Spreadsheet::sortDescending()
{
QicsSelectionList *list = table->selectionList();
if(!list)
return;
QicsSelectionList::const_iterator iter;
QVector<int> selectedCols;
for (iter = list->begin(); iter < list->end(); ++iter)
selectedCols << (*iter).anchorColumn();
if (selectedCols.size() <= 0) selectedCols << 0;
table->sortRows(selectedCols, Qics::Descending);
}
void Spreadsheet::resized()
{
}
void Spreadsheet::addSpan()
{
QicsSelectionList *slist = table->selectionList();
if(slist)
{
QicsSelectionList::const_iterator iter;
for (iter = slist->begin(); iter != slist->end(); ++iter)
{
const QicsSelection &sel = *iter;
int bottom_row = sel.numRows();
int right_column = sel.numColumns();
if(sel.bottomRow() == Qics::QicsLAST_ROW)
bottom_row = table->dataModel()->numRows();
if(sel.rightColumn() == Qics::QicsLAST_COLUMN)
right_column = table->dataModel()->numColumns();
table->addCellSpan(QicsSpan(sel.topRow(),sel.leftColumn(),bottom_row,right_column));
}
}
}
void Spreadsheet::removeSpan()
{
QicsSelectionList *slist = table->selectionList();
if(slist)
{
QicsSelectionList::const_iterator iter;
for (iter = slist->begin(); iter != slist->end(); ++iter)
{
const QicsSelection &sel = *iter;
table->removeCellSpan(sel.topRow(),sel.leftColumn());
}
}
}
#ifdef CREATE_OBJS_WITH_QICSTABLE
void Spreadsheet::print()
{
QPrinter* printer = new QPrinter;
QPrintDialog printDialog(printer, this);
if (printDialog.exec() == QDialog::Accepted) {
table->print( printer );
}
}
#endif