#include <QtWidgets>
#include "Utilities.h"
#include "MdiWindow.h"
#include "ui_ExtensibleObjectModelUI.h"
MdiChild::MdiChild()
{
setAttribute(Qt::WA_DeleteOnClose);
isUntitled = true;
connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged()));
}
MdiChild::~MdiChild()
{
closing();
}
void MdiChild::newFile()
{
static int sequenceNumber = 1;
isUntitled = true;
curFile = tr("document%1.txt").arg(sequenceNumber++);
setWindowTitle(curFile + "[*]");
connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified()));
}
bool MdiChild::loadFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("MDI"),
tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString()));
return false;
}
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
setPlainText(in.readAll());
QApplication::restoreOverrideCursor();
setCurrentFile(fileName);
connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified()));
return true;
}
bool MdiChild::save()
{
return (isUntitled) ? saveAs() : saveFile(curFile);
}
bool MdiChild::saveAs()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile);
if (fileName.isEmpty())
return false;
return saveFile(fileName);
}
bool MdiChild::saveFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("MDI"),
tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString()));
return false;
}
QTextStream out(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
out << toPlainText();
QApplication::restoreOverrideCursor();
setCurrentFile(fileName);
return true;
}
QString MdiChild::userFriendlyCurrentFile()
{
return strippedName(curFile);
}
void MdiChild::closeEvent(QCloseEvent *event)
{
if (maybeSave()) {
event->accept();
} else {
event->ignore();
}
}
void MdiChild::documentWasModified()
{
setWindowModified(document()->isModified());
}
bool MdiChild::maybeSave()
{
if (document()->isModified()) {
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("MDI"),
tr("'%1' has been modified.\n"
"Do you want to save your changes?")
.arg(userFriendlyCurrentFile()),
QMessageBox::Save | QMessageBox::Discard
| QMessageBox::Cancel);
if (ret == QMessageBox::Save)
return save();
else if (ret == QMessageBox::Cancel)
return false;
}
return true;
}
void MdiChild::setCurrentFile(const QString &fileName)
{
curFile = QFileInfo(fileName).canonicalFilePath();
isUntitled = false;
document()->setModified(false);
setWindowModified(false);
setWindowTitle(userFriendlyCurrentFile() + "[*]");
}
QString MdiChild::strippedName(const QString &fullFileName)
{
return QFileInfo(fullFileName).fileName();
}
void MdiChild::markdownSelection(const char* preText, const char* postText)
{
QTextCursor cur = textCursor();
cur.beginEditBlock();
QString selectedText = cur.selection().toPlainText();
cur.removeSelectedText();
cur.insertText(preText + selectedText + postText);
cur.endEditBlock();
}
void MdiChild::bold()
{
markdownSelection("**", "**");
}
void MdiChild::italic()
{
markdownSelection("*", "*");
}
void MdiChild::quote()
{
markdownSelection("`", "`");
}
void MdiChild::code()
{
//markdownSelection("*", "*");
// Need to add indentation of text with 4 spaces each line
}
void MdiChild::heading1()
{
markdownSelection("# ", " #");
}
void MdiChild::heading2()
{
markdownSelection("## ", " ##");
}
void MdiChild::heading3()
{
markdownSelection("### ", " ###");
}
void MdiChild::heading4()
{
markdownSelection("#### ", " ####");
}
void MdiChild::hyperlink()
{
}
void MdiChild::image()
{
}
void MdiChild::unorderedList()
{
}
void MdiChild::orderedList()
{
}
void MdiChild::horizontalRule()
{
}
void MdiChild::timestamp()
{
}
void MdiChild::pageNumber()
{
}
void MdiChild::pageCount()
{
}
void MdiChild::del()
{
//QTextEdit::cursor().pos()
}
void MdiChild::undo()
{
}
void MdiChild::redo()
{
}
void MdiChild::find()
{
}
void MdiChild::findNext()
{
}
void MdiChild::findPrevious()
{
}
void MdiChild::goToLine()
{
}
MdiWindow::MdiWindow(QWidget *parent) :
QMainWindow(parent), appWindow(nullptr)
{
}
void MdiWindow::init(Ui_MainWindow* ui)
{
appWindow = ui;
mdiArea = ui->mdiArea;//new QMdiArea;
connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions()));
connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updatePreview()));
windowMapper = new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped(QWidget*)), this, SLOT(setActiveSubWindow(QWidget*)));
QObject::connect(appWindow->actionNew, SIGNAL(triggered(bool)), this, SLOT(newFile()));
QObject::connect(appWindow->actionOpen, SIGNAL(triggered(bool)), this, SLOT(open()));
QObject::connect(appWindow->actionSave, SIGNAL(triggered(bool)), this, SLOT(save()));
QObject::connect(appWindow->actionSave_As, SIGNAL(triggered(bool)), this, SLOT(saveAs()));
QObject::connect(appWindow->actionSwitchRTL, SIGNAL(triggered(bool)), this, SLOT(switchLayoutDirection()));
#ifndef QT_NO_CLIPBOARD
QObject::connect(appWindow->actionCut, SIGNAL(triggered(bool)), this, SLOT(cut()));
QObject::connect(appWindow->actionCopy, SIGNAL(triggered(bool)), this, SLOT(copy()));
QObject::connect(appWindow->actionPaste, SIGNAL(triggered(bool)), this, SLOT(paste()));
#endif
QObject::connect(appWindow->actionBold, SIGNAL(triggered(bool)), this, SLOT(bold()));
QObject::connect(appWindow->actionItalic, SIGNAL(triggered(bool)), this, SLOT(italic()));
QObject::connect(appWindow->actionQuote, SIGNAL(triggered(bool)), this, SLOT(quote()));
QObject::connect(appWindow->actionCode, SIGNAL(triggered(bool)), this, SLOT(code()));
QObject::connect(appWindow->actionHeading_1, SIGNAL(triggered(bool)), this, SLOT(heading1()));
QObject::connect(appWindow->actionHeading_2, SIGNAL(triggered(bool)), this, SLOT(heading2()));
QObject::connect(appWindow->actionHeading_3, SIGNAL(triggered(bool)), this, SLOT(heading3()));
QObject::connect(appWindow->actionHeading_4, SIGNAL(triggered(bool)), this, SLOT(heading4()));
QObject::connect(appWindow->actionHyperlink, SIGNAL(triggered(bool)), this, SLOT(hyperlink()));
QObject::connect(appWindow->actionImage, SIGNAL(triggered(bool)), this, SLOT(image()));
QObject::connect(appWindow->actionUnordered_List, SIGNAL(triggered(bool)), this, SLOT(unorderedList()));
QObject::connect(appWindow->actionOrdered_List, SIGNAL(triggered(bool)), this, SLOT(orderedList()));
QObject::connect(appWindow->actionHorizontal_Rule,SIGNAL(triggered(bool)), this, SLOT(horizontalRule()));
QObject::connect(appWindow->actionTimestamp, SIGNAL(triggered(bool)), this, SLOT(timestamp()));
QObject::connect(appWindow->actionPage_Number, SIGNAL(triggered(bool)), this, SLOT(pageNumber()));
QObject::connect(appWindow->actionPage_Count, SIGNAL(triggered(bool)), this, SLOT(pageCount()));
QObject::connect(appWindow->actionOptions, SIGNAL(triggered(bool)), this, SLOT(options()));
QObject::connect(appWindow->actionSave_All, SIGNAL(triggered(bool)), this, SLOT(saveAll()));
QObject::connect(appWindow->actionSelect_All, SIGNAL(triggered(bool)), this, SLOT(selectAll()));
QObject::connect(appWindow->actionDelete, SIGNAL(triggered(bool)), this, SLOT(del()));
QObject::connect(appWindow->actionUndo, SIGNAL(triggered(bool)), this, SLOT(undo()));
QObject::connect(appWindow->actionRedo, SIGNAL(triggered(bool)), this, SLOT(redo()));
QObject::connect(appWindow->actionFind, SIGNAL(triggered(bool)), this, SLOT(find()));
QObject::connect(appWindow->actionFind_Next, SIGNAL(triggered(bool)), this, SLOT(findNext()));
QObject::connect(appWindow->actionFind_Previous,SIGNAL(triggered(bool)), this, SLOT(findPrevious()));
QObject::connect(appWindow->actionGo_to_Line, SIGNAL(triggered(bool)), this, SLOT(goToLine()));
QObject::connect(appWindow->action_Tile_Windows,SIGNAL(triggered(bool)), this, SLOT(tileSubWindows()));
QObject::connect(appWindow->action_Windowed, SIGNAL(triggered(bool)), this, SLOT(cascadeSubWindows()));
QObject::connect(appWindow->actionTabbed, SIGNAL(triggered(bool)), this, SLOT(tabSubWindows()));
QObject::connect(appWindow->actionClose, SIGNAL(triggered(bool)), mdiArea, SLOT(closeActiveSubWindow()));
QObject::connect(appWindow->actionClose_All, SIGNAL(triggered(bool)), mdiArea, SLOT(closeAllSubWindows()));
QObject::connect(appWindow->actionNext, SIGNAL(triggered(bool)), mdiArea, SLOT(activateNextSubWindow()));
QObject::connect(appWindow->actionPrevious, SIGNAL(triggered(bool)), mdiArea, SLOT(activatePreviousSubWindow()));
QObject::connect(appWindow->actionSupport, SIGNAL(triggered(bool)), this, SLOT(support()));
QObject::connect(appWindow->actionWebsite, SIGNAL(triggered(bool)), this, SLOT(website()));
statusBar()->showMessage(tr("Ready"));
updateActions();
readSettings();
setUnifiedTitleAndToolBarOnMac(true);
#if QT_VERSION >= 0x050000
menuBar()->setNativeMenuBar(false);
#endif
tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock);
tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock);
appWindow->projectDock->raise();
appWindow->eventLogDock->hide();
appWindow->consoleDock->hide();
}
void MdiWindow::closeEvent(QCloseEvent *event)
{
YQ_LOG_DEBUG("Closing all documents (received MdiWindow::closeEvent)");
mdiArea->closeAllSubWindows();
if (mdiArea->currentSubWindow()) {
YQ_LOG_DEBUG("Ignoring MdiWindow::closeEvent");
event->ignore();
} else {
writeSettings();
YQ_LOG_DEBUG("Accepting MdiWindow::closeEvent");
event->accept();
}
}
void MdiWindow::newFile()
{
YQ_LOG_DEBUG("newFile");
MdiChild *child = createMdiChild();
child->newFile();
child->show();
}
void MdiWindow::open()
{
YQ_LOG_DEBUG("open");
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty()) {
QMdiSubWindow *existing = findMdiChild(fileName);
if (existing) {
mdiArea->setActiveSubWindow(existing);
return;
}
if (openFile(fileName))
statusBar()->showMessage(tr("File loaded"), 2000);
}
}
bool MdiWindow::openFile(const QString &fileName)
{
YQ_LOG_DEBUG("openFile %s", fileName.toLatin1().data());
MdiChild *child = createMdiChild();
const bool succeeded = child->loadFile(fileName);
if (succeeded)
child->show();
else
child->close();
return succeeded;
}
void MdiWindow::save()
{
YQ_LOG_DEBUG("save");
if (activeMdiChild() && activeMdiChild()->save())
statusBar()->showMessage(tr("File saved"), 2000);
}
void MdiWindow::saveAs()
{
YQ_LOG_DEBUG("saveAs");
if (activeMdiChild() && activeMdiChild()->saveAs())
statusBar()->showMessage(tr("File saved"), 2000);
}
#ifndef QT_NO_CLIPBOARD
void MdiWindow::cut()
{
if (activeMdiChild())
activeMdiChild()->cut();
}
void MdiWindow::copy()
{
if (activeMdiChild())
activeMdiChild()->copy();
}
void MdiWindow::paste()
{
if (activeMdiChild())
activeMdiChild()->paste();
}
#endif
void MdiWindow::support()
{
QDesktopServices::openUrl(QUrl("http://stackoverflow.org/"));
}
void MdiWindow::website()
{
QDesktopServices::openUrl(QUrl("http://slashdot.org/"));
}
void MdiWindow::bold()
{
if (activeMdiChild()) activeMdiChild()->bold();
}
void MdiWindow::italic()
{
if (activeMdiChild()) activeMdiChild()->italic();
}
void MdiWindow::quote()
{
if (activeMdiChild()) activeMdiChild()->quote();
}
void MdiWindow::code()
{
if (activeMdiChild()) activeMdiChild()->code();
}
void MdiWindow::heading1()
{
if (activeMdiChild()) activeMdiChild()->heading1();
}
void MdiWindow::heading2()
{
if (activeMdiChild()) activeMdiChild()->heading2();
}
void MdiWindow::heading3()
{
if (activeMdiChild()) activeMdiChild()->heading3();
}
void MdiWindow::heading4()
{
if (activeMdiChild()) activeMdiChild()->heading4();
}
void MdiWindow::hyperlink()
{
if (activeMdiChild()) activeMdiChild()->hyperlink();
}
void MdiWindow::image()
{
if (activeMdiChild()) activeMdiChild()->image();
}
void MdiWindow::unorderedList()
{
if (activeMdiChild()) activeMdiChild()->unorderedList();
}
void MdiWindow::orderedList()
{
if (activeMdiChild()) activeMdiChild()->orderedList();
}
void MdiWindow::horizontalRule()
{
if (activeMdiChild()) activeMdiChild()->horizontalRule();
}
void MdiWindow::timestamp()
{
if (activeMdiChild()) activeMdiChild()->timestamp();
}
void MdiWindow::pageNumber()
{
if (activeMdiChild()) activeMdiChild()->pageNumber();
}
void MdiWindow::pageCount()
{
if (activeMdiChild()) activeMdiChild()->pageCount();
}
void MdiWindow::options()
{
}
void MdiWindow::saveAll()
{
}
void MdiWindow::selectAll()
{
if (activeMdiChild()) activeMdiChild()->selectAll();
}
void MdiWindow::del()
{
if (activeMdiChild()) activeMdiChild()->del();
}
void MdiWindow::undo()
{
if (activeMdiChild()) activeMdiChild()->undo();
}
void MdiWindow::redo()
{
if (activeMdiChild()) activeMdiChild()->redo();
}
void MdiWindow::find()
{
if (activeMdiChild()) activeMdiChild()->find();
}
void MdiWindow::findNext()
{
if (activeMdiChild()) activeMdiChild()->findNext();
}
void MdiWindow::findPrevious()
{
if (activeMdiChild()) activeMdiChild()->findPrevious();
}
void MdiWindow::goToLine()
{
if (activeMdiChild()) activeMdiChild()->goToLine();
}
#include "html.h"
#include "document.h"
void MdiWindow::updatePreview()
{
MdiChild* child = activeMdiChild();
if (child)
{
QByteArray text = child->toPlainText().toLatin1();
hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML);
hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0);
hoedown_buffer *ob = hoedown_buffer_new(1024);
hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64);
hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size());
hoedown_document_free(document);
hoedown_html_renderer_free(renderer);
appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size)));
hoedown_buffer_free(ob);
}
}
void MdiWindow::updateActions()
{
bool hasMdiChild = (activeMdiChild() != 0);
bool hasSelection = (hasMdiChild && activeMdiChild()->textCursor().hasSelection());
appWindow->actionSave->setEnabled(hasMdiChild);
appWindow->actionSave_As->setEnabled(hasMdiChild);
appWindow->actionSave_All->setEnabled(hasMdiChild);
appWindow->actionClose->setEnabled(hasMdiChild);
#ifndef QT_NO_CLIPBOARD
appWindow->actionCut->setEnabled(hasSelection);
appWindow->actionCopy->setEnabled(hasSelection);
appWindow->actionPaste->setEnabled(hasMdiChild);
#endif
appWindow->actionSelect_All->setEnabled(hasMdiChild);
appWindow->actionDelete->setEnabled(hasMdiChild);
appWindow->actionUndo->setEnabled(hasMdiChild);
appWindow->actionRedo->setEnabled(hasMdiChild);
appWindow->actionFind->setEnabled(hasMdiChild);
appWindow->actionFind_Next->setEnabled(hasMdiChild);
appWindow->actionFind_Previous->setEnabled(hasMdiChild);
appWindow->actionGo_to_Line->setEnabled(hasMdiChild);
appWindow->actionBold->setEnabled(hasMdiChild);
appWindow->actionItalic->setEnabled(hasMdiChild);
appWindow->actionQuote->setEnabled(hasMdiChild);
appWindow->actionCode->setEnabled(hasMdiChild);
appWindow->actionHeading_1->setEnabled(hasMdiChild);
appWindow->actionHeading_2->setEnabled(hasMdiChild);
appWindow->actionHeading_3->setEnabled(hasMdiChild);
appWindow->actionHeading_4->setEnabled(hasMdiChild);
appWindow->actionHyperlink->setEnabled(hasMdiChild);
appWindow->actionImage->setEnabled(hasMdiChild);
appWindow->actionUnordered_List->setEnabled(hasMdiChild);
appWindow->actionOrdered_List->setEnabled(hasMdiChild);
appWindow->actionHorizontal_Rule->setEnabled(hasMdiChild);
appWindow->actionTimestamp->setEnabled(hasMdiChild);
appWindow->actionPage_Number->setEnabled(hasMdiChild);
appWindow->actionPage_Count->setEnabled(hasMdiChild);
appWindow->actionClose_All->setEnabled(hasMdiChild);
appWindow->actionNext->setEnabled(hasMdiChild);
appWindow->actionPrevious->setEnabled(hasMdiChild);
appWindow->action_Tile_Windows->setEnabled(hasMdiChild);
appWindow->action_Windowed->setEnabled(hasMdiChild);
//appWindow->actionTabbed->setEnabled(hasMdiChild);
//separatorAct->setVisible(hasMdiChild);
appWindow->menuView->clear();
appWindow->menuView->addAction(appWindow->action_Tile_Windows);
appWindow->menuView->addAction(appWindow->action_Windowed);
appWindow->menuView->addAction(appWindow->actionTabbed);
appWindow->menuView->addSeparator();
appWindow->menuView->addAction(appWindow->actionNext);
appWindow->menuView->addAction(appWindow->actionPrevious);
QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
if (!windows.isEmpty())
appWindow->menuView->addSeparator();
for (int i = 0; i < windows.size(); ++i) {
MdiChild *child = qobject_cast<MdiChild *>(windows.at(i)->widget());
QString text = QString("%1 %2").arg(i + 1).arg(child->userFriendlyCurrentFile());
if (i < 9)
text = "&" + text;
QAction *action = appWindow->menuView->addAction(text);
action->setCheckable(true);
action->setChecked(child == activeMdiChild());
connect(action, SIGNAL(triggered(bool)), windowMapper, SLOT(map()));
windowMapper->setMapping(action, windows.at(i));
}
}
MdiChild *MdiWindow::createMdiChild()
{
MdiChild *child = new MdiChild;
mdiArea->addSubWindow(child);
connect(child, SIGNAL(documentContentsChanged()), this, SLOT(updatePreview()));
connect(child, SIGNAL(closing()), this, SLOT(updateActions()));
#ifndef QT_NO_CLIPBOARD
connect(child, SIGNAL(copyAvailable(bool)), appWindow->actionCut, SLOT(setEnabled(bool)));
connect(child, SIGNAL(copyAvailable(bool)), appWindow->actionCopy, SLOT(setEnabled(bool)));
#endif
return child;
}
void MdiWindow::cascadeSubWindows()
{
mdiArea->setViewMode(QMdiArea::SubWindowView);
mdiArea->cascadeSubWindows();
}
void MdiWindow::tileSubWindows()
{
mdiArea->setViewMode(QMdiArea::SubWindowView);
mdiArea->tileSubWindows();
}
void MdiWindow::tabSubWindows()
{
mdiArea->setViewMode(QMdiArea::TabbedView);
}
void MdiWindow::readSettings()
{
YQ_LOG_DEBUG("Reading settings");
QSettings settings("QtProject", "MDI Example");
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
move(pos);
resize(size);
}
void MdiWindow::writeSettings()
{
YQ_LOG_DEBUG("Saving settings");
QSettings settings("QtProject", "MDI Example");
settings.setValue("pos", pos());
settings.setValue("size", size());
}
MdiChild *MdiWindow::activeMdiChild()
{
if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
return qobject_cast<MdiChild *>(activeSubWindow->widget());
return 0;
}
QMdiSubWindow *MdiWindow::findMdiChild(const QString &fileName)
{
QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
if (mdiChild && mdiChild->currentFile() == canonicalFilePath)
return window;
}
return 0;
}
void MdiWindow::switchLayoutDirection()
{
if (layoutDirection() == Qt::LeftToRight)
qApp->setLayoutDirection(Qt::RightToLeft);
else
qApp->setLayoutDirection(Qt::LeftToRight);
}
void MdiWindow::setActiveSubWindow(QWidget *window)
{
if (!window)
return;
mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}