1 // Copyright (c) 2012 Dennco Project
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // Created by tkawata on Sep-30, 2012.
21 #include "mainwindow.h"
22 #include "ui_mainwindow.h"
24 #include "dccreator.h"
25 #include "dccontent.h"
26 #include "dcglvisualizerwidget.h"
27 #include "dctreeviewwidget.h"
28 #include "dccellcodescripttreeviewwidget.h"
29 #include "TKConsole.h"
30 #include "utils/dcresources.h"
31 #include "utils/dcskeltoncreatorutil.h"
32 #include "dialog/dcinputnewcontentdirdialog.h"
33 #include "dialog/dcmanagecellcodedialog.h"
34 #include "dialog/dccodeeditorexternaleditorsettingdialog.h"
35 #include "dccellscriptseditorwindow.h"
37 #include <QCloseEvent>
38 #include <QFileDialog>
39 #include <QMessageBox>
41 #include <QLocalSocket>
44 const QString DENNCO_ENGINE = "QtDennco.exe";
45 #elif defined(Q_WS_MAC)
46 const QString DENNCO_ENGINE = "QtDennco.app";
47 #elif defined(Q_OS_UNIX)
48 const QString DENNCO_ENGINE = "./QtDennco";
51 class SleeperThread : public QThread
54 static void msleep(unsigned long msecs)
56 QThread::msleep(msecs);
60 MainWindow::MainWindow(QWidget *parent) :
62 ui(new Ui::MainWindow)
66 DCResources::initResources();
75 TKLog::setDestination(new TKConsole);
77 d_creator = new DCCreator(this);
78 d_visualizerWidget = new DCGLVisualizerWidget(d_creator, this) ;
79 setCentralWidget(d_visualizerWidget);
81 d_treeViewWidget = new DCTreeViewWidget(this, d_creator);
82 ui->treeViewDock->layout()->addWidget(d_treeViewWidget);
84 d_cellCodeScriptTreeViewWidget = new DCCellCodeScriptTreeViewWidget(this, d_creator);
85 ui->cellCodeScriptTreeViewDock->layout()->addWidget(d_cellCodeScriptTreeViewWidget);
87 DCCellScriptsEditorWindow::construct(d_creator);
89 setCurrentContent("");
90 setUnifiedTitleAndToolBarOnMac(true);
92 tabifyDockWidget(ui->dock2,ui->dock1);
95 MainWindow::~MainWindow()
103 void MainWindow::closeEvent(QCloseEvent *event)
113 void MainWindow::newFile()
115 QString bdir = QDir::home().absolutePath();
116 if (d_contentOpenHistory.length()>0)
118 QDir d(d_contentOpenHistory.at(0));
120 bdir = d.absolutePath();
122 DCInputNewContentDirDialog dialog(bdir);
125 QString dirName = dialog.getResult();
126 if (dirName.length() > 0 && DCSkeltonCreatorUtil::createNewContent(dirName))
128 loadContent(dirName);
132 void MainWindow::open()
136 QString dir = QDir::home().absolutePath();
137 if (d_contentOpenHistory.length()>0)
139 QDir d(d_contentOpenHistory.at(0));
141 dir = d.absolutePath();
143 QString dirName = QFileDialog::getExistingDirectory(this, tr("Open a content"),dir);
144 if (!dirName.isEmpty())
145 loadContent(dirName);
149 bool MainWindow::openRecent(int idx)
153 if (d_contentOpenHistory.length() > idx)
155 loadContent(d_contentOpenHistory.at(idx));
162 void MainWindow::openRecent1()
167 void MainWindow::openRecent2()
172 void MainWindow::openRecent3()
177 void MainWindow::openRecent4()
182 void MainWindow::openRecent5()
187 bool MainWindow::save(bool showMessage)
192 return d_creator->saveAll(showMessage);
195 bool MainWindow::save()
200 bool MainWindow::saveAs()
206 void MainWindow::doExternalEditorSetting()
208 DCCodeEditorExternalEditorSettingDialog dialog(this);
212 void MainWindow::about()
214 QMessageBox::about(this, tr("About Application"),
215 tr("TODO: exampalin
\81@about <b>dennco creator</b> "
216 "TODO: exampalin
\81@about <b>dennco creator</b> "
217 "TODO: exampalin
\81@about <b>dennco creator</b>"));
220 void MainWindow::documentWasModified()
223 // setWindowModified(textEdit->document()->isModified());
227 void MainWindow::createActions()
229 newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
230 newAct->setShortcuts(QKeySequence::New);
231 newAct->setStatusTip(tr("Create a new file"));
232 connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
234 openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
235 openAct->setShortcuts(QKeySequence::Open);
236 openAct->setStatusTip(tr("Open an existing file"));
237 connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
239 QAction *openRecentAct = new QAction(this);
240 connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent1()));
241 openRecentActs.append(openRecentAct);
243 openRecentAct = new QAction(this);
244 connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent2()));
245 openRecentActs.append(openRecentAct);
247 openRecentAct = new QAction(this);
248 connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent3()));
249 openRecentActs.append(openRecentAct);
251 openRecentAct = new QAction(this);
252 connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent4()));
253 openRecentActs.append(openRecentAct);
255 openRecentAct = new QAction(this);
256 connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent5()));
257 openRecentActs.append(openRecentAct);
259 saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
260 saveAct->setShortcuts(QKeySequence::Save);
261 saveAct->setStatusTip(tr("Save the document to disk"));
262 connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
264 saveAsAct = new QAction(tr("Save &As..."), this);
265 saveAsAct->setShortcuts(QKeySequence::SaveAs);
266 saveAsAct->setStatusTip(tr("Save the document under a new name"));
267 connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
269 exitAct = new QAction(tr("E&xit"), this);
270 exitAct->setShortcuts(QKeySequence::Quit);
271 exitAct->setStatusTip(tr("Exit the application"));
272 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
274 manageCellCodeAct = new QAction(tr("Manage Cell Code..."), this);
275 connect(manageCellCodeAct, SIGNAL(triggered()), this, SLOT(manageCellCode()));
277 cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
278 cutAct->setShortcuts(QKeySequence::Cut);
279 cutAct->setStatusTip(tr("Cut the current selection's contents to the "
281 // connect(cutAct, SIGNAL(triggered()), textEdit, SLOT(cut()));
283 copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
284 copyAct->setShortcuts(QKeySequence::Copy);
285 copyAct->setStatusTip(tr("Copy the current selection's contents to the "
287 // connect(copyAct, SIGNAL(triggered()), textEdit, SLOT(copy()));
289 pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
290 pasteAct->setShortcuts(QKeySequence::Paste);
291 pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
294 // connect(pasteAct, SIGNAL(triggered()), textEdit, SLOT(paste()));
296 playAct = new QAction(QIcon(":/images/playbutton.png"), tr("Play"), this);
297 playAct->setStatusTip(tr("Play the editing content"));
299 connect(playAct, SIGNAL(triggered()), this, SLOT(playContent()));
301 externalEditorSettingAct = new QAction(tr("&External editor..."), this);
302 externalEditorSettingAct->setStatusTip(tr("Setup properties for external code editor."));
303 connect(externalEditorSettingAct, SIGNAL(triggered()), this, SLOT(doExternalEditorSetting()));
305 aboutAct = new QAction(tr("&About"), this);
306 aboutAct->setStatusTip(tr("Show the application's About box"));
307 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
309 cutAct->setEnabled(false);
310 copyAct->setEnabled(false);
311 playAct->setEnabled(false);
312 // connect(textEdit, SIGNAL(copyAvailable(bool)),
313 // cutAct, SLOT(setEnabled(bool)));
314 // connect(textEdit, SIGNAL(copyAvailable(bool)),
315 // copyAct, SLOT(setEnabled(bool)));
318 void MainWindow::createMenus()
320 fileMenu = menuBar()->addMenu(tr("&File"));
321 fileMenu->addAction(newAct);
322 fileMenu->addAction(openAct);
323 openRecentMenu = fileMenu->addMenu(tr("Opened recently"));
324 fileMenu->addAction(saveAct);
325 fileMenu->addAction(saveAsAct);
326 fileMenu->addSeparator();
327 fileMenu->addAction(exitAct);
329 editMenu = menuBar()->addMenu(tr("&Edit"));
330 editMenu->addAction(manageCellCodeAct);
331 editMenu->addSeparator();
332 editMenu->addAction(cutAct);
333 editMenu->addAction(copyAct);
334 editMenu->addAction(pasteAct);
336 menuBar()->addSeparator();
338 editMenu = menuBar()->addMenu(tr("&Play"));
339 editMenu->addAction(playAct);
341 menuBar()->addSeparator();
343 settingMenu = menuBar()->addMenu(tr("&Setting"));
344 settingMenu->addAction(externalEditorSettingAct);
345 helpMenu = menuBar()->addMenu(tr("&Help"));
346 helpMenu->addAction(aboutAct);
349 void MainWindow::createOpenRecentMenu()
351 openRecentMenu->clear();
352 for (int i = 0; i < d_contentOpenHistory.length() && i < openRecentActs.length(); i++)
354 openRecentActs.at(i)->setText(d_contentOpenHistory.at(i));
355 openRecentMenu->addAction(openRecentActs.at(i));
359 void MainWindow::createToolBars()
361 fileToolBar = addToolBar(tr("File"));
362 fileToolBar->addAction(newAct);
363 fileToolBar->addAction(openAct);
364 fileToolBar->addAction(saveAct);
366 editToolBar = addToolBar(tr("Edit"));
367 editToolBar->addAction(cutAct);
368 editToolBar->addAction(copyAct);
369 editToolBar->addAction(pasteAct);
371 playToolBar = addToolBar(tr("Play"));
372 playToolBar->addAction(playAct);
375 void MainWindow::createStatusBar()
378 statusBar()->showMessage(tr("Ready"));
382 void MainWindow::readSettings()
384 QSettings settings("dennco project", "dennco creator");
385 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
386 QSize size = settings.value("size", QSize(400, 400)).toSize();
387 d_contentOpenHistory = settings.value("contents", QStringList()).toStringList();
391 createOpenRecentMenu();
394 void MainWindow::writeSettings()
396 QSettings settings("dennco project", "dennco creator");
397 settings.setValue("pos", pos());
398 settings.setValue("size", size());
399 settings.setValue("contents", d_contentOpenHistory);
403 QByteArray MainWindow::readSettingsForCellScriptsEditorGeometory()
405 QSettings settings("dennco project", "dennco creator");
406 return settings.value("segeometory").toByteArray();
410 void MainWindow::writeSettingsForCellScriptsEditorGeometory(const QByteArray &value)
412 QSettings settings("dennco project", "dennco creator");
413 settings.setValue("segeometory", value);
417 QString MainWindow::readSettingsForExternalScriptEditorPath()
419 QSettings settings("dennco project", "dennco creator");
420 return settings.value("external editor path").toString();
424 QString MainWindow::readSettingsForExternalScriptEditorParameters()
426 QSettings settings("dennco project", "dennco creator");
427 return settings.value("external editor param").toString();
431 void MainWindow::writeSettingsForExternalScriptEditorPath(const QString &arg)
433 QSettings settings("dennco project", "dennco creator");
434 settings.setValue("external editor path", arg);
438 void MainWindow::writeSettingsForExternalScriptEditorParameters(const QString &arg)
440 QSettings settings("dennco project", "dennco creator");
441 settings.setValue("external editor param", arg);
444 bool MainWindow::maybeSave()
446 if (d_creator->getCurrentContent())
448 if (!DCCellScriptsEditorWindow::closeEditor())
451 if (d_creator->getCurrentContent()->getIsModified())
453 QMessageBox::StandardButton ret;
454 ret = QMessageBox::warning(this, tr("Application"),
455 tr("The content has been modified.\n"
456 "Do you want to save your changes?"),
457 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
458 if (ret == QMessageBox::Save)
460 else if (ret == QMessageBox::Cancel)
467 void MainWindow::loadContent(const QString &contentDirectory)
472 if (d_creator->loadContent(contentDirectory))
474 playAct->setEnabled(true);
478 playAct->setEnabled(false);
481 QString absContentDirectory = QDir().absoluteFilePath(contentDirectory);
482 int idx = d_contentOpenHistory.indexOf(absContentDirectory);
485 d_contentOpenHistory.removeAt(idx);
487 d_contentOpenHistory.prepend(absContentDirectory);
488 while (d_contentOpenHistory.length()>5)
490 d_contentOpenHistory.removeLast();
492 setCurrentContent(contentDirectory);
493 createOpenRecentMenu();
495 QDir dir(contentDirectory);
496 QString title = dir.dirName();
497 title.append(" - dennco creator");
498 setWindowTitle(title);
501 void MainWindow::setCurrentContent(const QString &contentDirectory)
503 curContent = contentDirectory;
504 setWindowModified(false);
506 QString shownName = curContent;
507 if (curContent.isEmpty())
508 shownName = "untitled.txt";
509 setWindowFilePath(shownName);
512 QString MainWindow::strippedName(const QString &fullFileName)
514 return QFileInfo(fullFileName).fileName();
517 void MainWindow::playContent()
519 if (!d_creator || !d_creator->getCurrentContent())
524 if (d_player.state() != QProcess::NotRunning)
526 QLocalSocket *socket = new QLocalSocket(this);
527 connect(socket, SIGNAL(disconnected()), socket,SLOT(deleteLater()));
529 for (int retry = 0; retry < 20; retry++)
531 socket->connectToServer(d_IPCServerName);
532 if (socket->waitForConnected())
536 SleeperThread::msleep(500);
538 QString requestData = "close,";
539 socket->write(requestData.toLocal8Bit());
541 socket->waitForBytesWritten();
544 if (!d_player.waitForFinished())
548 d_IPCServerName = "denncoCreator_";
549 QTextStream s(&d_IPCServerName);
550 s.setIntegerBase(16);
553 if (d_player.state() == QProcess::NotRunning)
557 args << QCoreApplication::applicationDirPath() + "/../../../" + DENNCO_ENGINE;
560 args << "-creatorControlled";
561 args << d_IPCServerName;
564 d_player.start("open" , args);
566 d_player.start(DENNCO_ENGINE, args);
568 d_player.waitForStarted();
571 if (d_player.state() == QProcess::Running)
573 QLocalSocket *socket = new QLocalSocket(this);
574 connect(socket, SIGNAL(disconnected()), socket,SLOT(deleteLater()));
575 for (int retry = 0; retry < 20; retry++)
577 socket->connectToServer(d_IPCServerName);
578 if (socket->waitForConnected())
582 SleeperThread::msleep(500);
584 QString requestData = "load,";
585 requestData.append(d_creator->getCurrentContent()->getContentRootPath());
586 socket->write(requestData.toLocal8Bit());
588 socket->waitForBytesWritten();
593 void MainWindow::manageCellCode()
598 DCManageCellCodeDialog dialog(d_creator, NULL, this);
604 bool MainWindow::openExternalEditorFor(const QString &path)
606 static QList<QProcess*> s_processes;
607 static QMutex s_mutex;
609 QMutexLocker locker(&s_mutex);
611 QString editorPath = readSettingsForExternalScriptEditorPath();
612 if (editorPath.isEmpty() || editorPath.length() == 0)
614 DCCodeEditorExternalEditorSettingDialog dialog;
616 editorPath = readSettingsForExternalScriptEditorPath();
618 if (editorPath.isEmpty() || editorPath.length() == 0)
621 QString parameterOrg = readSettingsForExternalScriptEditorParameters();
622 QString parameter = "";
624 int j = parameterOrg.indexOf(QRegExp("%F[ \t\"']|%F$"),i);
627 parameter += parameterOrg.mid(i, j-i);
630 if (i > parameterOrg.length())
632 j = parameterOrg.indexOf(QRegExp("%F[ \t\"']|%F$"),i);
634 if (i < parameterOrg.length())
635 parameter += parameterOrg.mid(i);
637 QList<QProcess*>::iterator it = s_processes.begin();
638 while (it != s_processes.end())
640 if ((*it)->state() != QProcess::Running)
643 it = s_processes.erase(it);
648 QProcess *newProcess = new QProcess;
649 newProcess->start("\"" + editorPath + "\" " + parameter);
651 s_processes.append(newProcess);