1 /**************************************************************************
2 ** This file is part of LiteIDE
3 **
4 ** Copyright (c) 2011-2019 LiteIDE. All rights reserved.
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** In addition, as a special exception,  that plugins developed for LiteIDE,
17 ** are allowed to remain closed sourced and can be distributed under any license .
18 ** These rights are included in the file LGPL_EXCEPTION.txt in this package.
19 **
20 **************************************************************************/
21 // Module: liteapp.cpp
22 // Creator: visualfc <visualfc@gmail.com>
23 
24 #include "liteapp.h"
25 #include "filemanager.h"
26 #include "editormanager.h"
27 #include "projectmanager.h"
28 #include "pluginmanager.h"
29 #include "actionmanager.h"
30 #include "mimetypemanager.h"
31 #include "optionmanager.h"
32 #include "toolwindowmanager.h"
33 #include "htmlwidgetmanager.h"
34 #include "recentmanager.h"
35 #include "mainwindow.h"
36 #include "liteappoptionfactory.h"
37 #include "folderprojectfactory.h"
38 #include "textbrowserhtmlwidget.h"
39 #include "pluginsdialog.h"
40 #include "liteapp_global.h"
41 #ifdef Q_OS_MAC
42 #include "macsupport.h"
43 #endif
44 #include "splitwindowstyle.h"
45 #include "sidewindowstyle.h"
46 #include "idletimer.h"
47 #include "iconutil/iconutil.h"
48 #include "liteapi/liteutil.h"
49 #include "liteapi/liteids.h"
50 #include <QApplication>
51 #include <QSplashScreen>
52 #include <QMenuBar>
53 #include <QDir>
54 #include <QToolBar>
55 #include <QAction>
56 #include <QDateTime>
57 #include <QSplitter>
58 #include <QTextCursor>
59 #include <QTextBlock>
60 #include <QTimer>
61 #include <QPainter>
62 #include <QComboBox>
63 #include <QProcessEnvironment>
64 #include <QDebug>
65 //lite_memory_check_begin
66 #if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
67      #define _CRTDBG_MAP_ALLOC
68      #include <stdlib.h>
69      #include <crtdbg.h>
70      #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
71      #define new DEBUG_NEW
72 #endif
73 //lite_memory_check_end
74 
75 #define LITEIDE_VERSION "X37.4"
76 
77 
getRootPath()78 QString LiteApp::getRootPath()
79 {
80     QDir rootDir = QApplication::applicationDirPath();
81     rootDir.cdUp();
82     return rootDir.canonicalPath();
83 }
84 
getToolPath()85 QString LiteApp::getToolPath()
86 {
87     static QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
88     QString path = env.value("LITEIDE_TOOL_PATH");
89     if (!path.isEmpty()) {
90         return path;
91     }
92     return QApplication::applicationDirPath();
93 }
94 
getPluginPath()95 QString LiteApp::getPluginPath()
96 {
97     static QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
98     QString path = env.value("LITEIDE_PLUGIN_PATH");
99     if (!path.isEmpty()) {
100         return path;
101     }
102     QString root = getRootPath();
103 #ifdef Q_OS_MAC
104     return root+"/PlugIns";
105 #else
106     return root+"/lib/liteide/plugins";
107 #endif
108 }
109 
getResoucePath()110 QString LiteApp::getResoucePath()
111 {
112     static QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
113     QString path = env.value("LITEIDE_RES_PATH");
114     if (!path.isEmpty()) {
115         return path;
116     }
117     QString root = getRootPath();
118 #ifdef Q_OS_MAC
119     return root+"/Resources";
120 #else
121     return root+"/share/liteide";
122 #endif
123 }
124 
getStoragePath()125 QString LiteApp::getStoragePath()
126 {
127 #if QT_VERSION >= 0x050000
128     QString root = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
129 #else
130     QString root = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
131 #endif
132     return root+"/liteide";
133 }
134 
NewApplication(const QString & sessionName,IApplication * baseApp)135 IApplication* LiteApp::NewApplication(const QString &sessionName, IApplication *baseApp)
136 {
137     LiteApp *app = new LiteApp;
138     app->load(sessionName,baseApp);
139     return app;
140 }
141 
pluginManager()142 PluginManager *LiteApp::pluginManager()
143 {
144     static PluginManager manager;
145     return &manager;
146 }
147 
appList()148 QList<IApplication *> LiteApp::appList()
149 {
150     return s_appList;
151 }
152 
153 QMap<QString,QVariant> LiteApp::s_cookie;
154 
155 QList<IApplication*> LiteApp::s_appList;
156 
LiteApp()157 LiteApp::LiteApp()
158     : m_rootPath(LiteApp::getRootPath()),
159       m_applicationPath(QApplication::applicationDirPath()),
160       m_toolPath(LiteApp::getToolPath()),
161       m_pluginPath(LiteApp::getPluginPath()),
162       m_resourcePath(LiteApp::getResoucePath()),
163       m_storagePath(LiteApp::getStoragePath())
164 {
165     s_appList.append(this);
166 
167     QSettings global(m_resourcePath+"/liteapp/config/global.ini",QSettings::IniFormat);
168     bool storeLocal = global.value(LITEIDE_STORELOCAL,false).toBool();
169 
170     QString flagLocalSetting = "--local-setting";
171     QString flagUserSetting = "--user-setting";
172 
173     if (s_cookie.value(flagUserSetting).toBool()) {
174         storeLocal = false;
175     } else if (s_cookie.value(flagLocalSetting).toBool()) {
176         storeLocal = true;
177     }
178 
179     if (storeLocal) {
180         m_settings = new QSettings(m_resourcePath+"/liteapp/config/liteide.ini", QSettings::IniFormat);
181     } else {
182         m_settings = new QSettings(QSettings::IniFormat,QSettings::UserScope,"liteide","liteide",this);
183     }
184 
185     QStringList searchPathList;
186     if (m_settings->value(LITEIDE_CUSTOMEICON,false).toBool()) {
187         QString iconPath = m_settings->value(LITEIDE_CUSTOMEICONPATH,"default").toString();
188         if (!iconPath.isEmpty()) {
189             searchPathList << m_resourcePath+"/liteapp/qrc/"+iconPath+"/liteapp";
190             searchPathList << m_resourcePath+"/liteapp/qrc/"+iconPath;
191         }
192     }
193     searchPathList << ":/";
194     searchPathList << m_resourcePath+"/liteapp/qrc/default/liteapp";
195     searchPathList << m_resourcePath+"/liteapp/qrc/default";
196     QDir::setSearchPaths("icon",searchPathList);
197 
198     m_extension = new Extension;
199 
200     //install idle timer;
201     m_idleTimer = new AppIdleTimer;
202     m_extension->addObject("LiteApi.IAppIdleTimer",m_idleTimer);
203 
204     m_mainwindow = new MainWindow(this);
205 
206     QString style = this->settings()->value(LITEAPP_STYLE,"sidebar").toString();
207     if (style == "splitter") {
208         SplitWindowStyle *style = new SplitWindowStyle(this,m_mainwindow);
209         m_mainwindow->setWindowStyle(style);
210     } else {
211         SideWindowStyle *style = new SideWindowStyle(this,m_mainwindow);
212         m_mainwindow->setWindowStyle(style);
213     }
214 
215     m_toolWindowManager = new ToolWindowManager;
216     m_htmlWidgetManager = new HtmlWidgetManager;
217     m_actionManager = new ActionManager;
218     m_projectManager = new ProjectManager;
219     m_fileManager = new FileManager;
220     m_editorManager = new EditorManager;
221     m_mimeTypeManager = new MimeTypeManager;
222     m_optionManager = new OptionManager;
223     m_recentManager = new RecentManager;
224 
225     m_goProxy = new GoProxy(this);
226     m_actionManager->initWithApp(this);
227 
228     m_mainwindow->createToolWindowMenu();
229 
230     m_toolWindowManager->initWithApp(this);
231     m_mimeTypeManager->initWithApp(this);
232     m_recentManager->initWithApp(this);
233     m_projectManager->initWithApp(this);
234     m_fileManager->initWithApp(this);
235     m_editorManager->initWithApp(this);
236     m_optionManager->initWithApp(this);
237 
238     //m_mainwindow->setCentralWidget(m_editorManager->widget());
239     m_mainwindow->splitter()->addWidget(m_editorManager->widget());
240     //m_mainwindow->splitter()->addWidget(m_outputManager->widget());
241     m_mainwindow->splitter()->setStretchFactor(0,50);
242     //m_mainwindow->setStatusBar(m_outputManager->statusBar());
243 
244     m_htmlWidgetManager->addFactory(new TextBrowserHtmlWidgetFactory(this));
245 
246     m_extension->addObject("LiteApi.IMimeTypeManager",m_mimeTypeManager);
247     m_extension->addObject("LiteApi.IProjectManager",m_projectManager);
248     m_extension->addObject("LiteApi.IEditManager",m_editorManager);
249     m_extension->addObject("LiteApi.IOptoinManager",m_optionManager);
250     m_extension->addObject("LiteApi.IToolWindowManager",m_toolWindowManager);
251     m_extension->addObject("LiteApi.QMainWindow",m_mainwindow);
252     m_extension->addObject("LiteApi.QMainWindow.QSplitter",m_mainwindow->splitter());
253     m_extension->addObject("LiteApi.IHtmlWidgetManager",m_htmlWidgetManager);
254 
255     //add actions
256     connect(m_projectManager,SIGNAL(currentProjectChanged(LiteApi::IProject*)),this,SLOT(currentProjectChanged(LiteApi::IProject*)));
257     connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),m_projectManager,SLOT(currentEditorChanged(LiteApi::IEditor*)));
258     connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),m_mainwindow,SLOT(currentEditorChanged(LiteApi::IEditor*)));
259     connect(m_editorManager,SIGNAL(editorModifyChanged(LiteApi::IEditor*,bool)),m_mainwindow,SLOT(editorModifyChanged(LiteApi::IEditor*,bool)));
260     connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*)));
261     connect(m_editorManager,SIGNAL(tabAddRequest()),m_fileManager,SLOT(openEditors()));
262     connect(m_editorManager,SIGNAL(editorSaved(LiteApi::IEditor*)),m_fileManager,SLOT(editorSaved(LiteApi::IEditor*)));
263     connect(m_editorManager,SIGNAL(editorCreated(LiteApi::IEditor*)),m_fileManager,SLOT(editorCreated(LiteApi::IEditor*)));
264     connect(m_editorManager,SIGNAL(editorAboutToClose(LiteApi::IEditor*)),m_fileManager,SLOT(editorAboutToClose(LiteApi::IEditor*)));
265     connect(m_editorManager,SIGNAL(doubleClickedTab()),m_mainwindow,SLOT(showOrHideToolWindow()));
266     connect(m_optionManager,SIGNAL(applyOption(QString)),m_fileManager,SLOT(applyOption(QString)));
267     connect(m_optionManager,SIGNAL(applyOption(QString)),m_projectManager,SLOT(applyOption(QString)));
268     connect(m_optionManager,SIGNAL(applyOption(QString)),m_editorManager,SLOT(applyOption(QString)));
269     connect(m_optionManager,SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString)));
270 
271     QAction *esc = new QAction(tr("Escape"),this);
272     m_actionManager->getActionContext(this,"App")->regAction(esc,"Escape","ESC");
273     m_mainwindow->addAction(esc);
274     connect(esc,SIGNAL(triggered()),this,SLOT(escape()));
275 
276     createActions();
277     createMenus();
278     createToolBars();
279 
280     m_editorManager->createActions();
281 
282     m_logOutput = new TextOutput(this);
283     //m_outputManager->addOutuput(m_logOutput,tr("Console"));
284     m_logAct = m_toolWindowManager->addToolWindow(Qt::BottomDockWidgetArea,m_logOutput,"EventLog",tr("Event Log"),true);
285     connect(m_logOutput,SIGNAL(dbclickEvent(QTextCursor)),this,SLOT(dbclickLogOutput(QTextCursor)));
286 
287     m_optionAct = new QAction(loadIcon("icon:images/options.png"),tr("Options"),this);
288     m_optionAct->setMenuRole(QAction::PreferencesRole);
289     m_actionManager->setViewMenuSeparator("sep/option",true);
290     m_actionManager->insertViewMenuAction(m_optionAct,"sep/option");
291 
292     m_stdToolBar->addSeparator();
293     m_stdToolBar->addAction(m_optionAct);
294 
295     connect(m_optionAct,SIGNAL(triggered()),m_optionManager,SLOT(exec()));
296 
297     this->appendLog("LiteApp","Initializing");
298     this->appendLog("Load Setting",m_settings->fileName());
299 
300     m_liteAppOptionFactory = new LiteAppOptionFactory(this,this);
301 
302     m_optionManager->addFactory(m_liteAppOptionFactory);
303 
304     connect(m_goProxy,SIGNAL(stdoutput(QByteArray)),this,SLOT(goproxyDone(QByteArray)));
305     //connect(this,SIGNAL(key_escape()),m_mainwindow,SLOT(hideOutputWindow()));
306     connect(m_mainwindow,SIGNAL(fullScreenStateChanged(bool)),m_fullScreent,SLOT(setChecked(bool)));
307 }
308 
makeSplashImage(LiteApi::IApplication * app)309 static QImage makeSplashImage(LiteApi::IApplication *app)
310 {
311     QRect r(0,0,400,280);
312     QImage image(r.size(),QImage::Format_ARGB32_Premultiplied);
313 
314     QPainter painter(&image);
315     painter.setRenderHint(QPainter::Antialiasing,true);
316 
317     QLinearGradient lg(0,0,r.width(),r.height());
318     lg.setColorAt(0.0,qRgb(0,125,127));
319     lg.setColorAt(1.0,qRgb(0,88,127));
320 
321     QBrush bk(lg);
322     painter.fillRect(r,bk);
323     int th = r.height()*2/5;
324     int bh = r.height()-th;
325     painter.fillRect(1,th,r.width()-2,bh-1,Qt::white);
326 
327     QFont font("Timer",32);
328     font.setPointSize(32);
329     font.setItalic(true);
330     painter.setPen(Qt::white);
331     painter.setFont(font);
332     painter.drawText(2,2,r.width()-2,th,Qt::AlignCenter,app->ideFullName());
333 
334     font.setPointSize(9);
335     font.setItalic(false);
336     font.setBold(true);
337     painter.setPen(Qt::black);
338     painter.setFont(font);
339     painter.drawText(10,th,r.width()-10,bh,Qt::AlignLeft|Qt::AlignVCenter,app->ideCopyright());
340 
341     painter.drawImage(r.width()-145,r.height()-145,QImage("icon:/images/liteide-logo128.png"));
342     return image;
343 }
344 
load(const QString & sessionName,IApplication * baseApp)345 void LiteApp::load(const QString &sessionName, IApplication *baseApp)
346 {
347     bool bLoadSession = true;
348     if (baseApp == 0) {
349         bLoadSession = m_settings->value(LITEAPP_AUTOLOADLASTSESSION,true).toBool();
350     }
351 
352     m_currentSession = sessionName;
353     if (!bLoadSession) {
354         m_currentSession = "emtpy";
355     }
356 
357     QSplashScreen *splash = 0;
358     bool bSplash = m_settings->value(LITEAPP_SPLASHVISIBLE,true).toBool();
359     if (baseApp) {
360         bSplash = false;
361     }
362     if (bSplash) {
363         splash = new QSplashScreen(QPixmap::fromImage(makeSplashImage(this)),Qt::WindowStaysOnTopHint);
364     }
365     if (bSplash) {
366         splash->show();
367     }
368 
369     if (bSplash) {
370         splash->showMessage("Scanning plugins...",Qt::AlignLeft|Qt::AlignBottom);
371     }
372 
373     qApp->processEvents();
374 
375     loadMimeType();
376     loadPlugins();
377 
378     if (bSplash) {
379         splash->showMessage("Loading plugins...",Qt::AlignLeft|Qt::AlignBottom);
380     }
381 
382     qApp->processEvents();
383     initPlugins();
384 
385     if (bSplash) {
386         splash->showMessage("Loading state...",Qt::AlignLeft|Qt::AlignBottom);
387     }
388 
389     qApp->processEvents();
390     loadState();
391     if (baseApp) {
392         if (baseApp->mainWindow()->isMaximized()) {
393             m_mainwindow->resize(800,600);
394             m_mainwindow->show();
395         } else {
396             QRect rc = baseApp->mainWindow()->geometry();
397             rc.adjust(20,20,20,20);
398             m_mainwindow->setGeometry(rc);
399             m_mainwindow->show();
400         }
401     } else {
402         m_mainwindow->show();
403     }
404 
405     emit loaded();
406     m_projectManager->setCurrentProject(0);
407 
408     if (bSplash) {
409         splash->showMessage("Loading session...",Qt::AlignLeft|Qt::AlignBottom);
410     }
411 
412     qApp->processEvents();
413 
414     if (bLoadSession && !sessionName.isEmpty()) {
415         loadSession(sessionName);
416         this->appendLog("Load session",sessionName);
417     }
418 
419     if (bSplash) {
420         m_mainwindow->raise();
421         splash->finish(m_mainwindow);
422         splash->deleteLater();
423     }
424 
425     this->appendLog("HtmlWidgetFactory",m_htmlWidgetManager->classNameList().join(" "));
426     this->appendLog("DefaultHtmlWidgetFactory",m_htmlWidgetManager->defaultClassName());
427 
428     m_goProxy->call("version");
429 
430     appendLog("LiteApp","Finished loading");
431 }
432 
~LiteApp()433 LiteApp::~LiteApp()
434 {
435     s_appList.removeAll(this);
436     cleanup();
437 }
438 
extension()439 IExtension *LiteApp::extension()
440 {
441     return m_extension;
442 }
443 
cleanup()444 void LiteApp::cleanup()
445 {
446     //
447     emit aboutToQuit();
448     //delete plugin by reverse depend
449     QListIterator<IPlugin*> it(m_pluginList);
450     it.toBack();
451     while(it.hasPrevious()) {
452         IPlugin *p = it.previous();
453         //qDebug() << "clean plugin" << p;
454         delete p;
455     }
456     m_pluginList.clear();
457 
458     delete m_idleTimer;
459     delete m_projectManager;
460     delete m_editorManager;
461     delete m_htmlWidgetManager;
462     delete m_liteAppOptionFactory;
463     delete m_fileManager;
464     delete m_mimeTypeManager;
465     delete m_optionManager;
466     delete m_logOutput;
467     delete m_toolWindowManager;
468     delete m_recentManager;
469     delete m_actionManager;
470     delete m_extension;
471     delete m_settings;
472 }
473 
aboutPlugins()474 void LiteApp::aboutPlugins()
475 {
476     PluginsDialog *dlg = new PluginsDialog(this,m_mainwindow);
477     foreach (LiteApi::IPluginFactory *factory, pluginManager()->factoryList()) {
478         dlg->appendInfo(factory->info());
479     }
480     dlg->exec();
481 }
482 
escape()483 void LiteApp::escape()
484 {
485     IEditor *editor = m_editorManager->currentEditor();
486     if (!editor) {
487         return;
488     }
489     bool bFocus = editor->widget()->isAncestorOf(qApp->focusWidget());
490     if (!bFocus) {
491         editor->onActive();
492     } else {
493         emit key_escape();
494         m_mainwindow->hideOutputWindow();
495     }
496 }
497 
newWindow()498 void LiteApp::newWindow()
499 {
500     LiteApp::newInstance("default");
501 }
502 
closeWindow()503 void LiteApp::closeWindow()
504 {
505     m_mainwindow->close();
506 }
507 
exit()508 void LiteApp::exit()
509 {
510     qApp->closeAllWindows();
511 }
512 
applyOption(QString id)513 void LiteApp::applyOption(QString id)
514 {
515     if (id != OPTION_LITEAPP) {
516         return;
517     }
518     //bool b = m_settings->value(LITEAPP_OPTNFOLDERINNEWWINDOW,true).toBool();
519     //m_openFolderNewWindowAct->setVisible(!b);
520 }
521 
hasGoProxy() const522 bool LiteApp::hasGoProxy() const
523 {
524     return GoProxy::hasProxy();
525 }
526 
createGoProxy(QObject * parent)527 IGoProxy *LiteApp::createGoProxy(QObject *parent)
528 {
529     return new GoProxy(parent);
530 }
531 
newInstance(const QString & sessionName)532 IApplication *LiteApp::newInstance(const QString &sessionName)
533 {
534     return LiteApp::NewApplication(sessionName,this);
535 }
536 
instanceList() const537 QList<IApplication *> LiteApp::instanceList() const
538 {
539     return s_appList;
540 }
541 
editorManager()542 IEditorManager *LiteApp::editorManager()
543 {
544     return m_editorManager;
545 }
546 
fileManager()547 IFileManager *LiteApp::fileManager()
548 {
549     return m_fileManager;
550 }
551 
projectManager()552 IProjectManager *LiteApp::projectManager()
553 {
554     return m_projectManager;
555 }
556 
actionManager()557 IActionManager  *LiteApp::actionManager()
558 {
559     return m_actionManager;
560 }
561 
mimeTypeManager()562 IMimeTypeManager *LiteApp::mimeTypeManager()
563 {
564     return m_mimeTypeManager;
565 }
566 
optionManager()567 IOptionManager  *LiteApp::optionManager()
568 {
569     return m_optionManager;
570 }
571 
toolWindowManager()572 IToolWindowManager *LiteApp::toolWindowManager()
573 {
574     return m_toolWindowManager;
575 }
576 
htmlWidgetManager()577 IHtmlWidgetManager *LiteApp::htmlWidgetManager()
578 {
579     return m_htmlWidgetManager;
580 }
581 
recentManager()582 IRecentManager *LiteApp::recentManager()
583 {
584     return m_recentManager;
585 }
586 
mainWindow() const587 QMainWindow *LiteApp::mainWindow() const
588 {
589     return m_mainwindow;
590 }
591 
settings()592 QSettings *LiteApp::settings()
593 {
594     return m_settings;
595 }
596 
globalCookie()597 QMap<QString,QVariant> &LiteApp::globalCookie()
598 {
599     return s_cookie;
600 }
601 
rootPath() const602 QString LiteApp::rootPath() const
603 {
604     return m_rootPath;
605 }
606 
resourcePath() const607 QString LiteApp::resourcePath() const
608 {
609     return m_resourcePath;
610 }
611 
applicationPath() const612 QString LiteApp::applicationPath() const
613 {
614     return m_applicationPath;
615 }
616 
toolPath() const617 QString LiteApp::toolPath() const
618 {
619     return m_toolPath;
620 }
621 
pluginPath() const622 QString LiteApp::pluginPath() const
623 {
624     return m_pluginPath;
625 }
626 
storagePath() const627 QString LiteApp::storagePath() const
628 {
629     return m_storagePath;
630 }
631 
ideVersion() const632 QString LiteApp::ideVersion() const
633 {
634     return LITEIDE_VERSION;
635 }
636 
ideFullName() const637 QString LiteApp::ideFullName() const
638 {
639     return this->ideName()+" "+this->ideVersion();
640 }
641 
ideName() const642 QString LiteApp::ideName() const
643 {
644     return "LiteIDE";
645 }
646 
ideCopyright() const647 QString LiteApp::ideCopyright() const
648 {
649     static QString s_info =
650     "2011-2021(c)\n"
651     "visualfc@gmail.com\n"
652     "\n"
653     "https://github.com/visualfc/liteide\n";
654     return s_info;
655 }
656 
setPluginPath(const QString & path)657 void LiteApp::setPluginPath(const QString &path)
658 {
659     m_pluginPath = path;
660     appendLog("LiteApp","Set plugin path to "+path);
661 }
662 
setResourcePath(const QString & path)663 void LiteApp::setResourcePath(const QString &path)
664 {
665     m_resourcePath = path;
666     appendLog("LiteApp","Set resource path to "+path);
667 }
668 
669 
pluginList() const670 QList<IPlugin*> LiteApp::pluginList() const
671 {
672     return m_pluginList;
673 }
674 
appendLog(const QString & model,const QString & log,bool error)675 void LiteApp::appendLog(const QString &model, const QString &log, bool error)
676 {
677     QDateTime dt = QDateTime::currentDateTime();
678     QString text = dt.toString("hh:mm:ss");
679     text += QLatin1Char(' ');
680     text += model;
681     text += ": ";
682     text += log;
683     text += QLatin1Char('\n');
684     m_logOutput->updateExistsTextColor();
685     if (error) {
686         m_logOutput->append(text,Qt::red);
687         m_logAct->setChecked(true);
688     } else {
689         m_logOutput->append(text);
690     }
691 }
692 
sendBroadcast(const QString & module,const QString & id,const QVariant & param)693 void LiteApp::sendBroadcast(const QString &module, const QString &id, const QVariant &param)
694 {
695     emit broadcast(module,id,param);
696 }
697 
loadPlugins()698 void LiteApp::loadPlugins()
699 {
700     pluginManager()->loadPlugins(m_pluginPath);
701 }
702 
loadMimeType()703 void LiteApp::loadMimeType()
704 {
705     QDir dir(m_resourcePath+"/liteapp/mimetype");
706     if (dir.exists()) {
707         m_mimeTypeManager->loadMimeTypes(dir.absolutePath());
708     }
709 }
710 
initPlugins()711 void LiteApp::initPlugins()
712 {
713     foreach (IPluginFactory *factory,pluginManager()->factoryList()) {
714         bool load = m_settings->value(QString("liteapp/%1_load").arg(factory->id()),true).toBool();
715         if (!load) {
716             continue;
717         }
718         LiteApi::IPlugin *plugin = factory->createPlugin();
719         if (plugin) {
720             bool ret = plugin->load(this);
721             if (ret) {
722                 m_pluginList.append(plugin);
723             }
724             appendLog("LiteApp",QString("%1 %2").arg(ret?"Loaded":"ERROR while loading").arg(factory->id()),!ret);
725         }
726     }
727 }
728 
createActions()729 void LiteApp::createActions()
730 {
731     IActionContext *actionContext =  m_actionManager->getActionContext(this,"App");
732 
733     m_newAct = new QAction(loadIcon("icon:images/new.png"),tr("New..."),m_mainwindow);
734     actionContext->regAction(m_newAct,"New",QKeySequence::New);
735 
736     m_openFileAct = new QAction(loadIcon("icon:images/openfile.png"),tr("Open File..."),m_mainwindow);
737     actionContext->regAction(m_openFileAct,"OpenFile",QKeySequence::Open);
738 
739     m_openFolderAct = new QAction(loadIcon("icon:images/openfolder.png"),tr("Open Folder..."),m_mainwindow);
740     actionContext->regAction(m_openFolderAct,"OpenFolder","");
741 
742     m_openFolderNewWindowAct = new QAction(loadIcon("icon:images/openfolder.png"),tr("Open Folder in New Window..."),m_mainwindow);
743     //bool b = m_settings->value(LITEAPP_OPTNFOLDERINNEWWINDOW,true).toBool();
744     //m_openFolderNewWindowAct->setVisible(!b);
745     actionContext->regAction(m_openFolderNewWindowAct,"OpenFolderNewWindow","");
746 
747     m_closeAllFolderAct = new QAction(tr("Close All Folders"),m_mainwindow);
748     actionContext->regAction(m_closeAllFolderAct,"CloseAllFolders","");
749 
750     m_newWindow = new QAction(tr("New Window"),m_mainwindow);
751     actionContext->regAction(m_newWindow,"NewWindow","Ctrl+Shift+N");
752 
753     m_closeWindow = new QAction(tr("Close Window"),m_mainwindow);
754     actionContext->regAction(m_closeWindow,"CloseWindow","Ctrl+Shift+W");
755 
756     m_closeAct = new QAction(loadIcon("icon:images/closefile.png"),tr("Close File"),m_mainwindow);
757     actionContext->regAction(m_closeAct,"CloseFile","Ctrl+W");
758 
759     m_closeAllAct = new QAction(tr("Close All Files"),m_mainwindow);
760     actionContext->regAction(m_closeAllAct,"CloseAllFiles","");
761 
762     m_openProjectAct = new QAction(loadIcon("icon:images/openproject.png"),tr("Open Project"),m_mainwindow);
763 
764     m_saveProjectAct = new QAction(loadIcon("icon:images/saveproject.png"),tr("Save Project"),m_mainwindow);
765 
766     m_closeProjectAct = new QAction(loadIcon("icon:images/closeproject.png"),tr("Close Project"),m_mainwindow);
767     actionContext->regAction(m_closeProjectAct,"CloseProject","");
768 
769     m_saveAct = new QAction(loadIcon("icon:images/save.png"),tr("Save File"),m_mainwindow);
770     actionContext->regAction(m_saveAct,"SaveFile",QKeySequence::Save);
771 
772     m_saveAsAct = new QAction(tr("Save File As..."),m_mainwindow);
773     actionContext->regAction(m_saveAsAct,"SaveFileAs",QKeySequence::SaveAs);
774 
775     m_saveAllAct = new QAction(loadIcon("icon:images/saveall.png"),tr("Save All Files"),m_mainwindow);
776     actionContext->regAction(m_saveAllAct,"SaveAllFiles","");
777 
778     m_exitAct = new QAction(tr("Exit"),m_mainwindow);
779 #ifdef Q_OS_WIN
780     actionContext->regAction(m_exitAct,"Exit","Ctrl+Q");
781 #else
782     actionContext->regAction(m_exitAct,"Exit",QKeySequence::Quit);
783 #endif
784     m_fullScreent = new QAction(tr("Full Screen"),m_mainwindow);
785     m_fullScreent->setCheckable(true);
786     actionContext->regAction(m_fullScreent,"FullScreen","Ctrl+Shift+F11");
787 
788     m_aboutAct = new QAction(tr("About LiteIDE"),m_mainwindow);
789 #if defined(Q_OS_OSX)
790     m_aboutAct->setMenuRole(QAction::AboutRole);
791 #endif
792     actionContext->regAction(m_aboutAct,"About","");
793 
794     m_aboutPluginsAct = new QAction(tr("About Plugins"),m_mainwindow);
795 #if defined(Q_OS_OSX)
796     m_aboutPluginsAct->setMenuRole(QAction::ApplicationSpecificRole);
797 #endif
798     actionContext->regAction(m_aboutPluginsAct,"AboutPlugins","");
799 
800     connect(m_newAct,SIGNAL(triggered()),m_fileManager,SLOT(newFile()));
801     connect(m_openFileAct,SIGNAL(triggered()),m_fileManager,SLOT(openFiles()));
802     connect(m_openFolderAct,SIGNAL(triggered()),m_fileManager,SLOT(openFolder()));
803     connect(m_openFolderNewWindowAct,SIGNAL(triggered()),m_fileManager,SLOT(openFolderNewWindow()));
804     connect(m_closeAllFolderAct,SIGNAL(triggered()),m_fileManager,SLOT(closeAllFolders()));
805     connect(m_newWindow,SIGNAL(triggered()),this,SLOT(newWindow()));
806     connect(m_closeWindow,SIGNAL(triggered()),this,SLOT(closeWindow()));
807     connect(m_closeAct,SIGNAL(triggered()),m_editorManager,SLOT(closeEditor()));
808     connect(m_closeAllAct,SIGNAL(triggered()),m_editorManager,SLOT(closeAllEditors()));
809     connect(m_openProjectAct,SIGNAL(triggered()),m_fileManager,SLOT(openProjects()));
810     connect(m_saveProjectAct,SIGNAL(triggered()),m_projectManager,SLOT(saveProject()));
811     connect(m_closeProjectAct,SIGNAL(triggered()),m_projectManager,SLOT(closeProject()));
812     connect(m_saveAct,SIGNAL(triggered()),m_editorManager,SLOT(saveEditor()));
813     connect(m_saveAsAct,SIGNAL(triggered()),m_editorManager,SLOT(saveEditorAs()));
814     connect(m_saveAllAct,SIGNAL(triggered()),m_editorManager,SLOT(saveAllEditors()));
815     connect(m_exitAct,SIGNAL(triggered()),this,SLOT(exit()));
816     connect(m_aboutAct,SIGNAL(triggered()),m_mainwindow,SLOT(about()));
817     connect(m_aboutPluginsAct,SIGNAL(triggered()),this,SLOT(aboutPlugins()));
818     connect(m_fullScreent,SIGNAL(toggled(bool)),m_mainwindow,SLOT(setFullScreen(bool)));
819 }
820 
createMenus()821 void LiteApp::createMenus()
822 {
823     m_fileMenu = m_actionManager->loadMenu(ID_MENU_FILE);
824     m_viewMenu = m_actionManager->loadMenu(ID_MENU_VIEW);
825     m_helpMenu = m_actionManager->loadMenu(ID_MENU_HELP);
826 
827     m_fileMenu->addAction(m_newAct);
828     m_fileMenu->addAction(m_openFileAct);
829     m_fileMenu->addAction(m_openFolderAct);
830     m_fileMenu->addAction(m_openFolderNewWindowAct);
831     m_fileMenu->addSeparator();
832     m_fileMenu->addAction(m_saveAct);
833     m_fileMenu->addAction(m_saveAsAct);
834     m_fileMenu->addAction(m_saveAllAct);
835     m_fileMenu->addSeparator();
836     m_fileMenu->addAction(m_newWindow);
837     m_fileMenu->addAction(m_closeWindow);
838     m_fileMenu->addSeparator();
839 
840     m_fileMenu->addAction(m_closeAct);
841     m_fileMenu->addAction(m_closeAllAct);
842     m_fileMenu->addAction(m_closeAllFolderAct);
843     //m_fileMenu->addAction(m_closeProjectAct);
844     //m_fileMenu->addAction(m_openProjectAct);
845     //m_fileMenu->addAction(m_saveProjectAct);
846     m_fileMenu->addSeparator();
847     m_fileMenu->addAction(m_exitAct);
848 
849 #ifdef Q_OS_MAC
850     if (MacSupport::isLionOrHigh()) {
851         MacSupport::setFullScreen(m_mainwindow);
852     } else {
853         m_viewMenu->addAction(m_fullScreent);
854     }
855 #else
856     m_viewMenu->addAction(m_fullScreent);
857 #endif
858 
859     m_viewMenu->addSeparator();
860 
861     m_helpMenu->addAction(m_aboutAct);
862     m_helpMenu->addAction(m_aboutPluginsAct);
863 }
864 
createToolBars()865 void LiteApp::createToolBars()
866 {
867     m_stdToolBar = m_actionManager->loadToolBar(ID_TOOLBAR_STD);
868     m_stdToolBar->addAction(m_newAct);
869     m_stdToolBar->addSeparator();
870     m_stdToolBar->addAction(m_openFileAct);
871     m_stdToolBar->addAction(m_openFolderAct);
872     m_stdToolBar->addAction(m_saveAct);
873     m_stdToolBar->addAction(m_saveAllAct);
874     //m_stdToolBar->addSeparator();
875     //m_stdToolBar->addAction(m_openProjectAct);
876     //m_stdToolBar->addAction(m_saveProjectAct);
877     //m_stdToolBar->addAction(m_closeProjectAct);
878 }
879 
projectReloaded()880 void LiteApp::projectReloaded()
881 {
882     LiteApi::IProject *project = (LiteApi::IProject*)sender();
883     if (project) {
884         //m_outputManager->setProjectInfo(project->filePath());
885     }
886 }
887 
currentProjectChanged(IProject * project)888 void LiteApp::currentProjectChanged(IProject *project)
889 {
890     bool b = (project != 0);
891     m_saveProjectAct->setEnabled(b);
892     m_closeProjectAct->setEnabled(b);
893     if (project) {
894         //m_outputManager->setProjectInfo(project->filePath());
895         connect(project,SIGNAL(reloaded()),this,SLOT(projectReloaded()));
896     } else {
897         //m_outputManager->setProjectInfo("");
898     }
899 }
900 
currentEditorChanged(IEditor * editor)901 void LiteApp::currentEditorChanged(IEditor *editor)
902 {
903     bool b = (editor != 0);
904 
905     if (b) {
906         connect(editor,SIGNAL(modificationChanged(bool)),this,SLOT(editorModifyChanged(bool)));
907     }
908     m_saveAct->setEnabled(b && editor->isModified() && !editor->isReadOnly());
909     m_saveAsAct->setEnabled(editor && !editor->filePath().isEmpty());
910     m_saveAllAct->setEnabled(b);
911     m_closeAct->setEnabled(b);
912     m_closeAllAct->setEnabled(b);
913 }
914 
editorModifyChanged(bool)915 void LiteApp::editorModifyChanged(bool /*b*/)
916 {
917     IEditor *editor = (IEditor*)sender();
918     if (editor && editor->isModified() && !editor->isReadOnly()) {
919         m_saveAct->setEnabled(true);
920     } else {
921         m_saveAct->setEnabled(false);
922     }
923 }
924 
loadState()925 void LiteApp::loadState()
926 {
927     QByteArray  geometry = m_settings->value("liteapp/geometry").toByteArray();
928     if (!geometry.isEmpty()) {
929         m_mainwindow->restoreGeometry(geometry);
930     } else {
931         m_mainwindow->resize(800,600);
932     }
933     m_mainwindow->updateConer();
934     //fix Qt 5.9.6 QDockWidget bug
935 #if QT_VERSION == 0x050906
936     QList<QDockWidget *> docks = m_mainwindow->findChildren<QDockWidget *>();
937     QList<int> horz;
938     QList<int> vert;
939     QList<QDockWidget*> ds;
940     foreach (QDockWidget *dock, docks) {
941         bool b = m_settings->value("dock_visible/"+dock->objectName()).toBool();
942         if (!b) {
943             continue;
944         }
945         dock->setVisible(b);
946         QSize sz = m_settings->value("dock_size/"+dock->objectName()).toSize();
947         horz << sz.width();
948         vert << sz.height();
949         ds << dock;
950     }
951     m_mainwindow->resizeDocks(ds,horz,Qt::Horizontal);
952     m_mainwindow->resizeDocks(ds,vert,Qt::Vertical);
953     foreach (QString id, m_actionManager->toolBarList()) {
954         QToolBar *tbar = m_actionManager->loadToolBar(id);
955         bool b = m_settings->value("toolbar_visible/"+tbar->objectName(),true).toBool();
956         tbar->setVisible(b);
957     }
958 #else
959     m_mainwindow->restoreState(m_settings->value("liteapp/state").toByteArray());
960 #endif
961 }
962 
saveState()963 void LiteApp::saveState()
964 {
965     m_settings->setValue("liteapp/geometry",m_mainwindow->saveGeometry());
966     m_settings->setValue("liteapp/state",m_mainwindow->saveState());
967 
968     //fix Qt 5.9.6 QDockWidget bug
969 #if QT_VERSION == 0x050906
970     QList<QDockWidget *> docks = m_mainwindow->findChildren<QDockWidget *>();
971     foreach (QDockWidget *dock, docks) {
972         m_settings->setValue("dock_size/"+dock->objectName(),dock->size());
973         m_settings->setValue("dock_visible/"+dock->objectName(),dock->isVisible());
974     }
975     foreach (QString id, m_actionManager->toolBarList()) {
976         QToolBar *tbar = m_actionManager->loadToolBar(id);
977         m_settings->setValue("toolbar_visible/"+tbar->objectName(),tbar->isVisible());
978     }
979 #endif
980 }
981 
982 
loadSession(const QString & session)983 void LiteApp::loadSession(const QString &session)
984 {
985     if (session.isEmpty()) {
986         return;
987     }
988 
989     m_recentManager->addRecent(session,"session");
990 
991     QString sessionKey = "session/"+session;
992     QString projectName = m_settings->value(sessionKey+"_project").toString();
993     QString scheme = m_settings->value(sessionKey+"_scheme").toString();
994     QString editorName = m_settings->value(sessionKey+"_cureditor").toString();
995     QStringList fileList = m_settings->value(sessionKey+"_alleditor").toStringList();
996     QStringList folderList = m_settings->value(sessionKey+"_folderList").toStringList();
997 
998     m_fileManager->setFolderList(folderList);
999 
1000     if (!projectName.isEmpty()) {
1001         if (scheme.isEmpty()) {
1002             m_fileManager->openProject(projectName);
1003         } else {
1004             m_fileManager->openProjectScheme(projectName,scheme);
1005         }
1006     } else {
1007         m_projectManager->closeProject();
1008     }
1009 
1010     if (m_settings->value(LITEAPP_STARTUPRELOADFILES,true).toBool()) {
1011         foreach(QString fileName, fileList) {
1012             m_fileManager->openEditor(fileName,false);
1013         }
1014         if (!editorName.isEmpty()) {
1015             m_fileManager->openEditor(editorName,true);
1016         } else if (!fileList.isEmpty()){
1017             m_fileManager->openEditor(fileList.last(),true);
1018         }
1019     }
1020 
1021     emit sessionListChanged();
1022 }
1023 
saveSession(const QString & session)1024 void LiteApp::saveSession(const QString &session)
1025 {
1026     if (session.isEmpty() || session == "empty") {
1027         return;
1028     }
1029     QString projectName;
1030     QString editorName;
1031     QString scheme;
1032     IProject *project = m_projectManager->currentProject();
1033     if (project) {
1034         projectName = project->filePath();
1035         IMimeType *type = m_mimeTypeManager->findMimeType(project->mimeType());
1036         if (type) {
1037             scheme = type->scheme();
1038         }
1039     }
1040 
1041     QStringList fileList;
1042     foreach (IEditor* ed,m_editorManager->sortedEditorList()) {
1043         if (ed->filePath().isEmpty()) {
1044             continue;
1045         }
1046         if (ed == m_editorManager->currentEditor()) {
1047             editorName = ed->filePath();
1048         } else {
1049             fileList.append(ed->filePath());
1050         }
1051     }
1052     QString sessionKey = "session/"+session;
1053 
1054     LiteApi::updateSetting(m_settings,sessionKey+"_project",projectName,"");
1055     LiteApi::updateSetting(m_settings,sessionKey+"_scheme",scheme,"");
1056     LiteApi::updateSetting(m_settings,sessionKey+"_cureditor",editorName,"");
1057     LiteApi::updateSetting(m_settings,sessionKey+"_alleditor",fileList,QStringList());
1058     LiteApi::updateSetting(m_settings,sessionKey+"_folderList",m_fileManager->folderList(),QStringList());
1059 }
1060 
sessionList() const1061 QStringList LiteApp::sessionList() const
1062 {
1063     return m_recentManager->recentNameList("session");
1064 }
1065 
currentSession() const1066 QString LiteApp::currentSession() const
1067 {
1068     return m_currentSession;
1069 }
1070 
dbclickLogOutput(QTextCursor cur)1071 void LiteApp::dbclickLogOutput(QTextCursor cur)
1072 {
1073     //QRegExp rep("(\\w?:?[\\w\\d_@\\-\\\\/\\.]+):(\\d+):");
1074     QString text = cur.block().text().trimmed();
1075     //skip time 08:38:49
1076     if (text.length() < 9) {
1077         return;
1078     }
1079     QRegExp rep("(\\w?\\:?[\\w\\d\\_\\-\\\\/\\.]+):(\\d+):");
1080     int index = rep.indexIn(text.mid(8));
1081     if (index < 0)
1082         return;
1083     QStringList capList = rep.capturedTexts();
1084 
1085     if (capList.count() < 3)
1086         return;
1087     QString fileName = capList[1];
1088     QString fileLine = capList[2];
1089 
1090     bool ok = false;
1091     int line = fileLine.toInt(&ok);
1092     if (!ok)
1093         return;
1094 
1095     LiteApi::IEditor *editor = m_fileManager->openEditor(fileName);
1096     if (editor) {
1097         LiteApi::ITextEditor *textEditor =  LiteApi::getTextEditor(editor);
1098         if (textEditor) {
1099             textEditor->gotoLine(line-1,0,true);
1100         }
1101     }
1102 }
1103 
goproxyDone(const QByteArray & reply)1104 void LiteApp::goproxyDone(const QByteArray &reply)
1105 {
1106     this->appendLog("GoProxy",QString("%1 = %2").arg(QString::fromUtf8(m_goProxy->commandId())).arg(QString::fromUtf8(reply).trimmed()));
1107 }
1108