/*!
* \file mainwindow.cpp
* \brief Реализация класса "Главное окно программы".
*/
#include <QtGui>
#include "mainwindow.h"
#include "mdichild.h"
#include "appearancedialog.h"
#include "syssettings.h"
MainWindow::MainWindow()
{
mdiArea = new QMdiArea;
setCentralWidget(mdiArea);
connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(updateMenus()));
windowMapper = new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *)));
createActions(); // Создаем действия
createMenus(); // Создаем меню
createToolBars(); // Создаем панель инструментов
createStatusBar(); // Создаем панель статуса
readWindowSettings();// Читаем настройки окна
// Создаем экземпляр класса сесии
auth = Session::InitInstance();
connect(this, SIGNAL(SigShow()), SLOT(SlotOnShow()));
}
MainWindow::~MainWindow()
{
auth->FreeInstance();
}
bool MainWindow::event(QEvent *p_event)
{
if( p_event->type() == QEvent::ShowToParent)
emit SigShow();
return QWidget::event(p_event);
}
/*=====================================================================
Постинициализация
===================================================================*/
void MainWindow::SlotOnShow()
{
QString errmsg;
QString title = tr("Ошибка программы");
qDebug() << "SlotOnShow: " << QDateTime::currentDateTime() << "\n\r";
// Вход от имени анонимного пользователя
auth->LoginAnonymous();
// Обновляем меню
updateMenus();
// Проверяем все ли хорошо с настройками
if (!auth->isGood(errmsg))
{
QMessageBox::critical(this, title, tr("Ошибка настроек, обратитесь к специалисту. Сообщение: \n\r") + errmsg);
return;
}
// Здесь проверяется и устанавливается соединение с БД.
bool ok;
QSqlDatabase app_db = QSqlDatabase::database("appdb");
QSqlQuery query(app_db);
QString querystr;
QString qerr;
QString db_driver;
QString db_name;
QString db_user_name;
QString db_user_paswd;
querystr="SELECT F_VALUE FROM APPSETTINGS \
WHERE ((F_TYPE='db_driver') OR (F_TYPE='db_name') OR \
(F_TYPE='db_user_name') OR (F_TYPE='db_user_paswd')) \
ORDER BY F_TYPE ASC";
ok = query.exec(querystr);
qDebug() << "select DB settings - " << ok << "\n\r";
if (!ok)
{
qerr = query.lastError().text();
QMessageBox::critical(0, title,
tr("Невозможно прочитать настройки БД.\n\r Причина: ")+qerr,
QMessageBox::ok);
}
query.first();
if (!query.isValid())
{
qerr = query.lastError().text();
QMessageBox::critical(0, title,
tr("Невозможно прочитать настройки БД.\n\r Причина: ")+qerr,
QMessageBox::ok);
}
db_driver = query.value(0).toString();
query.next();
db_name = query.value(0).toString();
query.next();
db_user_name = query.value(0).toString();
query.next();
db_user_paswd = query.value(0).toString();
db_main = QSqlDatabase::addDatabase(db_driver,"maindb");
db_main.setDatabaseName(db_name);
db_main.setUserName(db_user_name);
db_main.setPassword(db_user_paswd);
qDebug() << "db_main.open: " << QDateTime::currentDateTime() << "\n\r";
ok = db_main.open();
if (!ok)
{
qerr = db_main.lastError().text();
QMessageBox::critical(0, title,
QObject::tr("Невозможно установить соединение c БД.\n\r")+qerr,
QMessageBox::ok);
}
qDebug() << "db_main.open: " << QDateTime::currentDateTime() << "\n\r";
qDebug() << db_main << "\n\r";
}
/*=====================================================================
Создание действий
===================================================================*/
void MainWindow::createActions()
{
// Меню "Файл"
menuFile = menuBar()->addMenu(tr("&Файл"));
newAct = new QAction(QIcon(":/images/new.png"), tr("&Новый"), this);
newAct->setShortcut(tr("Ctrl+N"));
newAct->setStatusTip(tr("Создать новый файл"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
menuFile->addAction(newAct);
openAct = new QAction(QIcon(":/images/open.png"), tr("&Открыть..."), this);
openAct->setShortcut(tr("Ctrl+O"));
openAct->setStatusTip(tr("Открыть существующий файл"));
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
menuFile->addAction(openAct);
saveAct = new QAction(QIcon(":/images/save.png"), tr("&Сохранить"), this);
saveAct->setShortcut(tr("Ctrl+S"));
saveAct->setStatusTip(tr("Сохранить документ на диск"));
connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
menuFile->addAction(saveAct);
saveAsAct = new QAction(tr("Сохранить &как..."), this);
saveAsAct->setStatusTip(tr("Сохранить документ под другим именем"));
connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
menuFile->addAction(saveAsAct);
menuFile->addSeparator();
exitAct = new QAction(tr("В&ыход"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
exitAct->setStatusTip(tr("Выход из программы"));
connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
menuFile->addAction(exitAct);
// Меню "Правка"
menuEdit = menuBar()->addMenu(tr("&Правка"));
cutAct = new QAction(QIcon(":/images/cut.png"), tr("&Вырезать"), this);
cutAct->setShortcut(tr("Ctrl+X"));
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
"clipboard"));
connect(cutAct, SIGNAL(triggered()), this, SLOT(cut()));
menuEdit->addAction(cutAct);
copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Копировать"), this);
copyAct->setShortcut(tr("Ctrl+C"));
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
"clipboard"));
connect(copyAct, SIGNAL(triggered()), this, SLOT(copy()));
menuEdit->addAction(copyAct);
pasteAct = new QAction(QIcon(":/images/paste.png"), tr("Вст&авить"), this);
pasteAct->setShortcut(tr("Ctrl+V"));
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
"selection"));
connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste()));
menuEdit->addAction(pasteAct);
// Меню "Вид"
//menuView = menuBar()->addMenu(tr("&Вид"));
// Меню Отчеты
//actLogin = new QAction(tr("Войти..."), this);
//actLogin->setStatusTip(tr("Войти в систему с определенным именем"));
//connect(actLogin, SIGNAL(triggered()), this, SLOT(login()));
// Меню "Оператор"
menuOperator = menuBar()->addMenu(tr("Опе&ратор"));
actLogin = new QAction(tr("Войти..."), this);
actLogin->setStatusTip(tr("Войти в систему с определенным именем"));
connect(actLogin, SIGNAL(triggered()), this, SLOT(login()));
menuOperator->addAction(actLogin);
actLogout = new QAction(tr("Выйти"), this);
actLogout->setStatusTip(tr("Выйти из системы"));
connect(actLogout, SIGNAL(triggered()), this, SLOT(logout()));
menuOperator->addAction(actLogout);
// Меню "Настройка"
menuSetting = menuBar()->addMenu(tr("&Настройка"));
actSettings = new QAction(tr("Программа..."), this);
actSettings->setStatusTip(tr("Настройки ПО"));
connect(actSettings, SIGNAL(triggered()), this, SLOT(Settings()));
menuSetting->addAction(actSettings);
actAppear = new QAction(tr("Оформление..."), this);
actAppear->setStatusTip(tr("Настройки внешнего вида"));
connect(actAppear, SIGNAL(triggered()), this, SLOT(SlotAppearance()));
menuSetting->addAction(actAppear);
actCalibrate = new QAction(tr("Коррекция Т.У. ..."), this);
actCalibrate->setStatusTip(tr("Коррекция показаний эл. счетчиков Т.У."));
connect(actCalibrate, SIGNAL(triggered()), this, SLOT(SlotCalibrate()));
menuSetting->addAction(actCalibrate);
actPoint = new QAction(tr("Настройка Т.У. ..."), this);
actPoint->setStatusTip(tr("Настройка точек учета"));
connect(actPoint, SIGNAL(triggered()), this, SLOT(SlotPoint()));
menuSetting->addAction(actPoint);
// Меню "Окно"
menuWindow = menuBar()->addMenu(tr("&Окно"));
closeAct = new QAction(tr("&Закрыть"), this);
closeAct->setShortcut(tr("Ctrl+F4"));
closeAct->setStatusTip(tr("Закрыть активное окно"));
connect(closeAct, SIGNAL(triggered()),
mdiArea, SLOT(closeActiveSubWindow()));
closeAllAct = new QAction(tr("Закрыть все"), this);
closeAllAct->setStatusTip(tr("Закрыть все окна"));
connect(closeAllAct, SIGNAL(triggered()),
mdiArea, SLOT(closeAllSubWindows()));
tileAct = new QAction(tr("&Мозаика"), this);
tileAct->setStatusTip(tr("Tile the windows"));
connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));
cascadeAct = new QAction(tr("&Каскад"), this);
cascadeAct->setStatusTip(tr("Cascade the windows"));
connect(cascadeAct, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));
nextAct = new QAction(tr("Сл&едующее"), this);
nextAct->setStatusTip(tr("Move the focus to the next window"));
connect(nextAct, SIGNAL(triggered()),
mdiArea, SLOT(activateNextSubWindow()));
previousAct = new QAction(tr("П&редыдущее"), this);
previousAct->setStatusTip(tr("Move the focus to the previous "
"window"));
connect(previousAct, SIGNAL(triggered()),
mdiArea, SLOT(activatePreviousSubWindow()));
separatorAct = new QAction(this);
separatorAct->setSeparator(true);
updateWindowMenu();
connect(menuWindow, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));
menuBar()->addSeparator();
// Меню "Справка"
menuHelp = menuBar()->addMenu(tr("&Справка"));
aboutAct = new QAction(tr("&О программе"), this);
aboutAct->setStatusTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
menuHelp->addAction(aboutAct);
aboutQtAct = new QAction(tr("О библиотеке &Qt"), this);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
menuHelp->addAction(aboutQtAct);
}
/*=====================================================================
Создание Меню
===================================================================*/
void MainWindow::createMenus()
{
}
/*=====================================================================
Создание панели инструментов
===================================================================*/
void MainWindow::createToolBars()
{
// Панель инструментов "Файл"
ToolBarFile = addToolBar(tr("Файл"));
ToolBarFile->addAction(newAct);
ToolBarFile->addAction(openAct);
ToolBarFile->addAction(saveAct);
// Панель инструментов "Правка"
ToolBarEdit = addToolBar(tr("Правка"));
ToolBarEdit->addAction(cutAct);
ToolBarEdit->addAction(copyAct);
ToolBarEdit->addAction(pasteAct);
}
/*=====================================================================
Создание строки статуса
===================================================================*/
void MainWindow::createStatusBar()
{
statusBar()->showMessage(tr("Готов"));
}
/*=====================================================================
Обновление заголовка
===================================================================*/
void MainWindow::updateTitle()
{
setWindowTitle(tr("ЭСТОП АСУ @ %1").arg(auth->GetUserString()));
}
/*===================================================================
Обновление меню
=====================================================================*/
void MainWindow::updateMenus()
{
bool hasMdiChild;
bool hasSelection;
hasMdiChild = (activeMdiChild() != 0);
hasSelection = (activeMdiChild() && activeMdiChild()->textCursor().hasSelection());
// Запрещаем ответственные пункты
actSettings->setEnabled(false);
actPoint->setEnabled(false);
actCalibrate->setEnabled(false);
qDebug() << "MainWindow::updateMenus GetGroupID()= " << auth->GetGroupID() << "\n\r";
switch(auth->GetGroupID())
{
case Session::GID_ROOT:
{
}
case Session::GID_ADMIN:
{
// Делаем доступным для админа пункты в меню "Настройка"
actSettings->setEnabled(true);
actPoint->setEnabled(true);
}
case Session::GID_USER:
{
// Делаем доступным для пользователя пункты в меню "Настройка"
actCalibrate->setEnabled(true);
}
default:
{
// Меню "Файл"
saveAct->setEnabled(hasMdiChild);
saveAsAct->setEnabled(hasMdiChild);
// Меню "Правка"
pasteAct->setEnabled(hasMdiChild);
cutAct->setEnabled(hasSelection);
copyAct->setEnabled(hasSelection);
// Меню "Окно"
closeAct->setEnabled(hasMdiChild);
closeAllAct->setEnabled(hasMdiChild);
tileAct->setEnabled(hasMdiChild);
cascadeAct->setEnabled(hasMdiChild);
nextAct->setEnabled(hasMdiChild);
previousAct->setEnabled(hasMdiChild);
separatorAct->setVisible(hasMdiChild);
}
}
updateTitle(); // Обновляем заголовок главного окна
}
/*===================================================================
Обработка события closeEvent
=====================================================================*/
void MainWindow::closeEvent(QCloseEvent *p_event)
{
mdiArea->closeAllSubWindows();
if (activeMdiChild())
{
p_event->ignore();
//QMessageBox::about(this, tr("MainWindow::closeEvent"), tr("Закройте все окна"));
}
else
{
//QMessageBox::about(this, tr("MainWindow::closeEvent"), tr("activeMdiChild()==false"));
writeWindowSettings();
p_event->accept();
}
}
/*===================================================================
Обновление меню "Окно"
=====================================================================*/
void MainWindow::updateWindowMenu()
{
menuWindow->clear();
menuWindow->addAction(closeAct);
menuWindow->addAction(closeAllAct);
menuWindow->addSeparator();
menuWindow->addAction(tileAct);
menuWindow->addAction(cascadeAct);
menuWindow->addSeparator();
menuWindow->addAction(nextAct);
menuWindow->addAction(previousAct);
menuWindow->addAction(separatorAct);
QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
separatorAct->setVisible(!windows.isEmpty());
for (int i = 0; i < windows.size(); ++i) {
MdiChild *child = qobject_cast<MdiChild *>(windows.at(i)->widget());
QString text;
if (i < 9)
{
text = tr("&%1 %2").arg(i + 1)
.arg(child->userFriendlyCurrentFile());
}
else
{
text = tr("%1 %2").arg(i + 1)
.arg(child->userFriendlyCurrentFile());
}
QAction *action = menuWindow->addAction(text);
action->setCheckable(true);
action->setChecked(child == activeMdiChild());
connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
windowMapper->setMapping(action, windows.at(i));
}
}
/*=====================================================================
Создание дочернего окна
===================================================================*/
MdiChild *MainWindow::createMdiChild()
{
MdiChild *child = new MdiChild;
mdiArea->addSubWindow(child);
connect(child, SIGNAL(copyAvailable(bool)), cutAct, SLOT(setEnabled(bool)));
connect(child, SIGNAL(copyAvailable(bool)), copyAct, SLOT(setEnabled(bool)));
return child;
}
/*=====================================================================
Обработка действий
===================================================================*/
/* Файл->Новый */
void MainWindow::newFile()
{
MdiChild *child = createMdiChild();
child->newFile();
child->show();
}
/* Файл->Открыть */
void MainWindow::open()
{
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty()) {
QMdiSubWindow *existing = findMdiChild(fileName);
if (existing) {
mdiArea->setActiveSubWindow(existing);
return;
}
MdiChild *child = createMdiChild();
if (child->loadFile(fileName)) {
statusBar()->showMessage(tr("Файл загружен"), 2000);
child->show();
} else {
child->close();
}
}
}
/* Файл->Сохранить */
void MainWindow::save()
{
if (activeMdiChild() && activeMdiChild()->save())
statusBar()->showMessage(tr("Файл сохранен"), 2000);
}
/* Файл->Сохранить как */
void MainWindow::saveAs()
{
if (activeMdiChild() && activeMdiChild()->saveAs())
statusBar()->showMessage(tr("Файл сохранен"), 2000);
}
/* Правка->Вырезать */
void MainWindow::cut()
{
if (activeMdiChild())
activeMdiChild()->cut();
}
/* Правка->Копировать */
void MainWindow::copy()
{
if (activeMdiChild())
activeMdiChild()->copy();
}
/* Правка->Вставить */
void MainWindow::paste()
{
if (activeMdiChild())
activeMdiChild()->paste();
}
/* Оператор->Вход */
void MainWindow::login()
{
bool tf=false;
qDebug() << "================ MAIN WINDOW LOGIN ================" << "\n\r";
if (auth->ShowLoginDialog())
{
if (auth->GetGroupID()!=auth->GID_ANONYMOUS)
tf=false;
else
tf=true;
actLogin->setEnabled(tf);
updateMenus();
}
}
/* Оператор->Выход */
void MainWindow::logout()
{
auth->LoginAnonymous(); // Вход от имени анонимного пользователя
actLogin->setEnabled(true);
updateMenus();
}
/* Настройка->Настройка */
void MainWindow::Settings()
{
auth->ShowSettingDialog();
}
/* Настройка->Оформление */
void MainWindow::SlotAppearance()
{
AppearanceDialog dlg;
QSqlDatabase app_db = QSqlDatabase::database("appdb");
bool ok=false;
QSqlQuery query(app_db);
QString querystr;
QString qerr;
if (dlg.exec() == QDialog::Accepted)
{
// Заполняем таблицу прочих настроек
querystr="UPDATE APPSETTINGS SET F_VALUE=:value WHERE (F_TYPE=:type)";
ok = query.prepare(querystr);
if (!ok)
{
QString qerr = query.lastError().text();
QMessageBox::critical(0, QObject::tr("Ошибка"),
QObject::tr("Невозможно сохранить настройки.\n\r")+qerr,
QMessageBox::ok);
return;
}
query.bindValue(":type", "style");
query.bindValue(":value", dlg.box_style->currentText());
ok = query.exec();
if (!ok)
{
QString qerr = query.lastError().text();
QMessageBox::critical(0, QObject::tr("Ошибка"),
QObject::tr("Невозможно сохранить настройки.\n\r")+qerr,
QMessageBox::ok);
}
}
}
/* Настройка->Корекция Т.У. */
void MainWindow::SlotCalibrate()
{
//auth->ShowSettingDialog();
}
/* Настройка->Настойка Т.У. */
void MainWindow::SlotPoint()
{
SysSettings dlg(db_main, this);
dlg.exec();
}
/* Справка->О программе */
void MainWindow::about()
{
QMessageBox::about(this, tr("О программе"),
tr("Программа для ЭСТОП"));
}
/*=====================================================================
Чтение настроек окна
===================================================================*/
void MainWindow::readWindowSettings()
{
QSettings settings;
bool wstate = settings.value("winmax", false).toBool();
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
move(pos);
resize(size);
if (wstate)
showMaximized();
}
/*=====================================================================
Сохранение настроек окна
===================================================================*/
void MainWindow::writeWindowSettings()
{
QSettings settings;
settings.setValue("winmax",isMaximized());
settings.setValue("pos", pos());
settings.setValue("size", size()); // здесь касяк, надо нетолько размер запоминать но и состояние развернуто или нет
}
/*=====================================================================
Чтение настроек
===================================================================*/
void MainWindow::readSettings()
{
QSettings settings;
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
move(pos);
resize(size);
}
/*=====================================================================
Сохранение настроек
===================================================================*/
void MainWindow::writeSettings()
{
QSettings settings;
settings.setValue("pos", pos());
settings.setValue("size", size()); // здесь касяк, надо нетолько размер запоминать но и состояние развернуто или нет
}
/*=====================================================================
Чтение основных настроек и их проверка
===================================================================*/
void MainWindow::mainSettings()
{
}
/*=====================================================================
===================================================================*/
MdiChild *MainWindow::activeMdiChild()
{
if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
return qobject_cast<MdiChild *>(activeSubWindow->widget());
return 0;
}
QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName)
{
QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
if (mdiChild->currentFile() == canonicalFilePath)
return window;
}
return 0;
}
void MainWindow::setActiveSubWindow(QWidget *window)
{
if (!window)
return;
mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}