Files
lcd-image-converter/controls/main/mainwindow.cpp
2013-10-03 17:47:48 +06:00

525 lines
20 KiB
C++

/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2010 riuson
* mailto: riuson@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 <http://www.gnu.org/licenses/
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
//-----------------------------------------------------------------------------
#include <QList>
#include <QFileDialog>
#include <QInputDialog>
#include <QTextStream>
#include <QTextCodec>
#include <QTranslator>
#include <QLocale>
#include <QIcon>
#include "editortabimage.h"
#include "editortabfont.h"
#include "starttab.h"
#include "datacontainer.h"
#include "dialogsavechanges.h"
#include "widgetbitmapeditor.h"
#include "recentlist.h"
#include "statusmanager.h"
#include "languageoptions.h"
#include "actionfilehandlers.h"
#include "actionedithandlers.h"
#include "actionimagehandlers.h"
#include "actionfonthandlers.h"
#include "actionsetuphandlers.h"
#include "actionhelphandlers.h"
#include "ieditor.h"
#include "idocument.h"
//-----------------------------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
#ifndef USED_QT5
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
#endif
QIcon icon;
icon.addFile(":/images/icon64", QSize(64, 64));
this->setWindowIcon(icon);
this->updateMenuState();
this->mTrans = new QTranslator;
qApp->installTranslator(this->mTrans);
this->mStatusManager = new StatusManager(this->ui->statusBar, this);
QDir dir(":/translations");
QStringList translations = dir.entryList(QDir::Files, QDir::Name);
QStringListIterator it(translations);
it.toFront();
while (it.hasNext())
{
QString name = it.next();
QAction *action = this->ui->menuLanguage->addAction(name, this, SLOT(actionLanguage_triggered()));
action->setCheckable(true);
action->setData(QVariant(name));
QTranslator trans;
trans.load(":/translations/" + name);
QString a = trans.translate("MainWindow", "langName");
action->setText(a);
}
this->connect(this->ui->actionLanguageDefault, SIGNAL(triggered()), SLOT(actionLanguage_triggered()));
QString selectedLocale = LanguageOptions::locale();
this->selectLocale(selectedLocale);
// create recent list
this->mRecentList = new RecentList(this);
this->connect(this->mRecentList, SIGNAL(listChanged()), SLOT(updateRecentList()));
this->updateRecentList();
this->createHandlers();
this->connect(this->ui->menuEdit, SIGNAL(aboutToShow()), SLOT(updateMenuState()));
this->checkStartPageVisible();
}
//-----------------------------------------------------------------------------
MainWindow::~MainWindow()
{
delete this->mRecentList;
delete this->mImageHandlers;
delete this->mFontHandlers;
delete this->mHelpHandlers;
delete this->mEditHandlers;
delete this->mFileHandlers;
delete this->mSetupHandlers;
delete ui;
}
//-----------------------------------------------------------------------------
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
void MainWindow::selectLocale(const QString &localeName)
{
if (LanguageOptions::setLocale(localeName))
{
this->mTrans->load(":/translations/" + localeName);
qApp->installTranslator(this->mTrans);
}
else
{
qApp->removeTranslator(this->mTrans);
}
QList<QAction *> actions =this->ui->menuLanguage->actions();
QMutableListIterator<QAction *> it(actions);
it.toFront();
while (it.hasNext())
{
QAction *a = it.next();
QString b = a->data().toString();
a->setChecked(b == localeName);
}
}
//-----------------------------------------------------------------------------
void MainWindow::checkStartPageVisible()
{
// show startpage if no other tabs
int othersTabs = 0;
int startPageIndex = -1;
for (int i = 0; i < this->ui->tabWidget->count(); i++)
{
QWidget *w = this->ui->tabWidget->widget(i);
StartTab *tab = dynamic_cast<StartTab *> (w);
if (tab == NULL)
othersTabs++;
else
startPageIndex = i;
}
if (othersTabs == 0)
{
if (startPageIndex < 0)
{
StartTab *tab = new StartTab(this->ui->tabWidget);
tab->setParent(this->ui->tabWidget);
tab->setRecentFiles(this->mRecentList->files());
this->mFileHandlers->connect(tab, SIGNAL(openRecent(QString)), SLOT(openFile(QString)));
this->mFileHandlers->connect(tab, SIGNAL(createNewImage()), SLOT(newImage_triggered()));
this->mFileHandlers->connect(tab, SIGNAL(createNewFont()), SLOT(newFont_triggered()));
this->ui->tabWidget->addTab(tab, tab->tabName());
this->ui->tabWidget->setTabsClosable(false);
}
}
else
{
if (startPageIndex >= 0)
{
StartTab *tab = dynamic_cast<StartTab *> (this->ui->tabWidget->widget(startPageIndex));
this->ui->tabWidget->removeTab(startPageIndex);
this->ui->tabWidget->setTabsClosable(true);
delete tab;
}
}
}
//-----------------------------------------------------------------------------
void MainWindow::createHandlers()
{
this->mFileHandlers = new ActionFileHandlers(this);
this->mFileHandlers->connect(this->ui->actionNew_Image, SIGNAL(triggered()), SLOT(newImage_triggered()));
this->mFileHandlers->connect(this->ui->actionNew_Font, SIGNAL(triggered()), SLOT(newFont_triggered()));
this->mFileHandlers->connect(this->ui->actionOpen, SIGNAL(triggered()), SLOT(open_triggered()));
this->mFileHandlers->connect(this->ui->actionRename, SIGNAL(triggered()), SLOT(rename_triggered()));
this->mFileHandlers->connect(this->ui->actionSave, SIGNAL(triggered()), SLOT(save_triggered()));
this->mFileHandlers->connect(this->ui->actionSave_As, SIGNAL(triggered()), SLOT(saveAs_triggered()));
this->mFileHandlers->connect(this->ui->actionClose, SIGNAL(triggered()), SLOT(close_triggered()));
this->mFileHandlers->connect(this->ui->actionConvert, SIGNAL(triggered()), SLOT(convert_triggered()));
this->mFileHandlers->connect(this->ui->actionConvert_All, SIGNAL(triggered()), SLOT(convertAll_triggered()));
this->connect(this->ui->actionQuit, SIGNAL(triggered()), SLOT(close()));
this->connect(this->mFileHandlers, SIGNAL(rememberFilename(QString)), SLOT(rememberFilename(QString)));
this->connect(this->mFileHandlers, SIGNAL(closeRequest(QWidget*)), SLOT(closeRequest(QWidget*)));
this->connect(this->mFileHandlers, SIGNAL(tabChanged(QWidget*)), SLOT(tabChanged(QWidget*)));
this->connect(this->mFileHandlers, SIGNAL(tabCreated(QWidget*)), SLOT(tabCreated(QWidget*)));
this->mEditHandlers = new ActionEditHandlers(this);
this->mEditHandlers->connect(this->ui->actionEditUndo, SIGNAL(triggered()), SLOT(undo_triggered()));
this->mEditHandlers->connect(this->ui->actionEditRedo, SIGNAL(triggered()), SLOT(redo_triggered()));
this->mEditHandlers->connect(this->ui->actionEditCopy, SIGNAL(triggered()), SLOT(copy_triggered()));
this->mEditHandlers->connect(this->ui->actionEditPaste, SIGNAL(triggered()), SLOT(paste_triggered()));
this->mImageHandlers = new ActionImageHandlers(this);
this->mImageHandlers->connect(this->ui->actionImageFlip_Horizontal, SIGNAL(triggered()), SLOT(flipHorizontal_triggered()));
this->mImageHandlers->connect(this->ui->actionImageFlip_Vertical, SIGNAL(triggered()), SLOT(flipVertical_triggered()));
this->mImageHandlers->connect(this->ui->actionImageRotate_90_Clockwise, SIGNAL(triggered()), SLOT(rotate_90_Clockwise_triggered()));
this->mImageHandlers->connect(this->ui->actionImageRotate_180, SIGNAL(triggered()), SLOT(rotate_180_triggered()));
this->mImageHandlers->connect(this->ui->actionImageRotate_90_Counter_Clockwise, SIGNAL(triggered()), SLOT(rotate_90_Counter_Clockwise_triggered()));
this->mImageHandlers->connect(this->ui->actionImageShiftLeft, SIGNAL(triggered()), SLOT(shift_left_triggered()));
this->mImageHandlers->connect(this->ui->actionImageShiftRight, SIGNAL(triggered()), SLOT(shift_right_triggered()));
this->mImageHandlers->connect(this->ui->actionImageShiftUp, SIGNAL(triggered()), SLOT(shift_up_triggered()));
this->mImageHandlers->connect(this->ui->actionImageShiftDown, SIGNAL(triggered()), SLOT(shift_down_triggered()));
this->mImageHandlers->connect(this->ui->actionImageInverse, SIGNAL(triggered()), SLOT(inverse_triggered()));
this->mImageHandlers->connect(this->ui->actionImageResize, SIGNAL(triggered()), SLOT(resize_triggered()));
this->mImageHandlers->connect(this->ui->actionImageImport, SIGNAL(triggered()), SLOT(import_triggered()));
this->mImageHandlers->connect(this->ui->actionImageExport, SIGNAL(triggered()), SLOT(export_triggered()));
this->mImageHandlers->connect(this->ui->actionEdit_in_external_tool, SIGNAL(triggered()), SLOT(edit_in_external_tool_triggered()));
this->mFontHandlers = new ActionFontHandlers(this);
this->mFontHandlers->connect(this->ui->actionFontChange, SIGNAL(triggered()), SLOT(fontChange_triggered()));
this->mFontHandlers->connect(this->ui->actionFontInverse, SIGNAL(triggered()), SLOT(fontInverse_triggered()));
this->mFontHandlers->connect(this->ui->actionFontResize, SIGNAL(triggered()), SLOT(fontResize_triggered()));
this->mFontHandlers->connect(this->ui->actionFontMinimizeHeight, SIGNAL(triggered()), SLOT(fontMinimizeHeight_triggered()));
this->mFontHandlers->connect(this->ui->actionFontPreview, SIGNAL(triggered()), SLOT(fontPreview_triggered()));
this->mFontHandlers->connect(this->ui->actionFontToImage, SIGNAL(triggered()), SLOT(fontToImage_triggered()));
this->mSetupHandlers = new ActionSetupHandlers(this);
this->mSetupHandlers->connect(this->ui->actionConversionOptions, SIGNAL(triggered()), SLOT(conversion_triggered()));
this->mSetupHandlers->connect(this->ui->actionExternal_editor, SIGNAL(triggered()), SLOT(external_editor_triggered()));
this->mHelpHandlers = new ActionHelpHandlers(this);
this->mHelpHandlers->connect(this->ui->actionAboutApp, SIGNAL(triggered()), SLOT(about_application_triggered()));
this->mHelpHandlers->connect(this->ui->actionAboutQt, SIGNAL(triggered()), SLOT(about_qt_triggered()));
this->mHelpHandlers->connect(this->ui->actionUpdates, SIGNAL(triggered()), SLOT(updates_triggered()));
this->mHelpHandlers->connect(this->ui->actionWiki, SIGNAL(triggered()), SLOT(wiki_triggered()));
this->mFileHandlers->connect(this->mFontHandlers, SIGNAL(imageCreated(QImage*,QString)), SLOT(openImage(QImage*,QString)));
}
//-----------------------------------------------------------------------------
void MainWindow::tabTextUpdate(QWidget *widget)
{
int index = this->ui->tabWidget->indexOf(widget);
if (index >= 0)
{
IEditor *editor = qobject_cast<IEditor *>(widget);
if (editor != NULL)
{
QString name;
if (editor->document()->changed())
name = "* " + editor->document()->documentName();
else
name = editor->document()->documentName();
this->ui->tabWidget->setTabText(index, name);
this->ui->tabWidget->setTabToolTip(index, editor->document()->documentFilename());
}
}
}
//-----------------------------------------------------------------------------
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
QWidget *w = this->ui->tabWidget->widget(index);
IEditor *editor = dynamic_cast<IEditor *> (w);
bool cancel = false;
if (editor != NULL && editor->document()->changed())
{
DialogSaveChanges dialog(this);
dialog.exec();
switch (dialog.answer())
{
case DialogSaveChanges::Save:
{
if (!editor->document()->save(editor->document()->documentFilename()))
cancel = true;
}
break;
case DialogSaveChanges::SaveAs:
{
QFileDialog dialog(this);
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilter(tr("XML Files (*.xml)"));
dialog.setWindowTitle(tr("Save file as"));
if (dialog.exec() == QDialog::Accepted)
{
QString filename = dialog.selectedFiles().at(0);
if (!editor->document()->save(filename))
cancel = true;
}
else
cancel = true;
}
break;
case DialogSaveChanges::DontSave:
break;
case DialogSaveChanges::Cancel:
cancel = true;
break;
}
}
if (!cancel)
{
this->ui->tabWidget->removeTab(index);
this->checkStartPageVisible();
delete w;
}
}
//-----------------------------------------------------------------------------
void MainWindow::on_tabWidget_currentChanged(int index)
{
Q_UNUSED(index);
this->updateMenuState();
this->mStatusManager->hideAll();
IEditor *editor = this->currentEditor();
if (editor != NULL)
{
IEditor *editor = this->currentEditor();
this->mStatusManager->updateData(editor->statusData());
}
}
//-----------------------------------------------------------------------------
void MainWindow::actionLanguage_triggered()
{
QAction *action = qobject_cast<QAction *>(sender());
QString name = action->data().toString();
this->selectLocale(name);
}
//-----------------------------------------------------------------------------
void MainWindow::updateMenuState()
{
IEditor *editor = this->currentEditor();
bool editorSelected = (editor != NULL);
if (editor != NULL)
{
this->ui->menuFont->setEnabled(editor->type() == IEditor::EditorFont);
this->ui->actionEditUndo->setEnabled(editor->document()->canUndo());
this->ui->actionEditRedo->setEnabled(editor->document()->canRedo());
}
else
{
this->ui->menuFont->setEnabled(false);
this->ui->actionEditUndo->setEnabled(false);
this->ui->actionEditRedo->setEnabled(false);
}
this->ui->menuEdit->setEnabled(editorSelected);
this->ui->menuImage->setEnabled(editorSelected);
this->ui->actionRename->setEnabled(editorSelected);
this->ui->actionSave->setEnabled(editorSelected);
this->ui->actionSave_As->setEnabled(editorSelected);
this->ui->actionClose->setEnabled(editorSelected);
this->ui->actionConvert->setEnabled(editorSelected);
this->ui->actionConvert_All->setEnabled(editorSelected);
}
//-----------------------------------------------------------------------------
void MainWindow::updateRecentList()
{
QList<QAction *> actions = this->ui->menuRecent->actions();
QAction *action;
foreach(action, actions)
{
this->ui->menuRecent->removeAction(action);
}
for (int i = actions.count() - 1; i >= 0; i--)
{
action = actions.at(i);
delete action;
}
if (this->mRecentList->files()->count() > 0)
{
this->ui->menuRecent->setEnabled(true);
for (int i = 0; i < this->mRecentList->files()->count(); i++)
{
QString filename = this->mRecentList->files()->at(i);
QString strippedName = QFileInfo(filename).fileName();
QString text = QString("%1 %2").arg(i + 1).arg(strippedName);
action = new QAction(text, this);
action->setData(filename);
this->connect(action, SIGNAL(triggered()), SLOT(openRecentFile()));
//action->setVisible(true);
this->ui->menuRecent->addAction(action);
}
}
else
this->ui->menuRecent->setEnabled(false);
}
//-----------------------------------------------------------------------------
void MainWindow::openRecentFile()
{
QAction *action = qobject_cast<QAction *>(sender());
if (action)
this->mFileHandlers->openFile(action->data().toString());
}
//-----------------------------------------------------------------------------
void MainWindow::rememberFilename(const QString &filename)
{
this->mRecentList->add(filename);
}
//-----------------------------------------------------------------------------
void MainWindow::closeRequest(QWidget *tab)
{
int index = this->ui->tabWidget->indexOf(tab);
if (index >= 0)
this->on_tabWidget_tabCloseRequested(index);
}
//-----------------------------------------------------------------------------
IEditor *MainWindow::currentEditor()
{
IEditor *result = qobject_cast<IEditor *>(this->currentTab());
return result;
}
//-----------------------------------------------------------------------------
QWidget *MainWindow::currentTab()
{
int index = this->ui->tabWidget->currentIndex();
if (index >= 0)
{
QWidget *w = this->ui->tabWidget->widget(index);
return w;
}
return NULL;
}
//-----------------------------------------------------------------------------
void MainWindow::tabsList(QList<QWidget *> *list)
{
if (list != NULL)
{
list->clear();
for (int i = 0; i < this->ui->tabWidget->count(); i++)
{
list->append(this->ui->tabWidget->widget(i));
}
}
}
//-----------------------------------------------------------------------------
QWidget *MainWindow::parentWidget()
{
return this;
}
//-----------------------------------------------------------------------------
QString MainWindow::findAvailableName(const QString &prefix)
{
QString result = prefix;
QList<QString> names;
for (int i = 0; i < this->ui->tabWidget->count(); i++)
{
QWidget *w = this->ui->tabWidget->widget(i);
IDocument *doc = dynamic_cast<IDocument *> (w);
if (doc != NULL)
names.append(doc->documentName());
}
int i = 1;
if (names.contains(prefix))
{
while (true)
{
QString name = QString("%1 %2").arg(prefix).arg(i++);
if (!names.contains(name))
{
result = name;
break;
}
}
}
return result;
}
//-----------------------------------------------------------------------------
void MainWindow::tabChanged(QWidget *tab)
{
int index = this->ui->tabWidget->indexOf(tab);
if (index >= 0)
{
this->tabTextUpdate(tab);
}
}
//-----------------------------------------------------------------------------
int MainWindow::tabCreated(QWidget *newTab)
{
int index = this->ui->tabWidget->addTab(newTab, "");
this->ui->tabWidget->setCurrentIndex(index);
this->tabTextUpdate(newTab);
this->connect(newTab, SIGNAL(statusChanged()), SLOT(statusChanged()));
this->checkStartPageVisible();
IEditor *editor = this->currentEditor();
this->mStatusManager->updateData(editor->statusData());
return index;
}
//-----------------------------------------------------------------------------
void MainWindow::statusChanged()
{
QWidget *widget = qobject_cast<QWidget *>(sender());
if (widget != NULL)
{
if (this->ui->tabWidget->currentWidget() == widget)
{
IEditor *editor = this->currentEditor();
this->mStatusManager->updateData(editor->statusData());
}
}
}
//-----------------------------------------------------------------------------