OSDN Git Service

[denncoCreator] implemented the feature to list recent opened contents.
[dennco/denncoCreator.git] / Source / mainwindow.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
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.
7 //
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.
12 //
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/>.
15
16 //
17 //  Created by tkawata on Sep-30, 2012.
18 //
19 #include "TKLog.h"
20
21 #include "mainwindow.h"
22 #include "ui_mainwindow.h"
23
24 #include "dccreator.h"
25 #include "dccontent.h"
26 #include "dcglvisualizerwidget.h"
27 #include "dctreeviewwidget.h"
28 #include "TKConsole.h"
29 #include "utils/dcresources.h"
30 #include "utils/dcskeltoncreatorutil.h"
31
32 #include <QCloseEvent>
33 #include <QFileDialog>
34 #include <QMessageBox>
35 #include <QSettings>
36 #include <QLocalSocket>
37
38 #ifdef Q_WS_WIN
39     const QString DENNCO_ENGINE = "QtDennco.exe";
40 #elif Q_WS_MACX
41
42 #elif Q_OS_UNIX
43
44 #endif
45
46 class SleeperThread : public QThread
47 {
48 public:
49     static void msleep(unsigned long msecs)
50     {
51         QThread::msleep(msecs);
52     }
53 };
54
55 MainWindow::MainWindow(QWidget *parent) :
56     QMainWindow(parent),
57     ui(new Ui::MainWindow)
58 {
59     ui->setupUi(this);
60
61     DCResources::initResources();
62
63     createActions();
64     createMenus();
65     createToolBars();
66     createStatusBar();
67
68     readSettings();
69
70     TKLog::setDestination(new TKConsole);
71
72     d_creator = new DCCreator(this);
73     d_visualizerWidget = new DCGLVisualizerWidget(d_creator, this) ;
74     setCentralWidget(d_visualizerWidget);
75
76     d_treeViewWidget = new DCTreeViewWidget(this, d_creator);
77     ui->treeViewDock->layout()->addWidget(d_treeViewWidget);
78
79     setCurrentContent("");
80     setUnifiedTitleAndToolBarOnMac(true);
81 }
82
83 MainWindow::~MainWindow()
84 {
85     delete ui;
86     if (d_creator)
87         delete d_creator;
88 }
89
90
91 //! [3]
92 void MainWindow::closeEvent(QCloseEvent *event)
93 //! [3] //! [4]
94 {
95     if (maybeSave()) {
96         writeSettings();
97         event->accept();
98     } else {
99         event->ignore();
100     }
101 }
102
103 void MainWindow::newFile()
104 {
105     QString dirName = QFileDialog::getSaveFileName(this, tr("Create new content"));
106     if (!dirName.isEmpty() && DCSkeltonCreatorUtil::createNewContent(dirName))
107     {
108         loadContent(dirName);
109     }
110 }
111
112 void MainWindow::open()
113 {
114     if (maybeSave())
115     {
116         QString dir = QDir::home().absolutePath();
117         if (d_contentOpenHistory.length()>0)
118         {
119             QDir d(d_contentOpenHistory.at(0));
120             d.cdUp();
121             dir = d.absolutePath();
122         }
123         QString dirName = QFileDialog::getExistingDirectory(this, tr("Open a content"),dir);
124         if (!dirName.isEmpty())
125             loadContent(dirName);
126     }
127 }
128
129 bool MainWindow::openRecent(int idx)
130 {
131     if (maybeSave())
132     {
133         if (d_contentOpenHistory.length() > idx)
134         {
135             loadContent(d_contentOpenHistory.at(idx));
136             return true;
137         }
138     }
139     return false;
140 }
141
142 void MainWindow::openRecent1()
143 {
144     openRecent(0);
145 }
146
147 void MainWindow::openRecent2()
148 {
149     openRecent(1);
150 }
151
152 void MainWindow::openRecent3()
153 {
154     openRecent(2);
155 }
156
157 void MainWindow::openRecent4()
158 {
159     openRecent(3);
160 }
161
162 void MainWindow::openRecent5()
163 {
164     openRecent(4);
165 }
166
167 bool MainWindow::save()
168 {
169     return saveContent();
170 }
171
172 bool MainWindow::saveAs()
173 {
174     //TODO
175     return false;
176 }
177
178 void MainWindow::about()
179 {
180    QMessageBox::about(this, tr("About Application"),
181             tr("TODO: exampalin\81@about <b>dennco creator</b>  "
182                "TODO: exampalin\81@about <b>dennco creator</b> "
183                "TODO: exampalin\81@about <b>dennco creator</b>"));
184 }
185
186 void MainWindow::documentWasModified()
187 //! [15] //! [16]
188 {
189 //    setWindowModified(textEdit->document()->isModified());
190 }
191 //! [16]
192
193 void MainWindow::createActions()
194 {
195     newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
196     newAct->setShortcuts(QKeySequence::New);
197     newAct->setStatusTip(tr("Create a new file"));
198     connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
199
200     openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
201     openAct->setShortcuts(QKeySequence::Open);
202     openAct->setStatusTip(tr("Open an existing file"));
203     connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
204
205     QAction *openRecentAct = new QAction(this);
206     connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent1()));
207     openRecentActs.append(openRecentAct);
208
209     openRecentAct = new QAction(this);
210     connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent2()));
211     openRecentActs.append(openRecentAct);
212
213     openRecentAct = new QAction(this);
214     connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent3()));
215     openRecentActs.append(openRecentAct);
216
217     openRecentAct = new QAction(this);
218     connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent4()));
219     openRecentActs.append(openRecentAct);
220
221     openRecentAct = new QAction(this);
222     connect(openRecentAct, SIGNAL(triggered()), this, SLOT(openRecent5()));
223     openRecentActs.append(openRecentAct);
224
225     saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
226     saveAct->setShortcuts(QKeySequence::Save);
227     saveAct->setStatusTip(tr("Save the document to disk"));
228     connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
229
230     saveAsAct = new QAction(tr("Save &As..."), this);
231     saveAsAct->setShortcuts(QKeySequence::SaveAs);
232     saveAsAct->setStatusTip(tr("Save the document under a new name"));
233     connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
234
235     exitAct = new QAction(tr("E&xit"), this);
236     exitAct->setShortcuts(QKeySequence::Quit);
237     exitAct->setStatusTip(tr("Exit the application"));
238     connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
239
240     cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
241     cutAct->setShortcuts(QKeySequence::Cut);
242     cutAct->setStatusTip(tr("Cut the current selection's contents to the "
243                             "clipboard"));
244 //    connect(cutAct, SIGNAL(triggered()), textEdit, SLOT(cut()));
245
246     copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
247     copyAct->setShortcuts(QKeySequence::Copy);
248     copyAct->setStatusTip(tr("Copy the current selection's contents to the "
249                              "clipboard"));
250 //    connect(copyAct, SIGNAL(triggered()), textEdit, SLOT(copy()));
251
252     pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
253     pasteAct->setShortcuts(QKeySequence::Paste);
254     pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
255                               "selection"));
256
257     //    connect(pasteAct, SIGNAL(triggered()), textEdit, SLOT(paste()));
258
259     playAct = new QAction(QIcon(":/images/playbutton.png"), tr("Play"), this);
260     playAct->setStatusTip(tr("Play the editing content"));
261
262     connect(playAct, SIGNAL(triggered()), this, SLOT(playContent()));
263
264     aboutAct = new QAction(tr("&About"), this);
265     aboutAct->setStatusTip(tr("Show the application's About box"));
266     connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
267
268     cutAct->setEnabled(false);
269     copyAct->setEnabled(false);
270     playAct->setEnabled(false);
271 //    connect(textEdit, SIGNAL(copyAvailable(bool)),
272 //            cutAct, SLOT(setEnabled(bool)));
273 //    connect(textEdit, SIGNAL(copyAvailable(bool)),
274 //            copyAct, SLOT(setEnabled(bool)));
275 }
276
277 void MainWindow::createMenus()
278 {
279     fileMenu = menuBar()->addMenu(tr("&File"));
280     fileMenu->addAction(newAct);
281     fileMenu->addAction(openAct);
282     openRecentMenu = fileMenu->addMenu(tr("Opened recently"));
283     fileMenu->addAction(saveAct);
284     fileMenu->addAction(saveAsAct);
285     fileMenu->addSeparator();
286     fileMenu->addAction(exitAct);
287
288     editMenu = menuBar()->addMenu(tr("&Edit"));
289     editMenu->addAction(cutAct);
290     editMenu->addAction(copyAct);
291     editMenu->addAction(pasteAct);
292
293     menuBar()->addSeparator();
294
295     editMenu = menuBar()->addMenu(tr("&Play"));
296     editMenu->addAction(playAct);
297
298     menuBar()->addSeparator();
299
300     helpMenu = menuBar()->addMenu(tr("&Help"));
301     helpMenu->addAction(aboutAct);
302 }
303
304 void MainWindow::createOpenRecentMenu()
305 {
306     openRecentMenu->clear();
307     for (int i = 0; i < d_contentOpenHistory.length() && i < openRecentActs.length(); i++)
308     {
309         openRecentActs.at(i)->setText(d_contentOpenHistory.at(i));
310         openRecentMenu->addAction(openRecentActs.at(i));
311     }
312 }
313
314 void MainWindow::createToolBars()
315 {
316     fileToolBar = addToolBar(tr("File"));
317     fileToolBar->addAction(newAct);
318     fileToolBar->addAction(openAct);
319     fileToolBar->addAction(saveAct);
320
321     editToolBar = addToolBar(tr("Edit"));
322     editToolBar->addAction(cutAct);
323     editToolBar->addAction(copyAct);
324     editToolBar->addAction(pasteAct);
325
326     playToolBar = addToolBar(tr("Play"));
327     playToolBar->addAction(playAct);
328 }
329
330 void MainWindow::createStatusBar()
331 //! [32] //! [33]
332 {
333     statusBar()->showMessage(tr("Ready"));
334 }
335 //! [33]
336
337 void MainWindow::readSettings()
338 {
339     QSettings settings("dennco project", "dennco creator");
340     QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
341     QSize size = settings.value("size", QSize(400, 400)).toSize();
342     d_contentOpenHistory = settings.value("contents", QStringList()).toStringList();
343
344     resize(size);
345     move(pos);
346     createOpenRecentMenu();
347 }
348
349 void MainWindow::writeSettings()
350 {
351     QSettings settings("dennco project", "dennco creator");
352     settings.setValue("pos", pos());
353     settings.setValue("size", size());
354     settings.setValue("contents", d_contentOpenHistory);
355 }
356
357 //! [40]
358 bool MainWindow::maybeSave()
359 //! [40] //! [41]
360 {
361 //    if (textEdit->document()->isModified()) {
362  //       QMessageBox::StandardButton ret;
363  //       ret = QMessageBox::warning(this, tr("Application"),
364  //                    tr("The document has been modified.\n"
365 //                        "Do you want to save your changes?"),
366 //                     QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
367 //        if (ret == QMessageBox::Save)
368 //            return save();
369 //        else if (ret == QMessageBox::Cancel)
370 //            return false;
371 //    }
372     return true;
373 }
374 //! [41]
375
376 //! [42]
377 void MainWindow::loadContent(const QString &contentDirectory)
378 {
379     if (!d_creator)
380         return;
381
382     if (d_creator->loadContent(contentDirectory))
383     {
384         playAct->setEnabled(true);
385     }
386     else
387     {
388         playAct->setEnabled(false);
389     }
390
391     QString absContentDirectory = QDir().absoluteFilePath(contentDirectory);
392     int idx = d_contentOpenHistory.indexOf(absContentDirectory);
393     if (idx != -1)
394     {
395         d_contentOpenHistory.removeAt(idx);
396     }
397     d_contentOpenHistory.prepend(absContentDirectory);
398     while (d_contentOpenHistory.length()>5)
399     {
400         d_contentOpenHistory.removeLast();
401     }
402     setCurrentContent(contentDirectory);
403     createOpenRecentMenu();
404 }
405
406 bool MainWindow::saveContent()
407 {
408     if (!d_creator)
409         return false;
410
411     if (d_creator->getCurrentContainer())
412     {
413         d_creator->saveAll(true);
414     }
415
416     return true;
417 }
418
419 void MainWindow::setCurrentContent(const QString &contentDirectory)
420 {
421     curContent = contentDirectory;
422 //    textEdit->document()->setModified(false);
423     setWindowModified(false);
424
425     QString shownName = curContent;
426     if (curContent.isEmpty())
427         shownName = "untitled.txt";
428     setWindowFilePath(shownName);
429 }
430
431 QString MainWindow::strippedName(const QString &fullFileName)
432 {
433     return QFileInfo(fullFileName).fileName();
434 }
435
436 void MainWindow::playContent()
437 {
438     if (!d_creator || !d_creator->getCurrentContent())
439         return;
440
441     if (d_player.state() != QProcess::NotRunning)
442     {
443         QLocalSocket *socket = new QLocalSocket(this);
444         connect(socket, SIGNAL(disconnected()), socket,SLOT(deleteLater()));
445
446         for (int retry = 0; retry < 20; retry++)
447         {
448             socket->connectToServer(d_IPCServerName);
449             if (socket->waitForConnected())
450             {
451                 break;
452             }
453             SleeperThread::msleep(500);
454         }
455         QString requestData = "close,";
456         socket->write(requestData.toLocal8Bit());
457         socket->flush();
458         socket->waitForBytesWritten();
459         socket->close();
460
461         if (!d_player.waitForFinished())
462             d_player.kill();
463     }
464
465     d_IPCServerName = "denncoCreator_";
466     QTextStream s(&d_IPCServerName);
467     s.setIntegerBase(16);
468     s << qrand();
469
470     if (d_player.state() == QProcess::NotRunning)
471     {
472         QStringList args;
473         args << "-creatorControlled";
474         args << d_IPCServerName;
475
476         d_player.start(DENNCO_ENGINE, args);
477         d_player.waitForStarted();
478     }
479
480     if (d_player.state() == QProcess::Running)
481     {
482         QLocalSocket *socket = new QLocalSocket(this);
483         connect(socket, SIGNAL(disconnected()), socket,SLOT(deleteLater()));
484         for (int retry = 0; retry < 20; retry++)
485         {
486             socket->connectToServer(d_IPCServerName);
487             if (socket->waitForConnected())
488             {
489                 break;
490             }
491             SleeperThread::msleep(500);
492         }
493         QString requestData = "load,";
494         requestData.append(d_creator->getCurrentContent()->getContentRootPath());
495         socket->write(requestData.toLocal8Bit());
496         socket->flush();
497         socket->waitForBytesWritten();
498         socket->close();
499     }
500 }