1/*
2 * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#include "mainwindow.h"
18#include "ui_mainwindow.h"
19#include "editorlist.h"
20#include "editor.h"
21#include "systemconsts.h"
22#include "settings.h"
23#include "qsynedit/Constants.h"
24#include "debugger.h"
25#include "widgets/cpudialog.h"
26#include "widgets/filepropertiesdialog.h"
27#include "project.h"
28#include "projecttemplate.h"
29#include "widgets/newprojectdialog.h"
30#include <qt_utils/charsetinfo.h>
31#include "widgets/aboutdialog.h"
32#include "shortcutmanager.h"
33#include "colorscheme.h"
34#include "thememanager.h"
35#include "widgets/darkfusionstyle.h"
36#include "widgets/lightfusionstyle.h"
37#include "problems/problemcasevalidator.h"
38#include "widgets/ojproblempropertywidget.h"
39#include "iconsmanager.h"
40#include "widgets/newclassdialog.h"
41#include "widgets/newheaderdialog.h"
42#include "vcs/gitmanager.h"
43#include "vcs/gitrepository.h"
44#include "vcs/gitbranchdialog.h"
45#include "vcs/gitmergedialog.h"
46#include "vcs/gitlogdialog.h"
47#include "vcs/gitremotedialog.h"
48#include "vcs/gituserconfigdialog.h"
49#include "widgets/infomessagebox.h"
50#include "widgets/newtemplatedialog.h"
51
52#include <QCloseEvent>
53#include <QComboBox>
54#include <QDesktopServices>
55#include <QDragEnterEvent>
56#include <QFileDialog>
57#include <QInputDialog>
58#include <QJsonArray>
59#include <QJsonDocument>
60#include <QJsonObject>
61#include <QLabel>
62#include <QLineEdit>
63#include <QMessageBox>
64#include <QMimeData>
65#include <QScreen>
66#include <QTcpSocket>
67#include <QTemporaryFile>
68#include <QTextBlock>
69#include <QTranslator>
70#include <QFileIconProvider>
71#include <QMimeDatabase>
72#include <QMimeType>
73#include "mainwindow.h"
74#include <QScrollBar>
75#include <QTextDocumentFragment>
76
77#include "settingsdialog/settingsdialog.h"
78#include "compiler/compilermanager.h"
79#include <QGuiApplication>
80#include <QClipboard>
81#include <QMessageBox>
82#include <QTextCodec>
83#include "cpprefacter.h"
84
85#include "widgets/newprojectunitdialog.h"
86#include "widgets/searchdialog.h"
87
88#ifdef Q_OS_WIN
89#include <QMimeDatabase>
90#include <QMimeType>
91#include <windows.h>
92#endif
93
94
95static int findTabIndex(QTabWidget* tabWidget , QWidget* w) {
96 for (int i=0;i<tabWidget->count();i++) {
97 if (w==tabWidget->widget(i))
98 return i;
99 }
100 return -1;
101}
102
103MainWindow* pMainWindow;
104
105MainWindow::MainWindow(QWidget *parent)
106 : QMainWindow(parent),
107 ui(new Ui::MainWindow),
108 mSearchDialog(nullptr),
109 mQuitting(false),
110 mCheckSyntaxInBack(false),
111 mShouldRemoveAllSettings(false),
112 mClosing(false),
113 mClosingAll(false),
114 mOpenningFiles(false),
115 mSystemTurnedOff(false)
116{
117 ui->setupUi(this);
118 addActions( this->findChildren<QAction *>(QString(), Qt::FindChildrenRecursively));
119 // status bar
120 mFileInfoStatus=new QLabel();
121 mFileEncodingStatus = new LabelWithMenu();
122 mFileModeStatus = new QLabel();
123 mFileInfoStatus->setStyleSheet("margin-left:10px; margin-right:10px");
124 mFileEncodingStatus->setStyleSheet("margin-left:10px; margin-right:10px");
125 mFileModeStatus->setStyleSheet("margin-left:10px; margin-right:10px");
126 prepareTabInfosData();
127 prepareTabMessagesData();
128 ui->statusbar->insertPermanentWidget(0,mFileModeStatus);
129 ui->statusbar->insertPermanentWidget(0,mFileEncodingStatus);
130 ui->statusbar->insertPermanentWidget(0,mFileInfoStatus);
131 mEditorList = new EditorList(ui->EditorTabsLeft,
132 ui->EditorTabsRight,
133 ui->splitterEditorPanel,
134 ui->EditorPanel);
135 connect(mEditorList, &EditorList::editorRenamed,
136 this, &MainWindow::onEditorRenamed);
137 connect(mEditorList, &EditorList::editorClosed,
138 this, &MainWindow::onEditorClosed);
139 mProject = nullptr;
140 mProjectProxyModel = new ProjectModelSortFilterProxy(this);
141 ui->projectView->setModel(mProjectProxyModel);
142 mProjectProxyModel->setDynamicSortFilter(false);
143 ui->EditorTabsRight->setVisible(false);
144
145 mCompilerSet = new QComboBox();
146 mCompilerSet->setMinimumWidth(200);
147 mCompilerSet->setSizeAdjustPolicy(QComboBox::AdjustToContents);
148 ui->toolbarCompilerSet->insertWidget(ui->actionCompiler_Options, mCompilerSet);
149 ui->toolbarCompilerSet->insertSeparator(ui->actionCompiler_Options);
150 connect(mCompilerSet,QOverload<int>::of(&QComboBox::currentIndexChanged),
151 this, &MainWindow::onCompilerSetChanged);
152 //updateCompilerSet();
153
154 mCompilerManager = new CompilerManager(this);
155 mDebugger = new Debugger(this);
156
157 ui->tblBreakpoints->setModel(mDebugger->breakpointModel());
158 ui->tblStackTrace->setModel(mDebugger->backtraceModel());
159 ui->watchView->setModel(mDebugger->watchModel());
160 ui->tblMemoryView->setModel(mDebugger->memoryModel());
161
162 ui->tblMemoryView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
163
164
165 try {
166 mDebugger->breakpointModel()->load(includeTrailingPathDelimiter(pSettings->dirs().config())
167 +DEV_BREAKPOINTS_FILE);
168 } catch (FileError &e) {
169 QMessageBox::warning(nullptr,
170 tr("Error"),
171 e.reason());
172 }
173 try {
174 mDebugger->watchModel()->load(includeTrailingPathDelimiter(pSettings->dirs().config())
175 +DEV_WATCH_FILE);
176 } catch (FileError &e) {
177 QMessageBox::warning(nullptr,
178 tr("Error"),
179 e.reason());
180 }
181
182
183// ui->actionIndent->setShortcut(Qt::Key_Tab);
184// ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier);
185
186 mMenuNew = new QMenu();
187 mMenuNew->setTitle(tr("New"));
188 mMenuNew->addAction(ui->actionNew);
189 mMenuNew->addAction(ui->actionNew_Project);
190 mMenuNew->addSeparator();
191 mMenuNew->addAction(ui->actionNew_Template);
192 mMenuNew->addSeparator();
193 mMenuNew->addAction(ui->actionNew_Class);
194 mMenuNew->addAction(ui->actionNew_Header);
195
196 ui->menuFile->insertMenu(ui->actionOpen,mMenuNew);
197
198
199 mMenuExport = new QMenu(tr("Export"));
200 mMenuExport->addAction(ui->actionExport_As_RTF);
201 mMenuExport->addAction(ui->actionExport_As_HTML);
202 ui->menuFile->insertMenu(ui->actionPrint,mMenuExport);
203
204 buildEncodingMenu();
205
206 mMenuRecentProjects = new QMenu();
207 mMenuRecentProjects->setTitle(tr("Recent Projects"));
208 ui->menuFile->insertMenu(ui->actionExit, mMenuRecentProjects);
209
210 mMenuRecentFiles = new QMenu();
211 mMenuRecentFiles->setTitle(tr("Recent Files"));
212 ui->menuFile->insertMenu(ui->actionExit, mMenuRecentFiles);
213 ui->menuFile->insertSeparator(ui->actionExit);
214 rebuildOpenedFileHisotryMenu();
215
216 mMenuInsertCodeSnippet = new QMenu();
217 mMenuInsertCodeSnippet->setTitle(tr("Insert Snippet"));
218 ui->menuCode->insertMenu(ui->actionReformat_Code,mMenuInsertCodeSnippet);
219 ui->menuCode->insertSeparator(ui->actionReformat_Code);
220 connect(mMenuInsertCodeSnippet,&QMenu::aboutToShow,
221 this, &MainWindow::onShowInsertCodeSnippetMenu);
222
223 mCPUDialog = nullptr;
224
225// applySettings();
226// applyUISettings();
227// updateProjectView();
228// updateEditorActions();
229// updateCaretActions();
230
231 connect(ui->debugConsole,&QConsole::commandInput,this,&MainWindow::onDebugCommandInput);
232 connect(ui->cbEvaluate->lineEdit(), &QLineEdit::returnPressed,
233 this, &MainWindow::onDebugEvaluateInput);
234 connect(ui->cbMemoryAddress->lineEdit(), &QLineEdit::returnPressed,
235 this, &MainWindow::onDebugMemoryAddressInput);
236
237 mTodoParser = std::make_shared<TodoParser>();
238 mSymbolUsageManager = std::make_shared<SymbolUsageManager>();
239 try {
240 mSymbolUsageManager->load();
241 } catch (FileError &e) {
242 QMessageBox::warning(nullptr,
243 tr("Error"),
244 e.reason());
245 }
246
247 mCodeSnippetManager = std::make_shared<CodeSnippetsManager>();
248 try {
249 mCodeSnippetManager->load();
250 } catch (FileError &e) {
251 QMessageBox::warning(nullptr,
252 tr("Error"),
253 e.reason());
254 }
255 mToolsManager = std::make_shared<ToolsManager>();
256 try {
257 mToolsManager->load();
258 } catch (FileError &e) {
259 QMessageBox::warning(nullptr,
260 tr("Error"),
261 e.reason());
262 }
263 mBookmarkModel = std::make_shared<BookmarkModel>();
264 try {
265 mBookmarkModel->load(includeTrailingPathDelimiter(pSettings->dirs().config())
266 +DEV_BOOKMARK_FILE);
267 } catch (FileError &e) {
268 QMessageBox::warning(nullptr,
269 tr("Error"),
270 e.reason());
271 }
272 ui->tableBookmark->setModel(mBookmarkModel.get());
273 mSearchResultTreeModel = std::make_shared<SearchResultTreeModel>(&mSearchResultModel);
274 mSearchResultListModel = std::make_shared<SearchResultListModel>(&mSearchResultModel);
275 mSearchViewDelegate = std::make_shared<SearchResultTreeViewDelegate>(mSearchResultTreeModel);
276 ui->cbSearchHistory->setModel(mSearchResultListModel.get());
277 ui->searchView->setModel(mSearchResultTreeModel.get());
278 ui->searchView->setItemDelegate(mSearchViewDelegate.get());
279 ui->tableTODO->setModel(&mTodoModel);
280 connect(mSearchResultTreeModel.get() , &QAbstractItemModel::modelReset,
281 ui->searchView,&QTreeView::expandAll);
282 ui->replacePanel->setVisible(false);
283 ui->tabProblem->setEnabled(false);
284 ui->btnRemoveProblem->setEnabled(false);
285 ui->btnRemoveProblemCase->setEnabled(false);
286
287 //problem set
288 mOJProblemSetNameCounter=1;
289 mOJProblemSetModel.rename(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
290 ui->lstProblemSet->setModel(&mOJProblemSetModel);
291 ui->tblProblemCases->setModel(&mOJProblemModel);
292 connect(ui->lstProblemSet->selectionModel(),
293 &QItemSelectionModel::currentRowChanged,
294 this, &MainWindow::onProblemSetIndexChanged);
295 connect(ui->tblProblemCases->selectionModel(),
296 &QItemSelectionModel::currentRowChanged,
297 this, &MainWindow::onProblemCaseIndexChanged);
298 connect(&mOJProblemSetModel, &OJProblemSetModel::problemNameChanged,
299 this , &MainWindow::onProblemNameChanged);
300 ui->pbProblemCases->setVisible(false);
301 connect(&mTcpServer,&QTcpServer::newConnection,
302 this, &MainWindow::onNewProblemConnection);
303
304 connect(&mOJProblemModel, &OJProblemModel::dataChanged,
305 this, &MainWindow::updateProblemTitle);
306
307 //files view
308 ui->treeFiles->setModel(&mFileSystemModel);
309 connect(&mFileSystemModel, &QFileSystemModel::layoutChanged,
310 this, &MainWindow::onFileSystemModelLayoutChanged, Qt::QueuedConnection);
311 mFileSystemModel.setReadOnly(false);
312 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
313
314 mFileSystemModel.setNameFilters(pSystemConsts->defaultFileNameFilters());
315 mFileSystemModel.setNameFilterDisables(true);
316 //setFilesViewRoot(pSettings->environment().currentFolder());
317 for (int i=1;i<mFileSystemModel.columnCount();i++) {
318 ui->treeFiles->hideColumn(i);
319 }
320 connect(ui->cbFilesPath->lineEdit(),&QLineEdit::returnPressed,
321 this,&MainWindow::onFilesViewPathChanged);
322 connect(ui->cbFilesPath, QOverload<int>::of(&QComboBox::currentIndexChanged),
323 this, &MainWindow::onFilesViewPathChanged);
324
325 //class browser
326 ui->classBrowser->setUniformRowHeights(true);
327 ui->classBrowser->setModel(&mClassBrowserModel);
328
329 connect(&mFileSystemWatcher,&QFileSystemWatcher::fileChanged,
330 this, &MainWindow::onFileChanged);
331
332 mStatementColors = std::make_shared<QHash<StatementKind, PColorSchemeItem> >();
333 mCompletionPopup = std::make_shared<CodeCompletionPopup>();
334 mCompletionPopup->setColors(mStatementColors);
335 mHeaderCompletionPopup = std::make_shared<HeaderCompletionPopup>();
336 mFunctionTip = std::make_shared<FunctionTooltipWidget>();
337
338 mClassBrowserModel.setColors(mStatementColors);
339
340 connect(&mAutoSaveTimer, &QTimer::timeout,
341 this, &MainWindow::onAutoSaveTimeout);
342 resetAutoSaveTimer();
343
344 connect(ui->menuFile, &QMenu::aboutToShow,
345 this,&MainWindow::rebuildOpenedFileHisotryMenu);
346
347 connect(ui->menuProject, &QMenu::aboutToShow,
348 this, &MainWindow::updateProjectActions);
349
350 ui->actionEGE_Manual->setVisible(pSettings->environment().language()=="zh_CN");
351
352 connect(ui->EditorTabsLeft, &EditorsTabWidget::middleButtonClicked,
353 this, &MainWindow::on_EditorTabsLeft_tabCloseRequested);
354
355 connect(ui->EditorTabsRight, &EditorsTabWidget::middleButtonClicked,
356 this, &MainWindow::on_EditorTabsRight_tabCloseRequested);
357
358 //git menu
359 connect(ui->menuGit, &QMenu::aboutToShow,
360 this, &MainWindow::updateVCSActions);
361 buildContextMenus();
362 updateAppTitle();
363 //applySettings();
364 applyUISettings();
365 initDocks();
366 updateProjectView();
367 updateEditorActions();
368 updateCaretActions();
369 updateEditorColorSchemes();
370 updateShortcuts();
371 updateTools();
372 updateEditorSettings();
373}
374
375MainWindow::~MainWindow()
376{
377 delete mEditorList;
378 delete ui;
379}
380
381void MainWindow::updateForEncodingInfo(bool clear) {
382 Editor * editor = mEditorList->getEditor();
383 if (!clear && editor!=NULL) {
384 if (editor->encodingOption() != editor->fileEncoding()) {
385 mFileEncodingStatus->setText(
386 QString("%1(%2)")
387 .arg(QString(editor->encodingOption())
388 ,QString(editor->fileEncoding())));
389 } else {
390 mFileEncodingStatus->setText(
391 QString("%1")
392 .arg(QString(editor->encodingOption()))
393 );
394 }
395 ui->actionAuto_Detect->setChecked(editor->encodingOption() == ENCODING_AUTO_DETECT);
396 ui->actionEncode_in_ANSI->setChecked(editor->encodingOption() == ENCODING_SYSTEM_DEFAULT);
397 ui->actionEncode_in_UTF_8->setChecked(editor->encodingOption() == ENCODING_UTF8);
398 ui->actionEncode_in_UTF_8_BOM->setChecked(editor->encodingOption() == ENCODING_UTF8_BOM);
399 } else {
400 mFileEncodingStatus->setText("");
401 ui->actionAuto_Detect->setChecked(false);
402 ui->actionEncode_in_ANSI->setChecked(false);
403 ui->actionEncode_in_UTF_8->setChecked(false);
404 ui->actionEncode_in_UTF_8_BOM->setChecked(false);
405 }
406}
407
408void MainWindow::updateEditorSettings()
409{
410 pIconsManager->updateEditorGuttorIcons(pSettings->environment().iconSet(),pointToPixel(pSettings->editor().fontSize()));
411 mEditorList->applySettings();
412}
413
414void MainWindow::updateEditorActions()
415{
416 Editor* e = mEditorList->getEditor();
417 if (e==nullptr) {
418 ui->actionAuto_Detect->setEnabled(false);
419 ui->actionEncode_in_ANSI->setEnabled(false);
420 ui->actionEncode_in_UTF_8->setEnabled(false);
421 ui->actionEncode_in_UTF_8_BOM->setEnabled(false);
422 mMenuEncoding->setEnabled(false);
423 ui->actionConvert_to_ANSI->setEnabled(false);
424 ui->actionConvert_to_UTF_8->setEnabled(false);
425 ui->actionConvert_to_UTF_8_BOM->setEnabled(false);
426 ui->actionCopy->setEnabled(false);
427 ui->actionCut->setEnabled(false);
428 ui->actionFoldAll->setEnabled(false);
429 ui->actionIndent->setEnabled(false);
430 ui->actionPaste->setEnabled(false);
431 ui->actionRedo->setEnabled(false);
432 ui->actionSave->setEnabled(false);
433 ui->actionSaveAs->setEnabled(false);
434 ui->actionExport_As_HTML->setEnabled(false);
435 ui->actionExport_As_RTF->setEnabled(false);
436 ui->actionPrint->setEnabled(false);
437 ui->actionSelectAll->setEnabled(false);
438 ui->actionToggleComment->setEnabled(false);
439 ui->actionUnIndent->setEnabled(false);
440 ui->actionUndo->setEnabled(false);
441 ui->actionUnfoldAll->setEnabled(false);
442 ui->actionDelete_Line->setEnabled(false);
443 ui->actionDelete_Word->setEnabled(false);
444 ui->actionDuplicate_Line->setEnabled(false);
445 ui->actionDelete_to_BOL->setEnabled(false);
446 ui->actionDelete_to_EOL->setEnabled(false);
447
448 ui->actionFind->setEnabled(false);
449 ui->actionReplace->setEnabled(false);
450 ui->actionFind_Next->setEnabled(false);
451 ui->actionFind_Previous->setEnabled(false);
452
453 //code
454 ui->actionReformat_Code->setEnabled(false);
455
456 ui->actionClose->setEnabled(false);
457 ui->actionClose_All->setEnabled(false);
458
459 ui->actionAdd_bookmark->setEnabled(false);
460 ui->actionRemove_Bookmark->setEnabled(false);
461 ui->actionModify_Bookmark_Description->setEnabled(false);
462
463 ui->actionGo_to_Line->setEnabled(false);
464 ui->actionLocate_in_Files_View->setEnabled(false);
465 } else {
466 ui->actionAuto_Detect->setEnabled(true);
467 ui->actionEncode_in_ANSI->setEnabled(true);
468 ui->actionEncode_in_UTF_8->setEnabled(true);
469 ui->actionEncode_in_UTF_8_BOM->setEnabled(true);
470 mMenuEncoding->setEnabled(true);
471 ui->actionConvert_to_ANSI->setEnabled(e->encodingOption()!=ENCODING_SYSTEM_DEFAULT
472 && e->fileEncoding()!=ENCODING_SYSTEM_DEFAULT);
473 ui->actionConvert_to_UTF_8->setEnabled(e->encodingOption()!=ENCODING_UTF8 && e->fileEncoding()!=ENCODING_UTF8);
474 ui->actionConvert_to_UTF_8_BOM->setEnabled(e->encodingOption()!=ENCODING_UTF8_BOM && e->fileEncoding()!=ENCODING_UTF8_BOM);
475
476 ui->actionCopy->setEnabled(e->selAvail());
477 ui->actionCut->setEnabled(true);
478 ui->actionFoldAll->setEnabled(e->document()->count()>0);
479 ui->actionIndent->setEnabled(!e->readOnly());
480
481 ui->actionPaste->setEnabled(!e->readOnly() && !QGuiApplication::clipboard()->text().isEmpty());
482 ui->actionRedo->setEnabled(e->canRedo());
483 ui->actionUndo->setEnabled(e->canUndo());
484 ui->actionSave->setEnabled(!e->readOnly());
485 ui->actionSaveAs->setEnabled(true);
486 ui->actionExport_As_HTML->setEnabled(true);
487 ui->actionExport_As_RTF->setEnabled(true);
488 ui->actionPrint->setEnabled(true);
489 ui->actionSelectAll->setEnabled(e->document()->count()>0);
490 ui->actionToggleComment->setEnabled(!e->readOnly() && e->document()->count()>0);
491 ui->actionUnIndent->setEnabled(!e->readOnly() && e->document()->count()>0);
492 ui->actionUnfoldAll->setEnabled(e->document()->count()>0);
493 ui->actionDelete_Line->setEnabled(!e->readOnly() && e->document()->count()>0);
494 ui->actionDelete_Word->setEnabled(!e->readOnly() && e->document()->count()>0);
495 ui->actionDuplicate_Line->setEnabled(!e->readOnly() && e->document()->count()>0);
496 ui->actionDelete_to_BOL->setEnabled(!e->readOnly() && e->document()->count()>0);
497 ui->actionDelete_to_EOL->setEnabled(!e->readOnly() && e->document()->count()>0);
498
499 ui->actionFind->setEnabled(true);
500 ui->actionReplace->setEnabled(true);
501 ui->actionFind_Next->setEnabled(true);
502 ui->actionFind_Previous->setEnabled(true);
503
504 //code
505 ui->actionReformat_Code->setEnabled(true);
506
507 ui->actionClose->setEnabled(true);
508 ui->actionClose_All->setEnabled(true);
509
510 int line = e->caretY();
511 ui->actionAdd_bookmark->setEnabled(e->document()->count()>0 && !e->hasBookmark(line));
512 ui->actionRemove_Bookmark->setEnabled(e->hasBookmark(line));
513 ui->actionModify_Bookmark_Description->setEnabled(e->hasBookmark(line));
514
515 ui->actionGo_to_Line->setEnabled(true);
516 ui->actionLocate_in_Files_View->setEnabled(!e->isNew());
517 }
518
519 updateCompileActions();
520 updateCompilerSet();
521}
522
523void MainWindow::updateProjectActions()
524{
525 bool hasProject = (mProject != nullptr);
526 ui->actionNew_Template->setEnabled(hasProject);
527 ui->actionView_Makefile->setEnabled(hasProject);
528 ui->actionProject_New_File->setEnabled(hasProject);
529 ui->actionAdd_to_project->setEnabled(hasProject);
530 ui->actionRemove_from_project->setEnabled(hasProject && ui->projectView->selectionModel()->selectedIndexes().count()>0);
531 ui->actionMakeClean->setEnabled(hasProject);
532 ui->actionProject_options->setEnabled(hasProject);
533 ui->actionClose_Project->setEnabled(hasProject);
534 ui->actionNew_Class->setEnabled(hasProject);
535 ui->actionNew_Header->setEnabled(hasProject);
536 ui->actionProject_Open_Folder_In_Explorer->setEnabled(hasProject);
537 ui->actionProject_Open_In_Terminal->setEnabled(hasProject);
538 updateCompileActions();
539}
540
541void MainWindow::updateCompileActions()
542{
543 bool hasProject = (mProject!=nullptr);
544 bool editorCanCompile = false;
545 Editor * e = mEditorList->getEditor();
546 if (e) {
547 FileType fileType = getFileType(e->filename());
548 if (fileType == FileType::CSource
549 || fileType == FileType::CppSource || e->isNew())
550 editorCanCompile = true;
551 }
552 if (mCompilerManager->compiling() || mCompilerManager->running() || mDebugger->executing()
553 || (!hasProject && !editorCanCompile) ) {
554 ui->actionCompile->setEnabled(false);
555 ui->actionCompile_Run->setEnabled(false);
556 ui->actionRun->setEnabled(false);
557 ui->actionRebuild->setEnabled(false);
558 ui->actionDebug->setEnabled(false);
559 ui->btnRunAllProblemCases->setEnabled(false);
560 } else {
561 ui->actionCompile->setEnabled(true);
562 ui->actionCompile_Run->setEnabled(true);
563 ui->actionRun->setEnabled(true);
564 ui->actionRebuild->setEnabled(true);
565 ui->actionDebug->setEnabled(true);
566 ui->btnRunAllProblemCases->setEnabled(true);
567 }
568 if (!mDebugger->executing()) {
569 disableDebugActions();
570 }
571 ui->actionStop_Execution->setEnabled(mCompilerManager->running() || mDebugger->executing());
572
573 //it's not a compile action, but put here for convinience
574 ui->actionSaveAll->setEnabled(mProject!=nullptr
575 || mEditorList->pageCount()>0);
576
577}
578
579void MainWindow::updateEditorColorSchemes()
580{
581 if (!mStatementColors)
582 return;
583 mStatementColors->clear();
584
585 mEditorList->applyColorSchemes(pSettings->editor().colorScheme());
586 QString schemeName = pSettings->editor().colorScheme();
587 pColorManager->updateStatementColors(mStatementColors,schemeName);
588 //color for code completion popup
589 PColorSchemeItem item;
590 QColor localHeaderColor=palette().color(QPalette::Text);
591 QColor systemHeaderColor=palette().color(QPalette::Text);
592 QColor projectHeaderColor=palette().color(QPalette::Text);
593 QColor headerFolderColor=palette().color(QPalette::Text);
594 QColor baseColor = palette().color(QPalette::Base);
595 item = pColorManager->getItem(schemeName, SYNS_AttrPreprocessor);
596 if (item) {
597 localHeaderColor = item->foreground();
598 }
599 item = pColorManager->getItem(schemeName, SYNS_AttrPreprocessor);
600 if (item) {
601 systemHeaderColor = item->foreground();
602 }
603 item = pColorManager->getItem(schemeName, SYNS_AttrString);
604 if (item) {
605 projectHeaderColor = item->foreground();
606 }
607 item = pColorManager->getItem(schemeName, SYNS_AttrStringEscapeSequences);
608 if (item) {
609 headerFolderColor = item->foreground();
610 }
611 item = pColorManager->getItem(schemeName, COLOR_SCHEME_ERROR);
612 if (item && haveGoodContrast(item->foreground(), baseColor)) {
613 mErrorColor = item->foreground();
614 } else {
615 mErrorColor = palette().color(QPalette::Text);
616 }
617 ui->tableIssues->setErrorColor(mErrorColor);
618 item = pColorManager->getItem(schemeName, COLOR_SCHEME_WARNING);
619 if (item && haveGoodContrast(item->foreground(), baseColor)) {
620 ui->tableIssues->setWarningColor(item->foreground());
621 } else {
622 ui->tableIssues->setWarningColor(palette().color(QPalette::Text));
623 }
624 item = pColorManager->getItem(schemeName, COLOR_SCHEME_TEXT);
625 if (item) {
626 QPalette pal = palette();
627 pal.setColor(QPalette::Base,item->background());
628 pal.setColor(QPalette::Text,item->foreground());
629 mCompletionPopup->setPalette(pal);
630 mHeaderCompletionPopup->setPalette(pal);
631 ui->classBrowser->setPalette(pal);
632 ui->txtProblemCaseInput->setPalette(pal);
633 ui->txtProblemCaseExpected->setPalette(pal);
634 ui->txtProblemCaseOutput->setPalette(pal);
635 } else {
636 QPalette pal = palette();
637 mCompletionPopup->setPalette(pal);
638 mHeaderCompletionPopup->setPalette(pal);
639 ui->classBrowser->setPalette(pal);
640 ui->txtProblemCaseInput->setPalette(pal);
641 ui->txtProblemCaseExpected->setPalette(pal);
642 ui->txtProblemCaseOutput->setPalette(pal);
643 }
644 item = pColorManager->getItem(schemeName, COLOR_SCHEME_GUTTER);
645 if (item) {
646 ui->txtProblemCaseInput->setLineNumberAreaForeground(item->foreground());
647 ui->txtProblemCaseInput->setLineNumberAreaBackground(item->background());
648 ui->txtProblemCaseOutput->setLineNumberAreaForeground(item->foreground());
649 ui->txtProblemCaseOutput->setLineNumberAreaBackground(item->background());
650 ui->txtProblemCaseExpected->setLineNumberAreaForeground(item->foreground());
651 ui->txtProblemCaseExpected->setLineNumberAreaBackground(item->background());
652 } else {
653 QPalette pal = palette();
654 ui->txtProblemCaseInput->setLineNumberAreaForeground(pal.color(QPalette::ButtonText));
655 ui->txtProblemCaseInput->setLineNumberAreaBackground(pal.color(QPalette::Button));
656 ui->txtProblemCaseOutput->setLineNumberAreaForeground(pal.color(QPalette::ButtonText));
657 ui->txtProblemCaseOutput->setLineNumberAreaBackground(pal.color(QPalette::Button));
658 ui->txtProblemCaseExpected->setLineNumberAreaForeground(pal.color(QPalette::ButtonText));
659 ui->txtProblemCaseExpected->setLineNumberAreaBackground(pal.color(QPalette::Button));
660 }
661 item = pColorManager->getItem(schemeName, COLOR_SCHEME_GUTTER_ACTIVE_LINE);
662 if (item) {
663 ui->txtProblemCaseInput->setLineNumberAreaCurrentLine(item->foreground());
664 ui->txtProblemCaseOutput->setLineNumberAreaCurrentLine(item->foreground());
665 ui->txtProblemCaseExpected->setLineNumberAreaCurrentLine(item->foreground());
666 } else {
667 QPalette pal = palette();
668 ui->txtProblemCaseInput->setLineNumberAreaCurrentLine(pal.color(QPalette::ButtonText));
669 ui->txtProblemCaseOutput->setLineNumberAreaCurrentLine(pal.color(QPalette::ButtonText));
670 ui->txtProblemCaseExpected->setLineNumberAreaCurrentLine(pal.color(QPalette::ButtonText));
671 }
672 mHeaderCompletionPopup->setSuggestionColor(localHeaderColor,
673 projectHeaderColor,
674 systemHeaderColor,
675 headerFolderColor);
676}
677
678void MainWindow::applySettings()
679{
680 ThemeManager themeManager;
681 if (pSettings->environment().useCustomTheme()) {
682 themeManager.prepareCustomeTheme();
683 }
684 themeManager.setUseCustomTheme(pSettings->environment().useCustomTheme());
685 try {
686 PAppTheme appTheme = themeManager.theme(pSettings->environment().theme());
687 if (appTheme->isDark())
688 QApplication::setStyle(new DarkFusionStyle());
689 else
690 QApplication::setStyle(new LightFusionStyle());
691 qApp->setPalette(appTheme->palette());
692 //fix for qstatusbar bug
693 mFileEncodingStatus->setPalette(appTheme->palette());
694 mFileModeStatus->setPalette(appTheme->palette());
695 mFileInfoStatus->setPalette(appTheme->palette());
696 } catch (FileError e) {
697 QMessageBox::critical(this,
698 tr("Load Theme Error"),
699 e.reason());
700 }
701
702 updateEditorColorSchemes();
703
704 QFont font(pSettings->environment().interfaceFont());
705 font.setPixelSize(pointToPixel(pSettings->environment().interfaceFontSize()));
706 font.setStyleStrategy(QFont::PreferAntialias);
707 qApp->setFont(font);
708 this->setFont(font);
709 for (QWidget* p:findChildren<QWidget*>()) {
710 p->setFont(font);
711 }
712 if (pSettings->environment().useCustomIconSet()) {
713 QString customIconSetFolder = pSettings->dirs().config(Settings::Dirs::DataType::IconSet);
714 pIconsManager->prepareCustomIconSet(customIconSetFolder);
715 pIconsManager->setIconSetsFolder(customIconSetFolder);
716 }
717 pIconsManager->updateParserIcons(pSettings->environment().iconSet(),pointToPixel(pSettings->environment().interfaceFontSize()));
718
719 QFont caseEditorFont(pSettings->executor().caseEditorFontName());
720 caseEditorFont.setPixelSize(pointToPixel(pSettings->executor().caseEditorFontSize()));
721 font.setStyleStrategy(QFont::PreferAntialias);
722 ui->txtProblemCaseInput->setFont(caseEditorFont);
723 ui->lblProblemCaseInput->setFont(caseEditorFont);
724 ui->txtProblemCaseOutput->setFont(caseEditorFont);
725 ui->lblProblemCaseOutput->setFont(caseEditorFont);
726 ui->txtProblemCaseExpected->setFont(caseEditorFont);
727 ui->lblProblemCaseExpected->setFont(caseEditorFont);
728
729 mTcpServer.close();
730 if (pSettings->executor().enableProblemSet()) {
731 if (pSettings->executor().enableCompetitiveCompanion()) {
732 if (!mTcpServer.listen(QHostAddress::LocalHost,pSettings->executor().competivieCompanionPort())) {
733// QMessageBox::critical(nullptr,
734// tr("Listen failed"),
735// tr("Can't listen to port %1 form Competitive Companion.").arg(10045)
736// + "<BR/>"
737// +tr("You can turn off competitive companion support in the Problem Set options.")
738// + "<BR/>"
739// +tr("Or You can choose a different port number and try again."));
740 }
741 }
742 }
743
744 showHideInfosTab(ui->tabProblemSet,pSettings->ui().showProblemSet()
745 && pSettings->executor().enableProblemSet());
746 showHideMessagesTab(ui->tabProblem, pSettings->ui().showProblem()
747 && pSettings->executor().enableProblemSet());
748
749 ui->chkIgnoreSpaces->setChecked(pSettings->executor().ignoreSpacesWhenValidatingCases());
750 ui->actionInterrupt->setVisible(pSettings->debugger().useGDBServer());
751 //icon sets for editors
752 updateEditorSettings();
753 updateDebuggerSettings();
754 updateActionIcons();
755
756 //icon sets for files view
757 pIconsManager->updateFileSystemIcons(pSettings->environment().iconSet(),pointToPixel(pSettings->environment().interfaceFontSize()));
758 if (!mFileSystemModel.rootPath().isEmpty() && mFileSystemModel.rootPath()!=".")
759 setFilesViewRoot(pSettings->environment().currentFolder());
760// for (int i=0;i<ui->cbFilesPath->count();i++) {
761// ui->cbFilesPath->setItemIcon(i,pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
762// }
763
764 ui->menuGit->menuAction()->setVisible(pSettings->vcs().gitOk());
765
766 stretchExplorerPanel(!ui->tabExplorer->isShrinked());
767 stretchMessagesPanel(!ui->tabMessages->isShrinked());
768}
769
770void MainWindow::applyUISettings()
771{
772 const Settings::UI& settings = pSettings->ui();
773 restoreGeometry(settings.mainWindowGeometry());
774 restoreState(settings.mainWindowState());
775 ui->actionTool_Window_Bars->setChecked(settings.showToolWindowBars());
776 ui->tabExplorer->setVisible(settings.showToolWindowBars());
777 ui->tabMessages->setVisible(settings.showToolWindowBars());
778 ui->actionStatus_Bar->setChecked(settings.showStatusBar());
779 ui->statusbar->setVisible(settings.showStatusBar());
780
781 ui->actionProject->setChecked(settings.showProject());
782 showHideInfosTab(ui->tabProject,settings.showProject());
783 ui->actionWatch->setChecked(settings.showWatch());
784 showHideInfosTab(ui->tabWatch,settings.showWatch());
785 ui->actionStructure->setChecked(settings.showStructure());
786 showHideInfosTab(ui->tabStructure,settings.showStructure());
787 ui->actionFiles->setChecked(settings.showFiles());
788 showHideInfosTab(ui->tabFiles,settings.showFiles());
789 ui->actionProblem_Set->setChecked(settings.showProblemSet());
790 showHideInfosTab(ui->tabProblemSet,settings.showProblemSet()
791 && pSettings->executor().enableProblemSet());
792
793 ui->actionIssues->setChecked(settings.showIssues());
794 showHideMessagesTab(ui->tabIssues,settings.showIssues());
795 ui->actionTools_Output->setChecked(settings.showCompileLog());
796 showHideMessagesTab(ui->tabToolsOutput,settings.showCompileLog());
797 ui->actionDebug_Window->setChecked(settings.showDebug());
798 showHideMessagesTab(ui->tabDebug,settings.showDebug());
799 ui->actionSearch->setChecked(settings.showSearch());
800 showHideMessagesTab(ui->tabSearch,settings.showSearch());
801 ui->actionTODO->setChecked(settings.showTODO());
802 showHideMessagesTab(ui->tabTODO,settings.showTODO());
803 ui->actionBookmark->setChecked(settings.showBookmark());
804 showHideMessagesTab(ui->tabBookmark,settings.showBookmark());
805 ui->actionProblem->setChecked(settings.showProblem());
806 showHideMessagesTab(ui->tabProblem,settings.showProblem()
807 && pSettings->executor().enableProblemSet());
808
809 ui->tabMessages->setBeforeShrinkSize(settings.messagesTabsSize());
810 ui->tabExplorer->setBeforeShrinkSize(settings.explorerTabsSize());
811 if (settings.shrinkMessagesTabs())
812 ui->tabMessages->setShrinkedFlag(true);
813 if (settings.shrinkExplorerTabs())
814 ui->tabExplorer->setShrinkedFlag(true);
815}
816
817QFileSystemWatcher *MainWindow::fileSystemWatcher()
818{
819 return &mFileSystemWatcher;
820}
821
822void MainWindow::initDocks()
823{
824 ui->dockExplorer->setMinimumSize(0,0);
825 ui->dockMessages->setMinimumSize(0,0);
826 setDockExplorerToArea(dockWidgetArea(ui->dockExplorer));
827 setDockMessagesToArea(dockWidgetArea(ui->dockMessages));
828}
829
830void MainWindow::removeActiveBreakpoints()
831{
832 for (int i=0;i<mEditorList->pageCount();i++) {
833 Editor* e= (*mEditorList)[i];
834 e->removeBreakpointFocus();
835 }
836}
837
838void MainWindow::setActiveBreakpoint(QString FileName, int Line, bool setFocus)
839{
840 removeActiveBreakpoints();
841 // Then active the current line in the current file
842 Editor *e = mEditorList->getEditorByFilename(FileName);
843 if (e!=nullptr) {
844 e->setActiveBreakpointFocus(Line,setFocus);
845 }
846 if (setFocus) {
847 this->activateWindow();
848 }
849}
850
851void MainWindow::updateDPI(int oldDPI, int /*newDPI*/)
852{
853 //applySettings();
854 if (oldDPI<1)
855 oldDPI = 1;
856}
857
858void MainWindow::onFileSaved(const QString &path, bool inProject)
859{
860 if (pSettings->vcs().gitOk()) {
861 QString branch;
862 if (inProject && mProject && mProject->model()->iconProvider()->VCSRepository()->hasRepository(branch)) {
863 mProject->model()->beginUpdate();
864 mProject->model()->endUpdate();
865 }
866 QModelIndex index = mFileSystemModel.index(path);
867 if (index.isValid()) {
868 if (!inProject) {
869 if ( (isCFile(path) || isHFile(path))
870 && !mFileSystemModelIconProvider.VCSRepository()->isFileInRepository(path)) {
871 QString output;
872 mFileSystemModelIconProvider.VCSRepository()->add(extractRelativePath(mFileSystemModelIconProvider.VCSRepository()->folder(),path),output);
873 }
874 }
875// qDebug()<<"update icon provider";
876 mFileSystemModelIconProvider.update();
877 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
878 ui->treeFiles->update(index);
879 }
880 }
881 //updateForEncodingInfo();
882}
883
884void MainWindow::updateAppTitle()
885{
886 QString appName=tr("Red Panda C++");
887 Editor *e = mEditorList->getEditor();
888 QCoreApplication *app = QApplication::instance();
889 if (e && !e->inProject()) {
890 QString str;
891 if (e->modified())
892 str = e->filename() + " [*]";
893 else
894 str = e->filename();
895 if (mDebugger->executing()) {
896 setWindowTitle(QString("%1 - [%2] - %3 %4")
897 .arg(str,tr("Debugging"),appName,REDPANDA_CPP_VERSION));
898 app->setApplicationName(QString("%1 - [%2] - %3")
899 .arg(str,tr("Debugging"),appName));
900 } else if (mCompilerManager->running()) {
901 setWindowTitle(QString("%1 - [%2] - %3 %4")
902 .arg(str,tr("Running"),appName,REDPANDA_CPP_VERSION));
903 app->setApplicationName(QString("%1 - [%2] - %3")
904 .arg(str,tr("Running"),appName));
905 } else if (mCompilerManager->compiling()) {
906 setWindowTitle(QString("%1 - [%2] - %3 %4")
907 .arg(str,tr("Compiling"),appName,REDPANDA_CPP_VERSION));
908 app->setApplicationName(QString("%1 - [%2] - %3")
909 .arg(str,tr("Compiling"),appName));
910 } else {
911 this->setWindowTitle(QString("%1 - %2 %3")
912 .arg(str,appName,REDPANDA_CPP_VERSION));
913 app->setApplicationName(QString("%1 - %2")
914 .arg(str,appName));
915 }
916 } else if (e && e->inProject() && mProject) {
917 QString str,str2;
918 if (mProject->modified())
919 str = mProject->name() + " [*]";
920 else
921 str = mProject->name();
922 if (e->modified())
923 str2 = extractFileName(e->filename()) + " [*]";
924 else
925 str2 = extractFileName(e->filename());
926 if (mDebugger->executing()) {
927 setWindowTitle(QString("%1 - %2 [%3] - %4 %5")
928 .arg(str,str2,
929 tr("Debugging"),appName,REDPANDA_CPP_VERSION));
930 app->setApplicationName(QString("%1 - [%2] - %3")
931 .arg(str,tr("Debugging"),appName));
932 } else if (mCompilerManager->running()) {
933 setWindowTitle(QString("%1 - %2 [%3] - %4 %5")
934 .arg(str,str2,
935 tr("Running"),appName,REDPANDA_CPP_VERSION));
936 app->setApplicationName(QString("%1 - [%2] - %3")
937 .arg(str,tr("Running"),appName));
938 } else if (mCompilerManager->compiling()) {
939 setWindowTitle(QString("%1 - %2 [%3] - %4 %5")
940 .arg(str,str2,
941 tr("Compiling"),appName,REDPANDA_CPP_VERSION));
942 app->setApplicationName(QString("%1 - [%2] - %3")
943 .arg(str,tr("Compiling"),appName));
944 } else {
945 setWindowTitle(QString("%1 - %2 %3")
946 .arg(str,appName,REDPANDA_CPP_VERSION));
947 app->setApplicationName(QString("%1 - %2")
948 .arg(str,appName));
949 }
950 } else if (mProject) {
951 QString str,str2;
952 if (mProject->modified())
953 str = mProject->name() + " [*]";
954 else
955 str = mProject->name();
956 if (mDebugger->executing()) {
957 setWindowTitle(QString("%1 - [%2] - %3 %4")
958 .arg(str,tr("Debugging"),appName,REDPANDA_CPP_VERSION));
959 app->setApplicationName(QString("%1 - [%2] - %3")
960 .arg(str,tr("Debugging"),appName));
961 } else if (mCompilerManager->running()) {
962 setWindowTitle(QString("%1 - [%2] - %3 %4")
963 .arg(str,tr("Running"),appName,REDPANDA_CPP_VERSION));
964 app->setApplicationName(QString("%1 - [%2] - %3")
965 .arg(str,tr("Running"),appName));
966 } else if (mCompilerManager->compiling()) {
967 setWindowTitle(QString("%1 - [%2] - %3 %4")
968 .arg(str,tr("Compiling"),appName,REDPANDA_CPP_VERSION));
969 app->setApplicationName(QString("%1 - [%2] - %3")
970 .arg(str,tr("Compiling"),appName));
971 } else {
972 this->setWindowTitle(QString("%1 - %2 %3")
973 .arg(str,appName,REDPANDA_CPP_VERSION));
974 app->setApplicationName(QString("%1 - %2")
975 .arg(str,appName));
976 }
977 } else {
978 setWindowTitle(QString("%1 %2").arg(appName,REDPANDA_CPP_VERSION));
979 app->setApplicationName(QString("%1").arg(appName));
980 }
981}
982
983void MainWindow::addDebugOutput(const QString &text)
984{
985 if (!pSettings->debugger().enableDebugConsole())
986 return;
987 if (text.isEmpty()) {
988 ui->debugConsole->addLine("");
989 } else {
990 ui->debugConsole->addText(text);
991 }
992}
993
994void MainWindow::changeDebugOutputLastline(const QString &test)
995{
996 ui->debugConsole->changeLastLine(test);
997}
998
999void MainWindow::updateDebugEval(const QString &value)
1000{
1001 ui->txtEvalOutput->clear();
1002 ui->txtEvalOutput->appendPlainText(value);
1003 ui->txtEvalOutput->moveCursor(QTextCursor::Start);
1004}
1005
1006void MainWindow::rebuildOpenedFileHisotryMenu()
1007{
1008 mMenuRecentFiles->clear();
1009 mMenuRecentProjects->clear();
1010 if (pSettings->history().opennedFiles().size()==0) {
1011 mMenuRecentFiles->setEnabled(false);
1012 } else {
1013 mMenuRecentFiles->setEnabled(true);
1014 for (const QString& filename: pSettings->history().opennedFiles()) {
1015 QAction* action = new QAction(filename,mMenuRecentFiles);
1016 connect(action, &QAction::triggered, [&filename,this](bool){
1017 openFile(filename);
1018 });
1019 mMenuRecentFiles->addAction(action);
1020 }
1021 mMenuRecentFiles->addSeparator();
1022 QAction *action = new QAction(tr("Clear History"),mMenuRecentFiles);
1023 connect(action, &QAction::triggered, [](bool){
1024 pSettings->history().clearOpennedFiles();
1025 });
1026 mMenuRecentFiles->addAction(action);
1027 }
1028
1029 if (pSettings->history().opennedProjects().size()==0) {
1030 mMenuRecentProjects->setEnabled(false);
1031 } else {
1032 mMenuRecentProjects->setEnabled(true);
1033 for (const QString& filename: pSettings->history().opennedProjects()) {
1034 QAction* action = new QAction(filename,mMenuRecentProjects);
1035 connect(action, &QAction::triggered, [&filename,this](bool){
1036 this->openProject(filename);
1037 });
1038 mMenuRecentProjects->addAction(action);
1039 }
1040 mMenuRecentProjects->addSeparator();
1041 QAction *action = new QAction(tr("Clear History"),mMenuRecentProjects);
1042 connect(action, &QAction::triggered, [](bool){
1043 pSettings->history().clearOpennedProjects();
1044 });
1045 mMenuRecentProjects->addAction(action);
1046 }
1047
1048}
1049
1050void MainWindow::updateClassBrowserForEditor(Editor *editor)
1051{
1052 if (!editor) {
1053 mClassBrowserModel.setParser(nullptr);
1054 mClassBrowserModel.setCurrentFile("");
1055 return;
1056 }
1057 if (mQuitting)
1058 return;
1059// if not devCodeCompletion.Enabled then
1060// Exit;
1061 if ((mClassBrowserModel.currentFile() == editor->filename())
1062 && (mClassBrowserModel.parser() == editor->parser()))
1063 return;
1064
1065 mClassBrowserModel.beginUpdate();
1066 {
1067 auto action = finally([this] {
1068 mClassBrowserModel.endUpdate();
1069 });
1070 mClassBrowserModel.setParser(editor->parser());
1071// if e.InProject then begin
1072// ClassBrowser.StatementsType := devClassBrowsing.StatementsType;
1073// end else
1074// ClassBrowser.StatementsType := cbstFile;
1075 mClassBrowserModel.setCurrentFile(editor->filename());
1076 }
1077}
1078
1079void MainWindow::resetAutoSaveTimer()
1080{
1081 if (pSettings->editor().enableAutoSave()) {
1082 mAutoSaveTimer.stop();
1083 //minute to milliseconds
1084 mAutoSaveTimer.start(pSettings->editor().autoSaveInterval()*60*1000);
1085 onAutoSaveTimeout();
1086 } else {
1087 mAutoSaveTimer.stop();
1088 }
1089}
1090
1091void MainWindow::updateShortcuts()
1092{
1093 ShortcutManager manager;
1094 manager.load();
1095 manager.applyTo(listShortCutableActions());
1096}
1097
1098QPlainTextEdit *MainWindow::txtLocals()
1099{
1100 return ui->txtLocals;
1101}
1102
1103QMenuBar *MainWindow::menuBar() const
1104{
1105 return ui->menubar;
1106}
1107
1108void MainWindow::updateStatusbarForLineCol(bool clear)
1109{
1110 Editor* e = mEditorList->getEditor();
1111 if (!clear && e!=nullptr) {
1112 int col = e->charToColumn(e->caretY(),e->caretX());
1113 QString msg = tr("Line:%1 Col:%2 Selected:%3 Lines:%4 Length:%5")
1114 .arg(e->caretY())
1115 .arg(col)
1116 .arg(e->selText().length())
1117 .arg(e->document()->count())
1118 .arg(e->document()->getTextLength());
1119 mFileInfoStatus->setText(msg);
1120 } else {
1121 mFileInfoStatus->setText("");
1122 }
1123}
1124
1125void MainWindow::updateForStatusbarModeInfo(bool clear)
1126{
1127 Editor* e = mEditorList->getEditor();
1128 if (!clear && e!=nullptr) {
1129 QString msg;
1130 if (e->readOnly()) {
1131 msg = tr("Read Only");
1132 } else if (e->insertMode()) {
1133 msg = tr("Insert");
1134 } else {
1135 msg = tr("Overwrite");
1136 }
1137 mFileModeStatus->setText(msg);
1138 } else {
1139 mFileModeStatus->setText("");
1140 }
1141}
1142
1143void MainWindow::updateStatusbarMessage(const QString &s)
1144{
1145 ui->statusbar->showMessage(s);
1146}
1147
1148void MainWindow::openFiles(const QStringList &files)
1149{
1150 mEditorList->beginUpdate();
1151 mOpenningFiles = true;
1152 auto end = finally([this] {
1153 this->mEditorList->endUpdate();
1154 mOpenningFiles = false;
1155 });
1156 //Check if there is a project file in the list and open it
1157 for (const QString& file:files) {
1158 if (getFileType(file)==FileType::Project) {
1159 openProject(file);
1160 return;
1161 }
1162 }
1163 //Didn't find a project? Open all files
1164 for (int i=0;i<files.length()-1;i++) {
1165 openFile(files[i],false);
1166 }
1167 if (files.length()>0) {
1168 openFile(files.last(),true);
1169 }
1170 mEditorList->endUpdate();
1171 Editor* e=mEditorList->getEditor();
1172 if (e)
1173 e->activate();
1174}
1175
1176void MainWindow::openFile(const QString &filename, bool activate, QTabWidget* page)
1177{
1178 Editor* editor = mEditorList->getOpenedEditorByFilename(filename);
1179 if (editor!=nullptr) {
1180 if (activate) {
1181 editor->activate();
1182 }
1183 return;
1184 }
1185 try {
1186 pSettings->history().removeFile(filename);
1187 PProjectUnit unit;
1188 if (mProject) {
1189 unit = mProject->findUnitByFilename(filename);
1190 }
1191 bool inProject = (mProject && unit);
1192 QByteArray encoding = unit ? unit->encoding() :
1193 (pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding());
1194 editor = mEditorList->newEditor(filename,encoding,
1195 inProject, false, page);
1196// if (mProject) {
1197// mProject->associateEditorToUnit(editor,unit);
1198// }
1199 if (activate) {
1200 editor->activate();
1201 }
1202// editor->activate();
1203 } catch (FileError e) {
1204 QMessageBox::critical(this,tr("Error"),e.reason());
1205 }
1206}
1207
1208void MainWindow::openProject(const QString &filename, bool openFiles)
1209{
1210 if (!fileExists(filename)) {
1211 return;
1212 }
1213 if (mProject) {
1214 QString s;
1215 if (mProject->name().isEmpty())
1216 s = mProject->filename();
1217 else
1218 s = mProject->name();
1219 if (QMessageBox::question(this,
1220 tr("Close project"),
1221 tr("Are you sure you want to close %1?")
1222 .arg(s),
1223 QMessageBox::Yes | QMessageBox::No,
1224 QMessageBox::Yes) == QMessageBox::Yes) {
1225 closeProject(false);
1226 } else {
1227 return;
1228 }
1229 }
1230 ui->tabProject->setVisible(true);
1231 ui->tabExplorer->setCurrentWidget(ui->tabProject);
1232 stretchExplorerPanel(true);
1233// {
1234// LeftPageControl.ActivePage := LeftProjectSheet;
1235// fLeftPageControlChanged := False;
1236// ClassBrowser.TabVisible:= False;
1237// }
1238
1239 // Only update class browser once
1240 mClassBrowserModel.beginUpdate();
1241 {
1242 auto action = finally([this]{
1243 mClassBrowserModel.endUpdate();
1244 });
1245 mProject = std::make_shared<Project>(filename,DEV_INTERNAL_OPEN,
1246 mEditorList,
1247 &mFileSystemWatcher);
1248 updateProjectView();
1249 pSettings->history().removeProject(filename);
1250
1251 // // if project manager isn't open then open it
1252 // if not devData.ShowLeftPages then
1253 // actProjectManager.Execute;
1254 //checkForDllProfiling();
1255
1256 //parse the project
1257 // UpdateClassBrowsing;
1258 scanActiveProject(true);
1259 if (openFiles)
1260 mProject->doAutoOpen();
1261
1262 //update editor's inproject flag
1263 for (int i=0;i<mProject->units().count();i++) {
1264 PProjectUnit unit = mProject->units()[i];
1265 Editor* e = mEditorList->getOpenedEditorByFilename(unit->fileName());
1266 mProject->associateEditorToUnit(e,unit);
1267 }
1268
1269 Editor * e = mEditorList->getEditor();
1270 if (e) {
1271 checkSyntaxInBack(e);
1272 }
1273 updateAppTitle();
1274 updateCompilerSet();
1275 updateClassBrowserForEditor(e);
1276 }
1277 //updateForEncodingInfo();
1278}
1279
1280void MainWindow::changeOptions(const QString &widgetName, const QString &groupName)
1281{
1282 PSettingsDialog settingsDialog = SettingsDialog::optionDialog();
1283 if (!groupName.isEmpty()) {
1284 settingsDialog->setCurrentWidget(widgetName, groupName);
1285 }
1286 settingsDialog->exec();
1287 if (settingsDialog->appShouldQuit()) {
1288 mShouldRemoveAllSettings = true;
1289 close();
1290 return;
1291 }
1292
1293 Editor *e = mEditorList->getEditor();
1294 if (mProject && !e) {
1295 scanActiveProject(true);
1296 } else if (mProject && e && e->inProject()) {
1297 scanActiveProject(true);
1298 } else if (e) {
1299 e->reparse();
1300 }
1301
1302}
1303
1304void MainWindow::updateCompilerSet()
1305{
1306 mCompilerSet->blockSignals(true);
1307 mCompilerSet->clear();
1308 for (size_t i=0;i<pSettings->compilerSets().size();i++) {
1309 mCompilerSet->addItem(pSettings->compilerSets().getSet(i)->name());
1310 }
1311 int index=pSettings->compilerSets().defaultIndex();
1312 if (mProject) {
1313 Editor *e = mEditorList->getEditor();
1314 if ( !e || e->inProject()) {
1315 index = mProject->options().compilerSet;
1316 }
1317 }
1318 if (index < 0 || index>=mCompilerSet->count()) {
1319 index = pSettings->compilerSets().defaultIndex();
1320 }
1321 mCompilerSet->setCurrentIndex(index);
1322 mCompilerSet->blockSignals(false);
1323 mCompilerSet->update();
1324}
1325
1326void MainWindow::updateDebuggerSettings()
1327{
1328 QFont font(pSettings->debugger().fontName());
1329 font.setPixelSize(pointToPixel(pSettings->debugger().fontSize()));
1330 ui->debugConsole->setFont(font);
1331 ui->tblMemoryView->setFont(font);
1332 //ui->txtMemoryView->setFont(font);
1333 ui->txtLocals->setFont(font);
1334
1335 int idx = findTabIndex(ui->debugViews,ui->tabDebugConsole);
1336 if (idx>=0) {
1337 if (!pSettings->debugger().enableDebugConsole()) {
1338 ui->debugViews->removeTab(idx);
1339 }
1340 } else {
1341 if (pSettings->debugger().enableDebugConsole()) {
1342 ui->debugViews->insertTab(0, ui->tabDebugConsole, tr("Debug Console"));
1343 }
1344 }
1345
1346}
1347
1348void MainWindow::updateActionIcons()
1349{
1350 int size = pointToPixel(pSettings->environment().interfaceFontSize());
1351 pIconsManager->updateActionIcons(pSettings->environment().iconSet(), size);
1352 QSize iconSize(size,size);
1353 ui->toolbarMain->setIconSize(iconSize);
1354 ui->toolbarCode->setIconSize(iconSize);
1355 ui->toolbarCompile->setIconSize(iconSize);
1356 ui->toolbarDebug->setIconSize(iconSize);
1357 for (QToolButton* btn: mClassBrowserToolbar->findChildren<QToolButton *>()) {
1358 btn->setIconSize(iconSize);
1359 }
1360 for (QToolButton* btn: ui->panelFiles->findChildren<QToolButton *>()) {
1361 btn->setIconSize(iconSize);
1362 }
1363
1364 ui->tabExplorer->setIconSize(iconSize);
1365 ui->tabMessages->setIconSize(iconSize);
1366 ui->EditorTabsLeft->setIconSize(iconSize);
1367 ui->EditorTabsRight->setIconSize(iconSize);
1368
1369 ui->actionNew->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_NEW));
1370 ui->actionNew_Project->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_NEW));
1371 ui->actionOpen->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_OPEN));
1372 ui->actionOpen_Folder->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_OPEN_FOLDER));
1373 ui->actionSave->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_SAVE));
1374 ui->actionSaveAs->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_SAVE_AS));
1375 ui->actionSaveAll->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_SAVE_ALL));
1376 ui->actionClose->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_CLOSE));
1377 ui->actionClose_Project->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_CLOSE));
1378 ui->actionClose_All->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_CLOSE_ALL));
1379 ui->actionPrint->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_PRINT));
1380
1381 ui->actionUndo->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_UNDO));
1382 ui->actionRedo->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_REDO));
1383 ui->actionCut->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_CUT));
1384 ui->actionCopy->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_COPY));
1385 ui->actionPaste->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_PASTE));
1386 ui->actionIndent->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_INDENT));
1387 ui->actionUnIndent->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_UNINDENT));
1388
1389 ui->actionFind->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_SEARCH));
1390 ui->actionReplace->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_REPLACE));
1391 ui->actionFind_in_files->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_SEARCH_IN_FILES));
1392
1393 ui->actionBack->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_BACK));
1394 ui->actionForward->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_FORWARD));
1395 ui->actionAdd_bookmark->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_ADD_BOOKMARK));
1396 ui->actionRemove_Bookmark->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_REMOVE_BOOKMARK));
1397 ui->actionReformat_Code->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_REFORMAT));
1398
1399 ui->actionProject_New_File->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_NEW_FILE));
1400 ui->actionAdd_to_project->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_ADD_FILE));
1401 ui->actionRemove_from_project->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_REMOVE_FILE));
1402 ui->actionProject_Open_Folder_In_Explorer->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_FOLDER));
1403 ui->actionProject_Open_In_Terminal->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_TERM));
1404 ui->actionMakeClean->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1405 ui->actionProject_options->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROJECT_PROPERTIES));
1406
1407
1408 ui->actionCompile->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_COMPILE));
1409 ui->actionCompile_Run->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_COMPILE_RUN));
1410 ui->actionRun->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_RUN));
1411 ui->actionRebuild->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_REBUILD));
1412 ui->actionRun_Parameters->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_OPTIONS));
1413 ui->actionDebug->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_DEBUG));
1414 ui->actionInterrupt->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_INTERRUPT));
1415 ui->actionStep_Over->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_STEP_OVER));
1416 ui->actionStep_Into->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_STEP_INTO));
1417 ui->actionStep_Out->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_STEP_OUT));
1418 ui->actionRun_To_Cursor->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_RUN_TO_CURSOR));
1419 ui->actionContinue->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_CONTINUE));
1420 ui->actionStop_Execution->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_STOP));
1421 ui->actionAdd_Watch->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_ADD_WATCH));
1422 ui->actionRemove_Watch->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_REMOVE_WATCH));
1423 ui->actionRemove_All_Watches->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1424 ui->actionCompiler_Options->setIcon(pIconsManager->getIcon(IconsManager::ACTION_RUN_COMPILE_OPTIONS));
1425
1426 ui->actionOptions->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_GEAR));
1427
1428 ui->actionMaximize_Editor->setIcon(pIconsManager->getIcon(IconsManager::ACTION_VIEW_MAXIMUM));
1429 ui->actionNext_Editor->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_FORWARD));
1430 ui->actionPrevious_Editor->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_BACK));
1431
1432 ui->actionAbout->setIcon(pIconsManager->getIcon(IconsManager::ACTION_HELP_ABOUT));
1433
1434 //editor context menu
1435 ui->actionOpen_Containing_Folder->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_FOLDER));
1436 ui->actionOpen_Terminal->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_TERM));
1437 ui->actionFile_Properties->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_PROPERTIES));
1438 ui->actionLocate_in_Files_View->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_LOCATE));
1439
1440 //bookmark context menu
1441 mBookmark_Remove->setIcon(pIconsManager->getIcon(IconsManager::ACTION_CODE_REMOVE_BOOKMARK));
1442 mBookmark_RemoveAll->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1443
1444 //issues context menu
1445 mTableIssuesCopyAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_COPY));
1446 mTableIssuesClearAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1447
1448 //search context menu
1449 mSearchViewClearAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CROSS));
1450 mSearchViewClearAllAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1451
1452 //breakpoint context menu
1453 //mBreakpointViewPropertyAction
1454 mBreakpointViewRemoveAllAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1455 mBreakpointViewRemoveAction->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CROSS));
1456
1457 //Tools Output
1458
1459 //classbrowser
1460 mClassBrowser_Sort_By_Name->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_SORT_BY_NAME));
1461 mClassBrowser_Sort_By_Type->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_SORT_BY_TYPE));
1462 mClassBrowser_Show_Inherited->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_SHOW_INHERITED));
1463
1464 //debug console
1465 mDebugConsole_Copy->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_COPY));
1466 mDebugConsole_Paste->setIcon(pIconsManager->getIcon(IconsManager::ACTION_EDIT_PASTE));
1467 mDebugConsole_Clear->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_CLEAN));
1468
1469 //file view
1470 mFilesView_Open->setIcon(pIconsManager->getIcon(IconsManager::ACTION_FILE_OPEN));
1471 mFilesView_OpenInTerminal->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_TERM));
1472 mFilesView_OpenInExplorer->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_FOLDER));
1473 ui->actionFilesView_Hide_Non_Support_Files->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_FILTER));
1474
1475 //problem view
1476 pIconsManager->setIcon(ui->btnNewProblemSet, IconsManager::ACTION_PROBLEM_SET);
1477 pIconsManager->setIcon(ui->btnAddProblem, IconsManager::ACTION_MISC_ADD);
1478 pIconsManager->setIcon(ui->btnRemoveProblem, IconsManager::ACTION_MISC_CROSS);
1479 pIconsManager->setIcon(ui->btnSaveProblemSet, IconsManager::ACTION_FILE_SAVE_AS);
1480 pIconsManager->setIcon(ui->btnLoadProblemSet, IconsManager::ACTION_FILE_OPEN_FOLDER);
1481
1482 pIconsManager->setIcon(ui->btnAddProblemCase, IconsManager::ACTION_MISC_ADD);
1483 pIconsManager->setIcon(ui->btnRemoveProblemCase, IconsManager::ACTION_MISC_REMOVE);
1484 pIconsManager->setIcon(ui->btnOpenProblemAnswer, IconsManager::ACTION_PROBLEM_EDIT_SOURCE);
1485 pIconsManager->setIcon(ui->btnRunAllProblemCases, IconsManager::ACTION_PROBLEM_RUN_CASES);
1486 pIconsManager->setIcon(ui->btnCaseValidateOptions, IconsManager::ACTION_MISC_GEAR);
1487
1488 pIconsManager->setIcon(ui->btnProblemCaseClearInputFileName, IconsManager::ACTION_MISC_CLEAN);
1489 pIconsManager->setIcon(ui->btnProblemCaseInputFileName, IconsManager::ACTION_MISC_FOLDER);
1490 pIconsManager->setIcon(ui->btnProblemCaseClearExpectedOutputFileName, IconsManager::ACTION_MISC_CLEAN);
1491 pIconsManager->setIcon(ui->btnProblemCaseExpectedOutputFileName, IconsManager::ACTION_MISC_FOLDER);
1492
1493 mProblem_Properties->setIcon(pIconsManager->getIcon(IconsManager::ACTION_PROBLEM_PROPERTIES));
1494
1495
1496 int idx = ui->tabExplorer->indexOf(ui->tabWatch);
1497 if (idx>=0)
1498 ui->tabExplorer->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_RUN_ADD_WATCH));
1499 idx = ui->tabExplorer->indexOf(ui->tabProject);
1500 if (idx>=0)
1501 ui->tabExplorer->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_PROJECT_NEW));
1502 idx = ui->tabExplorer->indexOf(ui->tabFiles);
1503 if (idx>=0)
1504 ui->tabExplorer->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_VIEW_FILES));
1505 idx = ui->tabExplorer->indexOf(ui->tabStructure);
1506 if (idx>=0)
1507 ui->tabExplorer->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_VIEW_CLASSBROWSER));
1508 idx = ui->tabExplorer->indexOf(ui->tabProblemSet);
1509 if (idx>=0)
1510 ui->tabExplorer->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_PROBLEM_SET));
1511
1512 idx = ui->tabMessages->indexOf(ui->tabIssues);
1513 if (idx>=0)
1514 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_RUN_COMPILE));
1515 idx = ui->tabMessages->indexOf(ui->tabDebug);
1516 if (idx>=0)
1517 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_RUN_DEBUG));
1518 idx = ui->tabMessages->indexOf(ui->tabSearch);
1519 if (idx>=0)
1520 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_EDIT_SEARCH));
1521 idx = ui->tabMessages->indexOf(ui->tabToolsOutput);
1522 if (idx>=0)
1523 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_VIEW_COMPILELOG));
1524 idx = ui->tabMessages->indexOf(ui->tabTODO);
1525 if (idx>=0)
1526 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_VIEW_TODO));
1527 idx = ui->tabMessages->indexOf(ui->tabBookmark);
1528 if (idx>=0)
1529 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_VIEW_BOOKMARK));
1530
1531 idx = ui->tabMessages->indexOf(ui->tabProblem);
1532 if (idx>=0)
1533 ui->tabMessages->setTabIcon(idx,pIconsManager->getIcon(IconsManager::ACTION_PROBLEM_PROBLEM));
1534}
1535
1536void MainWindow::checkSyntaxInBack(Editor *e)
1537{
1538 if (e==nullptr)
1539 return;
1540
1541 if (!pSettings->editor().syntaxCheck()) {
1542 return;
1543 }
1544// if not devEditor.AutoCheckSyntax then
1545// Exit;
1546 //not c or cpp file
1547 if (!e->isNew()) {
1548 FileType fileType = getFileType(e->filename());
1549 if (fileType != FileType::CSource
1550 && fileType != FileType::CppSource
1551 && fileType != FileType::CHeader
1552 && fileType != FileType::CppHeader
1553 )
1554 return;
1555 }
1556 if (mCompilerManager->backgroundSyntaxChecking())
1557 return;
1558 if (mCompilerManager->compiling())
1559 return;
1560 if (!pSettings->compilerSets().defaultSet())
1561 return;
1562 if (mCheckSyntaxInBack)
1563 return;
1564
1565 mCheckSyntaxInBack=true;
1566 clearIssues();
1567 CompileTarget target =getCompileTarget();
1568 if (target ==CompileTarget::Project) {
1569 mCompilerManager->checkSyntax(e->filename(), e->fileEncoding(), e->text(), mProject);
1570 } else {
1571 mCompilerManager->checkSyntax(e->filename(),e->fileEncoding(),e->text(), nullptr);
1572 }
1573}
1574
1575bool MainWindow::compile(bool rebuild)
1576{
1577 mCompilerManager->stopPausing();
1578 CompileTarget target =getCompileTarget();
1579 if (target == CompileTarget::Project) {
1580 if (mProject->modified())
1581 mProject->saveAll();
1582 clearIssues();
1583
1584 // Increment build number automagically
1585 if (mProject->options().versionInfo.autoIncBuildNr) {
1586 mProject->incrementBuildNumber();
1587 }
1588 mProject->buildPrivateResource();
1589 if (mCompileSuccessionTask) {
1590 mCompileSuccessionTask->execName = mProject->executable();
1591 }
1592 stretchMessagesPanel(true);
1593 ui->tabMessages->setCurrentWidget(ui->tabToolsOutput);
1594 mCompilerManager->compileProject(mProject,rebuild);
1595 updateCompileActions();
1596 updateAppTitle();
1597 } else {
1598 Editor * editor = mEditorList->getEditor();
1599 if (editor != NULL ) {
1600 clearIssues();
1601 if (editor->modified() || editor->isNew()) {
1602 if (!editor->save(false,false))
1603 return false;
1604 }
1605 if (mCompileSuccessionTask) {
1606 mCompileSuccessionTask->execName = getCompiledExecutableName(editor->filename());
1607 }
1608 stretchMessagesPanel(true);
1609 ui->tabMessages->setCurrentWidget(ui->tabToolsOutput);
1610 mCompilerManager->compile(editor->filename(),editor->fileEncoding(),rebuild);
1611 updateCompileActions();
1612 updateAppTitle();
1613 return true;
1614 }
1615 }
1616 return false;
1617}
1618
1619void MainWindow::runExecutable(
1620 const QString &exeName,
1621 const QString &filename,
1622 RunType runType,
1623 const QStringList& binDirs)
1624{
1625 mCompilerManager->stopPausing();
1626 // Check if it exists
1627 if (!fileExists(exeName)) {
1628 if (ui->actionCompile_Run->isEnabled()) {
1629 if (QMessageBox::question(this,tr("Confirm"),
1630 tr("Source file is not compiled.")
1631 +"<br /><br />"+tr("Compile now?"),
1632 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
1633 doCompileRun(runType);
1634 }
1635 return;
1636 } else {
1637 QMessageBox::critical(this,"Error",
1638 tr("Source file is not compiled."));
1639 return;
1640 }
1641 } else {
1642 if (!filename.isEmpty() && compareFileModifiedTime(filename,exeName)>=0) {
1643// if (ui->actionCompile_Run->isEnabled()) {
1644 if (QMessageBox::warning(this,tr("Confirm"),
1645 tr("Source file is more recent than executable.")
1646 +"<br /><br />"+tr("Recompile now?"),
1647 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
1648 doCompileRun(runType);
1649 return;
1650 }
1651// } else {
1652// QMessageBox::warning(this,"Error",
1653// tr("Source file is more recent than executable."));
1654// }
1655 }
1656 }
1657
1658 QString params;
1659 if (pSettings->executor().useParams()) {
1660 params = pSettings->executor().params();
1661 }
1662 if (runType==RunType::Normal) {
1663 if (pSettings->executor().minimizeOnRun()) {
1664 showMinimized();
1665 }
1666 mCompilerManager->run(exeName,params,QFileInfo(exeName).absolutePath(),binDirs);
1667 } else if (runType == RunType::ProblemCases) {
1668 POJProblem problem = mOJProblemModel.problem();
1669 if (problem) {
1670 mCompilerManager->runProblem(exeName,params,QFileInfo(exeName).absolutePath(),
1671 problem->cases);
1672 stretchMessagesPanel(true);
1673 ui->tabMessages->setCurrentWidget(ui->tabProblem);
1674 }
1675 } else if (runType == RunType::CurrentProblemCase) {
1676 QModelIndex index = ui->tblProblemCases->currentIndex();
1677 if (index.isValid()) {
1678 POJProblemCase problemCase =mOJProblemModel.getCase(index.row());
1679 mCompilerManager->runProblem(exeName,params,QFileInfo(exeName).absolutePath(),
1680 problemCase);
1681 stretchMessagesPanel(true);
1682 ui->tabMessages->setCurrentWidget(ui->tabProblem);
1683 }
1684 }
1685 updateCompileActions();
1686 updateAppTitle();
1687}
1688
1689void MainWindow::runExecutable(RunType runType)
1690{
1691 CompileTarget target =getCompileTarget();
1692 if (target == CompileTarget::Project) {
1693 QStringList binDirs = mProject->binDirs();
1694 if (mProject->modified() &&
1695 QMessageBox::question(
1696 this,
1697 tr("Rebuild Project"),
1698 tr("Project has been modified, do you want to rebuild it?")
1699 ) == QMessageBox::Yes) {
1700 mProject->saveAll();
1701 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1702 mCompileSuccessionTask->type = CompileSuccessionTaskType::RunNormal;
1703 mCompileSuccessionTask->execName=mProject->executable();
1704 mCompileSuccessionTask->binDirs=binDirs;
1705 compile();
1706 return;
1707 }
1708
1709 runExecutable(mProject->executable(),mProject->filename(),runType,
1710 binDirs);
1711 } else {
1712 Editor * editor = mEditorList->getEditor();
1713 if (editor != NULL ) {
1714 if (editor->modified() || editor->isNew()) {
1715 if (!editor->save(false,false))
1716 return;
1717 }
1718 QStringList binDirs = getDefaultCompilerSetBinDirs();
1719 QString exeName= getCompiledExecutableName(editor->filename());
1720 runExecutable(exeName,editor->filename(),runType,binDirs);
1721 }
1722 }
1723}
1724
1725void MainWindow::debug()
1726{
1727 if (mCompilerManager->compiling())
1728 return;
1729 mCompilerManager->stopPausing();
1730 Settings::PCompilerSet compilerSet = pSettings->compilerSets().defaultSet();
1731 if (!compilerSet) {
1732 QMessageBox::critical(pMainWindow,
1733 tr("No compiler set"),
1734 tr("No compiler set is configured.")+"<BR/>"+tr("Can't start debugging."));
1735 return;
1736 }
1737 bool debugEnabled;
1738 bool stripEnabled;
1739 QString filePath;
1740 QFileInfo debugFile;
1741 QStringList binDirs;
1742 switch(getCompileTarget()) {
1743 case CompileTarget::Project:
1744 binDirs = mProject->binDirs();
1745 // Check if we enabled proper options
1746 debugEnabled = mProject->getCompileOption(CC_CMD_OPT_DEBUG_INFO) == COMPILER_OPTION_ON;
1747 stripEnabled = mProject->getCompileOption(LINK_CMD_OPT_STRIP_EXE) == COMPILER_OPTION_ON;
1748 // Ask the user if he wants to enable debugging...
1749 if (((!debugEnabled) || stripEnabled) &&
1750 (QMessageBox::question(this,
1751 tr("Enable debugging"),
1752 tr("You have not enabled debugging info (-g3) and/or stripped it from the executable (-s) in Compiler Options.<BR /><BR />Do you want to correct this now?")
1753 ) == QMessageBox::Yes)) {
1754 // Enable debugging, disable stripping
1755 mProject->setCompileOption(CC_CMD_OPT_DEBUG_INFO,COMPILER_OPTION_ON);
1756 mProject->setCompileOption(LINK_CMD_OPT_STRIP_EXE,"");
1757
1758 // Save changes to compiler set
1759 mProject->saveOptions();
1760
1761 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1762 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1763 mCompileSuccessionTask->execName = mProject->executable();
1764 mCompileSuccessionTask->binDirs = binDirs;
1765
1766 compile();
1767 return;
1768 }
1769 // Did we compile?
1770 if (!fileExists(mProject->executable())) {
1771 if (QMessageBox::question(
1772 this,
1773 tr("Project not built"),
1774 tr("Project hasn't been built. Build it now?"),
1775 QMessageBox::Yes | QMessageBox::No,
1776 QMessageBox::Yes) == QMessageBox::Yes) {
1777 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1778 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1779 mCompileSuccessionTask->execName = mProject->executable();
1780 mCompileSuccessionTask->binDirs = binDirs;
1781 compile();
1782 }
1783 return;
1784 }
1785 if (mProject->modified() &&
1786 QMessageBox::question(
1787 this,
1788 tr("Rebuild Project"),
1789 tr("Project has been modified, do you want to rebuild it?")
1790 ) == QMessageBox::Yes) {
1791 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1792 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1793 mCompileSuccessionTask->execName = mProject->executable();
1794 mCompileSuccessionTask->binDirs = binDirs;
1795 compile();
1796 return;
1797 }
1798 // Did we choose a host application for our DLL?
1799 if (mProject->options().type == ProjectType::DynamicLib) {
1800 if (mProject->options().hostApplication.isEmpty()) {
1801 QMessageBox::critical(this,
1802 tr("Host applcation missing"),
1803 tr("DLL project needs a host application to run.")
1804 +"<br />"
1805 +tr("But it's missing."),
1806 QMessageBox::Ok);
1807 return;
1808 } else if (!fileExists(mProject->options().hostApplication)) {
1809 QMessageBox::critical(this,
1810 tr("Host application not exists"),
1811 tr("Host application file '%1' doesn't exist.")
1812 .arg(mProject->options().hostApplication),
1813 QMessageBox::Ok);
1814 return;
1815 }
1816 }
1817 // Reset UI, remove invalid breakpoints
1818 prepareDebugger();
1819 filePath = mProject->executable();
1820
1821// mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM);
1822
1823 if (!mDebugger->start(mProject->options().compilerSet, filePath, binDirs))
1824 return;
1825 filePath.replace('\\','/');
1826 mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"');
1827
1828 if (mProject->options().type == ProjectType::DynamicLib) {
1829 QString host =mProject->options().hostApplication;
1830 host.replace('\\','/');
1831 mDebugger->sendCommand("-file-exec-file", '"' + host + '"');
1832 }
1833
1834 includeOrSkipDirs(mProject->options().includeDirs,
1835 pSettings->debugger().skipProjectLibraries());
1836 includeOrSkipDirs(mProject->options().libDirs,
1837 pSettings->debugger().skipProjectLibraries());
1838 break;
1839 case CompileTarget::File: {
1840 if (pSettings->compilerSets().defaultSet()) {
1841 binDirs = pSettings->compilerSets().defaultSet()->binDirs();
1842 }
1843
1844 // Check if we enabled proper options
1845 debugEnabled = compilerSet->getCompileOptionValue(CC_CMD_OPT_DEBUG_INFO) == COMPILER_OPTION_ON;
1846 stripEnabled = compilerSet->getCompileOptionValue(LINK_CMD_OPT_STRIP_EXE) == COMPILER_OPTION_ON;
1847 // Ask the user if he wants to enable debugging...
1848 if (((!debugEnabled) || stripEnabled) &&
1849 (QMessageBox::question(this,
1850 tr("Enable debugging"),
1851 tr("You have not enabled debugging info (-g3) and/or stripped it from the executable (-s) in Compiler Options.<BR /><BR />Do you want to correct this now?")
1852 ) == QMessageBox::Yes)) {
1853 // Enable debugging, disable stripping
1854 compilerSet->setCompileOption(CC_CMD_OPT_DEBUG_INFO,COMPILER_OPTION_ON);
1855 compilerSet->unsetCompileOption(LINK_CMD_OPT_STRIP_EXE);
1856
1857 // Save changes to compiler set
1858 pSettings->compilerSets().saveSet(pSettings->compilerSets().defaultIndex());
1859
1860 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1861 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1862 mCompileSuccessionTask->binDirs = binDirs;
1863 compile();
1864 return;
1865 }
1866
1867 Editor* e = mEditorList->getEditor();
1868 if (e!=nullptr) {
1869 // Did we saved?
1870 if (e->modified() || e->isNew()) {
1871 // if file is modified,save it first
1872 if (!e->save(false,false))
1873 return;
1874 }
1875
1876 // Did we compiled?
1877 filePath = getCompiledExecutableName(e->filename());
1878 debugFile.setFile(filePath);
1879 if (!debugFile.exists()) {
1880 if (QMessageBox::question(this,tr("Compile"),
1881 tr("Source file is not compiled.")+"<BR /><BR />" + tr("Compile now?"),
1882 QMessageBox::Yes|QMessageBox::No,
1883 QMessageBox::Yes) == QMessageBox::Yes) {
1884 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1885 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1886 mCompileSuccessionTask->binDirs = binDirs;
1887 compile();
1888 return;
1889 }
1890 } else {
1891 if (compareFileModifiedTime(e->filename(),filePath)>=0) {
1892 if (QMessageBox::question(this,tr("Compile"),
1893 tr("Source file is more recent than executable.")+"<BR /><BR />" + tr("Recompile?"),
1894 QMessageBox::Yes|QMessageBox::No,
1895 QMessageBox::Yes) == QMessageBox::Yes) {
1896 mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
1897 mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
1898 mCompileSuccessionTask->binDirs = binDirs;
1899 compile();
1900 return;
1901 }
1902 }
1903 }
1904
1905 prepareDebugger();
1906 QString filePath = debugFile.filePath().replace('\\','/');
1907 if (!mDebugger->start(pSettings->compilerSets().defaultIndex(),filePath, binDirs))
1908 return;
1909 mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(filePath));
1910 }
1911 }
1912 break;
1913 default:
1914 //don't compile
1915 updateEditorActions();
1916 return;
1917 }
1918
1919 updateEditorActions();
1920
1921 // Add library folders
1922 includeOrSkipDirs(compilerSet->libDirs(), pSettings->debugger().skipCustomLibraries());
1923 includeOrSkipDirs(compilerSet->CIncludeDirs(), pSettings->debugger().skipCustomLibraries());
1924 includeOrSkipDirs(compilerSet->CppIncludeDirs(), pSettings->debugger().skipCustomLibraries());
1925
1926 //gcc system libraries is auto loaded by gdb
1927 if (pSettings->debugger().skipSystemLibraries()) {
1928 includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true);
1929 includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true);
1930 includeOrSkipDirs(compilerSet->defaultCppIncludeDirs(),true);
1931 }
1932
1933 mDebugger->sendAllBreakpointsToDebugger();
1934
1935 // Run the debugger
1936 mDebugger->sendCommand("-gdb-set", "mi-async on");
1937 mDebugger->sendCommand("-enable-pretty-printing","");
1938 mDebugger->sendCommand("-data-list-register-names","");
1939 mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying
1940 mDebugger->sendCommand("-gdb-set", "confirm off");
1941 mDebugger->sendCommand("-gdb-set", "print repeats 0"); // don't repeat elements
1942 mDebugger->sendCommand("-gdb-set", "print elements 0"); // don't limit elements
1943 mDebugger->sendCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(filePath))); // restore working directory
1944 if (pSettings->debugger().useGDBServer()) {
1945 mDebugger->sendCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort()));
1946 if (!debugInferiorhasBreakpoint()) {
1947 mDebugger->sendCommand("-break-insert","-t main");
1948 }
1949 mDebugger->sendCommand("-exec-continue","");
1950 } else {
1951#ifdef Q_OS_WIN
1952 mDebugger->sendCommand("-gdb-set", "new-console on");
1953#endif
1954 if (!debugInferiorhasBreakpoint()) {
1955 mDebugger->sendCommand("-exec-run", "--start");
1956 } else {
1957 mDebugger->sendCommand("-exec-run","");
1958 }
1959
1960 }
1961}
1962
1963void MainWindow::showSearchPanel(bool showReplace)
1964{
1965 stretchMessagesPanel(true);
1966 showSearchReplacePanel(showReplace);
1967 ui->tabMessages->setCurrentWidget(ui->tabSearch);
1968}
1969
1970void MainWindow::showCPUInfoDialog()
1971{
1972 if (mCPUDialog==nullptr) {
1973 mCPUDialog = new CPUDialog();
1974 connect(mCPUDialog, &CPUDialog::closed, this, &MainWindow::cleanUpCPUDialog);
1975 updateCompileActions();
1976 }
1977 mCPUDialog->show();
1978}
1979
1980static void setDockMovable(QDockWidget* dock, bool movable) {
1981 if (movable) {
1982 dock->setFeatures(dock->features() | QDockWidget::DockWidgetMovable);
1983 } else {
1984 dock->setFeatures(dock->features() & ~QDockWidget::DockWidgetMovable);
1985 }
1986}
1987
1988void MainWindow::stretchMessagesPanel(bool open)
1989{
1990 //ui->dockMessages->setVisible(open);
1991 ui->tabMessages->setShrinked(!open);
1992 if (open) {
1993 resizeDocks({ui->dockMessages},
1994 {ui->tabMessages->beforeShrinkWidthOrHeight()},
1995 ui->tabMessages->shrinkOrientation());
1996 }
1997 setDockMovable(ui->dockMessages,open);
1998}
1999
2000
2001void MainWindow::stretchExplorerPanel(bool open)
2002{
2003 ui->tabExplorer->setShrinked(!open);
2004 if (open) {
2005 resizeDocks({ui->dockExplorer},
2006 {ui->tabExplorer->beforeShrinkWidthOrHeight()},
2007 ui->tabExplorer->shrinkOrientation());
2008 }
2009 setDockMovable(ui->dockExplorer,open);
2010}
2011
2012void MainWindow::prepareDebugger()
2013{
2014 mDebugger->stop();
2015
2016 // Clear logs
2017 ui->debugConsole->clear();
2018 if (pSettings->debugger().enableDebugConsole()) {
2019 ui->debugConsole->addLine("(gdb) ");
2020 }
2021 ui->txtEvalOutput->clear();
2022
2023 // Restore when no watch vars are shown
2024 mDebugger->setLeftPageIndexBackup(ui->tabExplorer->currentIndex());
2025
2026 // Focus on the debugging buttons
2027 ui->tabExplorer->setCurrentWidget(ui->tabWatch);
2028 ui->tabMessages->setCurrentWidget(ui->tabDebug);
2029 ui->debugViews->setCurrentWidget(ui->tabLocals);
2030 stretchMessagesPanel(true);
2031 stretchExplorerPanel(true);
2032
2033 // Reset watch vars
2034 // mDebugger->deleteWatchVars(false);
2035}
2036
2037void MainWindow::doAutoSave(Editor *e)
2038{
2039
2040 if (!e || !e->canAutoSave())
2041 return;
2042 QString filename = e->filename();
2043 try {
2044 QFileInfo fileInfo(filename);
2045 QDir parent = fileInfo.absoluteDir();
2046 QString baseName = fileInfo.completeBaseName();
2047 QString suffix = fileInfo.suffix();
2048 switch(pSettings->editor().autoSaveStrategy()) {
2049 case assOverwrite:
2050 e->save();
2051 return;
2052 case assAppendUnixTimestamp:
2053 filename = parent.filePath(
2054 QString("%1.%2.%3")
2055 .arg(baseName)
2056 .arg(QDateTime::currentSecsSinceEpoch())
2057 .arg(suffix));
2058 break;
2059 case assAppendFormatedTimeStamp: {
2060 QDateTime time = QDateTime::currentDateTime();
2061 filename = parent.filePath(
2062 QString("%1.%2.%3")
2063 .arg(baseName)
2064 .arg(time.toString("yyyy.MM.dd.hh.mm.ss"))
2065 .arg(suffix));
2066 }
2067 }
2068 if (e->isNew()) {
2069 e->saveAs();
2070 } else {
2071 e->saveFile(filename);
2072 e->setCanAutoSave(false);
2073 }
2074 } catch (FileError& error) {
2075 QMessageBox::critical(e,
2076 tr("Auto Save Error"),
2077 tr("Auto save \"%1\" to \"%2\" failed:%3")
2078 .arg(e->filename(), filename, error.reason()));
2079 }
2080}
2081
2082//static void limitActionShortCutScope(QAction* action,QWidget* scopeWidget) {
2083// action->setParent(scopeWidget);
2084// action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
2085//}
2086
2087QAction* MainWindow::createActionFor(
2088 const QString& text,
2089 QWidget* parent,
2090 QKeySequence shortcut) {
2091 QAction* action= new QAction(text,parent);
2092 if (!shortcut.isEmpty())
2093 action->setShortcut(shortcut);
2094 action->setPriority(QAction::HighPriority);
2095 action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
2096 parent->addAction(action);
2097 return action;
2098}
2099
2100void MainWindow::scanActiveProject(bool parse)
2101{
2102 if (!mProject)
2103 return;
2104 mProject->cppParser()->setEnabled(pSettings->codeCompletion().enabled());
2105
2106 //UpdateClassBrowsing;
2107 if (parse) {
2108 resetCppParser(mProject->cppParser(),mProject->options().compilerSet);
2109 mProject->resetParserProjectFiles();
2110 parseFileList(mProject->cppParser());
2111 } else {
2112 mProject->resetParserProjectFiles();
2113 };
2114}
2115
2116void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip)
2117{
2118 Q_ASSERT(mDebugger);
2119 foreach (QString dir,dirs) {
2120 QString dirName = dir.replace('\\','/');
2121 if (skip) {
2122 mDebugger->sendCommand(
2123 "skip",
2124 QString("-gfi \"%1/%2\"")
2125 .arg(dirName,"*.*"));
2126 } else {
2127 mDebugger->sendCommand(
2128 "-environment-directory",
2129 QString("\"%1\"").arg(dirName));
2130 }
2131 }
2132}
2133
2134void MainWindow::onBookmarkContextMenu(const QPoint &pos)
2135{
2136 QMenu menu(this);
2137 menu.addAction(mBookmark_Remove);
2138 menu.addAction(mBookmark_RemoveAll);
2139 menu.addAction(mBookmark_Modify);
2140 menu.exec(ui->tableBookmark->mapToGlobal(pos));
2141}
2142
2143void MainWindow::saveLastOpens()
2144{
2145 QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_LASTOPENS_FILE;
2146 if (fileExists(filename)) {
2147 if (!QFile::remove(filename)) {
2148 QMessageBox::critical(this,
2149 tr("Save last open info error"),
2150 tr("Can't remove old last open information file '%1'")
2151 .arg(filename),
2152 QMessageBox::Ok);
2153 return;
2154 }
2155
2156 }
2157 SimpleIni lastOpenIni;
2158 lastOpenIni.SetLongValue("LastOpens","Count", mEditorList->pageCount());
2159 if (mProject) {
2160 lastOpenIni.SetValue("LastOpens","Project",mProject->filename().toLocal8Bit());
2161 }
2162 for (int i=0;i<mEditorList->pageCount();i++) {
2163 Editor * editor = (*mEditorList)[i];
2164 QByteArray sectionName = QString("Editor_%1").arg(i).toLocal8Bit();
2165 lastOpenIni.SetValue(sectionName,"FileName", editor->filename().toLocal8Bit());
2166 lastOpenIni.SetBoolValue(sectionName, "OnLeft",editor->pageControl() != mEditorList->rightPageWidget());
2167 lastOpenIni.SetBoolValue(sectionName, "Focused",editor->hasFocus());
2168 lastOpenIni.SetLongValue(sectionName, "CursorCol", editor->caretX());
2169 lastOpenIni.SetLongValue(sectionName, "CursorRow", editor->caretY());
2170 lastOpenIni.SetLongValue(sectionName, "TopLine", editor->topLine());
2171 lastOpenIni.SetLongValue(sectionName, "LeftChar", editor->leftChar());
2172 }
2173 if (lastOpenIni.SaveFile(filename.toLocal8Bit())!=SI_Error::SI_OK) {
2174 QMessageBox::critical(this,
2175 tr("Save last open info error"),
2176 tr("Can't save last open info file '%1'")
2177 .arg(filename),
2178 QMessageBox::Ok);
2179 return;
2180 }
2181}
2182
2183void MainWindow::loadLastOpens()
2184{
2185 QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_LASTOPENS_FILE;
2186 if (!fileExists(filename))
2187 return;
2188 SimpleIni lastOpenIni;
2189 if (lastOpenIni.LoadFile(filename.toLocal8Bit())!=SI_Error::SI_OK) {
2190 QMessageBox::critical(this,
2191 tr("Load last open info error"),
2192 tr("Can't load last open info file '%1'")
2193 .arg(filename),
2194 QMessageBox::Ok);
2195 return;
2196 }
2197 QString projectFilename = QString::fromLocal8Bit((lastOpenIni.GetValue("LastOpens", "Project","")));
2198 int count = lastOpenIni.GetLongValue("LastOpens","Count",0);
2199 if (fileExists(projectFilename)) {
2200 openProject(projectFilename, false);
2201 }
2202 Editor * focusedEditor = nullptr;
2203 for (int i=0;i<count;i++) {
2204 QByteArray sectionName = QString("Editor_%1").arg(i).toLocal8Bit();
2205 QString editorFilename = QString::fromLocal8Bit(lastOpenIni.GetValue(sectionName,"FileName",""));
2206 if (!fileExists(editorFilename))
2207 continue;
2208 editorFilename = QFileInfo(editorFilename).absoluteFilePath();
2209 bool onLeft = lastOpenIni.GetBoolValue(sectionName,"OnLeft",true);
2210 QTabWidget* page;
2211 if (onLeft)
2212 page = mEditorList->leftPageWidget();
2213 else
2214 page = mEditorList->rightPageWidget();
2215 PProjectUnit unit;
2216 if (mProject) {
2217 unit = mProject->findUnitByFilename(editorFilename);
2218 }
2219 bool inProject = (mProject && unit);
2220 QByteArray encoding = unit ? unit->encoding() :
2221 (pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding());
2222 Editor * editor = mEditorList->newEditor(editorFilename, encoding, inProject,false,page);
2223// if (mProject) {
2224// mProject->associateEditorToUnit(editor,unit);
2225// }
2226 if (!editor)
2227 continue;
2228 QSynedit::BufferCoord pos;
2229 pos.ch = lastOpenIni.GetLongValue(sectionName,"CursorCol", 1);
2230 pos.line = lastOpenIni.GetLongValue(sectionName,"CursorRow", 1);
2231 editor->setCaretXY(pos);
2232 editor->setTopLine(
2233 lastOpenIni.GetLongValue(sectionName,"TopLine", 1)
2234 );
2235 editor->setLeftChar(
2236 lastOpenIni.GetLongValue(sectionName,"LeftChar", 1)
2237 );
2238 if (lastOpenIni.GetBoolValue(sectionName,"Focused",false))
2239 focusedEditor = editor;
2240 pSettings->history().removeFile(editorFilename);
2241 }
2242 if (count>0) {
2243 updateEditorActions();
2244 //updateForEncodingInfo();
2245 }
2246 if (focusedEditor)
2247 focusedEditor->activate();
2248}
2249
2250void MainWindow::updateTools()
2251{
2252 ui->menuTools->clear();
2253 ui->menuTools->addAction(ui->actionOptions);
2254 if (!mToolsManager->tools().isEmpty()) {
2255 ui->menuTools->addSeparator();
2256 foreach (const PToolItem& item, mToolsManager->tools()) {
2257 QAction* action = new QAction(item->title,ui->menuTools);
2258 connect(action, &QAction::triggered,
2259 [item] (){
2260 QString program = parseMacros(item->program);
2261 QString workDir = parseMacros(item->workingDirectory);
2262 QString params = parseMacros(item->parameters);
2263 if (!program.endsWith(".bat",Qt::CaseInsensitive)) {
2264 QTemporaryFile file(QDir::tempPath()+QDir::separator()+"XXXXXX.bat");
2265 file.setAutoRemove(false);
2266 if (file.open()) {
2267 file.write(QString("cd /d \"%1\"")
2268 .arg(localizePath(workDir))
2269 .toLocal8Bit()+LINE_BREAKER);
2270 file.write((program+" "+params).toLocal8Bit()
2271 + LINE_BREAKER);
2272 file.close();
2273 if (item->pauseAfterExit) {
2274 executeFile(
2275 includeTrailingPathDelimiter(pSettings->dirs().appLibexecDir())+"ConsolePauser.exe",
2276 " 1 \""+localizePath(file.fileName())+"\" ",
2277 workDir, file.fileName());
2278 } else {
2279 executeFile(
2280 file.fileName(),
2281 "",
2282 workDir, file.fileName());
2283 }
2284 }
2285 } else {
2286 if (item->pauseAfterExit) {
2287 executeFile(
2288 includeTrailingPathDelimiter(pSettings->dirs().appLibexecDir())+"ConsolePauser.exe",
2289 " 1 \""+program+"\" "+params,
2290 workDir, "");
2291 } else {
2292 executeFile(
2293 program,
2294 params,
2295 workDir, "");
2296 }
2297 }
2298
2299 });
2300 ui->menuTools->addAction(action);
2301 }
2302 }
2303}
2304
2305void MainWindow::newEditor()
2306{
2307 try {
2308 Editor * editor=mEditorList->newEditor("",
2309 pSettings->editor().defaultEncoding(),
2310 false,true);
2311 editor->activate();
2312 //updateForEncodingInfo();
2313 } catch (FileError e) {
2314 QMessageBox::critical(this,tr("Error"),e.reason());
2315 }
2316
2317}
2318
2319void MainWindow::buildContextMenus()
2320{
2321 //context menu signal for the problem list view
2322 ui->lstProblemSet->setContextMenuPolicy(Qt::CustomContextMenu);
2323 connect(ui->lstProblemSet, &QWidget::customContextMenuRequested,
2324 this, &MainWindow::onLstProblemSetContextMenu);
2325 mProblem_Properties = createActionFor(
2326 tr("Properties..."),
2327 this
2328 );
2329 mProblem_Properties->setObjectName("actionProbelm_Properties");
2330 connect(mProblem_Properties, &QAction::triggered, this,
2331 &MainWindow::onProblemProperties);
2332
2333 mProblem_OpenSource=createActionFor(
2334 tr("Open Source File"),
2335 ui->lstProblemSet
2336 );
2337 connect(mProblem_OpenSource, &QAction::triggered, this,
2338 &MainWindow::onProblemOpenSource);
2339
2340 //context menu signal for the problem list view
2341 ui->tblProblemCases->setContextMenuPolicy(Qt::CustomContextMenu);
2342 connect(ui->tblProblemCases, &QWidget::customContextMenuRequested,
2343 this, &MainWindow::onTableProblemCasesContextMenu);
2344 mProblem_RunAllCases = createActionFor(
2345 tr("Run All Cases"),
2346 this
2347 );
2348 mProblem_RunAllCases->setObjectName("Problem_RunAllCases");
2349 connect(mProblem_RunAllCases, &QAction::triggered, this,
2350 &MainWindow::on_btnRunAllProblemCases_clicked);
2351
2352 mProblem_RunCurrentCase = createActionFor(
2353 tr("Run Current Case"),
2354 this
2355 );
2356 mProblem_RunCurrentCase->setObjectName("Problem_RunCurrentCases");
2357 connect(mProblem_RunCurrentCase, &QAction::triggered, this,
2358 &MainWindow::onProblemRunCurrentCase);
2359
2360 mProblem_batchSetCases = createActionFor(
2361 tr("Batch Set Cases"),
2362 this);
2363 mProblem_batchSetCases->setObjectName("Problem_BatchSetCases");
2364 connect(mProblem_batchSetCases, &QAction::triggered, this,
2365 &MainWindow::onProblemBatchSetCases);
2366
2367 //context menu signal for the Problem Set lable
2368 ui->lblProblemSet->setContextMenuPolicy(Qt::CustomContextMenu);
2369 connect(ui->lblProblemSet, &QWidget::customContextMenuRequested,
2370 this, &MainWindow::onLableProblemSetContextMenuRequested);
2371
2372 //context menu signal for the watch view
2373 ui->watchView->setContextMenuPolicy(Qt::CustomContextMenu);
2374 connect(ui->watchView,&QWidget::customContextMenuRequested,
2375 this, &MainWindow::onWatchViewContextMenu);
2376
2377 //context menu signal for the bookmark view
2378 ui->tableBookmark->setContextMenuPolicy(Qt::CustomContextMenu);
2379 connect(ui->tableBookmark,&QWidget::customContextMenuRequested,
2380 this, &MainWindow::onBookmarkContextMenu);
2381 mBookmark_Remove=createActionFor(
2382 tr("Remove"),
2383 ui->tableBookmark);
2384 connect(mBookmark_Remove, &QAction::triggered,
2385 this, &MainWindow::onBookmarkRemove);
2386
2387 mBookmark_RemoveAll=createActionFor(
2388 tr("Remove All Bookmarks"),
2389 ui->tableBookmark);
2390 connect(mBookmark_RemoveAll, &QAction::triggered,
2391 this, &MainWindow::onBookmarkRemoveAll);
2392 mBookmark_Modify=createActionFor(
2393 tr("Modify Description"),
2394 ui->tableBookmark);
2395 connect(mBookmark_Modify, &QAction::triggered,
2396 this, &MainWindow::onBookmarkModify);
2397
2398 //context menu signal for the watch view
2399 ui->debugConsole->setContextMenuPolicy(Qt::CustomContextMenu);
2400 connect(ui->debugConsole,&QWidget::customContextMenuRequested,
2401 this, &MainWindow::onDebugConsoleContextMenu);
2402 mDebugConsole_ShowDetailLog = createActionFor(
2403 tr("Show detail debug logs"),
2404 ui->debugConsole);
2405 mDebugConsole_ShowDetailLog->setCheckable(true);
2406 connect(mDebugConsole_ShowDetailLog, &QAction::toggled,
2407 this, &MainWindow::onDebugConsoleShowDetailLog);
2408 mDebugConsole_Copy=createActionFor(
2409 tr("Copy"),
2410 ui->debugConsole,
2411 QKeySequence("Ctrl+C"));
2412 connect(mDebugConsole_Copy, &QAction::triggered,
2413 this, &MainWindow::onDebugConsoleCopy);
2414 mDebugConsole_Paste=createActionFor(
2415 tr("Paste"),
2416 ui->debugConsole,
2417 QKeySequence("Ctrl+V"));
2418 connect(mDebugConsole_Paste, &QAction::triggered,
2419 this, &MainWindow::onDebugConsolePaste);
2420 mDebugConsole_SelectAll=createActionFor(
2421 tr("Select All"),
2422 ui->debugConsole);
2423 connect(mDebugConsole_SelectAll, &QAction::triggered,
2424 this, &MainWindow::onDebugConsoleSelectAll);
2425 mDebugConsole_Clear=createActionFor(
2426 tr("Clear"),
2427 ui->debugConsole);
2428 connect(mDebugConsole_Clear, &QAction::triggered,
2429 this, &MainWindow::onDebugConsoleClear);
2430
2431 //context menu signal for Editor's tabbar
2432 ui->EditorTabsLeft->tabBar()->setContextMenuPolicy(Qt::CustomContextMenu);
2433 connect(ui->EditorTabsLeft->tabBar(),
2434 &QWidget::customContextMenuRequested,
2435 this,
2436 &MainWindow::onEditorLeftTabContextMenu
2437 );
2438
2439 ui->EditorTabsRight->tabBar()->setContextMenuPolicy(Qt::CustomContextMenu);
2440 connect(ui->EditorTabsRight->tabBar(),
2441 &QWidget::customContextMenuRequested,
2442 this,
2443 &MainWindow::onEditorRightTabContextMenu
2444 );
2445
2446 //context menu signal for Compile Issue view
2447 ui->tableIssues->setContextMenuPolicy(Qt::CustomContextMenu);
2448 connect(ui->tableIssues,&QWidget::customContextMenuRequested,
2449 this, &MainWindow::onTableIssuesContextMenu);
2450 mTableIssuesCopyAction = createActionFor(
2451 tr("Copy"),
2452 ui->tableIssues,
2453 QKeySequence("Ctrl+C"));
2454 connect(mTableIssuesCopyAction,&QAction::triggered,
2455 this, &MainWindow::onTableIssuesCopy);
2456
2457 mTableIssuesCopyAllAction = createActionFor(
2458 tr("Copy all"),
2459 ui->tableIssues,
2460 QKeySequence("Ctrl+Shift+C"));
2461 connect(mTableIssuesCopyAllAction,&QAction::triggered,
2462 this, &MainWindow::onTableIssuesCopyAll);
2463
2464 mTableIssuesClearAction = createActionFor(
2465 tr("Clear"),
2466 ui->tableIssues);
2467 connect(mTableIssuesClearAction,&QAction::triggered,
2468 this, &MainWindow::onTableIssuesClear);
2469
2470 //context menu signal for search view
2471 ui->searchHistoryPanel->setContextMenuPolicy(Qt::CustomContextMenu);
2472 connect(ui->searchHistoryPanel, &QWidget::customContextMenuRequested,
2473 this, &MainWindow::onSearchViewContextMenu);
2474 mSearchViewClearAction = createActionFor(
2475 tr("Remove this search"),
2476 ui->searchHistoryPanel);
2477 connect(mSearchViewClearAction, &QAction::triggered,
2478 this, &MainWindow::onSearchViewClear);
2479 mSearchViewClearAllAction = createActionFor(
2480 tr("Clear all searches"),
2481 ui->searchHistoryPanel);
2482 connect(mSearchViewClearAllAction,&QAction::triggered,
2483 this, &MainWindow::onSearchViewClearAll);
2484
2485 //context menu signal for breakpoints view
2486 ui->tblBreakpoints->setContextMenuPolicy(Qt::CustomContextMenu);
2487 connect(ui->tblBreakpoints,&QWidget::customContextMenuRequested,
2488 this, &MainWindow::onBreakpointsViewContextMenu);
2489 mBreakpointViewPropertyAction = createActionFor(
2490 tr("Breakpoint condition..."),
2491 ui->tblBreakpoints);
2492 connect(mBreakpointViewPropertyAction,&QAction::triggered,
2493 this, &MainWindow::onBreakpointViewProperty);
2494
2495 mBreakpointViewRemoveAllAction = createActionFor(
2496 tr("Remove All Breakpoints"),
2497 ui->tblBreakpoints);
2498 connect(mBreakpointViewRemoveAllAction,&QAction::triggered,
2499 this, &MainWindow::onBreakpointViewRemoveAll);
2500 mBreakpointViewRemoveAction = createActionFor(
2501 tr("Remove Breakpoint"),
2502 ui->tblBreakpoints);
2503 connect(mBreakpointViewRemoveAction,&QAction::triggered,
2504 this, &MainWindow::onBreakpointRemove);
2505
2506 //context menu signal for project view
2507 ui->projectView->setContextMenuPolicy(Qt::CustomContextMenu);
2508 connect(ui->projectView,&QWidget::customContextMenuRequested,
2509 this, &MainWindow::onProjectViewContextMenu);
2510 mProject_Rename_Unit = createActionFor(
2511 tr("Rename File"),
2512 ui->projectView);
2513 connect(mProject_Rename_Unit, &QAction::triggered,
2514 this, &MainWindow::onProjectRenameUnit);
2515 mProject_Add_Folder = createActionFor(
2516 tr("Add Folder"),
2517 ui->projectView);
2518 connect(mProject_Add_Folder, &QAction::triggered,
2519 this, &MainWindow::onProjectAddFolder);
2520
2521 mProject_Rename_Folder = createActionFor(
2522 tr("Rename Folder"),
2523 ui->projectView);
2524 connect(mProject_Rename_Folder, &QAction::triggered,
2525 this, &MainWindow::onProjectRenameFolder);
2526
2527 mProject_Remove_Folder = createActionFor(
2528 tr("Remove Folder"),
2529 ui->projectView);
2530 connect(mProject_Remove_Folder, &QAction::triggered,
2531 this, &MainWindow::onProjectRemoveFolder);
2532 mProject_SwitchFileSystemViewMode = createActionFor(
2533 tr("Switch to normal view"),
2534 ui->projectView);
2535 connect(mProject_SwitchFileSystemViewMode, &QAction::triggered,
2536 this, &MainWindow::onProjectSwitchFileSystemViewMode);
2537
2538 mProject_SwitchCustomViewMode = createActionFor(
2539 tr("Switch to custom view"),
2540 ui->projectView);
2541 connect(mProject_SwitchCustomViewMode, &QAction::triggered,
2542 this, &MainWindow::onProjectSwitchCustomViewMode);
2543
2544 //context menu signal for class browser
2545 ui->tabStructure->setContextMenuPolicy(Qt::CustomContextMenu);
2546 connect(ui->tabStructure,&QWidget::customContextMenuRequested,
2547 this, &MainWindow::onClassBrowserContextMenu);
2548 mClassBrowser_Sort_By_Type = createActionFor(
2549 tr("Sort By Type"),
2550 ui->tabStructure);
2551 mClassBrowser_Sort_By_Type->setCheckable(true);
2552 mClassBrowser_Sort_By_Type->setIcon(QIcon(":/icons/images/newlook24/077-sort-type.png"));
2553 mClassBrowser_Sort_By_Name = createActionFor(
2554 tr("Sort alphabetically"),
2555 ui->tabStructure);
2556 mClassBrowser_Sort_By_Name->setCheckable(true);
2557 mClassBrowser_Sort_By_Name->setIcon(QIcon(":/icons/images/newlook24/076-sort-alpha.png"));
2558 mClassBrowser_Show_Inherited = createActionFor(
2559 tr("Show inherited members"),
2560 ui->tabStructure);
2561 mClassBrowser_Show_Inherited->setCheckable(true);
2562 mClassBrowser_Show_Inherited->setIcon(QIcon(":/icons/images/newlook24/075-show-inheritance.png"));
2563 mClassBrowser_goto_declaration = createActionFor(
2564 tr("Goto declaration"),
2565 ui->tabStructure);
2566 mClassBrowser_goto_definition = createActionFor(
2567 tr("Goto definition"),
2568 ui->tabStructure);
2569
2570 mClassBrowser_Sort_By_Name->setChecked(pSettings->ui().classBrowserSortAlpha());
2571 mClassBrowser_Sort_By_Type->setChecked(pSettings->ui().classBrowserSortType());
2572 mClassBrowser_Show_Inherited->setChecked(pSettings->ui().classBrowserShowInherited());
2573 connect(mClassBrowser_Sort_By_Name, &QAction::toggled,
2574 this, &MainWindow::onClassBrowserSortByName);
2575 connect(mClassBrowser_Sort_By_Type, &QAction::toggled,
2576 this, &MainWindow::onClassBrowserSortByType);
2577 connect(mClassBrowser_Show_Inherited, &QAction::toggled,
2578 this, &MainWindow::onClassBrowserShowInherited);
2579
2580 connect(mClassBrowser_goto_definition,&QAction::triggered,
2581 this, &MainWindow::onClassBrowserGotoDefinition);
2582
2583 connect(mClassBrowser_goto_declaration,&QAction::triggered,
2584 this, &MainWindow::onClassBrowserGotoDeclaration);
2585
2586 //toolbar for class browser
2587 mClassBrowserToolbar = new QWidget();
2588 {
2589 QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>( ui->tabStructure->layout());
2590 layout->insertWidget(0,mClassBrowserToolbar);
2591 QHBoxLayout* hlayout = new QHBoxLayout();
2592 hlayout->setContentsMargins(2,2,2,2);
2593 mClassBrowserToolbar->setLayout(hlayout);
2594 QToolButton * toolButton;
2595 int size = pointToPixel(pSettings->environment().interfaceFontSize());
2596 QSize iconSize(size,size);
2597 toolButton = new QToolButton;
2598 toolButton->setIconSize(iconSize);
2599 toolButton->setDefaultAction(mClassBrowser_Sort_By_Type);
2600 hlayout->addWidget(toolButton);
2601 toolButton = new QToolButton;
2602 toolButton->setIconSize(iconSize);
2603 toolButton->setDefaultAction(mClassBrowser_Sort_By_Name);
2604 hlayout->addWidget(toolButton);
2605 QFrame * vLine = new QFrame();
2606 vLine->setFrameShape(QFrame::VLine);
2607 vLine->setFrameShadow(QFrame::Sunken);
2608 hlayout->addWidget(vLine);
2609 toolButton = new QToolButton;
2610 toolButton->setIconSize(iconSize);
2611 toolButton->setDefaultAction(mClassBrowser_Show_Inherited);
2612 hlayout->addWidget(toolButton);
2613 hlayout->addStretch();
2614 }
2615
2616 //menu for statusbar
2617 mFileEncodingStatus->setContextMenuPolicy(Qt::CustomContextMenu);
2618 connect(mFileEncodingStatus,&QWidget::customContextMenuRequested,
2619 this, &MainWindow::onFileEncodingContextMenu);
2620
2621 //menu for files view
2622 ui->treeFiles->setContextMenuPolicy(Qt::CustomContextMenu);
2623 connect(ui->treeFiles,&QWidget::customContextMenuRequested,
2624 this, &MainWindow::onFilesViewContextMenu);
2625
2626 mFilesView_CreateFolder = createActionFor(
2627 tr("New Folder"),
2628 ui->treeFiles);
2629 connect(mFilesView_CreateFolder, &QAction::triggered,
2630 this, &MainWindow::onFilesViewCreateFolder);
2631
2632 mFilesView_CreateFile = createActionFor(
2633 tr("New File"),
2634 ui->treeFiles);
2635 connect(mFilesView_CreateFile, &QAction::triggered,
2636 this, &MainWindow::onFilesViewCreateFile);
2637
2638 mFilesView_Rename = createActionFor(
2639 tr("Rename"),
2640 ui->treeFiles);
2641 connect(mFilesView_Rename, &QAction::triggered,
2642 this, &MainWindow::onFilesViewRename);
2643
2644 mFilesView_RemoveFile = createActionFor(
2645 tr("Delete"),
2646 ui->treeFiles);
2647 mFilesView_RemoveFile->setShortcut(Qt::Key_Delete);
2648 connect(mFilesView_RemoveFile, &QAction::triggered,
2649 this, &MainWindow::onFilesViewRemoveFiles);
2650 mFilesView_Open = createActionFor(
2651 tr("Open in Editor"),
2652 ui->treeFiles);
2653 connect(mFilesView_Open, &QAction::triggered,
2654 this, &MainWindow::onFilesViewOpen);
2655
2656 mFilesView_OpenWithExternal = createActionFor(
2657 tr("Open in External Program"),
2658 ui->treeFiles);
2659 connect(mFilesView_OpenWithExternal, &QAction::triggered,
2660 this, &MainWindow::onFilesViewOpenWithExternal);
2661 mFilesView_OpenInTerminal = createActionFor(
2662 tr("Open in Terminal"),
2663 ui->treeFiles);
2664 mFilesView_OpenInTerminal->setIcon(ui->actionOpen_Terminal->icon());
2665 connect(mFilesView_OpenInTerminal, &QAction::triggered,
2666 this, &MainWindow::onFilesViewOpenInTerminal);
2667 mFilesView_OpenInExplorer = createActionFor(
2668 tr("Open in Windows Explorer"),
2669 ui->treeFiles);
2670 mFilesView_OpenInExplorer->setIcon(ui->actionOpen_Containing_Folder->icon());
2671 connect(mFilesView_OpenInExplorer, &QAction::triggered,
2672 this, &MainWindow::onFilesViewOpenInExplorer);
2673
2674 //toolbar for files view
2675 {
2676 QHBoxLayout* hlayout = dynamic_cast<QHBoxLayout*>(ui->panelFiles->layout());
2677 QToolButton * toolButton;
2678 int size = pointToPixel(pSettings->environment().interfaceFontSize());
2679 QSize iconSize(size,size);
2680 toolButton = new QToolButton;
2681 toolButton->setIconSize(iconSize);
2682 toolButton->setDefaultAction(ui->actionOpen_Folder);
2683 hlayout->addWidget(toolButton);
2684 toolButton = new QToolButton;
2685 toolButton->setIconSize(iconSize);
2686 toolButton->setDefaultAction(ui->actionLocate_in_Files_View);
2687 hlayout->addWidget(toolButton);
2688 QFrame * vLine = new QFrame();
2689 vLine->setFrameShape(QFrame::VLine);
2690 vLine->setFrameShadow(QFrame::Sunken);
2691 hlayout->addWidget(vLine);
2692 toolButton = new QToolButton;
2693 toolButton->setIconSize(iconSize);
2694 toolButton->setDefaultAction(ui->actionFilesView_Hide_Non_Support_Files);
2695 ui->actionFilesView_Hide_Non_Support_Files->setChecked(pSettings->environment().hideNonSupportFilesInFileView());
2696 hlayout->addWidget(toolButton);
2697 }
2698
2699 //context menu signal for class browser
2700 ui->txtToolsOutput->setContextMenuPolicy(Qt::CustomContextMenu);
2701 connect(ui->txtToolsOutput,&QWidget::customContextMenuRequested,
2702 this, &MainWindow::onToolsOutputContextMenu);
2703 mToolsOutput_Clear = createActionFor(
2704 tr("Clear"),
2705 ui->txtToolsOutput);
2706 connect(mToolsOutput_Clear, &QAction::triggered,
2707 this, &MainWindow::onToolsOutputClear);
2708 mToolsOutput_Copy = createActionFor(
2709 tr("Copy"),
2710 ui->txtToolsOutput);
2711 mToolsOutput_Copy->setShortcut(QKeySequence("Ctrl+C"));
2712 connect(mToolsOutput_Copy, &QAction::triggered,
2713 this, &MainWindow::onToolsOutputCopy);
2714 mToolsOutput_SelectAll = createActionFor(
2715 tr("Select All"),
2716 ui->txtToolsOutput);
2717 connect(mToolsOutput_SelectAll, &QAction::triggered,
2718 this, &MainWindow::onToolsOutputSelectAll);
2719}
2720
2721void MainWindow::buildEncodingMenu()
2722{
2723 QMenu* menuCharsets = new QMenu();
2724 menuCharsets->setTitle(tr("Character sets"));
2725 QStringList languages = pCharsetInfoManager->languageNames();
2726 foreach (const QString& langName, languages) {
2727 QMenu* menuLang = new QMenu();
2728 menuLang->setTitle(langName);
2729 menuCharsets->addMenu(menuLang);
2730 QList<PCharsetInfo> charInfos = pCharsetInfoManager->findCharsetsByLanguageName(langName);
2731 connect(menuLang,&QMenu::aboutToShow,
2732 [langName,menuLang,this]() {
2733 menuLang->clear();
2734 Editor* editor = mEditorList->getEditor();
2735 QList<PCharsetInfo> charInfos = pCharsetInfoManager->findCharsetsByLanguageName(langName);
2736 foreach (const PCharsetInfo& info, charInfos) {
2737 QAction * action = new QAction(info->name);
2738 action->setCheckable(true);
2739 if (editor)
2740 action->setChecked(info->name == editor->encodingOption());
2741 connect(action, &QAction::triggered,
2742 [info,this](){
2743 Editor * editor = mEditorList->getEditor();
2744 if (editor == nullptr)
2745 return;
2746 try {
2747 editor->setEncodingOption(info->name);
2748 } catch(FileError e) {
2749 QMessageBox::critical(this,tr("Error"),e.reason());
2750 }
2751 });
2752 menuLang->addAction(action);
2753 }
2754 });
2755 }
2756
2757 mMenuEncoding = new QMenu();
2758 mMenuEncoding->setTitle(tr("File Encoding"));
2759 mMenuEncoding->addAction(ui->actionAuto_Detect);
2760 mMenuEncoding->addAction(ui->actionEncode_in_ANSI);
2761 mMenuEncoding->addAction(ui->actionEncode_in_UTF_8);
2762 mMenuEncoding->addAction(ui->actionEncode_in_UTF_8_BOM);
2763
2764 mMenuEncoding->addMenu(menuCharsets);
2765 mMenuEncoding->addSeparator();
2766 mMenuEncoding->addAction(ui->actionConvert_to_ANSI);
2767 mMenuEncoding->addAction(ui->actionConvert_to_UTF_8);
2768 mMenuEncoding->addAction(ui->actionConvert_to_UTF_8_BOM);
2769
2770 QList<PCharsetInfo> charsetsForLocale = pCharsetInfoManager->findCharsetByLocale(pCharsetInfoManager->localeName());
2771
2772 foreach(const PCharsetInfo& charset, charsetsForLocale) {
2773 QAction * action = new QAction(
2774 tr("Convert to %1").arg(QString(charset->name)));
2775 connect(action, &QAction::triggered,
2776 [charset,this](){
2777 Editor * editor = mEditorList->getEditor();
2778 if (editor == nullptr)
2779 return;
2780 if (QMessageBox::warning(this,tr("Confirm Convertion"),
2781 tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
2782 .arg(QString(charset->name)),
2783 QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
2784 return;
2785 editor->convertToEncoding(charset->name);
2786 });
2787 mMenuEncoding->addAction(action);
2788 }
2789
2790 ui->menuEdit->insertMenu(ui->actionFoldAll,mMenuEncoding);
2791 ui->menuEdit->insertSeparator(ui->actionFoldAll);
2792 ui->actionAuto_Detect->setCheckable(true);
2793 ui->actionEncode_in_ANSI->setCheckable(true);
2794 ui->actionEncode_in_UTF_8->setCheckable(true);
2795 ui->actionEncode_in_UTF_8_BOM->setCheckable(true);
2796}
2797
2798void MainWindow::maximizeEditor()
2799{
2800 if (ui->tabExplorer->isShrinked() && ui->tabExplorer->isShrinked()) {
2801 stretchMessagesPanel(true);
2802 stretchExplorerPanel(true);
2803 } else {
2804 stretchMessagesPanel(false);
2805 stretchExplorerPanel(false);
2806 }
2807}
2808
2809QStringList MainWindow::getBinDirsForCurrentEditor()
2810{
2811 Editor * e=mEditorList->getEditor();
2812 if (e) {
2813 if (e->inProject() && mProject) {
2814 return mProject->binDirs();
2815 } else {
2816 return getDefaultCompilerSetBinDirs();
2817 }
2818 } else if (mProject) {
2819 return mProject->binDirs();
2820 }
2821 return QStringList();
2822}
2823
2824QStringList MainWindow::getDefaultCompilerSetBinDirs()
2825{
2826 if (pSettings->compilerSets().defaultSet())
2827 return pSettings->compilerSets().defaultSet()->binDirs();
2828 return QStringList();
2829}
2830
2831void MainWindow::openShell(const QString &folder, const QString &shellCommand, const QStringList& binDirs)
2832{
2833 QProcess process;
2834 process.setWorkingDirectory(folder);
2835 process.setProgram(shellCommand);
2836#ifdef Q_OS_WIN
2837 process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments * args){
2838 args->flags |= CREATE_NEW_CONSOLE;
2839 args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; //
2840 });
2841#endif
2842 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2843 QString path = env.value("PATH");
2844 QStringList pathAdded;
2845 pathAdded.append(binDirs);
2846 pathAdded.append(pSettings->dirs().appDir());
2847 if (!path.isEmpty()) {
2848 path= pathAdded.join(PATH_SEPARATOR) + PATH_SEPARATOR + path;
2849 } else {
2850 path = pathAdded.join(PATH_SEPARATOR);
2851 }
2852 env.insert("PATH",path);
2853 process.setProcessEnvironment(env);
2854 process.startDetached();
2855}
2856
2857void MainWindow::onAutoSaveTimeout()
2858{
2859 if (mQuitting)
2860 return;
2861 if (!pSettings->editor().enableAutoSave())
2862 return;
2863 int updateCount = 0;
2864 switch (pSettings->editor().autoSaveTarget()) {
2865 case astCurrentFile: {
2866 Editor *e = mEditorList->getEditor();
2867 doAutoSave(e);
2868 updateCount++;
2869 }
2870 break;
2871 case astAllOpennedFiles:
2872 for (int i=0;i<mEditorList->pageCount();i++) {
2873 Editor *e = (*mEditorList)[i];
2874 doAutoSave(e);
2875 updateCount++;
2876 }
2877 break;
2878 case astAllProjectFiles:
2879 if (!mProject)
2880 return;
2881 for (int i=0;i<mEditorList->pageCount();i++) {
2882 Editor *e = (*mEditorList)[i];
2883 if (!e->inProject())
2884 return;
2885 doAutoSave(e);
2886 updateCount++;
2887 }
2888 //todo: auto save project files
2889 break;
2890 }
2891 updateStatusbarMessage(tr("%1 files autosaved").arg(updateCount));
2892}
2893
2894void MainWindow::onWatchViewContextMenu(const QPoint &pos)
2895{
2896 QMenu menu(this);
2897 menu.addAction(ui->actionAdd_Watch);
2898 menu.addAction(ui->actionRemove_Watch);
2899 menu.addAction(ui->actionRemove_All_Watches);
2900 menu.addAction(ui->actionModify_Watch);
2901 menu.exec(ui->watchView->mapToGlobal(pos));
2902}
2903
2904void MainWindow::onTableIssuesContextMenu(const QPoint &pos)
2905{
2906 QMenu menu(this);
2907 menu.addAction(mTableIssuesCopyAction);
2908 menu.addAction(mTableIssuesCopyAllAction);
2909 menu.addSeparator();
2910 menu.addAction(mTableIssuesClearAction);
2911 menu.exec(ui->tableIssues->mapToGlobal(pos));
2912}
2913
2914void MainWindow::onSearchViewContextMenu(const QPoint &pos)
2915{
2916 QMenu menu(this);
2917 menu.addAction(mSearchViewClearAction);
2918 menu.addAction(mSearchViewClearAllAction);
2919 menu.exec(ui->searchHistoryPanel->mapToGlobal(pos));
2920}
2921
2922void MainWindow::onBreakpointsViewContextMenu(const QPoint &pos)
2923{
2924 QMenu menu(this);
2925 menu.addAction(mBreakpointViewPropertyAction);
2926 menu.addAction(mBreakpointViewRemoveAllAction);
2927 menu.addAction(mBreakpointViewRemoveAction);
2928 mBreakpointViewPropertyAction->setEnabled(ui->tblBreakpoints->currentIndex().isValid());
2929 mBreakpointViewRemoveAction->setEnabled(ui->tblBreakpoints->currentIndex().isValid());
2930 menu.exec(ui->tblBreakpoints->mapToGlobal(pos));
2931}
2932
2933void MainWindow::onProjectViewContextMenu(const QPoint &pos)
2934{
2935 if (!mProject)
2936 return;
2937 bool onFolder = false;
2938 bool onUnit = false;
2939 bool onRoot = false;
2940 bool folderEmpty = false;
2941 bool multiSelection = ui->projectView->selectionModel()->selectedRows().count()>1;
2942 int unitIndex = -1;
2943 QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->selectionModel()->currentIndex());
2944 if (current.isValid() && mProject) {
2945 ProjectModelNode * node = static_cast<ProjectModelNode*>(current.internalPointer());
2946 PProjectModelNode pNode = mProject->pointerToNode(node);
2947 if (pNode) {
2948 unitIndex = pNode->unitIndex;
2949 onFolder = (unitIndex<0);
2950 onUnit = (unitIndex >= 0);
2951 onRoot = false;
2952 if (onFolder && !onRoot) {
2953 folderEmpty = pNode->children.isEmpty();
2954 }
2955 } else {
2956 onFolder = true;
2957 onRoot = true;
2958 }
2959 }
2960 GitManager vcsManager;
2961 QString branch;
2962 bool hasRepository = vcsManager.hasRepository(mProject->folder(),branch);
2963
2964 QMenu menu(this);
2965 QMenu vcsMenu(this);
2966 updateProjectActions();
2967 menu.addAction(ui->actionProject_New_File);
2968 menu.addAction(ui->actionNew_Class);
2969 menu.addAction(ui->actionNew_Header);
2970 menu.addAction(ui->actionAdd_to_project);
2971 if (!onFolder) {
2972 menu.addAction(ui->actionRemove_from_project);
2973 }
2974 if (onUnit && !multiSelection) {
2975 menu.addAction(mProject_Rename_Unit);
2976 }
2977 menu.addSeparator();
2978 if (pSettings->vcs().gitOk()) {
2979 if (hasRepository) {
2980 menu.addMenu(&vcsMenu);
2981 } else {
2982 ui->actionGit_Create_Repository->setEnabled(true);
2983 menu.addAction(ui->actionGit_Create_Repository);
2984 }
2985 menu.addSeparator();
2986 }
2987 if (onFolder && mProject->modelType()==ProjectModelType::Custom) {
2988 menu.addAction(mProject_Add_Folder);
2989 if (!onRoot) {
2990 menu.addAction(mProject_Rename_Folder);
2991 if (folderEmpty) {
2992 menu.addAction(mProject_Remove_Folder);
2993 }
2994 }
2995 menu.addSeparator();
2996 }
2997 menu.addAction(ui->actionProject_Open_Folder_In_Explorer);
2998 menu.addAction(ui->actionProject_Open_In_Terminal);
2999 menu.addSeparator();
3000 if (mProject->modelType() == ProjectModelType::Custom) {
3001 menu.addAction(mProject_SwitchFileSystemViewMode);
3002 } else {
3003 menu.addAction(mProject_SwitchCustomViewMode);
3004 }
3005 menu.addAction(ui->actionProject_options);
3006 menu.addSeparator();
3007 menu.addAction(ui->actionClose_Project);
3008
3009 if (pSettings->vcs().gitOk() && hasRepository) {
3010 mProject->model()->iconProvider()->update();
3011 vcsMenu.setTitle(tr("Version Control"));
3012 if (ui->projectView->selectionModel()->hasSelection()) {
3013 bool shouldAdd = true;
3014 foreach (const QModelIndex& index, ui->projectView->selectionModel()->selectedRows()) {
3015 if (!index.isValid()) {
3016 shouldAdd=false;
3017 break;
3018 }
3019 QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
3020 ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
3021 if (!node || node->unitIndex<0) {
3022 shouldAdd=false;
3023 break;
3024 }
3025 PProjectUnit pUnit=mProject->units()[node->unitIndex];
3026 if (mProject->model()->iconProvider()->VCSRepository()->isFileInRepository(
3027 pUnit->fileName()
3028 )
3029 &&
3030 !mProject->model()->iconProvider()->VCSRepository()->isFileConflicting(
3031 pUnit->fileName()
3032 )) {
3033 shouldAdd=false;
3034 break;
3035 }
3036 }
3037 if (shouldAdd)
3038 vcsMenu.addAction(ui->actionGit_Add_Files);
3039 }
3040 vcsMenu.addAction(ui->actionGit_Remotes);
3041 vcsMenu.addAction(ui->actionGit_Log);
3042 vcsMenu.addAction(ui->actionGit_Branch);
3043 vcsMenu.addAction(ui->actionGit_Merge);
3044 vcsMenu.addAction(ui->actionGit_Commit);
3045 vcsMenu.addAction(ui->actionGit_Restore);
3046
3047 bool canBranch = !mProject->model()->iconProvider()->VCSRepository()->hasChangedFiles()
3048 && !mProject->model()->iconProvider()->VCSRepository()->hasStagedFiles();
3049 ui->actionGit_Branch->setEnabled(canBranch);
3050 ui->actionGit_Merge->setEnabled(canBranch);
3051 ui->actionGit_Commit->setEnabled(true);
3052 ui->actionGit_Remotes->setEnabled(true);
3053 ui->actionGit_Log->setEnabled(true);
3054 ui->actionGit_Restore->setEnabled(true);
3055
3056// vcsMenu.addAction(ui->actionGit_Reset);
3057// vcsMenu.addAction(ui->actionGit_Revert);
3058// ui->actionGit_Reset->setEnabled(true);
3059// ui->actionGit_Revert->setEnabled(true);
3060 }
3061 menu.exec(ui->projectView->mapToGlobal(pos));
3062}
3063
3064void MainWindow::onClassBrowserContextMenu(const QPoint &pos)
3065{
3066 QMenu menu(this);
3067 bool canGoto = false;
3068 QModelIndex index = ui->classBrowser->currentIndex();
3069 if (index.isValid()) {
3070 ClassBrowserNode * node = static_cast<ClassBrowserNode*>(index.internalPointer());
3071 if (node) {
3072 PStatement statement = node->statement;
3073 if (statement) {
3074 canGoto = true;
3075 }
3076 }
3077 }
3078 mClassBrowser_goto_declaration->setEnabled(canGoto);
3079 mClassBrowser_goto_definition->setEnabled(canGoto);
3080 menu.addAction(mClassBrowser_goto_declaration);
3081 menu.addAction(mClassBrowser_goto_definition);
3082 menu.addSeparator();
3083 menu.addAction(mClassBrowser_Sort_By_Name);
3084 menu.addAction(mClassBrowser_Sort_By_Type);
3085 menu.addAction(mClassBrowser_Show_Inherited);
3086
3087 menu.exec(ui->projectView->mapToGlobal(pos));
3088}
3089
3090void MainWindow::onDebugConsoleContextMenu(const QPoint &pos)
3091{
3092 QMenu menu(this);
3093
3094 bool oldBlock = mDebugConsole_ShowDetailLog->blockSignals(true);
3095 mDebugConsole_ShowDetailLog->setChecked(pSettings->debugger().showDetailLog());
3096 mDebugConsole_ShowDetailLog->blockSignals(oldBlock);
3097
3098 menu.addAction(mDebugConsole_Copy);
3099 menu.addAction(mDebugConsole_Paste);
3100 menu.addAction(mDebugConsole_SelectAll);
3101 menu.addAction(mDebugConsole_Clear);
3102 menu.addSeparator();
3103 menu.addAction(mDebugConsole_ShowDetailLog);
3104 menu.exec(ui->debugConsole->mapToGlobal(pos));
3105}
3106
3107void MainWindow::onFileEncodingContextMenu(const QPoint &pos)
3108{
3109 mMenuEncoding->exec(mFileEncodingStatus->mapToGlobal(pos));
3110}
3111
3112void MainWindow::onFilesViewContextMenu(const QPoint &pos)
3113{
3114 GitManager vcsManager;
3115 QString branch;
3116 bool hasRepository = vcsManager.hasRepository(pSettings->environment().currentFolder(),branch);
3117 QMenu menu(this);
3118 QMenu vcsMenu(this);
3119 menu.addAction(ui->actionOpen_Folder);
3120 menu.addSeparator();
3121 menu.addAction(mFilesView_CreateFolder);
3122 menu.addAction(mFilesView_CreateFile);
3123 menu.addAction(mFilesView_RemoveFile);
3124 menu.addAction(mFilesView_Rename);
3125 menu.addSeparator();
3126 if (pSettings->vcs().gitOk()) {
3127 if (hasRepository) {
3128 menu.addMenu(&vcsMenu);
3129 } else {
3130 ui->actionGit_Create_Repository->setEnabled(true);
3131 menu.addAction(ui->actionGit_Create_Repository);
3132 }
3133 menu.addSeparator();
3134 }
3135 menu.addAction(mFilesView_Open);
3136 menu.addAction(mFilesView_OpenWithExternal);
3137 menu.addSeparator();
3138 menu.addAction(mFilesView_OpenInTerminal);
3139 menu.addAction(mFilesView_OpenInExplorer);
3140 menu.addSeparator();
3141 menu.addAction(ui->actionFilesView_Hide_Non_Support_Files);
3142 QString path = mFileSystemModel.filePath(ui->treeFiles->currentIndex());
3143 QFileInfo info(path);
3144 mFilesView_Open->setEnabled(info.isFile());
3145 mFilesView_OpenWithExternal->setEnabled(info.isFile());
3146 mFilesView_OpenInTerminal->setEnabled(!path.isEmpty());
3147 mFilesView_OpenInExplorer->setEnabled(!path.isEmpty());
3148 mFilesView_Rename->setEnabled(!path.isEmpty());
3149 mFilesView_RemoveFile->setEnabled(!path.isEmpty() || !ui->treeFiles->selectionModel()->selectedRows().isEmpty());
3150
3151 if (pSettings->vcs().gitOk() && hasRepository) {
3152 mFileSystemModelIconProvider.update();
3153 vcsMenu.setTitle(tr("Version Control"));
3154 if (ui->treeFiles->selectionModel()->hasSelection()) {
3155 bool shouldAdd = true;
3156 foreach (const QModelIndex& index, ui->treeFiles->selectionModel()->selectedRows()) {
3157 if (mFileSystemModelIconProvider.VCSRepository()->isFileInRepository(
3158 mFileSystemModel.fileInfo(index)
3159 ) &&
3160 ! mFileSystemModelIconProvider.VCSRepository()->isFileConflicting(
3161 mFileSystemModel.fileInfo(index)
3162 )
3163 ) {
3164 shouldAdd=false;
3165 break;
3166 }
3167 }
3168 if (shouldAdd)
3169 vcsMenu.addAction(ui->actionGit_Add_Files);
3170 }
3171 vcsMenu.addAction(ui->actionGit_Remotes);
3172 vcsMenu.addAction(ui->actionGit_Log);
3173 vcsMenu.addAction(ui->actionGit_Branch);
3174 vcsMenu.addAction(ui->actionGit_Merge);
3175 vcsMenu.addAction(ui->actionGit_Commit);
3176 vcsMenu.addAction(ui->actionGit_Restore);
3177
3178 bool canBranch = !mFileSystemModelIconProvider.VCSRepository()->hasChangedFiles()
3179 && !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles();
3180 ui->actionGit_Branch->setEnabled(canBranch);
3181 ui->actionGit_Merge->setEnabled(canBranch);
3182 ui->actionGit_Log->setEnabled(true);
3183 ui->actionGit_Remotes->setEnabled(true);
3184 ui->actionGit_Commit->setEnabled(true);
3185 ui->actionGit_Restore->setEnabled(true);
3186
3187// vcsMenu.addAction(ui->actionGit_Reset);
3188// vcsMenu.addAction(ui->actionGit_Revert);
3189// ui->actionGit_Reset->setEnabled(true);
3190// ui->actionGit_Revert->setEnabled(true);
3191 }
3192 menu.exec(ui->treeFiles->mapToGlobal(pos));
3193}
3194
3195void MainWindow::onLstProblemSetContextMenu(const QPoint &pos)
3196{
3197 QMenu menu(this);
3198 QModelIndex idx = ui->lstProblemSet->currentIndex();
3199 mProblem_Properties->setEnabled(idx.isValid());
3200 if (idx.isValid()) {
3201 POJProblem problem = mOJProblemSetModel.problem(idx.row());
3202 QMenu * menuSetAnswer = new QMenu(&menu);
3203 QActionGroup *actionGroup = new QActionGroup(menuSetAnswer);
3204 bool answerFound=false;
3205 menuSetAnswer->setTitle(tr("Set answer to..."));
3206 for (int i=0;i<mEditorList->pageCount();i++) {
3207 Editor *e = (*mEditorList)[i];
3208 QString filename = e->filename();
3209 QAction* action = new QAction(filename,menuSetAnswer);
3210 action->setCheckable(true);
3211 action->setActionGroup(actionGroup);
3212
3213 if (filename.compare(problem->answerProgram, PATH_SENSITIVITY)==0) {
3214 action->setChecked(true);
3215 answerFound = true;
3216 }
3217 menuSetAnswer->addAction(action);
3218 }
3219 if (!answerFound && !problem->answerProgram.isEmpty()) {
3220 QAction* action = new QAction(problem->answerProgram,menuSetAnswer);
3221 action->setCheckable(true);
3222 action->setChecked(true);
3223 action->setActionGroup(actionGroup);
3224 menuSetAnswer->addAction(action);
3225 }
3226 connect(actionGroup, &QActionGroup::triggered,
3227 [problem,this](QAction* action) {
3228 if (action->text().compare(problem->answerProgram, PATH_SENSITIVITY)
3229 !=0)
3230 problem->answerProgram = action->text();
3231 else
3232 problem->answerProgram = "";
3233 if (problem == mOJProblemModel.problem()) {
3234 ui->btnOpenProblemAnswer->setEnabled(!problem->answerProgram.isEmpty());
3235 }
3236 });
3237 QAction * action = new QAction(tr("select other file..."),menuSetAnswer);
3238 connect(action, &QAction::triggered,
3239 [problem,this](){
3240 QString filename = QFileDialog::getOpenFileName(
3241 this,
3242 tr("Select Answer Source File"),
3243 QString(),
3244 tr("C/C++ Source Files (*.c *.cpp *.cc *.cxx)"),
3245 nullptr);
3246 if (!filename.isEmpty()) {
3247 QDir::setCurrent(extractFileDir(filename));
3248 problem->answerProgram = filename;
3249 if (problem == mOJProblemModel.problem()) {
3250 ui->btnOpenProblemAnswer->setEnabled(!problem->answerProgram.isEmpty());
3251 }
3252 }
3253 });
3254 menuSetAnswer->addAction(action);
3255 menu.addMenu(menuSetAnswer);
3256 mProblem_OpenSource->setEnabled(!problem->answerProgram.isEmpty());
3257 }
3258 menu.addAction(mProblem_OpenSource);
3259 menu.addAction(mProblem_Properties);
3260 menu.exec(ui->lstProblemSet->mapToGlobal(pos));
3261}
3262
3263void MainWindow::onTableProblemCasesContextMenu(const QPoint &pos)
3264{
3265 QMenu menu(this);
3266 menu.addAction(mProblem_batchSetCases);
3267 menu.addSeparator();
3268 QModelIndex idx = ui->tblProblemCases->currentIndex();
3269 menu.addAction(mProblem_RunAllCases);
3270 menu.addAction(mProblem_RunCurrentCase);
3271 mProblem_RunAllCases->setEnabled(mOJProblemModel.count()>0);
3272 mProblem_RunCurrentCase->setEnabled(idx.isValid());
3273 menu.exec(ui->tblProblemCases->mapToGlobal(pos));
3274}
3275
3276void MainWindow::onToolsOutputContextMenu(const QPoint &pos)
3277{
3278 QMenu menu(this);
3279 menu.addAction(mToolsOutput_Copy);
3280 menu.addAction(mToolsOutput_SelectAll);
3281 menu.addSeparator();
3282 menu.addAction(mToolsOutput_Clear);
3283 menu.exec(ui->txtToolsOutput->mapToGlobal(pos));
3284}
3285
3286void MainWindow::onProblemSetIndexChanged(const QModelIndex &current, const QModelIndex &/* previous */)
3287{
3288 QModelIndex idx = current;
3289 if (!idx.isValid()) {
3290 ui->btnRemoveProblem->setEnabled(false);
3291 mOJProblemModel.setProblem(nullptr);
3292 ui->txtProblemCaseExpected->clear();
3293 ui->txtProblemCaseInput->clear();
3294 ui->txtProblemCaseOutput->clear();
3295 ui->tabProblem->setEnabled(false);
3296 ui->lblProblem->clear();
3297 ui->lblProblem->setToolTip("");
3298 ui->tabProblem->setEnabled(false);
3299 } else {
3300 ui->btnRemoveProblem->setEnabled(true);
3301 POJProblem problem = mOJProblemSetModel.problem(idx.row());
3302 if (problem && !problem->answerProgram.isEmpty()) {
3303 Editor * editor =editorList()->getEditorByFilename(problem->answerProgram);
3304 if (editor)
3305 editor->activate();
3306 }
3307 mOJProblemModel.setProblem(problem);
3308 updateProblemTitle();
3309 if (mOJProblemModel.count()>0) {
3310 ui->tblProblemCases->setCurrentIndex(mOJProblemModel.index(0,0));
3311 } else {
3312 onProblemCaseIndexChanged(QModelIndex(),QModelIndex());
3313 }
3314 stretchMessagesPanel(true);
3315 ui->tabMessages->setCurrentWidget(ui->tabProblem);
3316 ui->tabProblem->setEnabled(true);
3317 ui->btnOpenProblemAnswer->setEnabled(!problem->answerProgram.isEmpty());
3318 }
3319}
3320
3321void MainWindow::onProblemCaseIndexChanged(const QModelIndex &current, const QModelIndex &previous)
3322{
3323 QModelIndex idx = current;
3324 if (previous.isValid()) {
3325 POJProblemCase problemCase = mOJProblemModel.getCase(previous.row());
3326 problemCase->input = ui->txtProblemCaseInput->toPlainText();
3327 problemCase->expected = ui->txtProblemCaseExpected->toPlainText();
3328 }
3329 if (idx.isValid()) {
3330 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
3331 if (problemCase) {
3332 ui->btnProblemCaseInputFileName->setEnabled(false);
3333 ui->btnRemoveProblemCase->setEnabled(true);
3334 ui->btnProblemCaseInputFileName->setEnabled(true);
3335 fillProblemCaseInputAndExpected(problemCase);
3336 ui->txtProblemCaseOutput->clear();
3337 ui->txtProblemCaseOutput->setPlainText(problemCase->output);
3338 updateProblemCaseOutput(problemCase);
3339
3340 return;
3341 }
3342 }
3343 ui->btnProblemCaseClearInputFileName->setVisible(false);
3344 ui->btnProblemCaseInputFileName->setEnabled(false);
3345 ui->txtProblemCaseInputFileName->clear();
3346 ui->txtProblemCaseInputFileName->setToolTip("");
3347
3348 ui->btnProblemCaseClearExpectedOutputFileName->setVisible(false);
3349 ui->btnProblemCaseExpectedOutputFileName->setEnabled(false);
3350 ui->txtProblemCaseExpectedOutputFileName->clear();
3351 ui->txtProblemCaseExpectedOutputFileName->setToolTip("");
3352
3353 ui->btnRemoveProblemCase->setEnabled(false);
3354 ui->txtProblemCaseInputFileName->clear();
3355 ui->btnProblemCaseInputFileName->setEnabled(false);
3356 ui->txtProblemCaseInput->clear();
3357 ui->txtProblemCaseInput->setReadOnly(true);
3358 ui->txtProblemCaseExpected->clear();
3359 ui->txtProblemCaseExpected->setReadOnly(true);
3360 ui->txtProblemCaseOutput->clear();
3361
3362 ui->lblProblemCaseExpected->clear();
3363 ui->lblProblemCaseOutput->clear();
3364 ui->lblProblemCaseInput->clear();
3365}
3366
3367void MainWindow::onProblemNameChanged(int index)
3368{
3369 QModelIndex idx = ui->lstProblemSet->currentIndex();
3370 if (idx.isValid() && index == idx.row()) {
3371 updateProblemTitle();
3372 }
3373}
3374
3375void MainWindow::onProblemRunCurrentCase()
3376{
3377 if (!ui->tblProblemCases->currentIndex().isValid())
3378 return;
3379 showHideMessagesTab(ui->tabProblem,ui->actionProblem);
3380 applyCurrentProblemCaseChanges();
3381 runExecutable(RunType::CurrentProblemCase);
3382}
3383
3384void MainWindow::onProblemBatchSetCases()
3385{
3386 showHideMessagesTab(ui->tabProblem,ui->actionProblem);
3387 if (mOJProblemModel.count()>0 && QMessageBox::question(this,tr("Batch Set Cases"),
3388 tr("This operation will remove all cases for the current problem.")
3389 +"<br />"
3390 +tr("Do you really want to do that?"),
3391 QMessageBox::Yes| QMessageBox::No,
3392 QMessageBox::No)!=QMessageBox::Yes)
3393 return;
3394 QString folder = QDir::currentPath();
3395 if (!mOJProblemSetModel.exportFilename().isEmpty())
3396 folder = extractFileDir(mOJProblemSetModel.exportFilename());
3397 QStringList files = QFileDialog::getOpenFileNames(
3398 this,
3399 tr("Choose input files"),
3400 folder,
3401 tr("Input data files (*.in)"));
3402 if (files.isEmpty())
3403 return;
3404 mOJProblemModel.removeCases();
3405 foreach (const QString& filename, files) {
3406 POJProblemCase problemCase = std::make_shared<OJProblemCase>();
3407 problemCase->name = QFileInfo(filename).baseName();
3408 problemCase->testState = ProblemCaseTestState::NotTested;
3409 problemCase->inputFileName = filename;
3410 QString expectedFileName;
3411 expectedFileName = filename.mid(0,filename.length()-2)+"ans";
3412 if (fileExists(expectedFileName)) {
3413 problemCase->expectedOutputFileName = expectedFileName;
3414 } else {
3415 expectedFileName = filename.mid(0,filename.length()-2)+"out";
3416 if (fileExists(expectedFileName))
3417 problemCase->expectedOutputFileName = expectedFileName;
3418 }
3419 mOJProblemModel.addCase(problemCase);
3420 }
3421}
3422
3423void MainWindow::onNewProblemConnection()
3424{
3425 QTcpSocket* clientConnection = mTcpServer.nextPendingConnection();
3426
3427 connect(clientConnection, &QAbstractSocket::disconnected,
3428 clientConnection, &QObject::deleteLater);
3429 QByteArray content;
3430 int unreadCount = 0;
3431 while (clientConnection->state() == QTcpSocket::ConnectedState) {
3432 clientConnection->waitForReadyRead(100);
3433 QByteArray readed = clientConnection->readAll();
3434 if (readed.isEmpty()) {
3435 unreadCount ++;
3436 if (!content.isEmpty() || unreadCount>30)
3437 break;
3438 } else {
3439 unreadCount = 0;
3440 }
3441 content += readed;
3442 }
3443 content += clientConnection->readAll();
3444 clientConnection->write("HTTP/1.1 200 OK");
3445 clientConnection->disconnectFromHost();
3446// qDebug()<<"---------";
3447// qDebug()<<content;
3448 content = getHTTPBody(content);
3449// qDebug()<<"*********";
3450// qDebug()<<content;
3451 if (content.isEmpty()) {
3452 return;
3453 }
3454 QJsonParseError error;
3455 QJsonDocument doc = QJsonDocument::fromJson(content,&error);
3456 if (error.error!=QJsonParseError::NoError) {
3457 qDebug()<<"Read http content failed!";
3458 qDebug()<<error.errorString();
3459 return;
3460 }
3461 QJsonObject obj=doc.object();
3462 QString name = obj["name"].toString();
3463 if (!mOJProblemSetModel.problemNameUsed(name)) {
3464 POJProblem problem = std::make_shared<OJProblem>();
3465 problem->name = name;
3466 problem->url = obj["url"].toString();
3467 QJsonArray caseArray = obj["tests"].toArray();
3468 foreach ( const QJsonValue& val, caseArray) {
3469 QJsonObject caseObj = val.toObject();
3470 POJProblemCase problemCase = std::make_shared<OJProblemCase>();
3471 problemCase->testState = ProblemCaseTestState::NotTested;
3472 problemCase->name = tr("Problem Case %1").arg(problem->cases.count()+1);
3473 problemCase->input = caseObj["input"].toString();
3474 problemCase->expected = caseObj["output"].toString();
3475 problem->cases.append(problemCase);
3476 }
3477 mOJProblemSetModel.addProblem(problem);
3478 ui->tabExplorer->setCurrentWidget(ui->tabProblemSet);
3479 ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(
3480 mOJProblemSetModel.count()-1
3481 ,0));
3482 if (isMinimized())
3483 showNormal();
3484 raise(); // for mac OS?
3485 activateWindow();
3486 }
3487}
3488
3489void MainWindow::updateProblemTitle()
3490{
3491 ui->lblProblem->setText(mOJProblemModel.getTitle());
3492 ui->lblProblem->setToolTip(mOJProblemModel.getTooltip());
3493}
3494
3495void MainWindow::onEditorClosed()
3496{
3497 if (mQuitting)
3498 return;
3499 updateEditorActions();
3500 updateAppTitle();
3501}
3502
3503void MainWindow::onToolsOutputClear()
3504{
3505 ui->txtToolsOutput->clear();
3506}
3507
3508void MainWindow::onToolsOutputCopy()
3509{
3510 ui->txtToolsOutput->copy();
3511}
3512
3513void MainWindow::onToolsOutputSelectAll()
3514{
3515 ui->txtToolsOutput->selectAll();
3516}
3517
3518void MainWindow::onShowInsertCodeSnippetMenu()
3519{
3520 mMenuInsertCodeSnippet->clear();
3521 QList<PCodeSnippet> snippets;
3522 foreach (const PCodeSnippet& snippet, mCodeSnippetManager->snippets()) {
3523 if (snippet->section>=0 && !snippet->caption.isEmpty())
3524 snippets.append(snippet);
3525 }
3526 if (snippets.isEmpty())
3527 return;
3528 std::sort(snippets.begin(),snippets.end(),[](const PCodeSnippet& s1, const PCodeSnippet& s2){
3529 return s1->section<s2->section;
3530 });
3531 int section = 0;
3532 int sectionCount = 0;
3533 int count = 0;
3534 bool sectionNotEmpty = false;
3535 foreach (const PCodeSnippet& snippet, snippets) {
3536 if (snippet->section>section && sectionCount<6) {
3537 section = snippet->section;
3538 sectionCount++;
3539 if (sectionNotEmpty)
3540 mMenuInsertCodeSnippet->addSeparator();
3541 }
3542 QAction * action = mMenuInsertCodeSnippet->addAction(snippet->caption);
3543 connect(action, &QAction::triggered,
3544 [snippet,this](){
3545 Editor * editor = mEditorList->getEditor();
3546 if (editor) {
3547 editor->insertCodeSnippet(snippet->code);
3548 }
3549 });
3550 sectionNotEmpty = true;
3551 count++;
3552 if (count>15)
3553 break;
3554 }
3555
3556}
3557
3558void MainWindow::onFilesViewCreateFolder()
3559{
3560 QModelIndex index = ui->treeFiles->currentIndex();
3561 QModelIndex parentIndex;
3562 QDir dir;
3563 if (index.isValid()
3564 && ui->treeFiles->selectionModel()->isSelected(index)) {
3565 if (mFileSystemModel.isDir(index)) {
3566 dir = QDir(mFileSystemModel.fileInfo(index).absoluteFilePath());
3567 parentIndex = index;
3568 } else {
3569 dir = mFileSystemModel.fileInfo(index).absoluteDir();
3570 parentIndex = mFileSystemModel.index(dir.absolutePath());
3571 }
3572 ui->treeFiles->expand(index);
3573 } else {
3574 dir = mFileSystemModel.rootDirectory();
3575 parentIndex=mFileSystemModel.index(dir.absolutePath());
3576 }
3577 QString folderName = tr("New Folder");
3578 int count = 0;
3579 while (dir.exists(folderName)) {
3580 count++;
3581 folderName = tr("New Folder %1").arg(count);
3582 }
3583 QModelIndex newIndex = mFileSystemModel.mkdir(parentIndex,folderName);
3584 ui->treeFiles->setCurrentIndex(newIndex);
3585}
3586
3587void MainWindow::onFilesViewCreateFile()
3588{
3589 QModelIndex index = ui->treeFiles->currentIndex();
3590 QDir dir;
3591 if (index.isValid()
3592 && ui->treeFiles->selectionModel()->isSelected(index)) {
3593 if (mFileSystemModel.isDir(index))
3594 dir = QDir(mFileSystemModel.fileInfo(index).absoluteFilePath());
3595 else
3596 dir = mFileSystemModel.fileInfo(index).absoluteDir();
3597 ui->treeFiles->expand(index);
3598 } else {
3599 dir = mFileSystemModel.rootDirectory();
3600 }
3601 QString suffix;
3602 if (pSettings->editor().defaultFileCpp())
3603 suffix=".cpp";
3604 else
3605 suffix=".c";
3606 QString fileName = tr("untitled")+suffix;
3607 int count = 0;
3608 while (dir.exists(fileName)) {
3609 count++;
3610 fileName = tr("untitled%1").arg(count)+suffix;
3611 }
3612 QFile file(dir.filePath(fileName));
3613 file.open(QFile::NewOnly);
3614 QModelIndex newIndex = mFileSystemModel.index(fileName);
3615 ui->treeFiles->setCurrentIndex(newIndex);
3616}
3617
3618
3619void MainWindow::onFilesViewRemoveFiles()
3620{
3621 QModelIndexList indexList = ui->treeFiles->selectionModel()->selectedRows();
3622 if (indexList.isEmpty()) {
3623 QModelIndex index = ui->treeFiles->currentIndex();
3624 if (QMessageBox::question(ui->treeFiles,tr("Delete")
3625 ,tr("Do you really want to delete %1?").arg(mFileSystemModel.fileName(index)),
3626 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)!=QMessageBox::Yes)
3627 return;
3628 doFilesViewRemoveFile(index);
3629 } else {
3630 if (QMessageBox::question(ui->treeFiles,tr("Delete")
3631 ,tr("Do you really want to delete %1 files?").arg(indexList.count()),
3632 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)!=QMessageBox::Yes)
3633 return;
3634 foreach (const QModelIndex& index, indexList) {
3635 doFilesViewRemoveFile(index);
3636 }
3637 }
3638}
3639
3640void MainWindow::onFilesViewRename() {
3641 QModelIndex index = ui->treeFiles->currentIndex();
3642 if (!index.isValid())
3643 return ;
3644 ui->treeFiles->edit(index);
3645}
3646
3647void MainWindow::onProblemProperties()
3648{
3649 showHideMessagesTab(ui->tabProblem,ui->actionProblem);
3650 QModelIndex idx = ui->lstProblemSet->currentIndex();
3651 if (!idx.isValid())
3652 return;
3653 POJProblem problem=mOJProblemSetModel.problem(idx.row());
3654 if (!problem)
3655 return;
3656 OJProblemPropertyWidget dialog;
3657 dialog.setName(problem->name);
3658 dialog.setUrl(problem->url);
3659 dialog.setDescription(problem->description);
3660 if (dialog.exec() == QDialog::Accepted) {
3661 problem->url = dialog.url();
3662 problem->description = dialog.description();
3663 if (problem == mOJProblemModel.problem()) {
3664 updateProblemTitle();
3665 }
3666 }
3667}
3668
3669void MainWindow::onProblemOpenSource()
3670{
3671 QModelIndex idx = ui->lstProblemSet->currentIndex();
3672 if (!idx.isValid())
3673 return;
3674 POJProblem problem=mOJProblemSetModel.problem(idx.row());
3675 if (!problem)
3676 return;
3677 if (!problem->answerProgram.isEmpty()) {
3678 Editor * editor = editorList()->getEditorByFilename(problem->answerProgram);
3679 if (editor) {
3680 editor->activate();
3681 }
3682 }
3683}
3684
3685void MainWindow::onLableProblemSetContextMenuRequested()
3686{
3687 QString newName = QInputDialog::getText(
3688 ui->lblProblemSet,
3689 tr("Set Problem Set Name"),
3690 tr("Problem Set Name:"),
3691 QLineEdit::Normal,
3692 ui->lblProblemSet->text());
3693 newName = newName.trimmed();
3694 if (!newName.isEmpty()){
3695 mOJProblemSetModel.rename(newName);
3696 ui->lblProblemSet->setText(mOJProblemSetModel.name());
3697 }
3698}
3699
3700void MainWindow::onBookmarkRemove()
3701{
3702 QModelIndex index = ui->tableBookmark->currentIndex();
3703 if (index.isValid()) {
3704 PBookmark bookmark = mBookmarkModel->bookmark(index.row());
3705 if (bookmark) {
3706 Editor * editor = mEditorList->getOpenedEditorByFilename(bookmark->filename);
3707 if (editor) {
3708 editor->removeBookmark(bookmark->line);
3709 } else {
3710 mBookmarkModel->removeBookmarkAt(index.row());
3711 }
3712 }
3713 }
3714}
3715
3716void MainWindow::onBookmarkRemoveAll()
3717{
3718 mBookmarkModel->clear();
3719 for (int i=0;i<mEditorList->pageCount();i++) {
3720 Editor * editor = (*mEditorList)[i];
3721 editor->clearBookmarks();
3722 }
3723}
3724
3725void MainWindow::onBookmarkModify()
3726{
3727 QModelIndex index = ui->tableBookmark->currentIndex();
3728 if (index.isValid()) {
3729 PBookmark bookmark = mBookmarkModel->bookmark(index.row());
3730 if (bookmark) {
3731 QString desc = QInputDialog::getText(ui->tableBookmark,tr("Bookmark Description"),
3732 tr("Description:"),QLineEdit::Normal,
3733 bookmark->description);
3734 desc = desc.trimmed();
3735 mBookmarkModel->updateDescription(bookmark->filename,bookmark->line,desc);
3736 }
3737 }
3738}
3739
3740void MainWindow::onDebugConsoleShowDetailLog()
3741{
3742 pSettings->debugger().setShowDetailLog(mDebugConsole_ShowDetailLog->isChecked());
3743 pSettings->debugger().save();
3744}
3745
3746void MainWindow::onDebugConsolePaste()
3747{
3748 ui->debugConsole->paste();
3749}
3750
3751void MainWindow::onDebugConsoleSelectAll()
3752{
3753 ui->debugConsole->selectAll();
3754}
3755
3756void MainWindow::onDebugConsoleCopy()
3757{
3758 ui->debugConsole->copy();
3759}
3760
3761void MainWindow::onDebugConsoleClear()
3762{
3763 ui->debugConsole->clear();
3764}
3765
3766void MainWindow::onFilesViewOpenInExplorer()
3767{
3768 QString path = mFileSystemModel.filePath(ui->treeFiles->currentIndex());
3769 if (!path.isEmpty()) {
3770 QFileInfo info(path);
3771 if (info.isFile()){
3772 QDesktopServices::openUrl(
3773 QUrl("file:///"+
3774 includeTrailingPathDelimiter(info.path()),QUrl::TolerantMode));
3775 } else if (info.isDir()){
3776 QDesktopServices::openUrl(
3777 QUrl("file:///"+
3778 includeTrailingPathDelimiter(path),QUrl::TolerantMode));
3779 }
3780 }
3781}
3782
3783void MainWindow::onFilesViewOpenInTerminal()
3784{
3785 QString path = mFileSystemModel.filePath(ui->treeFiles->currentIndex());
3786 if (!path.isEmpty()) {
3787 QFileInfo fileInfo(path);
3788#ifdef Q_OS_WIN
3789 openShell(fileInfo.path(),"cmd.exe",getDefaultCompilerSetBinDirs());
3790#else
3791 openShell(fileInfo.path(),pSettings->environment().terminalPath(),getDefaultCompilerSetBinDirs());
3792#endif
3793 }
3794}
3795
3796void MainWindow::onFilesViewOpenWithExternal()
3797{
3798 QString path = mFileSystemModel.filePath(ui->treeFiles->currentIndex());
3799 if (!path.isEmpty() && QFileInfo(path).isFile()) {
3800 QDesktopServices::openUrl(QUrl::fromLocalFile(path));
3801 }
3802}
3803
3804void MainWindow::onFilesViewOpen()
3805{
3806 QString path = mFileSystemModel.filePath(ui->treeFiles->currentIndex());
3807 if (!path.isEmpty() && QFileInfo(path).isFile()) {
3808 if (getFileType(path)==FileType::Project) {
3809 openProject(path);
3810 } else {
3811 openFile(path);
3812 }
3813 }
3814}
3815
3816void MainWindow::onClassBrowserGotoDeclaration()
3817{
3818 on_classBrowser_doubleClicked(ui->classBrowser->currentIndex());
3819}
3820
3821void MainWindow::onClassBrowserGotoDefinition()
3822{
3823 QModelIndex index = ui->classBrowser->currentIndex();
3824 if (!index.isValid())
3825 return ;
3826 ClassBrowserNode * node = static_cast<ClassBrowserNode*>(index.internalPointer());
3827 if (!node)
3828 return ;
3829 PStatement statement = node->statement;
3830 if (!statement) {
3831 return;
3832 }
3833 QString filename;
3834 int line;
3835 filename = statement->definitionFileName;
3836 line = statement->definitionLine;
3837 Editor* e = pMainWindow->editorList()->getEditorByFilename(filename);
3838 if (e) {
3839 e->setCaretPositionAndActivate(line,1);
3840 }
3841}
3842
3843void MainWindow::onClassBrowserShowInherited()
3844{
3845 pSettings->ui().setClassBrowserShowInherited(mClassBrowser_Show_Inherited->isChecked());
3846 pSettings->ui().save();
3847 mClassBrowserModel.fillStatements();
3848}
3849
3850void MainWindow::onClassBrowserSortByType()
3851{
3852 pSettings->ui().setClassBrowserSortType(mClassBrowser_Sort_By_Type->isChecked());
3853 pSettings->ui().save();
3854 mClassBrowserModel.fillStatements();
3855}
3856
3857void MainWindow::onClassBrowserSortByName()
3858{
3859 pSettings->ui().setClassBrowserSortAlpha(mClassBrowser_Sort_By_Name->isChecked());
3860 pSettings->ui().save();
3861 mClassBrowserModel.fillStatements();
3862}
3863
3864void MainWindow::onProjectSwitchCustomViewMode()
3865{
3866 mProject->setModelType(ProjectModelType::Custom);
3867}
3868
3869void MainWindow::onProjectSwitchFileSystemViewMode()
3870{
3871 mProject->setModelType(ProjectModelType::FileSystem);
3872}
3873
3874void MainWindow::onProjectRemoveFolder()
3875{
3876 if (!mProject)
3877 return;
3878 QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->currentIndex());
3879 if (!current.isValid()) {
3880 return;
3881 }
3882 ProjectModelNode * node = static_cast<ProjectModelNode*>(current.internalPointer());
3883 PProjectModelNode folderNode = mProject->pointerToNode(node);
3884 if (!folderNode)
3885 return;
3886 if (folderNode->unitIndex>=0)
3887 return;
3888 mProject->removeFolder(folderNode);
3889 mProject->saveOptions();
3890
3891}
3892
3893void MainWindow::onProjectRenameFolder()
3894{
3895 if (ui->projectView->currentIndex().isValid()) {
3896 ui->projectView->edit(ui->projectView->currentIndex());
3897 }
3898}
3899
3900void MainWindow::onProjectAddFolder()
3901{
3902 if (!mProject)
3903 return;
3904 QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->currentIndex());
3905 if (!current.isValid()) {
3906 return;
3907 }
3908 ProjectModelNode * node = static_cast<ProjectModelNode*>(current.internalPointer());
3909 PProjectModelNode folderNode = mProject->pointerToNode(node);
3910 if (!folderNode)
3911 folderNode = mProject->rootNode();
3912 if (folderNode->unitIndex>=0)
3913 return;
3914 QString s=tr("New folder");
3915 bool ok;
3916 s = QInputDialog::getText(ui->projectView,
3917 tr("Add Folder"),
3918 tr("Folder name:"),
3919 QLineEdit::Normal, s,
3920 &ok).trimmed();
3921 if (ok && !s.isEmpty()) {
3922 QString path = mProject->getFolderPath(folderNode);
3923 if (path.isEmpty()) {
3924 mProject->addFolder(s);
3925 } else {
3926 mProject->addFolder(path + '/' +s);
3927 }
3928 mProject->saveOptions();
3929 }
3930}
3931
3932void MainWindow::onProjectRenameUnit()
3933{
3934 if (ui->projectView->currentIndex().isValid()) {
3935 ui->projectView->edit(ui->projectView->currentIndex());
3936 }
3937}
3938
3939void MainWindow::onBreakpointRemove()
3940{
3941 int index =ui->tblBreakpoints->selectionModel()->currentIndex().row();
3942
3943 PBreakpoint breakpoint = debugger()->breakpointModel()->breakpoint(index);
3944 if (breakpoint) {
3945 Editor * e = mEditorList->getOpenedEditorByFilename(breakpoint->filename);
3946 if (e) {
3947 if (e->hasBreakpoint(breakpoint->line))
3948 e->toggleBreakpoint(breakpoint->line);
3949 } else {
3950 debugger()->breakpointModel()->removeBreakpoint(index);
3951 }
3952 }
3953}
3954
3955void MainWindow::onBreakpointViewRemoveAll()
3956{
3957 pMainWindow->debugger()->deleteBreakpoints();
3958 for (int i=0;i<mEditorList->pageCount();i++) {
3959 Editor * e = (*(mEditorList))[i];
3960 if (e) {
3961 e->resetBreakpoints();
3962 }
3963 }
3964}
3965
3966void MainWindow::onBreakpointViewProperty()
3967{
3968 int index =ui->tblBreakpoints->selectionModel()->currentIndex().row();
3969
3970 PBreakpoint breakpoint = debugger()->breakpointModel()->breakpoint(
3971 index
3972 );
3973 if (breakpoint) {
3974 bool isOk;
3975 QString s=QInputDialog::getText(this,
3976 tr("Break point condition"),
3977 tr("Enter the condition of the breakpoint:"),
3978 QLineEdit::Normal,
3979 breakpoint->condition,&isOk);
3980 if (isOk) {
3981 pMainWindow->debugger()->setBreakPointCondition(index,s);
3982 }
3983 }
3984}
3985
3986void MainWindow::onSearchViewClearAll()
3987{
3988 mSearchResultModel.clear();
3989}
3990
3991void MainWindow::onSearchViewClear()
3992{
3993 int index = ui->cbSearchHistory->currentIndex();
3994 if (index>=0) {
3995 mSearchResultModel.removeSearchResults(index);
3996 }
3997}
3998
3999void MainWindow::onTableIssuesClear()
4000{
4001 clearIssues();
4002}
4003
4004void MainWindow::onTableIssuesCopyAll()
4005{
4006 QClipboard* clipboard=QGuiApplication::clipboard();
4007 QMimeData * mimeData = new QMimeData();
4008 mimeData->setText(ui->tableIssues->toTxt());
4009 mimeData->setHtml(ui->tableIssues->toHtml());
4010 clipboard->clear();
4011 clipboard->setMimeData(mimeData);
4012}
4013
4014void MainWindow::onTableIssuesCopy()
4015{
4016 QModelIndex index = ui->tableIssues->selectionModel()->currentIndex();
4017 PCompileIssue issue = ui->tableIssues->issue(index);
4018 if (issue) {
4019 QClipboard* clipboard = QApplication::clipboard();
4020 clipboard->setText(issue->description);
4021 }
4022}
4023
4024void MainWindow::onEditorContextMenu(const QPoint& pos)
4025{
4026 Editor * editor = mEditorList->getEditor();
4027 if (!editor)
4028 return;
4029 QMenu menu(this);
4030 QSynedit::BufferCoord p;
4031 mEditorContextMenuPos = pos;
4032 int line;
4033 if (editor->getPositionOfMouse(p)) {
4034 line=p.line;
4035 //mouse on editing area
4036 menu.addAction(ui->actionCompile_Run);
4037 menu.addAction(ui->actionDebug);
4038 menu.addSeparator();
4039 menu.addAction(ui->actionGoto_Declaration);
4040 menu.addAction(ui->actionGoto_Definition);
4041 menu.addAction(ui->actionFind_references);
4042
4043 menu.addSeparator();
4044 menu.addAction(ui->actionOpen_Containing_Folder);
4045 menu.addAction(ui->actionOpen_Terminal);
4046 menu.addAction(ui->actionLocate_in_Files_View);
4047 menu.addSeparator();
4048 menu.addAction(ui->actionReformat_Code);
4049 menu.addSeparator();
4050 menu.addAction(ui->actionCut);
4051 menu.addAction(ui->actionCopy);
4052 menu.addAction(ui->actionPaste);
4053 menu.addAction(ui->actionSelectAll);
4054 menu.addSeparator();
4055 menu.addAction(ui->actionAdd_Watch);
4056 menu.addAction(ui->actionToggle_Breakpoint);
4057 menu.addAction(ui->actionClear_all_breakpoints);
4058 menu.addSeparator();
4059 menu.addAction(ui->actionAdd_bookmark);
4060 menu.addAction(ui->actionRemove_Bookmark);
4061 menu.addAction(ui->actionModify_Bookmark_Description);
4062 menu.addSeparator();
4063 menu.addAction(ui->actionGo_to_Line);
4064 menu.addSeparator();
4065 menu.addAction(ui->actionFile_Properties);
4066
4067 //these actions needs parser
4068 ui->actionGoto_Declaration->setEnabled(!editor->parser()->parsing());
4069 ui->actionGoto_Definition->setEnabled(!editor->parser()->parsing());
4070 ui->actionFind_references->setEnabled(!editor->parser()->parsing());
4071 } else {
4072 //mouse on gutter
4073
4074 if (!editor->getLineOfMouse(line))
4075 line=-1;
4076 menu.addAction(ui->actionToggle_Breakpoint);
4077 menu.addAction(ui->actionBreakpoint_property);
4078 menu.addAction(ui->actionClear_all_breakpoints);
4079 menu.addSeparator();
4080 menu.addAction(ui->actionAdd_bookmark);
4081 menu.addAction(ui->actionRemove_Bookmark);
4082 menu.addAction(ui->actionModify_Bookmark_Description);
4083 menu.addSeparator();
4084 menu.addAction(ui->actionGo_to_Line);
4085 }
4086 ui->actionLocate_in_Files_View->setEnabled(!editor->isNew());
4087 ui->actionBreakpoint_property->setEnabled(editor->hasBreakpoint(line));
4088 ui->actionAdd_bookmark->setEnabled(
4089 line>=0 && editor->document()->count()>0
4090 && !editor->hasBookmark(line)
4091 );
4092 ui->actionRemove_Bookmark->setEnabled(editor->hasBookmark(line));
4093 ui->actionModify_Bookmark_Description->setEnabled(editor->hasBookmark(line));
4094 menu.exec(editor->viewport()->mapToGlobal(pos));
4095}
4096
4097void MainWindow::onEditorRightTabContextMenu(const QPoint& pos)
4098{
4099 onEditorTabContextMenu(ui->EditorTabsRight,pos);
4100}
4101
4102void MainWindow::onEditorLeftTabContextMenu(const QPoint& pos)
4103{
4104 onEditorTabContextMenu(ui->EditorTabsLeft,pos);
4105}
4106
4107
4108void MainWindow::onEditorTabContextMenu(QTabWidget* tabWidget, const QPoint &pos)
4109{
4110 int index = tabWidget->tabBar()->tabAt(pos);
4111 if (index<0)
4112 return;
4113 tabWidget->setCurrentIndex(index);
4114 QMenu menu(this);
4115 QTabBar* tabBar = tabWidget->tabBar();
4116 menu.addAction(ui->actionClose);
4117 menu.addAction(ui->actionClose_All);
4118 menu.addSeparator();
4119 menu.addAction(ui->actionOpen_Containing_Folder);
4120 menu.addAction(ui->actionOpen_Terminal);
4121 menu.addAction(ui->actionLocate_in_Files_View);
4122 menu.addSeparator();
4123 menu.addAction(ui->actionMove_To_Other_View);
4124 menu.addSeparator();
4125 menu.addAction(ui->actionFile_Properties);
4126 ui->actionMove_To_Other_View->setEnabled(
4127 tabWidget==ui->EditorTabsRight
4128 || tabWidget->count()>1
4129 );
4130 Editor * editor = dynamic_cast<Editor *>(tabWidget->widget(index));
4131 if (editor ) {
4132 ui->actionLocate_in_Files_View->setEnabled(!editor->isNew());
4133 }
4134 menu.exec(tabBar->mapToGlobal(pos));
4135}
4136
4137void MainWindow::disableDebugActions()
4138{
4139 ui->actionInterrupt->setEnabled(false);
4140 ui->actionStep_Into->setEnabled(false);
4141 ui->actionStep_Over->setEnabled(false);
4142 ui->actionStep_Out->setEnabled(false);
4143 ui->actionRun_To_Cursor->setEnabled(false);
4144 ui->actionContinue->setEnabled(false);
4145 ui->cbEvaluate->setEnabled(false);
4146 ui->cbMemoryAddress->setEnabled(false);
4147 if (mCPUDialog) {
4148 mCPUDialog->updateButtonStates(false);
4149 }
4150}
4151
4152void MainWindow::enableDebugActions()
4153{
4154 if (pSettings->debugger().useGDBServer())
4155 ui->actionInterrupt->setEnabled(mDebugger->inferiorRunning());
4156 ui->actionStep_Into->setEnabled(!mDebugger->inferiorRunning());
4157 ui->actionStep_Over->setEnabled(!mDebugger->inferiorRunning());
4158 ui->actionStep_Out->setEnabled(!mDebugger->inferiorRunning());
4159 ui->actionRun_To_Cursor->setEnabled(!mDebugger->inferiorRunning());
4160 ui->actionContinue->setEnabled(!mDebugger->inferiorRunning());
4161 ui->cbEvaluate->setEnabled(!mDebugger->inferiorRunning());
4162 ui->cbMemoryAddress->setEnabled(!mDebugger->inferiorRunning());
4163 if (mCPUDialog) {
4164 mCPUDialog->updateButtonStates(true);
4165 }
4166}
4167
4168void MainWindow::onTodoParseStarted(const QString&)
4169{
4170 mTodoModel.clear();
4171}
4172
4173void MainWindow::onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line)
4174{
4175 mTodoModel.addItem(filename,lineNo,ch,line);
4176}
4177
4178void MainWindow::onTodoParseFinished()
4179{
4180
4181}
4182
4183void MainWindow::prepareProjectForCompile()
4184{
4185 if (!mProject)
4186 return;
4187 if (!mProject->saveUnits())
4188 return;
4189 // Check if saves have been succesful
4190 for (int i=0; i<mEditorList->pageCount();i++) {
4191 Editor * e= (*(mEditorList))[i];
4192 if (e->inProject() && e->modified())
4193 return;
4194 }
4195 mProject->buildPrivateResource();
4196}
4197
4198void MainWindow::closeProject(bool refreshEditor)
4199{
4200 // Stop executing program
4201 on_actionStop_Execution_triggered();
4202
4203 // Only update file monitor once (and ignore updates)
4204 bool oldBlock= mFileSystemWatcher.blockSignals(true);
4205 {
4206 auto action = finally([&,this]{
4207 mFileSystemWatcher.blockSignals(oldBlock);
4208 });
4209 // TODO: should we save watches?
4210 if (mProject->modified()) {
4211 QString s;
4212 if (mProject->name().isEmpty()) {
4213 s = mProject->filename();
4214 } else {
4215 s = mProject->name();
4216 }
4217 if (mSystemTurnedOff) {
4218 mProject->saveAll();
4219 } else {
4220 int answer = QMessageBox::question(
4221 this,
4222 tr("Save project"),
4223 tr("The project '%1' has modifications.").arg(s)
4224 + "<br />"
4225 + tr("Do you want to save it?"),
4226 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
4227 QMessageBox::Yes);
4228 switch (answer) {
4229 case QMessageBox::Yes:
4230 mProject->saveAll();
4231 break;
4232 case QMessageBox::No:
4233 mProject->setModified(false);
4234 mProject->saveLayout();
4235 break;
4236 case QMessageBox::Cancel:
4237 mProject->saveLayout();
4238 return;
4239 }
4240 }
4241 } else
4242 mProject->saveLayout(); // always save layout, but not when SaveAll has been called
4243
4244 mClassBrowserModel.beginUpdate();
4245 {
4246 auto action2 = finally([this]{
4247 mClassBrowserModel.endUpdate();
4248 });
4249 // Remember it
4250 pSettings->history().addToOpenedProjects(mProject->filename());
4251
4252 mEditorList->beginUpdate();
4253 {
4254 auto action3 = finally([this]{
4255 mEditorList->endUpdate();
4256 });
4257 mProject.reset();
4258
4259 if (!mQuitting && refreshEditor) {
4260 //reset Class browsing
4261 ui->tabExplorer->setCurrentWidget(ui->tabStructure);
4262 Editor * e = mEditorList->getEditor();
4263 updateClassBrowserForEditor(e);
4264 } else {
4265 mClassBrowserModel.setParser(nullptr);
4266 mClassBrowserModel.setCurrentFile("");
4267 }
4268 }
4269 }
4270 if (!mQuitting) {
4271 // Clear error browser
4272 clearIssues();
4273 updateProjectView();
4274 }
4275 }
4276}
4277
4278void MainWindow::updateProjectView()
4279{
4280 if (mProject) {
4281 if (mProjectProxyModel->sourceModel()!=mProject->model()) {
4282 mProjectProxyModel->setSourceModel(mProject->model());
4283 mProjectProxyModel->sort(0);
4284 connect(mProject->model(), &ProjectModel::dataChanged,
4285 this, &MainWindow::invalidateProjectProxyModel);
4286 connect(mProject->model(), &ProjectModel::rowsRemoved,
4287 this, &MainWindow::invalidateProjectProxyModel);
4288 connect(mProject->model(), &ProjectModel::rowsInserted,
4289 this, &MainWindow::invalidateProjectProxyModel);
4290 connect(mProject->model(), &QAbstractItemModel::modelReset,
4291 ui->projectView,&QTreeView::expandAll);
4292 } else
4293 mProjectProxyModel->invalidate();
4294 ui->projectView->expandAll();
4295 stretchExplorerPanel(true);
4296 ui->tabProject->setVisible(true);
4297 ui->tabExplorer->setCurrentWidget(ui->tabProject);
4298 } else {
4299 // Clear project browser
4300 mProjectProxyModel->setSourceModel(nullptr);
4301 ui->tabProject->setVisible(false);
4302 }
4303 updateProjectActions();
4304}
4305
4306void MainWindow::onFileChanged(const QString &path)
4307{
4308 if (mFilesChangedNotifying.contains(path))
4309 return;
4310 mFilesChangedNotifying.insert(path);
4311 Editor *e = mEditorList->getOpenedEditorByFilename(path);
4312 if (e) {
4313 if (fileExists(path)) {
4314 e->activate();
4315 if (QMessageBox::question(this,tr("File Changed"),
4316 tr("File '%1' was changed.").arg(path)+"<BR /><BR />" + tr("Reload its content from disk?"),
4317 QMessageBox::Yes|QMessageBox::No,
4318 QMessageBox::No) == QMessageBox::Yes) {
4319 try {
4320 e->loadFile();
4321 } catch(FileError e) {
4322 QMessageBox::critical(this,tr("Error"),e.reason());
4323 }
4324 } else {
4325 e->setModified(true);
4326 }
4327 } else {
4328 mFileSystemWatcher.removePath(path);
4329 if (QMessageBox::question(this,tr("File Changed"),
4330 tr("File '%1' was removed.").arg(path)+"<BR /><BR />" + tr("Keep it open?"),
4331 QMessageBox::Yes|QMessageBox::No,
4332 QMessageBox::Yes) == QMessageBox::No) {
4333 mEditorList->closeEditor(e);
4334 } else {
4335 e->setModified(true);
4336 }
4337 }
4338 }
4339 mFilesChangedNotifying.remove(path);
4340}
4341
4342void MainWindow::onFilesViewPathChanged()
4343{
4344 QString filesPath = ui->cbFilesPath->currentText();
4345 QFileInfo fileInfo(filesPath);
4346 ui->cbFilesPath->blockSignals(true);
4347 if (fileInfo.exists() && fileInfo.isDir()) {
4348 setFilesViewRoot(filesPath);
4349 } else {
4350 ui->cbFilesPath->setCurrentText(pSettings->environment().currentFolder());
4351 }
4352 ui->cbFilesPath->blockSignals(false);
4353}
4354
4355const std::shared_ptr<HeaderCompletionPopup> &MainWindow::headerCompletionPopup() const
4356{
4357 return mHeaderCompletionPopup;
4358}
4359
4360const std::shared_ptr<FunctionTooltipWidget> &MainWindow::functionTip() const
4361{
4362 return mFunctionTip;
4363}
4364
4365const std::shared_ptr<CodeCompletionPopup> &MainWindow::completionPopup() const
4366{
4367 return mCompletionPopup;
4368}
4369
4370SearchDialog *MainWindow::searchDialog() const
4371{
4372 return mSearchDialog;
4373}
4374
4375SearchResultModel *MainWindow::searchResultModel()
4376{
4377 return &mSearchResultModel;
4378}
4379
4380EditorList *MainWindow::editorList() const
4381{
4382 return mEditorList;
4383}
4384
4385Debugger *MainWindow::debugger() const
4386{
4387 return mDebugger;
4388}
4389
4390CPUDialog *MainWindow::cpuDialog() const
4391{
4392 return mCPUDialog;
4393}
4394
4395
4396void MainWindow::on_actionNew_triggered()
4397{
4398 if (mProject) {
4399 if (QMessageBox::question(this,
4400 tr("New Project File?"),
4401 tr("Do you want to add the new file to the project?"),
4402 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
4403 newProjectUnitFile();
4404 return;
4405 }
4406 }
4407 newEditor();
4408}
4409
4410void MainWindow::on_EditorTabsLeft_tabCloseRequested(int index)
4411{
4412 Editor* editor = mEditorList->getEditor(index,ui->EditorTabsLeft);
4413 mEditorList->closeEditor(editor);
4414}
4415
4416void MainWindow::on_EditorTabsRight_tabCloseRequested(int index)
4417{
4418 Editor* editor = mEditorList->getEditor(index,ui->EditorTabsRight);
4419 mEditorList->closeEditor(editor);
4420}
4421
4422void MainWindow::onFileSystemModelLayoutChanged()
4423{
4424 ui->treeFiles->scrollTo(ui->treeFiles->currentIndex(),QTreeView::PositionAtCenter);
4425}
4426
4427void MainWindow::on_actionOpen_triggered()
4428{
4429 try {
4430 QString selectedFileFilter;
4431 selectedFileFilter = pSystemConsts->defaultAllFileFilter();
4432 QStringList files = QFileDialog::getOpenFileNames(pMainWindow,
4433 tr("Open"), QString(), pSystemConsts->defaultFileFilters().join(";;"),
4434 &selectedFileFilter);
4435 if (!files.isEmpty()) {
4436 QDir::setCurrent(extractFileDir(files[0]));
4437 }
4438 openFiles(files);
4439 } catch (FileError e) {
4440 QMessageBox::critical(this,tr("Error"),e.reason());
4441 }
4442}
4443
4444void MainWindow::closeEvent(QCloseEvent *event) {
4445 mQuitting = true;
4446 if (!mShouldRemoveAllSettings) {
4447 Settings::UI& settings = pSettings->ui();
4448 settings.setMainWindowState(saveState());
4449 settings.setMainWindowGeometry(saveGeometry());
4450 settings.setBottomPanelIndex(ui->tabMessages->currentIndex());
4451 settings.setLeftPanelIndex(ui->tabExplorer->currentIndex());
4452
4453 settings.setShowStatusBar(ui->actionStatus_Bar->isChecked());
4454 settings.setShowToolWindowBars(ui->actionTool_Window_Bars->isChecked());
4455
4456 settings.setShowProject(ui->actionProject->isChecked());
4457 settings.setShowWatch(ui->actionWatch->isChecked());
4458 settings.setShowStructure(ui->actionStructure->isChecked());
4459 settings.setShowFiles(ui->actionFiles->isChecked());
4460 settings.setShowProblemSet(ui->actionProblem_Set->isChecked());
4461
4462 settings.setShowIssues(ui->actionIssues->isChecked());
4463 settings.setShowCompileLog(ui->actionTools_Output->isChecked());
4464 settings.setShowDebug(ui->actionDebug_Window->isChecked());
4465 settings.setShowSearch(ui->actionSearch->isChecked());
4466 settings.setShowTODO(ui->actionTODO->isChecked());
4467 settings.setShowBookmark(ui->actionBookmark->isChecked());
4468 settings.setShowProblem(ui->actionProblem->isChecked());
4469
4470 settings.setMessagesTabsSize(ui->tabMessages->currentSize());
4471 settings.setExplorerTabsSize(ui->tabExplorer->currentSize());
4472 settings.setShrinkExplorerTabs(ui->tabExplorer->isShrinked());
4473 settings.setShrinkMessagesTabs(ui->tabMessages->isShrinked());
4474 settings.save();
4475
4476 //save current folder ( for files view )
4477 pSettings->environment().setDefaultOpenFolder(QDir::currentPath());
4478 pSettings->environment().save();
4479 try {
4480 mBookmarkModel->save(includeTrailingPathDelimiter(pSettings->dirs().config())
4481 +DEV_BOOKMARK_FILE);
4482 } catch (FileError& e) {
4483 QMessageBox::warning(nullptr,
4484 tr("Save Error"),
4485 e.reason());
4486 }
4487
4488 if (pSettings->debugger().autosaveBreakpoints()) {
4489 try {
4490 mDebugger->breakpointModel()->save(includeTrailingPathDelimiter(pSettings->dirs().config())
4491 +DEV_BREAKPOINTS_FILE);
4492 } catch (FileError& e) {
4493 QMessageBox::warning(nullptr,
4494 tr("Save Error"),
4495 e.reason());
4496 }
4497 } else
4498 removeFile(includeTrailingPathDelimiter(pSettings->dirs().config())
4499 +DEV_BREAKPOINTS_FILE);
4500 if (pSettings->debugger().autosaveWatches()) {
4501 try {
4502 mDebugger->watchModel()->save(includeTrailingPathDelimiter(pSettings->dirs().config())
4503 +DEV_WATCH_FILE);
4504 } catch (FileError& e) {
4505 QMessageBox::warning(nullptr,
4506 tr("Save Error"),
4507 e.reason());
4508 }
4509 } else
4510 removeFile(includeTrailingPathDelimiter(pSettings->dirs().config())
4511 +DEV_WATCH_FILE);
4512
4513 }
4514
4515 if (!mShouldRemoveAllSettings && pSettings->editor().autoLoadLastFiles()) {
4516 saveLastOpens();
4517 } else {
4518 //if don't save last open files, close project before editors, to save project openned editors;
4519 if (mProject) {
4520 closeProject(false);
4521 }
4522 }
4523
4524 mClosingAll=true;
4525 if (!mEditorList->closeAll(false)) {
4526 mClosingAll=false;
4527 mQuitting = false;
4528 event->ignore();
4529 return ;
4530 }
4531 mClosingAll=false;
4532
4533 if (!mShouldRemoveAllSettings && pSettings->editor().autoLoadLastFiles()) {
4534 if (mProject) {
4535 closeProject(false);
4536 }
4537 }
4538
4539 mTcpServer.close();
4540 mCompilerManager->stopAllRunners();
4541 mCompilerManager->stopCompile();
4542 mCompilerManager->stopRun();
4543 if (!mShouldRemoveAllSettings)
4544 mSymbolUsageManager->save();
4545
4546 if (mCPUDialog!=nullptr)
4547 cleanUpCPUDialog();
4548 event->accept();
4549 return;
4550}
4551
4552void MainWindow::showEvent(QShowEvent *)
4553{
4554 applySettings();
4555 const Settings::UI& settings = pSettings->ui();
4556 ui->tabMessages->setCurrentIndex(settings.bottomPanelIndex());
4557 ui->tabExplorer->setCurrentIndex(settings.leftPanelIndex());
4558}
4559
4560void MainWindow::hideEvent(QHideEvent *)
4561{
4562 Settings::UI& settings = pSettings->ui();
4563 settings.setBottomPanelIndex(ui->tabMessages->currentIndex());
4564 settings.setLeftPanelIndex(ui->tabExplorer->currentIndex());
4565}
4566
4567bool MainWindow::event(QEvent *event)
4568{
4569 if (event->type()==DPI_CHANGED_EVENT) {
4570 applySettings();
4571 event->accept();
4572 return true;
4573 }
4574 return QMainWindow::event(event);
4575}
4576
4577//void MainWindow::dragEnterEvent(QDragEnterEvent *event)
4578//{
4579// if (event->mimeData()->hasUrls()){
4580// event->acceptProposedAction();
4581// }
4582//}
4583
4584//void MainWindow::dropEvent(QDropEvent *event)
4585//{
4586// if (event->mimeData()->hasUrls()) {
4587// foreach(const QUrl& url, event->mimeData()->urls()){
4588// if (!url.isLocalFile())
4589// continue;
4590// QString file = url.toLocalFile();
4591// if (getFileType(file)==FileType::Project) {
4592// openProject(file);
4593// return;
4594// }
4595// }
4596// foreach(const QUrl& url, event->mimeData()->urls()){
4597// if (!url.isLocalFile())
4598// continue;
4599// QString file = url.toLocalFile();
4600// openFile(file);
4601// }
4602// }
4603//}
4604
4605void MainWindow::on_actionSave_triggered()
4606{
4607 Editor * editor = mEditorList->getEditor();
4608 if (editor != NULL) {
4609 try {
4610 editor->save();
4611 if (editor->inProject() && (mProject))
4612 mProject->saveAll();
4613 } catch(FileError e) {
4614 QMessageBox::critical(editor,tr("Error"),e.reason());
4615 }
4616 }
4617}
4618
4619void MainWindow::on_actionSaveAs_triggered()
4620{
4621 Editor * editor = mEditorList->getEditor();
4622 if (editor != NULL) {
4623 try {
4624 editor->saveAs();
4625 } catch(FileError e) {
4626 QMessageBox::critical(editor,tr("Error"),e.reason());
4627 }
4628 }
4629}
4630
4631void MainWindow::on_actionOptions_triggered()
4632{
4633 changeOptions();
4634}
4635
4636void MainWindow::onCompilerSetChanged(int index)
4637{
4638 if (index<0)
4639 return;
4640 if (mProject) {
4641 Editor *e = mEditorList->getEditor();
4642 if (!e || e->inProject()) {
4643 if(QMessageBox::warning(
4644 e,
4645 tr("Change Project Compiler Set"),
4646 tr("Change the project's compiler set will lose all custom compiler set options.")
4647 +"<br />"
4648 + tr("Do you really want to do that?"),
4649 QMessageBox::Yes | QMessageBox::No,
4650 QMessageBox::No) != QMessageBox::Yes) {
4651 return;
4652 }
4653 mProject->setCompilerSet(index);
4654 mProject->saveOptions();
4655 return;
4656 }
4657 }
4658 pSettings->compilerSets().setDefaultIndex(index);
4659 pSettings->compilerSets().saveDefaultIndex();
4660}
4661
4662void MainWindow::logToolsOutput(const QString& msg)
4663{
4664 ui->txtToolsOutput->appendPlainText(msg);
4665 ui->txtToolsOutput->moveCursor(QTextCursor::End);
4666 ui->txtToolsOutput->moveCursor(QTextCursor::StartOfLine);
4667 ui->txtToolsOutput->ensureCursorVisible();
4668}
4669
4670void MainWindow::onCompileIssue(PCompileIssue issue)
4671{
4672 ui->tableIssues->addIssue(issue);
4673
4674 // Update tab caption
4675// if CompilerOutput.Items.Count = 1 then
4676// CompSheet.Caption := Lang[ID_SHEET_COMP] + ' (' + IntToStr(CompilerOutput.Items.Count) + ')';
4677
4678 if (issue->type == CompileIssueType::Error || issue->type ==
4679 CompileIssueType::Warning) {
4680 Editor* e = mEditorList->getOpenedEditorByFilename(issue->filename);
4681 if (e!=nullptr && (issue->line>0)) {
4682 int line = issue->line;
4683 if (line > e->document()->count())
4684 return;
4685 int col = std::min(issue->column,e->document()->getString(line-1).length()+1);
4686 if (col < 1)
4687 col = e->document()->getString(line-1).length()+1;
4688 e->addSyntaxIssues(line,col,issue->endColumn,issue->type,issue->description);
4689 }
4690 }
4691}
4692
4693void MainWindow::clearToolsOutput()
4694{
4695 ui->txtToolsOutput->clear();
4696}
4697
4698void MainWindow::onCompileStarted()
4699{
4700 //do nothing
4701}
4702
4703void MainWindow::onCompileFinished(bool isCheckSyntax)
4704{
4705 if (mQuitting) {
4706 if (isCheckSyntax)
4707 mCheckSyntaxInBack = false;
4708 else
4709 mCompileSuccessionTask = nullptr;
4710 return;
4711 }
4712 // Update tab caption
4713 int i = ui->tabMessages->indexOf(ui->tabIssues);
4714 if (i!=-1) {
4715 if (isCheckSyntax) {
4716 if (mCompilerManager->syntaxCheckIssueCount()>0) {
4717 ui->tabMessages->setTabText(i, tr("Issues") +
4718 QString(" (%1)").arg(mCompilerManager->syntaxCheckIssueCount()));
4719 } else {
4720 ui->tabMessages->setTabText(i, tr("Issues"));
4721 }
4722 } else {
4723 if (mCompilerManager->compileIssueCount()>0) {
4724 ui->tabMessages->setTabText(i, tr("Issues") +
4725 QString(" (%1)").arg(mCompilerManager->compileIssueCount()));
4726 } else {
4727 ui->tabMessages->setTabText(i, tr("Issues"));
4728 }
4729 }
4730 }
4731
4732 if (isCheckSyntax) {
4733 // check syntax in back, don't change message panel
4734 } else if (ui->tableIssues->count() == 0) {
4735 // Close it if there's nothing to show
4736 if (ui->tabMessages->currentIndex() == i)
4737 stretchMessagesPanel(false);
4738 } else {
4739 if (ui->tabMessages->currentIndex() != i) {
4740 ui->tabMessages->setCurrentIndex(i);
4741 }
4742 stretchMessagesPanel(true);
4743 }
4744
4745 Editor * e = mEditorList->getEditor();
4746 if (e!=nullptr) {
4747 e->invalidate();
4748 }
4749
4750 if (!isCheckSyntax) {
4751 //run succession task if there aren't any errors
4752 if (mCompileSuccessionTask && mCompilerManager->compileErrorCount()==0) {
4753 switch (mCompileSuccessionTask->type) {
4754 case MainWindow::CompileSuccessionTaskType::RunNormal:
4755 runExecutable(mCompileSuccessionTask->execName,QString(),RunType::Normal, mCompileSuccessionTask->binDirs);
4756 break;
4757 case MainWindow::CompileSuccessionTaskType::RunProblemCases:
4758 runExecutable(mCompileSuccessionTask->execName,QString(),RunType::ProblemCases, mCompileSuccessionTask->binDirs);
4759 break;
4760 case MainWindow::CompileSuccessionTaskType::RunCurrentProblemCase:
4761 runExecutable(mCompileSuccessionTask->execName,QString(),RunType::CurrentProblemCase, mCompileSuccessionTask->binDirs);
4762 break;
4763 case MainWindow::CompileSuccessionTaskType::Debug:
4764 debug();
4765 break;
4766 default:
4767 break;
4768 }
4769 mCompileSuccessionTask.reset();
4770 // Jump to problem location, sorted by significance
4771 } else if ((mCompilerManager->compileIssueCount() > 0) && (!mCheckSyntaxInBack)) {
4772 bool hasError = false;
4773 // First try to find errors
4774 for (int i=0;i<ui->tableIssues->count();i++) {
4775 PCompileIssue issue = ui->tableIssues->issue(i);
4776 if (issue->type == CompileIssueType::Error) {
4777 ui->tableIssues->selectRow(i);
4778 hasError = true;
4779 break;
4780 }
4781 }
4782 if (!hasError) {
4783 // Then try to find warnings
4784 for (int i=0;i<ui->tableIssues->count();i++) {
4785 PCompileIssue issue = ui->tableIssues->issue(i);
4786 if (issue->type == CompileIssueType::Warning) {
4787 ui->tableIssues->selectRow(i);
4788 break;
4789 }
4790 }
4791 }
4792 }
4793 } else {
4794 mCheckSyntaxInBack=false;
4795 }
4796 updateCompileActions();
4797 updateAppTitle();
4798}
4799
4800void MainWindow::onCompileErrorOccured(const QString& reason)
4801{
4802 QMessageBox::critical(this,tr("Compile Failed"),reason);
4803}
4804
4805void MainWindow::onRunErrorOccured(const QString& reason)
4806{
4807 mCompilerManager->stopRun();
4808 QMessageBox::critical(this,tr("Run Failed"),reason);
4809}
4810
4811void MainWindow::onRunFinished()
4812{
4813 updateCompileActions();
4814 if (pSettings->executor().minimizeOnRun()) {
4815 showNormal();
4816 }
4817 updateAppTitle();
4818}
4819
4820void MainWindow::onRunPausingForFinish()
4821{
4822 updateCompileActions();
4823}
4824
4825void MainWindow::onRunProblemFinished()
4826{
4827 updateProblemTitle();
4828 ui->pbProblemCases->setVisible(false);
4829 updateCompileActions();
4830 updateAppTitle();
4831}
4832
4833void MainWindow::onOJProblemCaseStarted(const QString& id,int current, int total)
4834{
4835 ui->pbProblemCases->setVisible(true);
4836 ui->pbProblemCases->setMaximum(total);
4837 ui->pbProblemCases->setValue(current);
4838 int row = mOJProblemModel.getCaseIndexById(id);
4839 if (row>=0) {
4840 POJProblemCase problemCase = mOJProblemModel.getCase(row);
4841 problemCase->testState = ProblemCaseTestState::Testing;
4842 mOJProblemModel.update(row);
4843 QModelIndex idx = ui->tblProblemCases->currentIndex();
4844 if (!idx.isValid() || row != idx.row()) {
4845 ui->tblProblemCases->setCurrentIndex(mOJProblemModel.index(row,0));
4846 }
4847 ui->txtProblemCaseOutput->clear();
4848 }
4849}
4850
4851void MainWindow::onOJProblemCaseFinished(const QString& id, int current, int total)
4852{
4853 int row = mOJProblemModel.getCaseIndexById(id);
4854 if (row>=0) {
4855 POJProblemCase problemCase = mOJProblemModel.getCase(row);
4856 ProblemCaseValidator validator;
4857 problemCase->testState = validator.validate(problemCase,pSettings->executor().ignoreSpacesWhenValidatingCases())?
4858 ProblemCaseTestState::Passed:
4859 ProblemCaseTestState::Failed;
4860 mOJProblemModel.update(row);
4861 updateProblemCaseOutput(problemCase);
4862 }
4863 ui->pbProblemCases->setMaximum(total);
4864 ui->pbProblemCases->setValue(current);
4865 updateProblemTitle();
4866}
4867
4868void MainWindow::onOJProblemCaseNewOutputGetted(const QString &/* id */, const QString &line)
4869{
4870 ui->txtProblemCaseOutput->appendPlainText(line);
4871}
4872
4873void MainWindow::onOJProblemCaseResetOutput(const QString &/* id */, const QString &line)
4874{
4875 ui->txtProblemCaseOutput->setPlainText(line);
4876}
4877
4878void MainWindow::cleanUpCPUDialog()
4879{
4880 disconnect(mCPUDialog,&CPUDialog::closed,
4881 this,&MainWindow::cleanUpCPUDialog);
4882 CPUDialog* ptr=mCPUDialog;
4883 mCPUDialog=nullptr;
4884 ptr->deleteLater();
4885}
4886
4887void MainWindow::onDebugCommandInput(const QString& command)
4888{
4889 if (mDebugger->executing()) {
4890 mDebugger->sendCommand(command,"", DebugCommandSource::Console);
4891 }
4892}
4893
4894void MainWindow::on_actionCompile_triggered()
4895{
4896 mCompileSuccessionTask.reset();
4897 compile();
4898}
4899
4900void MainWindow::on_actionRun_triggered()
4901{
4902 runExecutable();
4903}
4904
4905void MainWindow::on_actionUndo_triggered()
4906{
4907 Editor * editor = mEditorList->getEditor();
4908 if (editor != NULL ) {
4909 editor->undo();
4910 }
4911}
4912
4913void MainWindow::on_actionRedo_triggered()
4914{
4915 Editor * editor = mEditorList->getEditor();
4916 if (editor != NULL ) {
4917 editor->redo();
4918 }
4919}
4920
4921void MainWindow::on_actionCut_triggered()
4922{
4923 Editor * editor = mEditorList->getEditor();
4924 if (editor != NULL ) {
4925 editor->cutToClipboard();
4926 }
4927}
4928
4929void MainWindow::on_actionSelectAll_triggered()
4930{
4931 Editor * editor = mEditorList->getEditor();
4932 if (editor != NULL ) {
4933 editor->selectAll();
4934 }
4935}
4936
4937void MainWindow::on_actionCopy_triggered()
4938{
4939 Editor * editor = mEditorList->getEditor();
4940 if (editor != NULL ) {
4941 editor->copyToClipboard();
4942 }
4943}
4944
4945void MainWindow::on_actionPaste_triggered()
4946{
4947 QClipboard* clipboard = QGuiApplication::clipboard();
4948 const QMimeData* data = clipboard->mimeData();
4949 if (!data)
4950 return;
4951 if (data->hasText()) {
4952 Editor * editor = mEditorList->getEditor();
4953 if (editor != NULL ) {
4954 editor->pasteFromClipboard();
4955 editor->activate();
4956 }
4957 } else if (data->hasUrls()) {
4958 QStringList filesToOpen;
4959 foreach (const QUrl& url, data->urls()) {
4960 QString s = url.toLocalFile();
4961 if (!s.isEmpty()) {
4962 filesToOpen.append(s);
4963 }
4964 }
4965 if (!filesToOpen.isEmpty())
4966 openFiles(filesToOpen);
4967 }
4968}
4969
4970void MainWindow::on_actionIndent_triggered()
4971{
4972 Editor * editor = mEditorList->getEditor();
4973 if (editor != NULL ) {
4974 editor->tab();
4975 }
4976}
4977
4978void MainWindow::on_actionUnIndent_triggered()
4979{
4980 Editor * editor = mEditorList->getEditor();
4981 if (editor != NULL ) {
4982 editor->shifttab();
4983 }
4984}
4985
4986void MainWindow::on_actionToggleComment_triggered()
4987{
4988 Editor * editor = mEditorList->getEditor();
4989 if (editor != NULL ) {
4990 editor->toggleComment();
4991 }
4992}
4993
4994void MainWindow::on_actionUnfoldAll_triggered()
4995{
4996 Editor * editor = mEditorList->getEditor();
4997 if (editor != NULL ) {
4998 editor->unCollpaseAll();
4999 }
5000}
5001
5002void MainWindow::on_actionFoldAll_triggered()
5003{
5004 Editor * editor = mEditorList->getEditor();
5005 if (editor != NULL ) {
5006 editor->collapseAll();
5007 }
5008}
5009
5010void MainWindow::on_tableIssues_doubleClicked(const QModelIndex &index)
5011{
5012 PCompileIssue issue = ui->tableIssues->issue(index);
5013 if (!issue)
5014 return;
5015
5016 Editor * editor = mEditorList->getEditorByFilename(issue->filename);
5017 if (editor == nullptr)
5018 return;
5019
5020 editor->setCaretPositionAndActivate(issue->line,issue->column);
5021}
5022
5023void MainWindow::on_actionEncode_in_ANSI_triggered()
5024{
5025 Editor * editor = mEditorList->getEditor();
5026 if (editor == nullptr)
5027 return;
5028 try {
5029 editor->setEncodingOption(ENCODING_SYSTEM_DEFAULT);
5030 } catch(FileError e) {
5031 QMessageBox::critical(this,tr("Error"),e.reason());
5032 }
5033}
5034
5035void MainWindow::on_actionEncode_in_UTF_8_triggered()
5036{
5037 Editor * editor = mEditorList->getEditor();
5038 if (editor == nullptr)
5039 return;
5040 try {
5041 editor->setEncodingOption(ENCODING_UTF8);
5042 } catch(FileError e) {
5043 QMessageBox::critical(this,tr("Error"),e.reason());
5044 }
5045}
5046
5047void MainWindow::on_actionAuto_Detect_triggered()
5048{
5049 Editor * editor = mEditorList->getEditor();
5050 if (editor == nullptr)
5051 return;
5052 editor->setEncodingOption(ENCODING_AUTO_DETECT);
5053}
5054
5055void MainWindow::on_actionConvert_to_ANSI_triggered()
5056{
5057 Editor * editor = mEditorList->getEditor();
5058 if (editor == nullptr)
5059 return;
5060 if (QMessageBox::warning(this,tr("Confirm Convertion"),
5061 tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
5062 .arg(QString(QTextCodec::codecForLocale()->name())),
5063 QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
5064 return;
5065 editor->convertToEncoding(ENCODING_SYSTEM_DEFAULT);
5066
5067}
5068
5069void MainWindow::on_actionConvert_to_UTF_8_triggered()
5070{
5071 Editor * editor = mEditorList->getEditor();
5072 if (editor == nullptr)
5073 return;
5074 if (QMessageBox::warning(this,tr("Confirm Convertion"),
5075 tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
5076 .arg(ENCODING_UTF8),
5077 QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
5078 return;
5079 editor->convertToEncoding(ENCODING_UTF8);
5080}
5081
5082void MainWindow::on_tabMessages_tabBarClicked(int index)
5083{
5084 if (index == ui->tabMessages->currentIndex() && !ui->tabMessages->isShrinked()) {
5085 stretchMessagesPanel(false);
5086 } else {
5087 stretchMessagesPanel(true);
5088 }
5089}
5090
5091
5092void MainWindow::on_actionCompile_Run_triggered()
5093{
5094 doCompileRun(RunType::Normal);
5095}
5096
5097void MainWindow::on_actionRebuild_triggered()
5098{
5099 mCompileSuccessionTask.reset();
5100 compile(true);
5101}
5102
5103void MainWindow::on_actionStop_Execution_triggered()
5104{
5105 mCompilerManager->stopRun();
5106 mDebugger->stop();
5107}
5108
5109void MainWindow::on_actionDebug_triggered()
5110{
5111 debug();
5112}
5113
5114CompileTarget MainWindow::getCompileTarget()
5115{
5116 // Check if the current file belongs to a project
5117 CompileTarget target = CompileTarget::None;
5118 Editor* e = mEditorList->getEditor();
5119 if (e!=nullptr) {
5120 // Treat makefiles as InProject files too
5121 if (mProject
5122 && (e->inProject() || (mProject->makeFileName() == e->filename()))
5123 ) {
5124 target = CompileTarget::Project;
5125 } else {
5126 target = CompileTarget::File;
5127 }
5128 // No editors have been opened. Check if a project is open
5129 } else if (mProject) {
5130 target = CompileTarget::Project;
5131 }
5132 return target;
5133}
5134
5135bool MainWindow::debugInferiorhasBreakpoint()
5136{
5137 Editor * e = mEditorList->getEditor();
5138 if (e==nullptr)
5139 return false;
5140 if (!e->inProject()) {
5141 for (const PBreakpoint& breakpoint:mDebugger->breakpointModel()->breakpoints()) {
5142 if (e->filename() == breakpoint->filename) {
5143 return true;
5144 }
5145 }
5146 } else {
5147 for (const PBreakpoint& breakpoint:mDebugger->breakpointModel()->breakpoints()) {
5148 Editor* e1 = mEditorList->getOpenedEditorByFilename(breakpoint->filename);
5149 if (e1 && e1->inProject()) {
5150 return true;
5151 }
5152 }
5153 }
5154 return false;
5155}
5156
5157void MainWindow::on_actionStep_Over_triggered()
5158{
5159 if (mDebugger->executing()) {
5160 //WatchView.Items.BeginUpdate();
5161 mDebugger->sendCommand("-exec-next", "");
5162 }
5163}
5164
5165void MainWindow::on_actionStep_Into_triggered()
5166{
5167 if (mDebugger->executing()) {
5168 //WatchView.Items.BeginUpdate();
5169 mDebugger->sendCommand("-exec-step", "");
5170 }
5171
5172}
5173
5174void MainWindow::on_actionStep_Out_triggered()
5175{
5176 if (mDebugger->executing()) {
5177 //WatchView.Items.BeginUpdate();
5178 mDebugger->sendCommand("-exec-finish", "");
5179 }
5180
5181}
5182
5183void MainWindow::on_actionRun_To_Cursor_triggered()
5184{
5185 if (mDebugger->executing()) {
5186 Editor *e=mEditorList->getEditor();
5187 if (e!=nullptr) {
5188 //WatchView.Items.BeginUpdate();
5189 mDebugger->sendCommand("-exec-until", QString("\"%1\":%2")
5190 .arg(e->filename())
5191 .arg(e->caretY()));
5192 }
5193 }
5194
5195}
5196
5197void MainWindow::on_actionContinue_triggered()
5198{
5199 if (mDebugger->executing()) {
5200 //WatchView.Items.BeginUpdate();
5201 mDebugger->sendCommand("-exec-continue", "");
5202 }
5203}
5204
5205void MainWindow::on_actionAdd_Watch_triggered()
5206{
5207 QString s = "";
5208 Editor *e = mEditorList->getEditor();
5209 if (e!=nullptr) {
5210 if (e->selAvail()) {
5211 s = e->selText();
5212 } else {
5213 s = e->wordAtCursor();
5214 }
5215 }
5216 bool isOk;
5217 s=QInputDialog::getText(this,
5218 tr("New Watch Expression"),
5219 tr("Enter Watch Expression (it is recommended to use 'this->' for class members):"),
5220 QLineEdit::Normal,
5221 s,&isOk);
5222 if (!isOk)
5223 return;
5224 s = s.trimmed();
5225 if (!s.isEmpty()) {
5226 mDebugger->addWatchVar(s);
5227 }
5228}
5229
5230void MainWindow::on_actionView_CPU_Window_triggered()
5231{
5232 showCPUInfoDialog();
5233}
5234
5235void MainWindow::on_actionExit_triggered()
5236{
5237 close();
5238}
5239
5240void MainWindow::onDebugEvaluateInput()
5241{
5242 QString s=ui->cbEvaluate->currentText().trimmed();
5243 if (!s.isEmpty()) {
5244 connect(mDebugger, &Debugger::evalValueReady,
5245 this, &MainWindow::onEvalValueReady);
5246 mDebugger->sendCommand("-data-evaluate-expression",s);
5247 pMainWindow->debugger()->refreshAll();
5248 }
5249}
5250
5251void MainWindow::onDebugMemoryAddressInput()
5252{
5253 QString s=ui->cbMemoryAddress->currentText().trimmed();
5254 if (!s.isEmpty()) {
5255// connect(mDebugger, &Debugger::memoryExamineReady,
5256// this, &MainWindow::onMemoryExamineReady);
5257 mDebugger->sendCommand("-data-read-memory",QString("%1 x 1 %2 %3 ")
5258 .arg(s)
5259 .arg(pSettings->debugger().memoryViewRows())
5260 .arg(pSettings->debugger().memoryViewColumns())
5261 );
5262 }
5263}
5264
5265void MainWindow::onParserProgress(const QString &fileName, int total, int current)
5266{
5267 // Mention every 5% progress
5268 int showStep = total / 20;
5269
5270 // For Total = 1, avoid division by zero
5271 if (showStep == 0)
5272 showStep = 1;
5273
5274 // Only show if needed (it's a very slow operation)
5275 if (current ==1 || current % showStep==0) {
5276 updateStatusbarMessage(tr("Parsing file %1 of %2: \"%3\"")
5277 .arg(current).arg(total).arg(fileName));
5278 }
5279}
5280
5281void MainWindow::onStartParsing()
5282{
5283 mParserTimer.restart();
5284}
5285
5286void MainWindow::onEndParsing(int total, int)
5287{
5288 double parseTime = mParserTimer.elapsed() / 1000.0;
5289 double parsingFrequency;
5290
5291
5292 if (total > 1) {
5293 if (parseTime>0) {
5294 parsingFrequency = total / parseTime;
5295 } else {
5296 parsingFrequency = 999;
5297 }
5298 updateStatusbarMessage(tr("Done parsing %1 files in %2 seconds")
5299 .arg(total).arg(parseTime)
5300 + " "
5301 + tr("(%1 files per second)")
5302 .arg(parsingFrequency));
5303 } else {
5304 updateStatusbarMessage(tr("Done parsing %1 files in %2 seconds")
5305 .arg(total).arg(parseTime));
5306 }
5307}
5308
5309void MainWindow::onEvalValueReady(const QString& value)
5310{
5311 updateDebugEval(value);
5312 disconnect(mDebugger, &Debugger::evalValueReady,
5313 this, &MainWindow::onEvalValueReady);
5314}
5315
5316void MainWindow::onLocalsReady(const QStringList& value)
5317{
5318 ui->txtLocals->clear();
5319 foreach (QString s, value) {
5320 ui->txtLocals->appendPlainText(s);
5321 }
5322 ui->txtLocals->moveCursor(QTextCursor::Start);
5323}
5324
5325void MainWindow::on_actionFind_triggered()
5326{
5327 Editor *e = mEditorList->getEditor();
5328 if (!e)
5329 return;
5330 if (mSearchDialog==nullptr) {
5331 mSearchDialog = new SearchDialog(this);
5332 }
5333 QString s = e->wordAtCursor();
5334 mSearchDialog->find(s);
5335}
5336
5337void MainWindow::on_actionFind_in_files_triggered()
5338{
5339 if (mSearchDialog==nullptr) {
5340 mSearchDialog = new SearchDialog(this);
5341 }
5342 Editor *e = mEditorList->getEditor();
5343 if (e) {
5344 QString s = e->wordAtCursor();
5345 mSearchDialog->findInFiles(s);
5346 } else {
5347 mSearchDialog->findInFiles("");
5348 }
5349}
5350
5351void MainWindow::on_actionReplace_triggered()
5352{
5353 Editor *e = mEditorList->getEditor();
5354 if (!e)
5355 return;
5356 if (mSearchDialog==nullptr) {
5357 mSearchDialog = new SearchDialog(this);
5358 }
5359 QString s = e->wordAtCursor();
5360 mSearchDialog->replace(s,s);
5361}
5362
5363void MainWindow::on_actionFind_Next_triggered()
5364{
5365 Editor *e = mEditorList->getEditor();
5366 if (e==nullptr)
5367 return;
5368
5369 if (mSearchDialog==nullptr)
5370 return;
5371
5372 mSearchDialog->findNext();
5373}
5374
5375void MainWindow::on_actionFind_Previous_triggered()
5376{
5377 Editor *e = mEditorList->getEditor();
5378 if (e==nullptr)
5379 return;
5380
5381 if (mSearchDialog==nullptr)
5382 return;
5383
5384 mSearchDialog->findPrevious();
5385}
5386
5387void MainWindow::on_cbSearchHistory_currentIndexChanged(int index)
5388{
5389 mSearchResultModel.setCurrentIndex(index);
5390 PSearchResults results = mSearchResultModel.results(index);
5391 if (results) {
5392 ui->btnSearchAgain->setEnabled(true);
5393 } else {
5394 ui->btnSearchAgain->setEnabled(false);
5395 }
5396}
5397
5398void MainWindow::on_btnSearchAgain_clicked()
5399{
5400 if (mSearchDialog==nullptr) {
5401 mSearchDialog = new SearchDialog(this);
5402 }
5403 PSearchResults results=mSearchResultModel.currentResults();
5404 if (!results)
5405 return;
5406 if (results->searchType == SearchType::Search){
5407 mSearchDialog->findInFiles(results->keyword,
5408 results->scope,
5409 results->options);
5410 } else if (results->searchType == SearchType::FindOccurences) {
5411 CppRefacter refactor;
5412 refactor.findOccurence(results->statementFullname,results->scope);
5413 }
5414}
5415
5416void MainWindow::on_actionRemove_Watch_triggered()
5417{
5418 QModelIndexList lst=ui->watchView->selectionModel()->selectedRows();
5419 if (lst.count()<=1) {
5420 QModelIndex index =ui->watchView->currentIndex();
5421 QModelIndex parent;
5422 while (true) {
5423 parent = ui->watchView->model()->parent(index);
5424 if (parent.isValid()) {
5425 index=parent;
5426 } else {
5427 break;
5428 }
5429 }
5430 mDebugger->removeWatchVar(index);
5431 } else {
5432 QModelIndexList filteredList;
5433 foreach(const QModelIndex& index,lst) {
5434 if (!index.parent().isValid())
5435 filteredList.append(index);
5436 };
5437 std::sort(filteredList.begin(),filteredList.end(), [](const QModelIndex& index1,
5438 const QModelIndex& index2) {
5439 return index1.row()>index2.row();
5440 });
5441 foreach(const QModelIndex& index,filteredList) {
5442 mDebugger->removeWatchVar(index);
5443 };
5444 }
5445}
5446
5447
5448void MainWindow::on_actionRemove_All_Watches_triggered()
5449{
5450 mDebugger->removeWatchVars(true);
5451}
5452
5453
5454void MainWindow::on_actionModify_Watch_triggered()
5455{
5456 QModelIndexList lst=ui->watchView->selectionModel()->selectedRows();
5457 if (lst.count()<=1) {
5458 QModelIndex index =ui->watchView->currentIndex();
5459 QModelIndex parent;
5460 parent = ui->watchView->model()->parent(index);
5461 if (parent.isValid())
5462 return;
5463 PWatchVar var = mDebugger->watchVarAt(index);
5464 if (!var)
5465 return;
5466 bool isOk;
5467 QString newExpr = QInputDialog::getText(
5468 this,tr("Modify Watch"),
5469 tr("Watch Expression"),
5470 QLineEdit::Normal,
5471 var->expression,
5472 &isOk);
5473 if (isOk) {
5474 mDebugger->modifyWatchVarExpression(var->expression,newExpr);
5475 }
5476 }
5477}
5478
5479
5480void MainWindow::on_actionReformat_Code_triggered()
5481{
5482 Editor* e = mEditorList->getEditor();
5483 if (e) {
5484 e->reformat();
5485 e->activate();
5486 }
5487}
5488
5489CaretList &MainWindow::caretList()
5490{
5491 return mCaretList;
5492}
5493
5494void MainWindow::updateCaretActions()
5495{
5496 ui->actionBack->setEnabled(mCaretList.hasPrevious());
5497 ui->actionForward->setEnabled(mCaretList.hasNext());
5498}
5499
5500
5501void MainWindow::on_actionBack_triggered()
5502{
5503 PEditorCaret caret = mCaretList.gotoAndGetPrevious();
5504 mCaretList.pause();
5505 if (caret) {
5506 caret->editor->setCaretPositionAndActivate(caret->line,caret->aChar);
5507 }
5508 mCaretList.unPause();
5509 updateCaretActions();
5510}
5511
5512
5513void MainWindow::on_actionForward_triggered()
5514{
5515 PEditorCaret caret = mCaretList.gotoAndGetNext();
5516 mCaretList.pause();
5517 if (caret) {
5518 caret->editor->setCaretPositionAndActivate(caret->line,caret->aChar);
5519 }
5520 mCaretList.unPause();
5521 updateCaretActions();
5522}
5523
5524
5525void MainWindow::on_tabExplorer_tabBarClicked(int index)
5526{
5527 if (index == ui->tabExplorer->currentIndex() && !ui->tabExplorer->isShrinked()) {
5528 stretchExplorerPanel(false);
5529 } else {
5530 stretchExplorerPanel(true);
5531 }
5532}
5533
5534
5535void MainWindow::on_EditorTabsLeft_tabBarDoubleClicked(int)
5536{
5537 maximizeEditor();
5538}
5539
5540void MainWindow::on_EditorTabsRight_tabBarDoubleClicked(int)
5541{
5542 maximizeEditor();
5543}
5544
5545
5546void MainWindow::on_actionClose_triggered()
5547{
5548 mClosing = true;
5549 Editor* e = mEditorList->getEditor();
5550 if (e) {
5551 mEditorList->closeEditor(e);
5552 }
5553 mClosing = false;
5554}
5555
5556
5557void MainWindow::on_actionClose_All_triggered()
5558{
5559 mClosingAll=true;
5560 mClosing = true;
5561 mEditorList->closeAll(mSystemTurnedOff);
5562 mClosing = false;
5563 mClosingAll=false;
5564}
5565
5566
5567void MainWindow::on_actionMaximize_Editor_triggered()
5568{
5569 maximizeEditor();
5570}
5571
5572
5573void MainWindow::on_actionNext_Editor_triggered()
5574{
5575 mEditorList->selectNextPage();
5576}
5577
5578
5579void MainWindow::on_actionPrevious_Editor_triggered()
5580{
5581 mEditorList->selectPreviousPage();
5582}
5583
5584
5585void MainWindow::on_actionToggle_Breakpoint_triggered()
5586{
5587 Editor * editor = mEditorList->getEditor();
5588 int line;
5589 if (editor && editor->pointToLine(mEditorContextMenuPos,line))
5590 editor->toggleBreakpoint(line);
5591}
5592
5593
5594void MainWindow::on_actionClear_all_breakpoints_triggered()
5595{
5596 Editor *e=mEditorList->getEditor();
5597 if (!e)
5598 return;
5599 if (QMessageBox::question(this,
5600 tr("Clear all breakpoints"),
5601 tr("Do you really want to clear all breakpoints in this file?"),
5602 QMessageBox::Yes | QMessageBox::No,
5603 QMessageBox::No) == QMessageBox::Yes) {
5604 e->clearBreakpoints();
5605 }
5606}
5607
5608
5609void MainWindow::on_actionBreakpoint_property_triggered()
5610{
5611 Editor * editor = mEditorList->getEditor();
5612 int line;
5613 if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
5614 if (editor->hasBreakpoint(line))
5615 editor->modifyBreakpointProperty(line);
5616 }
5617
5618}
5619
5620
5621void MainWindow::on_actionGoto_Declaration_triggered()
5622{
5623 Editor * editor = mEditorList->getEditor();
5624 if (editor) {
5625 editor->gotoDeclaration(editor->caretXY());
5626 }
5627}
5628
5629void MainWindow::on_actionGoto_Definition_triggered()
5630{
5631 Editor * editor = mEditorList->getEditor();
5632 if (editor) {
5633 editor->gotoDefinition(editor->caretXY());
5634 }
5635}
5636
5637
5638void MainWindow::on_actionFind_references_triggered()
5639{
5640 Editor * editor = mEditorList->getEditor();
5641 QSynedit::BufferCoord pos;
5642 if (editor && editor->pointToCharLine(mEditorContextMenuPos,pos)) {
5643 CppRefacter refactor;
5644 refactor.findOccurence(editor,pos);
5645 showSearchPanel(true);
5646 }
5647}
5648
5649
5650void MainWindow::on_actionOpen_Containing_Folder_triggered()
5651{
5652 Editor* editor = mEditorList->getEditor();
5653 if (editor) {
5654 QFileInfo info(editor->filename());
5655 if (!info.path().isEmpty()) {
5656 QDesktopServices::openUrl(
5657 QUrl("file:///"+
5658 includeTrailingPathDelimiter(info.path()),QUrl::TolerantMode));
5659 }
5660 }
5661}
5662
5663
5664void MainWindow::on_actionOpen_Terminal_triggered()
5665{
5666 Editor* editor = mEditorList->getEditor();
5667 if (editor) {
5668 QFileInfo info(editor->filename());
5669 if (!info.path().isEmpty()) {
5670#ifdef Q_OS_WIN
5671 openShell(info.path(),"cmd.exe",getBinDirsForCurrentEditor());
5672#else
5673 openShell(info.path(),pSettings->environment().terminalPath(),getBinDirsForCurrentEditor());
5674#endif
5675 }
5676 }
5677
5678}
5679
5680
5681void MainWindow::on_actionFile_Properties_triggered()
5682{
5683 Editor* editor = mEditorList->getEditor();
5684 if (editor) {
5685 FilePropertiesDialog dialog(editor,this);
5686 dialog.exec();
5687 dialog.setParent(nullptr);
5688 }
5689}
5690
5691void MainWindow::on_searchView_doubleClicked(const QModelIndex &index)
5692{
5693 QString filename;
5694 int line;
5695 int start;
5696 if (mSearchResultTreeModel->getItemFileAndLineChar(
5697 index,filename,line,start)) {
5698 Editor *e = mEditorList->getEditorByFilename(filename);
5699 if (e) {
5700 e->setCaretPositionAndActivate(line,start);
5701 }
5702 }
5703}
5704
5705
5706void MainWindow::on_tblStackTrace_doubleClicked(const QModelIndex &index)
5707{
5708 PTrace trace = mDebugger->backtraceModel()->backtrace(index.row());
5709 if (trace) {
5710 Editor *e = mEditorList->getEditorByFilename(trace->filename);
5711 if (e) {
5712 e->setCaretPositionAndActivate(trace->line,1);
5713 }
5714 mDebugger->sendCommand("-stack-select-frame", QString("%1").arg(trace->level));
5715 mDebugger->sendCommand("-stack-list-variables", "--all-values");
5716 mDebugger->sendCommand("-var-update", "--all-values *");
5717 if (this->mCPUDialog) {
5718 this->mCPUDialog->updateInfo();
5719 }
5720 }
5721}
5722
5723
5724void MainWindow::on_tblBreakpoints_doubleClicked(const QModelIndex &index)
5725{
5726 PBreakpoint breakpoint = mDebugger->breakpointModel()->breakpoint(index.row());
5727 if (breakpoint) {
5728 Editor * e = mEditorList->getEditorByFilename(breakpoint->filename);
5729 if (e) {
5730 e->setCaretPositionAndActivate(breakpoint->line,1);
5731 }
5732 }
5733}
5734
5735std::shared_ptr<Project> MainWindow::project()
5736{
5737 return mProject;
5738}
5739
5740
5741void MainWindow::on_projectView_doubleClicked(const QModelIndex &index)
5742{
5743 QModelIndex sourceIndex = mProjectProxyModel->mapToSource(index);
5744 if (!sourceIndex.isValid())
5745 return;
5746 ProjectModelNode * node = static_cast<ProjectModelNode*>(sourceIndex.internalPointer());
5747 if (!node)
5748 return;
5749 if (node->unitIndex>=0) {
5750 mProject->openUnit(node->unitIndex);
5751 }
5752}
5753
5754
5755void MainWindow::on_actionClose_Project_triggered()
5756{
5757 mClosing = true;
5758 closeProject(true);
5759 mClosing = false;
5760}
5761
5762
5763void MainWindow::on_actionProject_options_triggered()
5764{
5765 if (!mProject)
5766 return;
5767 QString oldName = mProject->name();
5768 PSettingsDialog dialog = SettingsDialog::projectOptionDialog();
5769 dialog->exec();
5770 updateCompilerSet();
5771}
5772
5773
5774void MainWindow::on_actionNew_Project_triggered()
5775{
5776 NewProjectDialog dialog;
5777 if (dialog.exec() == QDialog::Accepted) {
5778 if (dialog.makeDefaultLanguage()) {
5779 pSettings->editor().setDefaultFileCpp(dialog.isCppProject());
5780 pSettings->editor().save();
5781 }
5782 if (dialog.useAsDefaultProjectDir()) {
5783 pSettings->dirs().setProjectDir(dialog.getLocation());
5784 pSettings->dirs().save();
5785 }
5786 // Take care of the currently opened project
5787 QString s;
5788 if (mProject) {
5789 if (mProject->name().isEmpty())
5790 s = mProject->filename();
5791 else
5792 s = mProject->name();
5793
5794 // Ask if the user wants to close the current one. If not, abort
5795 if (QMessageBox::question(this,
5796 tr("New project"),
5797 tr("Close %1 and start new project?").arg(s),
5798 QMessageBox::Yes | QMessageBox::No,
5799 QMessageBox::Yes)==QMessageBox::Yes) {
5800 closeProject(false);
5801 } else
5802 return;
5803 }
5804
5805 //Create the project folder
5806 QString location = includeTrailingPathDelimiter(dialog.getLocation())+dialog.getProjectName();
5807 QDir dir(location);
5808 if (!dir.exists()) {
5809 if (QMessageBox::question(this,
5810 tr("Folder not exist"),
5811 tr("Folder '%1' doesn't exist. Create it now?").arg(location),
5812 QMessageBox::Yes | QMessageBox::No,
5813 QMessageBox::Yes) != QMessageBox::Yes) {
5814 return;
5815 }
5816 if (!dir.mkpath(location)) {
5817 QMessageBox::critical(this,
5818 tr("Can't create folder"),
5819 tr("Failed to create folder '%1'.").arg(location),
5820 QMessageBox::Yes);
5821 return;
5822 }
5823 }
5824
5825// if cbDefault.Checked then
5826// devData.DefCpp := rbCpp.Checked;
5827
5828 s = includeTrailingPathDelimiter(location)
5829 + dialog.getProjectName() + "." + DEV_PROJECT_EXT;
5830
5831 if (fileExists(s)) {
5832 QString saveName = QFileDialog::getSaveFileName(
5833 this,
5834 tr("Save new project as"),
5835 location,
5836 tr("Red Panda C++ project file (*.dev)"));
5837 if (!saveName.isEmpty()) {
5838 s = saveName;
5839 }
5840 }
5841
5842 // Create an empty project
5843 mProject = std::make_shared<Project>(s,dialog.getProjectName(),
5844 mEditorList,
5845 &mFileSystemWatcher);
5846 if (!mProject->assignTemplate(dialog.getTemplate(),dialog.isCppProject())) {
5847 mProject = nullptr;
5848 QMessageBox::critical(this,
5849 tr("New project fail"),
5850 tr("Can't assign project template"),
5851 QMessageBox::Ok);
5852 }
5853 mProject->saveAll();
5854 updateProjectView();
5855 }
5856 pSettings->ui().setNewProjectDialogWidth(dialog.width());
5857 pSettings->ui().setNewProjectDialogHeight(dialog.height());
5858}
5859
5860
5861void MainWindow::on_actionSaveAll_triggered()
5862{
5863 // Pause the change notifier
5864 bool oldBlock = mFileSystemWatcher.blockSignals(true);
5865 auto action = finally([oldBlock,this] {
5866 mFileSystemWatcher.blockSignals(oldBlock);
5867 });
5868 if (mProject) {
5869 mProject->saveAll();
5870 }
5871
5872 // Make changes to files
5873 for (int i=0;i<mEditorList->pageCount();i++) {
5874 Editor * e= (*mEditorList)[i];
5875 if (e->modified() && !e->inProject()) {
5876 if (!e->save())
5877 break;
5878 }
5879 }
5880 updateAppTitle();
5881}
5882
5883
5884void MainWindow::on_actionProject_New_File_triggered()
5885{
5886 newProjectUnitFile();
5887}
5888
5889
5890void MainWindow::on_actionAdd_to_project_triggered()
5891{
5892 if (!mProject)
5893 return;
5894 QFileDialog dialog(this,tr("Add to project"),
5895 mProject->directory(),
5896 pSystemConsts->defaultFileFilters().join(";;"));
5897 dialog.setFileMode(QFileDialog::ExistingFiles);
5898 dialog.setAcceptMode(QFileDialog::AcceptOpen);
5899 if (dialog.exec()) {
5900 QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->currentIndex());
5901 ProjectModelNode * node = nullptr;
5902 if (current.isValid()) {
5903 node = static_cast<ProjectModelNode*>(current.internalPointer());
5904 }
5905 PProjectModelNode folderNode = mProject->pointerToNode(node);
5906 foreach (const QString& filename, dialog.selectedFiles()) {
5907 mProject->addUnit(filename,folderNode,false);
5908 mProject->cppParser()->addFileToScan(filename);
5909 QString branch;
5910 if (pSettings->vcs().gitOk() && mProject->model()->iconProvider()->VCSRepository()->hasRepository(branch)) {
5911 QString output;
5912 mProject->model()->iconProvider()->VCSRepository()->add(
5913 extractRelativePath(mProject->folder(),filename),
5914 output
5915 );
5916 }
5917 }
5918 mProject->rebuildNodes();
5919 mProject->saveUnits();
5920 parseFileList(mProject->cppParser());
5921 updateProjectView();
5922 }
5923}
5924
5925
5926void MainWindow::on_actionRemove_from_project_triggered()
5927{
5928 if (!mProject)
5929 return;
5930 if (!ui->projectView->selectionModel()->hasSelection())
5931 return;
5932 mProject->model()->beginUpdate();
5933 QSet<int> selected;
5934 foreach (const QModelIndex& index, ui->projectView->selectionModel()->selectedIndexes()){
5935 if (!index.isValid())
5936 continue;
5937 QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
5938 ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
5939 PProjectModelNode folderNode = mProject->pointerToNode(node);
5940 if (!folderNode)
5941 continue;
5942 selected.insert(folderNode->unitIndex);
5943 };
5944
5945 bool removeFile = (QMessageBox::question(this,tr("Remove file"),
5946 tr("Remove the file from disk?"),
5947 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes);
5948
5949 for (int i=mProject->units().count()-1;i>=0;i--) {
5950 if (selected.contains(i)) {
5951 mProject->removeUnit(i,true,removeFile);
5952 }
5953 }
5954
5955 mProject->saveUnits();
5956 mProject->model()->endUpdate();
5957 updateProjectView();
5958}
5959
5960
5961void MainWindow::on_actionView_Makefile_triggered()
5962{
5963 if (!mProject)
5964 return;
5965 prepareProjectForCompile();
5966 mCompilerManager->buildProjectMakefile(mProject);
5967 openFile(mProject->makeFileName());
5968}
5969
5970
5971void MainWindow::on_actionMakeClean_triggered()
5972{
5973 if (!mProject)
5974 return;
5975 prepareProjectForCompile();
5976 mCompilerManager->cleanProject(mProject);
5977}
5978
5979
5980void MainWindow::on_actionProject_Open_Folder_In_Explorer_triggered()
5981{
5982 if (!mProject)
5983 return;
5984 QDesktopServices::openUrl(
5985 QUrl("file:///"+includeTrailingPathDelimiter(mProject->directory()),QUrl::TolerantMode));
5986}
5987
5988
5989void MainWindow::on_actionProject_Open_In_Terminal_triggered()
5990{
5991 if (!mProject)
5992 return;
5993#ifdef Q_OS_WIN
5994 openShell(mProject->directory(),"cmd.exe",mProject->binDirs());
5995#else
5996 openShell(mProject->directory(),pSettings->environment().terminalPath(),mProject->binDirs());
5997#endif
5998}
5999
6000const std::shared_ptr<QHash<StatementKind, std::shared_ptr<ColorSchemeItem> > > &MainWindow::statementColors() const
6001{
6002 return mStatementColors;
6003}
6004
6005
6006void MainWindow::on_classBrowser_doubleClicked(const QModelIndex &index)
6007{
6008 if (!index.isValid())
6009 return ;
6010 ClassBrowserNode * node = static_cast<ClassBrowserNode*>(index.internalPointer());
6011 if (!node)
6012 return ;
6013 PStatement statement = node->statement;
6014 if (!statement) {
6015 return;
6016 }
6017 QString filename;
6018 int line;
6019 filename = statement->fileName;
6020 line = statement->line;
6021 Editor* e = pMainWindow->editorList()->getEditorByFilename(filename);
6022 if (e) {
6023 e->setCaretPositionAndActivate(line,1);
6024 }
6025}
6026
6027const PTodoParser &MainWindow::todoParser() const
6028{
6029 return mTodoParser;
6030}
6031
6032PCodeSnippetManager &MainWindow::codeSnippetManager()
6033{
6034 return mCodeSnippetManager;
6035}
6036
6037PSymbolUsageManager &MainWindow::symbolUsageManager()
6038{
6039 return mSymbolUsageManager;
6040}
6041
6042void MainWindow::showHideInfosTab(QWidget *widget, bool show)
6043{
6044 int idx = findTabIndex(ui->tabExplorer,widget);
6045 if (idx>=0) {
6046 if (!show) {
6047 if (mTabInfosData.contains(widget)) {
6048 PTabWidgetInfo info = mTabInfosData[widget];
6049 info->icon = ui->tabExplorer->tabIcon(idx);
6050 info->text = ui->tabExplorer->tabText(idx);
6051 }
6052
6053 ui->tabExplorer->removeTab(idx);
6054 }
6055 } else {
6056 if (show && mTabInfosData.contains(widget)) {
6057 PTabWidgetInfo info = mTabInfosData[widget];
6058 int insert = -1;
6059 for (int i=0;i<ui->tabExplorer->count();i++) {
6060 QWidget * w=ui->tabExplorer->widget(i);
6061 PTabWidgetInfo infoW = mTabInfosData[w];
6062 if (infoW->order>info->order) {
6063 insert = i;
6064 break;
6065 }
6066 }
6067 if (insert>=0) {
6068 ui->tabExplorer->insertTab(insert, widget, info->icon, info->text);
6069 } else {
6070 ui->tabExplorer->addTab(widget, info->icon, info->text);
6071 }
6072 }
6073 }
6074}
6075
6076void MainWindow::showHideMessagesTab(QWidget *widget, bool show)
6077{
6078 int idx = findTabIndex(ui->tabMessages,widget);
6079 if (idx>=0) {
6080 if (!show) {
6081 if (mTabMessagesData.contains(widget)) {
6082 PTabWidgetInfo info = mTabMessagesData[widget];
6083 info->icon = ui->tabMessages->tabIcon(idx);
6084 info->text = ui->tabMessages->tabText(idx);
6085 }
6086 ui->tabMessages->removeTab(idx);
6087 }
6088 } else {
6089 if (show && mTabMessagesData.contains(widget)) {
6090 PTabWidgetInfo info = mTabMessagesData[widget];
6091 int insert = -1;
6092 for (int i=0;i<ui->tabMessages->count();i++) {
6093 QWidget * w=ui->tabMessages->widget(i);
6094 PTabWidgetInfo infoW = mTabMessagesData[w];
6095 if (infoW->order>info->order) {
6096 insert = i;
6097 break;
6098 }
6099 }
6100 if (insert>=0) {
6101 ui->tabMessages->insertTab(insert, widget, info->icon, info->text);
6102 } else {
6103 ui->tabMessages->addTab(widget, info->icon, info->text);
6104 }
6105 }
6106 }
6107}
6108
6109
6110void MainWindow::prepareTabInfosData()
6111{
6112 for (int i=0;i<ui->tabExplorer->count();i++) {
6113 QWidget* widget = ui->tabExplorer->widget(i);
6114 PTabWidgetInfo info = std::make_shared<TabWidgetInfo>();
6115 info->order =i;
6116 info->text = ui->tabExplorer->tabText(i);
6117 info->icon = ui->tabExplorer->tabIcon(i);
6118 mTabInfosData[widget]=info;
6119 }
6120}
6121
6122void MainWindow::prepareTabMessagesData()
6123{
6124 for (int i=0;i<ui->tabMessages->count();i++) {
6125 QWidget* widget = ui->tabMessages->widget(i);
6126 PTabWidgetInfo info = std::make_shared<TabWidgetInfo>();
6127 info->order =i;
6128 info->text = ui->tabMessages->tabText(i);
6129 info->icon = ui->tabMessages->tabIcon(i);
6130 mTabMessagesData[widget]=info;
6131 }
6132}
6133
6134void MainWindow::newProjectUnitFile()
6135{
6136 if (!mProject)
6137 return;
6138 int idx = -1;
6139 QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->currentIndex());
6140 ProjectModelNode * node = nullptr;
6141 if (current.isValid()) {
6142 node = static_cast<ProjectModelNode*>(current.internalPointer());
6143 }
6144 PProjectModelNode pNode = mProject->pointerToNode(node);
6145
6146 while (pNode && pNode->unitIndex>0) {
6147 pNode = pNode->parent.lock();
6148 }
6149
6150 if (!pNode) {
6151 pNode = mProject->rootNode();
6152 }
6153
6154 QString newFileName;
6155 PProjectUnit newUnit;
6156 if (mProject->modelType() == ProjectModelType::FileSystem) {
6157 PProjectModelNode modelTypeNode = pNode;
6158 while (modelTypeNode && modelTypeNode->folderNodeType==ProjectSpecialFolderNode::NonSpecial) {
6159 modelTypeNode=modelTypeNode->parent.lock();
6160 }
6161 if (!modelTypeNode) {
6162 modelTypeNode = mProject->rootNode();
6163 }
6164 NewProjectUnitDialog newProjectUnitDialog;
6165 if (modelTypeNode == mProject->rootNode()) {
6166 if (mProject->options().isCpp)
6167 newProjectUnitDialog.setSuffix("cpp");
6168 else
6169 newProjectUnitDialog.setSuffix("c");
6170 } else {
6171 switch (modelTypeNode->folderNodeType) {
6172 case ProjectSpecialFolderNode::HEADERS:
6173 newProjectUnitDialog.setSuffix("h");
6174 break;
6175 case ProjectSpecialFolderNode::SOURCES:
6176 if (mProject->options().isCpp)
6177 newProjectUnitDialog.setSuffix("cpp");
6178 else
6179 newProjectUnitDialog.setSuffix("c");
6180 break;
6181 default:
6182 newProjectUnitDialog.setSuffix("txt");
6183 }
6184 }
6185 QString folder = mProject->fileSystemNodeFolderPath(pNode);
6186// qDebug()<<folder;
6187 newProjectUnitDialog.setFolder(folder);
6188 if (newProjectUnitDialog.exec()!=QDialog::Accepted) {
6189 return;
6190 }
6191 newFileName=QDir(newProjectUnitDialog.folder()).absoluteFilePath(newProjectUnitDialog.filename());
6192 if (newFileName.isEmpty())
6193 return;
6194 } else {
6195 do {
6196 newFileName = tr("untitled")+QString("%1").arg(getNewFileNumber());
6197 if (mProject->options().isCpp)
6198 newFileName += ".cpp";
6199 else
6200 newFileName += ".c";
6201 } while (QDir(mProject->directory()).exists(newFileName));
6202 newFileName = QInputDialog::getText(
6203 this,
6204 tr("New Project File Name"),
6205 tr("File Name:"),
6206 QLineEdit::Normal,
6207 newFileName);
6208 if (newFileName.isEmpty())
6209 return;
6210 newFileName = QDir(mProject->directory()).absoluteFilePath(newFileName);
6211 }
6212 if (fileExists(newFileName)) {
6213 QMessageBox::critical(this,tr("File Already Exists!"),
6214 tr("File '%1' already exists!").arg(newFileName));
6215 return;
6216 }
6217 newUnit = mProject->newUnit(
6218 pNode,newFileName);
6219
6220 mProject->rebuildNodes();
6221 mProject->saveAll();
6222 updateProjectView();
6223 idx = mProject->units().count()-1;
6224 Editor * editor = mProject->openUnit(idx, false);
6225 //editor->setUseCppSyntax(mProject->options().useGPP);
6226 //editor->setModified(true);
6227 if (editor)
6228 editor->activate();
6229 QString branch;
6230 if (pSettings->vcs().gitOk() && mProject->model()->iconProvider()->VCSRepository()->hasRepository(branch)) {
6231 QString output;
6232 mProject->model()->iconProvider()->VCSRepository()->add(newFileName,output);
6233 mProject->model()->beginUpdate();
6234 mProject->model()->endUpdate();
6235 }
6236 updateProjectView();
6237}
6238
6239void MainWindow::fillProblemCaseInputAndExpected(const POJProblemCase &problemCase)
6240{
6241 ui->btnProblemCaseInputFileName->setEnabled(true);
6242 if (fileExists(problemCase->inputFileName)) {
6243 ui->txtProblemCaseInput->setReadOnly(true);
6244 ui->txtProblemCaseInput->setPlainText(readFileToByteArray(problemCase->inputFileName));
6245 ui->btnProblemCaseClearInputFileName->setVisible(true);
6246 ui->txtProblemCaseInputFileName->setText(extractFileName(problemCase->inputFileName));
6247 ui->txtProblemCaseInputFileName->setToolTip(problemCase->inputFileName);
6248 } else {
6249 ui->txtProblemCaseInput->setReadOnly(false);
6250 ui->txtProblemCaseInput->setPlainText(problemCase->input);
6251 ui->btnProblemCaseClearInputFileName->setVisible(false);
6252 ui->txtProblemCaseInputFileName->clear();
6253 ui->txtProblemCaseInputFileName->setToolTip("");
6254 }
6255 ui->btnProblemCaseExpectedOutputFileName->setEnabled(true);
6256 if (fileExists(problemCase->expectedOutputFileName)) {
6257 ui->txtProblemCaseExpected->setReadOnly(true);
6258 ui->txtProblemCaseExpected->setPlainText(readFileToByteArray(problemCase->expectedOutputFileName));
6259 ui->btnProblemCaseClearExpectedOutputFileName->setVisible(true);
6260 ui->txtProblemCaseExpectedOutputFileName->setText(extractFileName(problemCase->expectedOutputFileName));
6261 ui->txtProblemCaseExpectedOutputFileName->setToolTip(problemCase->inputFileName);
6262 } else {
6263 ui->txtProblemCaseExpected->setReadOnly(false);
6264 ui->txtProblemCaseExpected->setPlainText(problemCase->expected);
6265 ui->btnProblemCaseClearExpectedOutputFileName->setVisible(false);
6266 ui->txtProblemCaseExpectedOutputFileName->clear();
6267 ui->txtProblemCaseExpectedOutputFileName->setToolTip("");
6268 }
6269}
6270
6271void MainWindow::doFilesViewRemoveFile(const QModelIndex &index)
6272{
6273 if (!index.isValid())
6274 return;
6275 if (mFileSystemModel.isDir(index)) {
6276 QDir dir(mFileSystemModel.fileInfo(index).absoluteFilePath());
6277 if (!dir.isEmpty() &&
6278 QMessageBox::question(ui->treeFiles
6279 ,tr("Delete")
6280 ,tr("Folder %1 is not empty.").arg(mFileSystemModel.fileName(index))
6281 + tr("Do you really want to delete it?"),
6282 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)!=QMessageBox::Yes)
6283 return;
6284 dir.removeRecursively();
6285 } else {
6286 QFile::remove(mFileSystemModel.filePath(index));
6287 }
6288}
6289
6290static void setDockTitlebarLocation(QDockWidget* dock, const Qt::DockWidgetArea &area) {
6291 switch(area) {
6292 case Qt::DockWidgetArea::BottomDockWidgetArea:
6293 case Qt::DockWidgetArea::TopDockWidgetArea:
6294 dock->setFeatures(dock->features() | QDockWidget::DockWidgetVerticalTitleBar);
6295 break;
6296 default:
6297 dock->setFeatures(dock->features() & ~QDockWidget::DockWidgetVerticalTitleBar);
6298 }
6299}
6300
6301static void setTabsInDockLocation(QTabWidget* tabs, const Qt::DockWidgetArea &area) {
6302 switch(area) {
6303 case Qt::DockWidgetArea::BottomDockWidgetArea:
6304 case Qt::DockWidgetArea::TopDockWidgetArea:
6305 tabs->setTabPosition(QTabWidget::TabPosition::South);
6306 break;
6307 case Qt::DockWidgetArea::LeftDockWidgetArea:
6308 tabs->setTabPosition(QTabWidget::TabPosition::West);
6309 break;
6310 case Qt::DockWidgetArea::RightDockWidgetArea:
6311 tabs->setTabPosition(QTabWidget::TabPosition::East);
6312 break;
6313 default:
6314 break;
6315 }
6316}
6317
6318static void setSplitterInDockLocation(QSplitter* splitter, const Qt::DockWidgetArea& area) {
6319 switch(area) {
6320 case Qt::DockWidgetArea::BottomDockWidgetArea:
6321 case Qt::DockWidgetArea::TopDockWidgetArea:
6322 splitter->setOrientation(Qt::Orientation::Horizontal);
6323 break;
6324 default:
6325 splitter->setOrientation(Qt::Orientation::Vertical);
6326 }
6327
6328}
6329void MainWindow::setDockExplorerToArea(const Qt::DockWidgetArea &area)
6330{
6331 ui->dockMessages->setAllowedAreas(
6332 (Qt::DockWidgetArea::LeftDockWidgetArea |
6333 Qt::DockWidgetArea::BottomDockWidgetArea |
6334 Qt::DockWidgetArea::RightDockWidgetArea)
6335 & ~area);
6336 if (area==Qt::DockWidgetArea::NoDockWidgetArea)
6337 return;
6338 setDockTitlebarLocation(ui->dockExplorer,area);
6339 setTabsInDockLocation(ui->tabExplorer,area);
6340}
6341
6342void MainWindow::setDockMessagesToArea(const Qt::DockWidgetArea &area)
6343{
6344 ui->dockExplorer->setAllowedAreas(
6345 (Qt::DockWidgetArea::LeftDockWidgetArea |
6346 Qt::DockWidgetArea::BottomDockWidgetArea |
6347 Qt::DockWidgetArea::RightDockWidgetArea)
6348 & ~area);
6349 Qt::DockWidgetArea effectiveArea;
6350 if (area==Qt::DockWidgetArea::NoDockWidgetArea) {
6351 switch (mMessagesDockLocation) {
6352 case Qt::DockWidgetArea::BottomDockWidgetArea:
6353 case Qt::DockWidgetArea::TopDockWidgetArea:
6354 effectiveArea = Qt::DockWidgetArea::RightDockWidgetArea;
6355 break;
6356 default:
6357 if (dockWidgetArea(ui->dockExplorer)!=Qt::DockWidgetArea::BottomDockWidgetArea)
6358 effectiveArea = Qt::DockWidgetArea::BottomDockWidgetArea;
6359 else
6360 effectiveArea = Qt::DockWidgetArea::LeftDockWidgetArea;
6361 }
6362 } else {
6363 effectiveArea = area;
6364 mMessagesDockLocation = area;
6365 setDockTitlebarLocation(ui->dockMessages,effectiveArea);
6366 }
6367 setTabsInDockLocation(ui->tabMessages,effectiveArea);
6368 setSplitterInDockLocation(ui->splitterDebug,effectiveArea);
6369 setSplitterInDockLocation(ui->splitterProblem,effectiveArea);
6370 QGridLayout* layout=(QGridLayout*)ui->panelProblemCase->layout();
6371 layout->removeWidget(ui->widgetProblemCaseInputCaption);
6372 layout->removeWidget(ui->widgetProblemCaseOutputCaption);
6373 layout->removeWidget(ui->widgetProblemCaseExpectedCaption);
6374 layout->removeWidget(ui->txtProblemCaseInput);
6375 layout->removeWidget(ui->txtProblemCaseOutput);
6376 layout->removeWidget(ui->txtProblemCaseExpected);
6377 layout->removeWidget(ui->lblProblemCaseInput);
6378 layout->removeWidget(ui->lblProblemCaseOutput);
6379 layout->removeWidget(ui->lblProblemCaseExpected);
6380 switch(effectiveArea) {
6381 case Qt::DockWidgetArea::BottomDockWidgetArea:
6382 case Qt::DockWidgetArea::TopDockWidgetArea:
6383 layout->addWidget(ui->widgetProblemCaseInputCaption, 0, 0, 1, 1);
6384 layout->addWidget(ui->txtProblemCaseInput, 1, 0, 1, 1);
6385// layout->addWidget(ui->lblProblemCaseInput, 2, 0, 1, 1);
6386
6387 layout->addWidget(ui->widgetProblemCaseOutputCaption, 0, 1, 1, 1);
6388 layout->addWidget(ui->txtProblemCaseOutput, 1, 1, 1, 1);
6389// layout->addWidget(ui->lblProblemCaseOutput, 2, 1, 1, 1);
6390
6391 layout->addWidget(ui->widgetProblemCaseExpectedCaption, 0, 2, 1, 1);
6392 layout->addWidget(ui->txtProblemCaseExpected, 1, 2, 1, 1);
6393// layout->addWidget(ui->lblProblemCaseExpected, 2, 2, 1, 1);
6394
6395
6396
6397 break;
6398 default:
6399 layout->addWidget(ui->widgetProblemCaseInputCaption, 0, 0, 1, 1);
6400 layout->addWidget(ui->txtProblemCaseInput, 1, 0, 1, 1);
6401 //layout->addWidget(ui->lblProblemCaseInput, 2, 0, 1, 1);
6402
6403
6404 layout->addWidget(ui->widgetProblemCaseOutputCaption, 3, 0, 1, 1);
6405 layout->addWidget(ui->txtProblemCaseOutput, 4, 0, 1, 1);
6406 //layout->addWidget(ui->lblProblemCaseOutput, 5, 0, 1, 1);
6407
6408 layout->addWidget(ui->widgetProblemCaseExpectedCaption, 6, 0, 1, 1);
6409 layout->addWidget(ui->txtProblemCaseExpected, 7, 0, 1, 1);
6410 //layout->addWidget(ui->lblProblemCaseExpected, 8, 0, 1, 1);
6411 }
6412}
6413
6414void MainWindow::updateVCSActions()
6415{
6416 bool hasRepository = false;
6417 bool shouldEnable = false;
6418 bool canBranch = false;
6419 if (ui->projectView->isVisible() && mProject) {
6420 mProject->model()->iconProvider()->update();
6421 QString branch;
6422 hasRepository = mProject->model()->iconProvider()->VCSRepository()->hasRepository(branch);
6423 shouldEnable = true;
6424 canBranch = !mProject->model()->iconProvider()->VCSRepository()->hasChangedFiles()
6425 && !mProject->model()->iconProvider()->VCSRepository()->hasStagedFiles();
6426 } else if (ui->treeFiles->isVisible()) {
6427 mFileSystemModelIconProvider.update();
6428 QString branch;
6429 hasRepository = mFileSystemModelIconProvider.VCSRepository()->hasRepository(branch);
6430 shouldEnable = true;
6431 canBranch =!mFileSystemModelIconProvider.VCSRepository()->hasChangedFiles()
6432 && !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles();
6433 }
6434 ui->actionGit_Remotes->setEnabled(hasRepository && shouldEnable);
6435 ui->actionGit_Create_Repository->setEnabled(!hasRepository && shouldEnable);
6436 ui->actionGit_Log->setEnabled(hasRepository && shouldEnable);
6437 ui->actionGit_Commit->setEnabled(hasRepository && shouldEnable);
6438 ui->actionGit_Branch->setEnabled(hasRepository && shouldEnable && canBranch);
6439 ui->actionGit_Merge->setEnabled(hasRepository && shouldEnable && canBranch);
6440 ui->actionGit_Reset->setEnabled(hasRepository && shouldEnable);
6441 ui->actionGit_Restore->setEnabled(hasRepository && shouldEnable);
6442 ui->actionGit_Revert->setEnabled(hasRepository && shouldEnable);
6443}
6444
6445void MainWindow::invalidateProjectProxyModel()
6446{
6447 mProjectProxyModel->invalidate();
6448}
6449
6450void MainWindow::onEditorRenamed(const QString &oldFilename, const QString &newFilename, bool firstSave)
6451{
6452 if (firstSave)
6453 mOJProblemSetModel.updateProblemAnswerFilename(oldFilename, newFilename);
6454}
6455
6456void MainWindow::on_EditorTabsLeft_currentChanged(int)
6457{
6458}
6459
6460
6461void MainWindow::on_EditorTabsRight_currentChanged(int)
6462{
6463}
6464
6465void MainWindow::on_tableTODO_doubleClicked(const QModelIndex &index)
6466{
6467 PTodoItem item = mTodoModel.getItem(index);
6468 if (item) {
6469 Editor * editor = mEditorList->getOpenedEditorByFilename(item->filename);
6470 if (editor) {
6471 editor->setCaretPositionAndActivate(item->lineNo,item->ch+1);
6472 }
6473 }
6474}
6475
6476
6477void MainWindow::on_actionAbout_triggered()
6478{
6479 AboutDialog dialog;
6480 dialog.exec();
6481}
6482
6483
6484void MainWindow::on_actionRename_Symbol_triggered()
6485{
6486 Editor * editor = mEditorList->getEditor();
6487 if (!editor)
6488 return;
6489 if (!editor->parser())
6490 return;
6491 editor->beginUpdate();
6492 QSynedit::BufferCoord oldCaretXY = editor->caretXY();
6493 // mClassBrowserModel.beginUpdate();
6494 QCursor oldCursor = editor->cursor();
6495 editor->setCursor(Qt::CursorShape::WaitCursor);
6496 auto action = finally([oldCursor,editor]{
6497 editor->endUpdate();
6498// mClassBrowserModel.EndTreeUpdate;
6499 editor->setCursor(oldCursor);
6500 });
6501
6502 QStringList expression = editor->getExpressionAtPosition(oldCaretXY);
6503 if (expression.isEmpty() && oldCaretXY.ch>1) {
6504 QSynedit::BufferCoord coord=oldCaretXY;
6505 coord.ch--;
6506 expression = editor->getExpressionAtPosition(coord);
6507 }
6508
6509 if (editor->inProject() && mProject) {
6510 for (int i=0;i<mEditorList->pageCount();i++) {
6511 Editor * e=(*mEditorList)[i];
6512 if (e->modified()) {
6513 mProject->cppParser()->parseFile(editor->filename(), editor->inProject(), false, false);
6514 }
6515 }
6516
6517 // Find it's definition
6518 PStatement oldStatement = editor->parser()->findStatementOf(
6519 editor->filename(),
6520 expression,
6521 oldCaretXY.line);
6522 // definition of the symbol not found
6523 if (!oldStatement)
6524 return;
6525 // found but not in this file
6526 if (editor->filename() != oldStatement->fileName
6527 || editor->filename() != oldStatement->definitionFileName) {
6528 // it's defined in system header, dont rename
6529 if (mProject->cppParser()->isSystemHeaderFile(oldStatement->fileName)) {
6530 QMessageBox::critical(editor,
6531 tr("Rename Error"),
6532 tr("Symbol '%1' is defined in system header.")
6533 .arg(oldStatement->fullName));
6534 return;
6535 }
6536 CppRefacter refactor;
6537 refactor.findOccurence(editor,oldCaretXY);
6538 showSearchPanel(true);
6539 return;
6540 }
6541 }
6542 //not in project
6543 PStatement oldStatement = editor->parser()->findStatementOf(
6544 editor->filename(),
6545 expression,
6546 oldCaretXY.line);
6547 if (!oldStatement)
6548 return;
6549 QString word = oldStatement->command;
6550 if (word.isEmpty())
6551 return;
6552 if (isCppKeyword(word)) {
6553 return;
6554 }
6555
6556 bool ok;
6557 QString newWord = QInputDialog::getText(editor,
6558 tr("Rename Symbol"),
6559 tr("New Name"),
6560 QLineEdit::Normal,word, &ok);
6561 if (!ok)
6562 return;
6563
6564 if (word == newWord)
6565 return;
6566
6567 if (!editor->inProject() && editor->modified() ) {
6568 PCppParser parser = editor->parser();
6569 //here we must reparse the file in sync, or rename may fail
6570 parser->parseFile(editor->filename(), editor->inProject(), false, false);
6571 }
6572 CppRefacter refactor;
6573
6574 refactor.renameSymbol(editor,oldCaretXY,newWord);
6575 editor->reparse();
6576
6577}
6578
6579
6580void MainWindow::showSearchReplacePanel(bool show)
6581{
6582 ui->replacePanel->setVisible(show);
6583 ui->cbSearchHistory->setDisabled(show);
6584 if (show && mSearchResultModel.currentResults()) {
6585 ui->cbReplaceInHistory->setCurrentText(
6586 mSearchResultModel.currentResults()->keyword);
6587 }
6588 mSearchResultTreeModel->setSelectable(show);
6589}
6590
6591void MainWindow::setFilesViewRoot(const QString &path, bool setOpenFolder)
6592{
6593 mFileSystemModelIconProvider.setRootFolder(path);
6594 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
6595 mFileSystemModel.setRootPath(path);
6596 ui->treeFiles->setRootIndex(mFileSystemModel.index(path));
6597 pSettings->environment().setCurrentFolder(path);
6598 if (setOpenFolder)
6599 QDir::setCurrent(path);
6600 int pos = ui->cbFilesPath->findText(path);
6601 if (pos<0) {
6602 ui->cbFilesPath->addItem(mFileSystemModel.iconProvider()->icon(QFileIconProvider::Folder),path);
6603 pos = ui->cbFilesPath->findText(path);
6604 } else if (ui->cbFilesPath->itemIcon(pos).isNull()) {
6605 ui->cbFilesPath->setItemIcon(pos,mFileSystemModel.iconProvider()->icon(QFileIconProvider::Folder));
6606 }
6607 ui->cbFilesPath->setCurrentIndex(pos);
6608 ui->cbFilesPath->lineEdit()->setCursorPosition(1);
6609}
6610
6611void MainWindow::clearIssues()
6612{
6613 int i = ui->tabMessages->indexOf(ui->tabIssues);
6614 if (i!=-1) {
6615 ui->tabMessages->setTabText(i, tr("Issues"));
6616 }
6617 ui->tableIssues->clearIssues();
6618}
6619
6620void MainWindow::doCompileRun(RunType runType)
6621{
6622 CompileTarget target =getCompileTarget();
6623 QStringList binDirs;
6624 QString execName;
6625 if (target == CompileTarget::Project) {
6626 binDirs = mProject->binDirs();
6627 execName = mProject->executable();
6628 } else {
6629 binDirs = getDefaultCompilerSetBinDirs();
6630 }
6631 mCompileSuccessionTask = std::make_shared<CompileSuccessionTask>();
6632 mCompileSuccessionTask->binDirs=binDirs;
6633 switch (runType) {
6634 case RunType::CurrentProblemCase:
6635 mCompileSuccessionTask->type = CompileSuccessionTaskType::RunCurrentProblemCase;
6636 break;
6637 case RunType::ProblemCases:
6638 mCompileSuccessionTask->type = CompileSuccessionTaskType::RunProblemCases;
6639 break;
6640 default:
6641 mCompileSuccessionTask->type = CompileSuccessionTaskType::RunNormal;
6642 }
6643 compile();
6644}
6645
6646void MainWindow::updateProblemCaseOutput(POJProblemCase problemCase)
6647{
6648 if (problemCase->testState == ProblemCaseTestState::Failed) {
6649 int diffLine;
6650 if (problemCase->outputLineCounts > problemCase->expectedLineCounts) {
6651 diffLine = problemCase->expectedLineCounts;
6652 } else if (problemCase->outputLineCounts < problemCase->expectedLineCounts) {
6653 diffLine = problemCase->outputLineCounts;
6654 } else {
6655 diffLine = problemCase->firstDiffLine;
6656 }
6657 if (diffLine < problemCase->outputLineCounts) {
6658 QTextBlock block = ui->txtProblemCaseOutput->document()->findBlockByLineNumber(diffLine);
6659 if (!block.isValid())
6660 return;
6661 QTextCursor cur(block);
6662 if (cur.isNull())
6663 return;
6664 cur = QTextCursor(block);
6665 QTextCharFormat oldFormat = cur.charFormat();
6666 QTextCharFormat format = cur.charFormat();
6667 cur.select(QTextCursor::LineUnderCursor);
6668 format.setUnderlineColor(mErrorColor);
6669 format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
6670 cur.setCharFormat(format);
6671 cur.clearSelection();
6672 cur.setCharFormat(oldFormat);
6673 ui->txtProblemCaseOutput->setTextCursor(cur);
6674 } else if (diffLine < problemCase->expectedLineCounts) {
6675 ui->txtProblemCaseOutput->moveCursor(QTextCursor::MoveOperation::End);
6676 }
6677 }
6678}
6679
6680void MainWindow::applyCurrentProblemCaseChanges()
6681{
6682 QModelIndex idx = ui->tblProblemCases->currentIndex();
6683 if (idx.isValid()) {
6684 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
6685 if (problemCase) {
6686 if (!fileExists(problemCase->inputFileName))
6687 problemCase->input = ui->txtProblemCaseInput->toPlainText();
6688 problemCase->expected = ui->txtProblemCaseExpected->toPlainText();
6689 }
6690 }
6691}
6692
6693void MainWindow::on_btnReplace_clicked()
6694{
6695 //select all items by default
6696 PSearchResults results = mSearchResultModel.currentResults();
6697 if (!results) {
6698 return;
6699 }
6700 QString newWord = ui->cbReplaceInHistory->currentText();
6701 foreach (const PSearchResultTreeItem& file, results->results) {
6702 QStringList contents;
6703 Editor* editor = mEditorList->getEditorByFilename(file->filename);
6704 if (!editor) {
6705 QMessageBox::critical(this,
6706 tr("Replace Error"),
6707 tr("Can't open file '%1' for replace!").arg(file->filename));
6708 return;
6709 }
6710 contents = editor->contents();
6711 for (int i=file->results.count()-1;i>=0;i--) {
6712 const PSearchResultTreeItem& item = file->results[i];
6713 if (!item->selected)
6714 continue;
6715 QString line = contents[item->line-1];
6716 if (line.mid(item->start-1,results->keyword.length())!=results->keyword) {
6717 QMessageBox::critical(editor,
6718 tr("Replace Error"),
6719 tr("Contents has changed since last search!"));
6720 return;
6721 }
6722 line.remove(item->start-1,results->keyword.length());
6723 line.insert(item->start-1, newWord);
6724 contents[item->line-1] = line;
6725 }
6726 QSynedit::BufferCoord coord=editor->caretXY();
6727 int topLine = editor->topLine();
6728 int leftChar = editor->leftChar();
6729 editor->replaceAll(contents.join(editor->lineBreak()));
6730 editor->setCaretXY(coord);
6731 editor->setTopLine(topLine);
6732 editor->setLeftChar(leftChar);
6733 }
6734 showSearchReplacePanel(false);
6735 stretchMessagesPanel(false);
6736}
6737
6738void MainWindow::on_btnCancelReplace_clicked()
6739{
6740 showSearchReplacePanel(false);
6741}
6742
6743void MainWindow::on_actionPrint_triggered()
6744{
6745 Editor * editor = mEditorList->getEditor();
6746 if (!editor)
6747 return;
6748 editor->print();
6749}
6750
6751bool MainWindow::shouldRemoveAllSettings() const
6752{
6753 return mShouldRemoveAllSettings;
6754}
6755
6756const PToolsManager &MainWindow::toolsManager() const
6757{
6758 return mToolsManager;
6759}
6760
6761
6762void MainWindow::on_actionExport_As_RTF_triggered()
6763{
6764 Editor * editor = mEditorList->getEditor();
6765 if (!editor)
6766 return;
6767 QString rtfFile = QFileDialog::getSaveFileName(editor,
6768 tr("Export As RTF"),
6769 extractFilePath(editor->filename()),
6770 tr("Rich Text Format Files (*.rtf)")
6771 );
6772 if (rtfFile.isEmpty())
6773 return;
6774 try {
6775 editor->exportAsRTF(rtfFile);
6776 } catch (FileError e) {
6777 QMessageBox::critical(editor,
6778 "Error",
6779 e.reason());
6780 }
6781}
6782
6783
6784void MainWindow::on_actionExport_As_HTML_triggered()
6785{
6786 Editor * editor = mEditorList->getEditor();
6787 if (!editor)
6788 return;
6789 QString htmlFile = QFileDialog::getSaveFileName(editor,
6790 tr("Export As HTML"),
6791 extractFilePath(editor->filename()),
6792 tr("HTML Files (*.html)")
6793 );
6794 if (htmlFile.isEmpty())
6795 return;
6796 try {
6797 editor->exportAsHTML(htmlFile);
6798 } catch (FileError e) {
6799 QMessageBox::critical(editor,
6800 "Error",
6801 e.reason());
6802 }
6803}
6804
6805
6806void MainWindow::on_actionMove_To_Other_View_triggered()
6807{
6808 Editor * editor = mEditorList->getEditor();
6809 if (editor) {
6810 mEditorList->swapEditor(editor);
6811 }
6812}
6813
6814
6815void MainWindow::on_actionC_C_Reference_triggered()
6816{
6817 if (pSettings->environment().language()=="zh_CN") {
6818 QFileInfo fileInfo(includeTrailingPathDelimiter(pSettings->dirs().appDir())+"cppreference-zh.chm");
6819 if (fileInfo.exists()) {
6820 QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
6821 } else {
6822
6823 QDesktopServices::openUrl(QUrl("https://qingcms.gitee.io/cppreference/20210212/zh/cpp.html"));
6824 }
6825 } else {
6826 QDesktopServices::openUrl(QUrl("https://en.cppreference.com/w/cpp"));
6827 }
6828}
6829
6830
6831void MainWindow::on_actionEGE_Manual_triggered()
6832{
6833 QDesktopServices::openUrl(QUrl("https://xege.org/ege-open-source"));
6834}
6835
6836const PBookmarkModel &MainWindow::bookmarkModel() const
6837{
6838 return mBookmarkModel;
6839}
6840
6841
6842void MainWindow::on_actionAdd_bookmark_triggered()
6843{
6844 Editor* editor = mEditorList->getEditor();
6845 int line;
6846 if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
6847 if (editor->document()->count()<=0)
6848 return;
6849 QString desc = QInputDialog::getText(editor,tr("Bookmark Description"),
6850 tr("Description:"),QLineEdit::Normal,
6851 editor->document()->getString(line-1).trimmed());
6852 desc = desc.trimmed();
6853 editor->addBookmark(line,desc);
6854 }
6855}
6856
6857
6858void MainWindow::on_actionRemove_Bookmark_triggered()
6859{
6860 Editor* editor = mEditorList->getEditor();
6861 int line;
6862 if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
6863 editor->removeBookmark(line);
6864 }
6865}
6866
6867
6868void MainWindow::on_tableBookmark_doubleClicked(const QModelIndex &index)
6869{
6870 if (!index.isValid())
6871 return;
6872 PBookmark bookmark = mBookmarkModel->bookmark(index.row());
6873 if (bookmark) {
6874 Editor *editor= mEditorList->getEditorByFilename(bookmark->filename);
6875 if (editor) {
6876 editor->setCaretPositionAndActivate(bookmark->line,1);
6877 }
6878 }
6879}
6880
6881
6882void MainWindow::on_actionModify_Bookmark_Description_triggered()
6883{
6884 Editor* editor = mEditorList->getEditor();
6885 int line;
6886 if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
6887 PBookmark bookmark = mBookmarkModel->bookmark(editor->filename(),line);
6888 if (bookmark) {
6889 QString desc = QInputDialog::getText(editor,tr("Bookmark Description"),
6890 tr("Description:"),QLineEdit::Normal,
6891 bookmark->description);
6892 desc = desc.trimmed();
6893 mBookmarkModel->updateDescription(editor->filename(),line,desc);
6894 }
6895 }
6896}
6897
6898
6899void MainWindow::on_actionLocate_in_Files_View_triggered()
6900{
6901 Editor * editor = mEditorList->getEditor();
6902 if (editor) {
6903 QFileInfo fileInfo(editor->filename());
6904 qDebug()<<fileInfo.absoluteFilePath();
6905 qDebug()<<includeTrailingPathDelimiter(mFileSystemModel.rootDirectory().absolutePath());
6906 if (!fileInfo.absoluteFilePath().startsWith(
6907 includeTrailingPathDelimiter(mFileSystemModel.rootDirectory().absolutePath()),
6908 PATH_SENSITIVITY
6909 )) {
6910 QString fileDir = extractFileDir(editor->filename());
6911 if (QMessageBox::question(this,
6912 tr("Change working folder"),
6913 tr("File '%1' is not in the current working folder.")
6914 .arg(extractFileName(editor->filename()))
6915 +"<br />"
6916 +tr("Do you want to change working folder to '%1'?")
6917 .arg(fileDir),
6918 QMessageBox::Yes | QMessageBox::No,
6919 QMessageBox::Yes
6920 )!=QMessageBox::Yes) {
6921 return;
6922 }
6923 if (!fileDir.isEmpty())
6924 setFilesViewRoot(fileDir,true);
6925 else
6926 return;
6927 }
6928 QModelIndex index = mFileSystemModel.index(editor->filename());
6929 ui->treeFiles->setCurrentIndex(index);
6930 ui->treeFiles->scrollTo(index, QAbstractItemView::PositionAtCenter);
6931 ui->tabExplorer->setCurrentWidget(ui->tabFiles);
6932 stretchExplorerPanel(true);
6933 }
6934}
6935
6936
6937void MainWindow::on_treeFiles_doubleClicked(const QModelIndex &index)
6938{
6939 if (index!=ui->treeFiles->currentIndex())
6940 return;
6941 QString filepath = mFileSystemModel.filePath(index);
6942 QFileInfo file(filepath);
6943 if (file.isFile()) {
6944 switch (getFileType(filepath)) {
6945 case FileType::Project:
6946 openProject(filepath);
6947 break;
6948 case FileType::Other:
6949 {
6950 QMimeDatabase db;
6951 QMimeType mimeType=db.mimeTypeForFile(file);
6952 if (mimeType.isValid() && mimeType.name().startsWith("text/")) {
6953 openFile(filepath);
6954 } else {
6955 QDesktopServices::openUrl(QUrl::fromLocalFile(file.absoluteFilePath()));
6956 }
6957 }
6958 break;
6959 default:
6960 openFile(filepath);
6961 }
6962 }
6963}
6964
6965
6966void MainWindow::on_actionOpen_Folder_triggered()
6967{
6968 QString folder = QFileDialog::getExistingDirectory(this,tr("Choose Working Folder"),
6969 pSettings->environment().currentFolder());
6970 if (!folder.isEmpty()) {
6971 setFilesViewRoot(folder,true);
6972 }
6973}
6974
6975
6976void MainWindow::on_actionRun_Parameters_triggered()
6977{
6978 changeOptions(
6979 SettingsDialog::tr("General"),
6980 SettingsDialog::tr("Program Runner")
6981 );
6982}
6983
6984
6985void MainWindow::on_btnNewProblemSet_clicked()
6986{
6987 if (mOJProblemSetModel.count()>0) {
6988 if (QMessageBox::warning(this,
6989 tr("New Problem Set"),
6990 tr("The current problem set is not empty.")
6991 +"<br />"
6992 +tr("Do you want to save it?"),
6993 QMessageBox::Yes | QMessageBox::No)==QMessageBox::Yes) {
6994 on_btnSaveProblemSet_clicked();
6995 }
6996 }
6997 mOJProblemSetNameCounter++;
6998 mOJProblemSetModel.create(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
6999 ui->lblProblemSet->setText(mOJProblemSetModel.name());
7000}
7001
7002
7003void MainWindow::on_btnAddProblem_clicked()
7004{
7005 int startCount = mOJProblemSetModel.count();
7006 QString name;
7007 while (true) {
7008 name = tr("Problem %1").arg(startCount+1);
7009 if (!mOJProblemSetModel.problemNameUsed(name))
7010 break;
7011 }
7012 POJProblem problem = std::make_shared<OJProblem>();
7013 problem->name = name;
7014 mOJProblemSetModel.addProblem(problem);
7015 ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(mOJProblemSetModel.count()-1));
7016}
7017
7018
7019void MainWindow::on_btnRemoveProblem_clicked()
7020{
7021 QModelIndex idx = ui->lstProblemSet->currentIndex();
7022 if (!idx.isValid())
7023 return;
7024 mOJProblemSetModel.removeProblem(idx.row());
7025}
7026
7027
7028void MainWindow::on_btnSaveProblemSet_clicked()
7029{
7030 QFileDialog dialog(this);
7031 dialog.setWindowTitle(tr("Save Problem Set"));
7032 if (!mOJProblemSetModel.exportFilename().isEmpty()) {
7033 dialog.setDirectory(mOJProblemSetModel.exportFilename());
7034 dialog.selectFile(mOJProblemSetModel.exportFilename());
7035 } else {
7036 dialog.setDirectory(QDir().absolutePath());
7037 }
7038 dialog.setNameFilter(tr("Problem Set Files (*.pbs)"));
7039 dialog.setDefaultSuffix("pbs");
7040 dialog.setFileMode(QFileDialog::AnyFile);
7041 dialog.setAcceptMode(QFileDialog::AcceptSave);
7042 if (dialog.exec() == QDialog::Accepted) {
7043 QString fileName=dialog.selectedFiles()[0];
7044 QFileInfo fileInfo(fileName);
7045 if (fileInfo.suffix().isEmpty()) {
7046 fileName.append(".pbs");
7047 }
7048 QDir::setCurrent(extractFileDir(fileName));
7049 try {
7050 applyCurrentProblemCaseChanges();
7051 mOJProblemSetModel.saveToFile(fileName);
7052 } catch (FileError& error) {
7053 QMessageBox::critical(this,tr("Save Error"),
7054 error.reason());
7055 }
7056 }
7057}
7058
7059
7060void MainWindow::on_btnLoadProblemSet_clicked()
7061{
7062 QString fileName = QFileDialog::getOpenFileName(
7063 this,
7064 tr("Load Problem Set"),
7065 QString(),
7066 tr("Problem Set Files (*.pbs)"));
7067 if (!fileName.isEmpty()) {
7068 QDir::setCurrent(extractFileDir(fileName));
7069 try {
7070 mOJProblemSetModel.loadFromFile(fileName);
7071 } catch (FileError& error) {
7072 QMessageBox::critical(this,tr("Load Error"),
7073 error.reason());
7074 }
7075 }
7076 ui->lblProblemSet->setText(mOJProblemSetModel.name());
7077 ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(0,0));
7078}
7079
7080
7081void MainWindow::on_btnAddProblemCase_clicked()
7082{
7083 int startCount = mOJProblemModel.count();
7084 QString name;
7085 while (true) {
7086 name = tr("Problem Case %1").arg(startCount+1);
7087 if (!mOJProblemSetModel.problemNameUsed(name))
7088 break;
7089 }
7090 POJProblemCase problemCase = std::make_shared<OJProblemCase>();
7091 problemCase->name = name;
7092 problemCase->testState = ProblemCaseTestState::NotTested;
7093 mOJProblemModel.addCase(problemCase);
7094 ui->tblProblemCases->setCurrentIndex(mOJProblemModel.index(mOJProblemModel.count()-1,0));
7095}
7096
7097void MainWindow::on_btnRunAllProblemCases_clicked()
7098{
7099 if (mOJProblemModel.count()<=0)
7100 return;
7101 showHideMessagesTab(ui->tabProblem,ui->actionProblem);
7102 applyCurrentProblemCaseChanges();
7103 runExecutable(RunType::ProblemCases);
7104}
7105
7106
7107void MainWindow::on_actionC_Reference_triggered()
7108{
7109 if (pSettings->environment().language()=="zh_CN") {
7110 QDesktopServices::openUrl(QUrl("https://qingcms.gitee.io/cppreference/20210212/zh/c.html"));
7111 } else {
7112 QDesktopServices::openUrl(QUrl("https://en.cppreference.com/w/c"));
7113 }
7114}
7115
7116
7117void MainWindow::on_btnRemoveProblemCase_clicked()
7118{
7119 QModelIndex idx = ui->tblProblemCases->currentIndex();
7120 if (idx.isValid()) {
7121 mOJProblemModel.removeCase(idx.row());
7122 }
7123}
7124
7125
7126void MainWindow::on_btnOpenProblemAnswer_clicked()
7127{
7128 POJProblem problem = mOJProblemModel.problem();
7129 if (!problem || problem->answerProgram.isEmpty())
7130 return;
7131 Editor *e = mEditorList->getEditorByFilename(problem->answerProgram);
7132 if (e) {
7133 e->activate();
7134 }
7135}
7136
7137bool MainWindow::openningFiles() const
7138{
7139 return mOpenningFiles;
7140}
7141
7142QList<QAction *> MainWindow::listShortCutableActions()
7143{
7144 QList<QAction*> actions = findChildren<QAction *>(QString(), Qt::FindDirectChildrenOnly);
7145 return actions;
7146}
7147
7148
7149void MainWindow::on_actionTool_Window_Bars_triggered()
7150{
7151 bool state = ui->tabExplorer->isVisible();
7152 state = !state;
7153 ui->tabExplorer->setVisible(state);
7154 ui->tabMessages->setVisible(state);
7155 ui->actionTool_Window_Bars->setChecked(state);
7156}
7157
7158void MainWindow::on_actionStatus_Bar_triggered()
7159{
7160 bool state = ui->statusbar->isVisible();
7161 state = !state;
7162 ui->statusbar->setVisible(state);
7163 ui->actionStatus_Bar->setChecked(state);
7164}
7165
7166void MainWindow::on_actionProject_triggered()
7167{
7168 bool state = ui->actionProject->isChecked();
7169 ui->actionProject->setChecked(state);
7170 showHideInfosTab(ui->tabProject,state);
7171}
7172
7173
7174void MainWindow::on_actionWatch_triggered()
7175{
7176 bool state = ui->actionWatch->isChecked();
7177 ui->actionWatch->setChecked(state);
7178 showHideInfosTab(ui->tabWatch,state);
7179}
7180
7181
7182void MainWindow::on_actionStructure_triggered()
7183{
7184 bool state = ui->actionStructure->isChecked();
7185 ui->actionStructure->setChecked(state);
7186 showHideInfosTab(ui->tabStructure,state);
7187}
7188
7189
7190void MainWindow::on_actionFiles_triggered()
7191{
7192 bool state = ui->actionFiles->isChecked();
7193 ui->actionFiles->setChecked(state);
7194 showHideInfosTab(ui->tabFiles,state);
7195}
7196
7197
7198void MainWindow::on_actionProblem_Set_triggered()
7199{
7200 bool state = ui->actionProblem_Set->isChecked();
7201 ui->actionProblem_Set->setChecked(state);
7202 showHideInfosTab(ui->tabProblemSet,state);
7203}
7204
7205
7206void MainWindow::on_actionIssues_triggered()
7207{
7208 bool state = ui->actionIssues->isChecked();
7209 ui->actionIssues->setChecked(state);
7210 showHideMessagesTab(ui->tabIssues,state);
7211}
7212
7213
7214void MainWindow::on_actionTools_Output_triggered()
7215{
7216 bool state = ui->actionTools_Output->isChecked();
7217 ui->actionTools_Output->setChecked(state);
7218 showHideMessagesTab(ui->tabToolsOutput,state);
7219}
7220
7221
7222void MainWindow::on_actionDebug_Window_triggered()
7223{
7224 bool state = ui->actionDebug_Window->isChecked();
7225 ui->actionDebug_Window->setChecked(state);
7226 showHideMessagesTab(ui->tabDebug, state);
7227}
7228
7229
7230void MainWindow::on_actionSearch_triggered()
7231{
7232 bool state = ui->actionSearch->isChecked();
7233 ui->actionSearch->setChecked(state);
7234 showHideMessagesTab(ui->tabSearch,state);
7235}
7236
7237
7238
7239void MainWindow::on_actionTODO_triggered()
7240{
7241 bool state = ui->actionTODO->isChecked();
7242 ui->actionTODO->setChecked(state);
7243 showHideMessagesTab(ui->tabTODO,state);
7244}
7245
7246
7247void MainWindow::on_actionBookmark_triggered()
7248{
7249 bool state = ui->actionBookmark->isChecked();
7250 ui->actionBookmark->setChecked(state);
7251 showHideMessagesTab(ui->tabBookmark,state);
7252}
7253
7254
7255void MainWindow::on_actionProblem_triggered()
7256{
7257 bool state = ui->actionProblem->isChecked();
7258 ui->actionProblem->setChecked(state);
7259 showHideMessagesTab(ui->tabProblem,state);
7260}
7261
7262void MainWindow::on_actionDelete_Line_triggered()
7263{
7264 Editor *e=mEditorList->getEditor();
7265 if (e) {
7266 e->deleteLine();
7267 }
7268}
7269
7270void MainWindow::on_actionDuplicate_Line_triggered()
7271{
7272 Editor *e=mEditorList->getEditor();
7273 if (e) {
7274 e->duplicateLine();
7275 }
7276}
7277
7278
7279void MainWindow::on_actionDelete_Word_triggered()
7280{
7281 Editor *e=mEditorList->getEditor();
7282 if (e) {
7283 e->deleteWord();
7284 }
7285}
7286
7287
7288void MainWindow::on_actionDelete_to_EOL_triggered()
7289{
7290 Editor *e=mEditorList->getEditor();
7291 if (e) {
7292 e->deleteToEOL();
7293 }
7294}
7295
7296void MainWindow::on_actionDelete_to_BOL_triggered()
7297{
7298 Editor *e=mEditorList->getEditor();
7299 if (e) {
7300 e->deleteToBOL();
7301 }
7302}
7303
7304
7305void MainWindow::on_btnCaseValidateOptions_clicked()
7306{
7307 changeOptions(
7308 SettingsDialog::tr("Problem Set"),
7309 SettingsDialog::tr("Program Runner")
7310 );
7311}
7312
7313
7314void MainWindow::on_actionInterrupt_triggered()
7315{
7316 if (mDebugger->executing()) {
7317 //WatchView.Items.BeginUpdate();
7318 mDebugger->interrupt();
7319 }
7320}
7321
7322void MainWindow::on_actionDelete_Last_Word_triggered()
7323{
7324 Editor *e=mEditorList->getEditor();
7325 if (e) {
7326 e->deleteToWordStart();
7327 }
7328}
7329
7330
7331void MainWindow::on_actionDelete_to_Word_End_triggered()
7332{
7333 Editor *e=mEditorList->getEditor();
7334 if (e) {
7335 e->deleteToWordEnd();
7336 }
7337}
7338
7339
7340void MainWindow::on_actionNew_Header_triggered()
7341{
7342 if (!mProject)
7343 return;
7344 NewHeaderDialog dialog;
7345 dialog.setPath(mProject->folder());
7346 if (dialog.exec()==QDialog::Accepted) {
7347 QDir dir(dialog.path());
7348 if (dialog.headerName().isEmpty()
7349 || !dir.exists())
7350 return;
7351 QString headerFilename = includeTrailingPathDelimiter(dialog.path())+dialog.headerName();
7352 if (fileExists(headerFilename)){
7353 QMessageBox::critical(this,
7354 tr("Header Exists"),
7355 tr("Header file \"%1\" already exists!").arg(headerFilename));
7356 return;
7357 }
7358 QString header_macro = QFileInfo(dialog.headerName()).baseName().toUpper()+"_H";
7359 QStringList header;
7360 QString indents;
7361 if (pSettings->editor().tabToSpaces()) {
7362 indents = QString(pSettings->editor().tabWidth(),' ');
7363 } else {
7364 indents = "\t";
7365 }
7366 header.append(QString("#ifndef %1").arg(header_macro));
7367 header.append(QString("#define %1").arg(header_macro));
7368 header.append("");
7369 header.append("#endif");
7370 stringsToFile(header, headerFilename);
7371
7372 mProject->addUnit(headerFilename,mProject->rootNode(),false);
7373 mProject->cppParser()->addFileToScan(headerFilename);
7374 mProject->rebuildNodes();
7375 mProject->saveUnits();
7376 parseFileList(mProject->cppParser());
7377 updateProjectView();
7378
7379 Editor * editor = mEditorList->getEditorByFilename(headerFilename);
7380 if (editor){
7381 editor->activate();
7382 }
7383 }
7384 pSettings->ui().setNewClassDialogWidth(dialog.width());
7385 pSettings->ui().setNewClassDialogHeight(dialog.height());
7386}
7387
7388
7389void MainWindow::on_actionNew_Class_triggered()
7390{
7391 if (!mProject)
7392 return;
7393 NewClassDialog dialog;
7394 dialog.setPath(mProject->folder());
7395 if (dialog.exec()==QDialog::Accepted) {
7396 QDir dir(dialog.path());
7397 if (dialog.className().isEmpty()
7398 || dialog.sourceName().isEmpty()
7399 || dialog.headerName().isEmpty()
7400 || !dir.exists())
7401 return;
7402 QString headerFilename = includeTrailingPathDelimiter(dialog.path())+dialog.headerName();
7403 QString sourceFilename = includeTrailingPathDelimiter(dialog.path())+dialog.sourceName();
7404 if (fileExists(headerFilename)){
7405 QMessageBox::critical(this,
7406 tr("Header Exists"),
7407 tr("Header file \"%1\" already exists!").arg(headerFilename));
7408 return;
7409 }
7410 if (fileExists(sourceFilename)){
7411 QMessageBox::critical(this,
7412 tr("Source Exists"),
7413 tr("Source file \"%1\" already exists!").arg(sourceFilename));
7414 return;
7415 }
7416 QString header_macro = dialog.className().toUpper()+"_H";
7417 QStringList header;
7418 QString indents;
7419 if (pSettings->editor().tabToSpaces()) {
7420 indents = QString(pSettings->editor().tabWidth(),' ');
7421 } else {
7422 indents = "\t";
7423 }
7424 header.append(QString("#ifndef %1").arg(header_macro));
7425 header.append(QString("#define %1").arg(header_macro));
7426 header.append("");
7427 header.append(QString("class %1 {").arg(dialog.className()));
7428 header.append("public:");
7429 header.append("");
7430 header.append("private:");
7431 header.append("");
7432 header.append("};");
7433 header.append("");
7434 header.append("#endif");
7435 stringsToFile(header, headerFilename);
7436 QStringList source;
7437 source.append(QString("#include \"%1\"").arg(dialog.headerName()));
7438 source.append("");
7439 source.append("");
7440 stringsToFile(source, sourceFilename);
7441
7442 mProject->addUnit(headerFilename,mProject->rootNode(),false);
7443 mProject->cppParser()->addFileToScan(headerFilename);
7444 mProject->addUnit(sourceFilename,mProject->rootNode(),false);
7445 mProject->cppParser()->addFileToScan(sourceFilename);
7446 mProject->rebuildNodes();
7447 mProject->saveUnits();
7448 parseFileList(mProject->cppParser());
7449 updateProjectView();
7450
7451 Editor * editor = mEditorList->getEditorByFilename(headerFilename);
7452 if (editor){
7453 editor->activate();
7454 }
7455 editor = mEditorList->getEditorByFilename(sourceFilename);
7456 }
7457 pSettings->ui().setNewHeaderDialogWidth(dialog.width());
7458 pSettings->ui().setNewHeaderDialogHeight(dialog.height());
7459}
7460
7461
7462void MainWindow::on_actionGit_Create_Repository_triggered()
7463{
7464 if (ui->treeFiles->isVisible()) {
7465 GitManager vcsManager;
7466 vcsManager.createRepository(pSettings->environment().currentFolder());
7467 //update files view;
7468 int pos = ui->cbFilesPath->findText(pSettings->environment().currentFolder());
7469 if (pos>=0) {
7470 ui->cbFilesPath->setItemIcon(pos, pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
7471 }
7472 mFileSystemModelIconProvider.setRootFolder(pSettings->environment().currentFolder());
7473 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7474 //update project view
7475 if (mProject && mProject->folder() == mFileSystemModel.rootPath()) {
7476 mProject->addUnit(includeTrailingPathDelimiter(mProject->folder())+".gitignore", mProject->rootNode(), true);
7477 } else if (mProject && mFileSystemModel.index(mProject->folder()).isValid()) {
7478 mProject->model()->beginUpdate();
7479 mProject->model()->endUpdate();
7480 }
7481 } else if (ui->projectView->isVisible() && mProject) {
7482 GitManager vcsManager;
7483 vcsManager.createRepository(mProject->folder());
7484 QString output;
7485 vcsManager.add(mProject->folder(), extractFileName(mProject->filename()), output);
7486 vcsManager.add(mProject->folder(), extractFileName(mProject->options().icon), output);
7487 foreach (PProjectUnit pUnit, mProject->units()) {
7488 vcsManager.add(mProject->folder(),extractRelativePath(mProject->folder(),pUnit->fileName()),output);
7489 }
7490 //update project view
7491 mProject->addUnit(includeTrailingPathDelimiter(mProject->folder())+".gitignore", mProject->rootNode(), true);
7492 mProject->saveAll();
7493 if (mProject->folder() == mFileSystemModel.rootPath()
7494 || mFileSystemModel.rootPath().startsWith(includeTrailingPathDelimiter(mProject->folder()), PATH_SENSITIVITY)) {
7495
7496 //update files view;
7497 int pos = ui->cbFilesPath->findText(pSettings->environment().currentFolder());
7498 if (pos>=0) {
7499 ui->cbFilesPath->setItemIcon(pos, pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
7500 }
7501 mFileSystemModelIconProvider.update();
7502 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7503 }
7504 }
7505}
7506
7507
7508void MainWindow::on_actionGit_Add_Files_triggered()
7509{
7510 if (ui->treeFiles->isVisible()) {
7511 GitManager vcsManager;
7512 QModelIndexList indices = ui->treeFiles->selectionModel()->selectedRows();
7513 QString output;
7514 foreach (const QModelIndex index,indices) {
7515 QFileInfo info = mFileSystemModel.fileInfo(index);
7516 vcsManager.add(info.absolutePath(),info.fileName(),output);
7517 }
7518 //update icons in files view
7519 mFileSystemModelIconProvider.update();
7520 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7521 } else if (ui->projectView->isVisible() && mProject) {
7522 GitManager vcsManager;
7523 QModelIndexList indices = ui->projectView->selectionModel()->selectedRows();
7524 foreach (const QModelIndex index,indices) {
7525 QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
7526 ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
7527 PProjectModelNode folderNode = mProject->pointerToNode(node);
7528 if (!folderNode)
7529 continue;
7530 if (folderNode->unitIndex>=0) {
7531 PProjectUnit unit = mProject->units()[folderNode->unitIndex];
7532 QFileInfo info(unit->fileName());
7533 QString output;
7534 vcsManager.add(info.absolutePath(),info.fileName(),output);
7535 }
7536 }
7537 }
7538 //update icons in project view
7539 if (mProject) {
7540 mProject->model()->beginUpdate();
7541 mProject->model()->endUpdate();
7542 }
7543 //update icons in files view too
7544 mFileSystemModelIconProvider.update();
7545 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7546}
7547
7548
7549void MainWindow::on_actionGit_Commit_triggered()
7550{
7551 QString folder;
7552 if (ui->treeFiles->isVisible()) {
7553 folder = pSettings->environment().currentFolder();
7554 } else if (ui->projectView->isVisible() && mProject) {
7555 folder = mProject->folder();
7556 }
7557 if (folder.isEmpty())
7558 return;
7559
7560 GitManager vcsManager;
7561 QStringList conflicts = vcsManager.listConflicts(folder);
7562 if (!conflicts.isEmpty()) {
7563 InfoMessageBox infoBox;
7564 infoBox.setMessage(
7565 tr("Can't commit!") + "<br />"
7566 +tr("The following files are in conflicting:")+"<br />"
7567 + linesToText(conflicts));
7568 infoBox.exec();
7569 return;
7570 }
7571 QString message = QInputDialog::getText(this,tr("Commit Message"),tr("Commit Message:"));
7572 if (message.isEmpty()) {
7573 QMessageBox::critical(this,
7574 tr("Commit Failed"),
7575 tr("Commit message shouldn't be empty!")
7576 );
7577 return;
7578 }
7579 QString output;
7580 QString userName = vcsManager.getUserName(folder);
7581 QString userEmail = vcsManager.getUserEmail(folder);
7582 if (userName.isEmpty() || userEmail.isEmpty()) {
7583 GitUserConfigDialog dialog(folder);
7584 if (dialog.exec()!=QDialog::Accepted) {
7585 QMessageBox::critical(this,
7586 tr("Can't Commit"),
7587 tr("Git needs user info to commit."));
7588 return;
7589 }
7590 }
7591 if (vcsManager.commit(folder,message,true,output)) {
7592 //update project view
7593 if (mProject) {
7594 mProject->model()->beginUpdate();
7595 mProject->model()->endUpdate();
7596 }
7597 //update files view
7598 mFileSystemModelIconProvider.update();
7599 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7600 }
7601 if (!output.isEmpty()) {
7602 InfoMessageBox infoBox;
7603 infoBox.showMessage(output);
7604 }
7605}
7606
7607
7608void MainWindow::on_actionGit_Restore_triggered()
7609{
7610 QString folder;
7611 if (ui->treeFiles->isVisible()) {
7612 folder = pSettings->environment().currentFolder();
7613 } else if (ui->projectView->isVisible() && mProject) {
7614 folder = mProject->folder();
7615 }
7616 if (folder.isEmpty())
7617 return;
7618 GitManager vcsManager;
7619 QString output;
7620 if (vcsManager.restore(folder,"",output)) {
7621
7622 //update project view
7623 if (mProject) {
7624 mProject->model()->beginUpdate();
7625 mProject->model()->endUpdate();
7626 }
7627 //update files view
7628 mFileSystemModelIconProvider.update();
7629 mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
7630 }
7631 if (!output.isEmpty()) {
7632 InfoMessageBox infoBox;
7633 infoBox.showMessage(output);
7634 }
7635}
7636
7637
7638void MainWindow::on_actionWebsite_triggered()
7639{
7640 if (pSettings->environment().language()=="zh_CN") {
7641 QDesktopServices::openUrl(QUrl("https://royqh1979.gitee.io/redpandacpp/docsy/docs/"));
7642 } else {
7643 QDesktopServices::openUrl(QUrl("https://sourceforge.net/projects/redpanda-cpp/"));
7644 }
7645}
7646
7647
7648void MainWindow::on_actionGit_Branch_triggered()
7649{
7650 QString folder;
7651 if (ui->treeFiles->isVisible()) {
7652 folder = pSettings->environment().currentFolder();
7653 } else if (ui->projectView->isVisible() && mProject) {
7654 folder = mProject->folder();
7655 }
7656 if (folder.isEmpty())
7657 return;
7658 GitBranchDialog dialog(folder);
7659 if (dialog.exec()==QDialog::Accepted) {
7660 //update project view
7661 if (mProject) {
7662 mProject->model()->beginUpdate();
7663 mProject->model()->endUpdate();
7664 }
7665 //update files view
7666 setFilesViewRoot(pSettings->environment().currentFolder());
7667 }
7668}
7669
7670
7671void MainWindow::on_actionGit_Merge_triggered()
7672{
7673 QString folder;
7674 if (ui->treeFiles->isVisible()) {
7675 folder = pSettings->environment().currentFolder();
7676 } else if (ui->projectView->isVisible() && mProject) {
7677 folder = mProject->folder();
7678 }
7679 if (folder.isEmpty())
7680 return;
7681 GitMergeDialog dialog(folder);
7682 if (dialog.exec()==QDialog::Accepted) {
7683 //update project view
7684 if (mProject) {
7685 mProject->model()->beginUpdate();
7686 mProject->model()->endUpdate();
7687 }
7688 //update files view
7689 setFilesViewRoot(pSettings->environment().currentFolder());
7690 }
7691}
7692
7693
7694void MainWindow::on_actionGit_Log_triggered()
7695{
7696 QString folder;
7697 if (ui->treeFiles->isVisible()) {
7698 folder = pSettings->environment().currentFolder();
7699 } else if (ui->projectView->isVisible() && mProject) {
7700 folder = mProject->folder();
7701 }
7702 if (folder.isEmpty())
7703 return;
7704 GitLogDialog dialog(folder);
7705 if (dialog.exec()==QDialog::Accepted) {
7706 qDebug()<<"yes";
7707 //update project view
7708 if (mProject) {
7709 mProject->model()->beginUpdate();
7710 mProject->model()->endUpdate();
7711 }
7712 //update files view
7713 setFilesViewRoot(pSettings->environment().currentFolder());
7714 }
7715 return ;
7716}
7717
7718
7719void MainWindow::on_actionGit_Remotes_triggered()
7720{
7721 QString folder;
7722 if (ui->treeFiles->isVisible()) {
7723 folder = pSettings->environment().currentFolder();
7724 } else if (ui->projectView->isVisible() && mProject) {
7725 folder = mProject->folder();
7726 }
7727 if (folder.isEmpty())
7728 return;
7729 GitRemoteDialog dialog(folder);
7730 dialog.exec();
7731}
7732
7733
7734void MainWindow::on_actionGit_Fetch_triggered()
7735{
7736 QString folder;
7737 if (ui->treeFiles->isVisible()) {
7738 folder = pSettings->environment().currentFolder();
7739 } else if (ui->projectView->isVisible() && mProject) {
7740 folder = mProject->folder();
7741 }
7742 if (folder.isEmpty())
7743 return;
7744 GitManager manager;
7745 QString output;
7746 if (!manager.fetch(folder,output)) {
7747 InfoMessageBox infoBox;
7748 infoBox.showMessage(output);
7749 }
7750}
7751
7752
7753void MainWindow::on_actionGit_Pull_triggered()
7754{
7755 QString folder;
7756 if (ui->treeFiles->isVisible()) {
7757 folder = pSettings->environment().currentFolder();
7758 } else if (ui->projectView->isVisible() && mProject) {
7759 folder = mProject->folder();
7760 }
7761 if (folder.isEmpty())
7762 return;
7763 GitManager manager;
7764 QString branch;
7765 if (!manager.hasRepository(folder,branch))
7766 return;
7767 QString remote = manager.getBranchRemote(folder,branch);
7768 QString output;
7769 if (remote.isEmpty()) {
7770 GitRemoteDialog dialog(folder);
7771 QString remote = dialog.chooseRemote();
7772 if (remote.trimmed().isEmpty())
7773 return;
7774 if (!manager.setBranchUpstream(folder,branch,remote,output)) {
7775 InfoMessageBox infoBox;
7776 infoBox.showMessage(output);
7777 return;
7778 }
7779 }
7780 manager.pull(folder,output);
7781 if (!output.isEmpty()) {
7782 InfoMessageBox infoBox;
7783 infoBox.showMessage(output);
7784 }
7785}
7786
7787
7788void MainWindow::on_actionGit_Push_triggered()
7789{
7790 QString folder;
7791 if (ui->treeFiles->isVisible()) {
7792 folder = pSettings->environment().currentFolder();
7793 } else if (ui->projectView->isVisible() && mProject) {
7794 folder = mProject->folder();
7795 }
7796 if (folder.isEmpty())
7797 return;
7798 GitManager manager;
7799 QString branch;
7800 if (!manager.hasRepository(folder,branch))
7801 return;
7802 QString remote = manager.getBranchRemote(folder,branch);
7803 QString output;
7804 if (remote.isEmpty()) {
7805 GitRemoteDialog dialog(folder);
7806 QString remote = dialog.chooseRemote();
7807 if (remote.trimmed().isEmpty())
7808 return;
7809 manager.push(folder,remote,branch,output);
7810 if (!output.isEmpty()) {
7811 InfoMessageBox infoBox;
7812 infoBox.showMessage(output);
7813 }
7814 } else {
7815 if (!output.isEmpty()) {
7816 InfoMessageBox infoBox;
7817 infoBox.showMessage(output);
7818 }
7819 }
7820}
7821
7822
7823void MainWindow::on_actionFilesView_Hide_Non_Support_Files_toggled(bool /* arg1 */)
7824{
7825 mFileSystemModel.setNameFilterDisables(!ui->actionFilesView_Hide_Non_Support_Files->isChecked());
7826 if (!mFileSystemModel.nameFilterDisables()) {
7827 mFileSystemModel.setNameFilters(pSystemConsts->defaultFileNameFilters());
7828 } else {
7829 mFileSystemModel.setNameFilters(QStringList());
7830 }
7831 if (pSettings->environment().hideNonSupportFilesInFileView()
7832 != ui->actionFilesView_Hide_Non_Support_Files->isChecked()) {
7833 pSettings->environment().setHideNonSupportFilesInFileView(ui->actionFilesView_Hide_Non_Support_Files->isChecked());
7834 pSettings->environment().save();
7835 }
7836}
7837
7838
7839void MainWindow::on_actionToggle_Block_Comment_triggered()
7840{
7841 Editor * editor = mEditorList->getEditor();
7842 if (editor != NULL ) {
7843 editor->toggleBlockComment();
7844 }
7845}
7846
7847
7848void MainWindow::on_actionMatch_Bracket_triggered()
7849{
7850 Editor * editor = mEditorList->getEditor();
7851 if (editor != NULL ) {
7852 editor->matchBracket();
7853 }
7854}
7855
7856
7857void MainWindow::on_btnProblemCaseInputFileName_clicked()
7858{
7859 QString fileName = QFileDialog::getOpenFileName(
7860 this,
7861 tr("Choose Input Data File"),
7862 QString(),
7863 tr("All files (*.*)"));
7864 if (!fileName.isEmpty()) {
7865 QModelIndex idx = ui->tblProblemCases->currentIndex();
7866 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
7867 if (!problemCase)
7868 return;
7869 if (problemCase->inputFileName == fileName)
7870 return;
7871 problemCase->inputFileName = fileName;
7872 if (problemCase->expectedOutputFileName.isEmpty()
7873 && problemCase->expected.isEmpty()
7874 && QFileInfo(fileName).suffix()=="in") {
7875 QString expectedFileName;
7876 expectedFileName = fileName.mid(0,fileName.length()-2)+"ans";
7877 if (fileExists(expectedFileName)) {
7878 problemCase->expectedOutputFileName = expectedFileName;
7879 } else {
7880 expectedFileName = fileName.mid(0,fileName.length()-2)+"out";
7881 if (fileExists(expectedFileName))
7882 problemCase->expectedOutputFileName = expectedFileName;
7883 }
7884 }
7885 fillProblemCaseInputAndExpected(problemCase);
7886 }
7887}
7888
7889
7890void MainWindow::on_btnProblemCaseClearExpectedOutputFileName_clicked()
7891{
7892 QModelIndex idx = ui->tblProblemCases->currentIndex();
7893 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
7894 if (!problemCase)
7895 return;
7896 problemCase->expectedOutputFileName = "";
7897 fillProblemCaseInputAndExpected(problemCase);
7898}
7899
7900
7901void MainWindow::on_btnProblemCaseClearInputFileName_clicked()
7902{
7903 QModelIndex idx = ui->tblProblemCases->currentIndex();
7904 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
7905 if (!problemCase)
7906 return;
7907 problemCase->inputFileName = "";
7908 fillProblemCaseInputAndExpected(problemCase);
7909}
7910
7911
7912void MainWindow::on_btnProblemCaseExpectedOutputFileName_clicked()
7913{
7914 QString fileName = QFileDialog::getOpenFileName(
7915 this,
7916 tr("Choose Expected Output Data File"),
7917 QString(),
7918 tr("All files (*.*)"));
7919 if (!fileName.isEmpty()) {
7920 QModelIndex idx = ui->tblProblemCases->currentIndex();
7921 POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
7922 if (!problemCase)
7923 return;
7924 if (problemCase->expectedOutputFileName == fileName)
7925 return;
7926 problemCase->expectedOutputFileName = fileName;
7927 fillProblemCaseInputAndExpected(problemCase);
7928 }
7929}
7930
7931
7932void MainWindow::on_txtProblemCaseOutput_cursorPositionChanged()
7933{
7934 QTextCursor cursor = ui->txtProblemCaseOutput->textCursor();
7935 int val = ui->txtProblemCaseOutput->verticalScrollBar()->value();
7936 int line = cursor.block().firstLineNumber();
7937 //ui->lblProblemCaseOutput->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1));
7938
7939 QTextBlock block = ui->txtProblemCaseExpected->document()->findBlockByLineNumber(line);
7940 if (!block.isValid())
7941 return;
7942 cursor = QTextCursor(block);
7943 ui->txtProblemCaseExpected->setTextCursor(cursor);
7944 ui->txtProblemCaseExpected->verticalScrollBar()->setValue(val);
7945}
7946
7947
7948void MainWindow::on_txtProblemCaseExpected_cursorPositionChanged()
7949{
7950 QTextCursor cursor = ui->txtProblemCaseExpected->textCursor();
7951 //ui->lblProblemCaseExpected->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1));
7952}
7953
7954
7955void MainWindow::on_txtProblemCaseInput_cursorPositionChanged()
7956{
7957 QTextCursor cursor = ui->txtProblemCaseInput->textCursor();
7958 //ui->lblProblemCaseInput->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1));
7959}
7960
7961
7962void MainWindow::on_actionMove_Selection_Up_triggered()
7963{
7964 Editor * editor = mEditorList->getEditor();
7965 if (editor != NULL ) {
7966 editor->moveSelUp();
7967 }
7968}
7969
7970
7971void MainWindow::on_actionMove_Selection_Down_triggered()
7972{
7973 Editor * editor = mEditorList->getEditor();
7974 if (editor != NULL ) {
7975 editor->moveSelDown();
7976 }
7977}
7978
7979void MainWindow::on_actionConvert_to_UTF_8_BOM_triggered()
7980{
7981 Editor * editor = mEditorList->getEditor();
7982 if (editor == nullptr)
7983 return;
7984 if (QMessageBox::warning(this,tr("Confirm Convertion"),
7985 tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
7986 .arg(ENCODING_UTF8_BOM),
7987 QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
7988 return;
7989 editor->convertToEncoding(ENCODING_UTF8_BOM);
7990}
7991
7992
7993void MainWindow::on_actionEncode_in_UTF_8_BOM_triggered()
7994{
7995 Editor * editor = mEditorList->getEditor();
7996 if (editor == nullptr)
7997 return;
7998 try {
7999 editor->setEncodingOption(ENCODING_UTF8_BOM);
8000 } catch(FileError e) {
8001 QMessageBox::critical(this,tr("Error"),e.reason());
8002 }
8003}
8004
8005
8006void MainWindow::on_actionCompiler_Options_triggered()
8007{
8008 changeOptions(
8009 SettingsDialog::tr("Compiler Set"),
8010 SettingsDialog::tr("Compiler")
8011 );
8012}
8013
8014void MainWindow::on_dockExplorer_dockLocationChanged(const Qt::DockWidgetArea &area)
8015{
8016 setDockExplorerToArea(area);
8017}
8018
8019
8020void MainWindow::on_dockMessages_dockLocationChanged(const Qt::DockWidgetArea &area)
8021{
8022 setDockMessagesToArea(area);
8023}
8024
8025
8026void MainWindow::on_actionToggle_Explorer_Panel_triggered()
8027{
8028 stretchExplorerPanel(ui->tabExplorer->isShrinked());
8029}
8030
8031
8032void MainWindow::on_actionToggle_Messages_Panel_triggered()
8033{
8034 stretchMessagesPanel(ui->tabMessages->isShrinked());
8035}
8036
8037
8038void MainWindow::on_chkIgnoreSpaces_stateChanged(int /*arg1*/)
8039{
8040 pSettings->executor().setIgnoreSpacesWhenValidatingCases(ui->chkIgnoreSpaces->isChecked());
8041}
8042
8043
8044
8045void MainWindow::on_actionRaylib_Manual_triggered()
8046{
8047 if (pSettings->environment().language()=="zh_CN") {
8048 QDesktopServices::openUrl(QUrl("https://zhuanlan.zhihu.com/p/458335134"));
8049 } else {
8050 QDesktopServices::openUrl(QUrl("https://www.raylib.com/"));
8051 }
8052}
8053
8054
8055void MainWindow::on_actionSelect_Word_triggered()
8056{
8057 Editor* e=mEditorList->getEditor();
8058 if (e) {
8059 e->selectWord();
8060 }
8061}
8062
8063
8064void MainWindow::on_actionGo_to_Line_triggered()
8065{
8066 Editor* e=mEditorList->getEditor();
8067 if (!e)
8068 return;
8069 bool ok;
8070 int lineNo=QInputDialog::getInt(e,tr("Go to Line"),tr("Line"),
8071 e->caretY(),1,e->document()->count(),
8072 1,&ok);
8073 if (ok && lineNo!=e->caretY()) {
8074 e->setCaretPosition(lineNo,1);
8075 e->setFocus();
8076 }
8077}
8078
8079
8080void MainWindow::on_actionNew_Template_triggered()
8081{
8082 if (!mProject)
8083 return;
8084 NewTemplateDialog dialog(this);
8085 if (dialog.exec()==QDialog::Accepted) {
8086 QDir folder(
8087 includeTrailingPathDelimiter(
8088 pSettings->dirs().config(Settings::Dirs::DataType::Template))
8089 +dialog.getName());
8090 if (folder.exists()) {
8091 if (QMessageBox::warning(this,
8092 tr("Template Exists"),
8093 tr("Template %1 already exists. Do you want to overwrite?").arg(dialog.getName()),
8094 QMessageBox::Yes | QMessageBox::No,
8095 QMessageBox::No
8096 )!=QMessageBox::Yes)
8097 return;
8098 }
8099
8100 mProject->saveAsTemplate(
8101 folder.absolutePath(),
8102 dialog.getName(),
8103 dialog.getDescription(),
8104 dialog.getCategory()
8105 );
8106 }
8107}
8108
8109bool MainWindow::isQuitting() const
8110{
8111 return mQuitting;
8112}
8113
8114bool MainWindow::isClosingAll() const
8115{
8116 return mClosingAll;
8117}
8118
8119