/* * 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 #include #include #include #include #include #include #include #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 actions =this->ui->menuLanguage->actions(); QMutableListIterator 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 (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 (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(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 (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(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 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(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(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 *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 names; for (int i = 0; i < this->ui->tabWidget->count(); i++) { QWidget *w = this->ui->tabWidget->widget(i); IDocument *doc = dynamic_cast (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(sender()); if (widget != NULL) { if (this->ui->tabWidget->currentWidget() == widget) { IEditor *editor = this->currentEditor(); this->mStatusManager->updateData(editor->statusData()); } } } //-----------------------------------------------------------------------------