RedPanda-CPP/RedPandaIDE/mainwindow.cpp

1289 lines
41 KiB
C++
Raw Normal View History

2021-04-06 23:10:57 +08:00
#include "mainwindow.h"
#include "ui_mainwindow.h"
2021-04-07 21:13:15 +08:00
#include "editorlist.h"
#include "editor.h"
2021-04-11 21:33:08 +08:00
#include "systemconsts.h"
#include "settings.h"
2021-06-24 20:43:09 +08:00
#include "qsynedit/Constants.h"
2021-07-23 13:22:05 +08:00
#include "debugger.h"
2021-07-26 11:47:54 +08:00
#include "cpudialog.h"
2021-04-09 17:48:25 +08:00
#include <QCloseEvent>
2021-04-18 11:41:41 +08:00
#include <QComboBox>
2021-04-11 21:33:08 +08:00
#include <QFileDialog>
#include <QLabel>
2021-06-25 12:40:11 +08:00
#include <QMessageBox>
2021-06-20 09:27:37 +08:00
#include <QTranslator>
2021-04-20 22:24:33 +08:00
#include "settingsdialog/settingsdialog.h"
#include "compiler/compilermanager.h"
#include <QGuiApplication>
#include <QClipboard>
#include <QMessageBox>
#include <QTextCodec>
2021-04-20 22:24:33 +08:00
#include <QDebug>
2021-04-16 22:04:48 +08:00
MainWindow* pMainWindow;
2021-04-06 23:10:57 +08:00
MainWindow::MainWindow(QWidget *parent)
2021-06-23 22:38:02 +08:00
: QMainWindow(parent),
ui(new Ui::MainWindow),
mMessageControlChanged(false),
mTabMessagesTogglingState(false),
2021-06-23 22:38:02 +08:00
mCheckSyntaxInBack(false)
2021-04-06 23:10:57 +08:00
{
ui->setupUi(this);
// status bar
2021-04-18 11:41:41 +08:00
mFileInfoStatus=new QLabel();
mFileEncodingStatus = new QLabel();
mFileModeStatus = new QLabel();
mFileInfoStatus->setStyleSheet("margin-left:10px; margin-right:10px");
mFileEncodingStatus->setStyleSheet("margin-left:10px; margin-right:10px");
mFileModeStatus->setStyleSheet("margin-left:10px; margin-right:10px");
ui->statusbar->addWidget(mFileInfoStatus);
ui->statusbar->addWidget(mFileEncodingStatus);
ui->statusbar->addWidget(mFileModeStatus);
2021-04-07 21:13:15 +08:00
mEditorList = new EditorList(ui->EditorTabsLeft,
ui->EditorTabsRight,
ui->splitterEditorPanel,
2021-04-07 21:13:15 +08:00
ui->EditorPanel);
setupActions();
2021-04-07 22:44:08 +08:00
ui->EditorTabsRight->setVisible(false);
2021-04-18 11:41:41 +08:00
mCompilerSet = new QComboBox();
2021-06-24 20:43:09 +08:00
mCompilerSet->setMinimumWidth(200);
2021-04-18 11:41:41 +08:00
ui->toolbarCompilerSet->addWidget(mCompilerSet);
connect(mCompilerSet,QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::onCompilerSetChanged);
updateCompilerSet();
2021-04-20 22:24:33 +08:00
mCompilerManager = new CompilerManager(this);
2021-07-23 13:22:05 +08:00
mDebugger = new Debugger(this);
2021-04-24 15:57:45 +08:00
2021-07-25 00:26:13 +08:00
ui->tblBreakpoints->setModel(mDebugger->breakpointModel());
ui->tblStackTrace->setModel(mDebugger->backtraceModel());
2021-04-24 15:57:45 +08:00
ui->actionIndent->setShortcut(Qt::Key_Tab);
ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier);
ui->tableIssues->setErrorColor(QColor("Red"));
ui->tableIssues->setWarningColor(QColor("Orange"));
mMenuEncoding = new QMenu();
mMenuEncoding->setTitle(tr("File Encoding"));
mMenuEncoding->addAction(ui->actionAuto_Detect);
mMenuEncoding->addAction(ui->actionEncode_in_ANSI);
mMenuEncoding->addAction(ui->actionEncode_in_UTF_8);
mMenuEncoding->addSeparator();
mMenuEncoding->addAction(ui->actionConvert_to_ANSI);
mMenuEncoding->addAction(ui->actionConvert_to_UTF_8);
ui->menuEdit->insertMenu(ui->actionFoldAll,mMenuEncoding);
ui->menuEdit->insertSeparator(ui->actionFoldAll);
ui->actionAuto_Detect->setCheckable(true);
ui->actionEncode_in_ANSI->setCheckable(true);
ui->actionEncode_in_UTF_8->setCheckable(true);
2021-07-26 11:47:54 +08:00
mCPUDialog = new CPUDialog(this);
updateEditorActions();
2021-06-18 21:48:40 +08:00
applySettings();
openCloseMessageSheet(false);
mPreviousHeight = 250;
2021-04-06 23:10:57 +08:00
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateForEncodingInfo() {
Editor * editor = mEditorList->getEditor();
if (editor!=NULL) {
mFileEncodingStatus->setText(
QString("%1(%2)")
.arg(QString(editor->encodingOption()))
.arg(QString(editor->fileEncoding())));
ui->actionAuto_Detect->setChecked(editor->encodingOption() == ENCODING_AUTO_DETECT);
ui->actionEncode_in_ANSI->setChecked(editor->encodingOption() == ENCODING_SYSTEM_DEFAULT);
ui->actionEncode_in_UTF_8->setChecked(editor->encodingOption() == ENCODING_UTF8);
} else {
mFileEncodingStatus->setText("");
ui->actionAuto_Detect->setChecked(false);
ui->actionEncode_in_ANSI->setChecked(false);
ui->actionEncode_in_UTF_8->setChecked(false);
}
2021-04-11 13:55:31 +08:00
}
void MainWindow::updateEditorSettings()
2021-04-11 13:55:31 +08:00
{
mEditorList->applySettings();
}
void MainWindow::updateEditorActions()
{
Editor* e = mEditorList->getEditor();
if (e==nullptr) {
ui->actionAuto_Detect->setEnabled(false);
ui->actionEncode_in_ANSI->setEnabled(false);
ui->actionEncode_in_UTF_8->setEnabled(false);
ui->actionConvert_to_ANSI->setEnabled(false);
ui->actionConvert_to_UTF_8->setEnabled(false);
ui->actionCopy->setEnabled(false);
ui->actionCut->setEnabled(false);
ui->actionFoldAll->setEnabled(false);
ui->actionIndent->setEnabled(false);
ui->actionPaste->setEnabled(false);
ui->actionRedo->setEnabled(false);
ui->actionSave->setEnabled(false);
ui->actionSaveAs->setEnabled(false);
ui->actionSaveAll->setEnabled(false);
ui->actionSelectAll->setEnabled(false);
ui->actionToggleComment->setEnabled(false);
ui->actionUnIndent->setEnabled(false);
ui->actionUndo->setEnabled(false);
ui->actionUnfoldAll->setEnabled(false);
2021-07-01 19:44:38 +08:00
ui->actionCompile->setEnabled(false);
ui->actionCompile_Run->setEnabled(false);
ui->actionRun->setEnabled(false);
ui->actionRebuild->setEnabled(false);
ui->actionStop_Execution->setEnabled(false);
} else {
ui->actionAuto_Detect->setEnabled(true);
ui->actionEncode_in_ANSI->setEnabled(true);
ui->actionEncode_in_UTF_8->setEnabled(true);
ui->actionConvert_to_ANSI->setEnabled(e->encodingOption()!=ENCODING_SYSTEM_DEFAULT && e->fileEncoding()!=ENCODING_SYSTEM_DEFAULT);
ui->actionConvert_to_UTF_8->setEnabled(e->encodingOption()!=ENCODING_UTF8 && e->fileEncoding()!=ENCODING_UTF8);
2021-07-01 19:44:38 +08:00
ui->actionCopy->setEnabled(e->selAvail());
ui->actionCut->setEnabled(e->selAvail());
ui->actionFoldAll->setEnabled(e->lines()->count()>0);
ui->actionIndent->setEnabled(!e->readOnly());
ui->actionPaste->setEnabled(!e->readOnly() && !QGuiApplication::clipboard()->text().isEmpty());
ui->actionRedo->setEnabled(e->canRedo());
ui->actionUndo->setEnabled(e->canUndo());
ui->actionSave->setEnabled(e->modified());
ui->actionSaveAs->setEnabled(true);
ui->actionSaveAll->setEnabled(true);
ui->actionSelectAll->setEnabled(e->lines()->count()>0);
ui->actionToggleComment->setEnabled(!e->readOnly() && e->lines()->count()>0);
ui->actionUnIndent->setEnabled(!e->readOnly() && e->lines()->count()>0);
ui->actionUnfoldAll->setEnabled(e->lines()->count()>0);
2021-07-01 19:44:38 +08:00
updateCompileActions();
2021-04-11 13:55:31 +08:00
}
}
2021-07-01 19:44:38 +08:00
void MainWindow::updateCompileActions()
{
if (mCompilerManager->compiling()|| mCompilerManager->running()) {
ui->actionCompile->setEnabled(false);
ui->actionCompile_Run->setEnabled(false);
ui->actionRun->setEnabled(false);
ui->actionRebuild->setEnabled(false);
} else {
ui->actionCompile->setEnabled(true);
ui->actionCompile_Run->setEnabled(true);
ui->actionRun->setEnabled(true);
ui->actionRebuild->setEnabled(true);
}
ui->actionStop_Execution->setEnabled(mCompilerManager->running());
}
2021-06-20 14:30:47 +08:00
void MainWindow::updateEditorColorSchemes()
{
mEditorList->applyColorSchemes(pSettings->editor().colorScheme());
}
2021-06-18 21:48:40 +08:00
void MainWindow::applySettings()
{
changeTheme(pSettings->environment().theme());
QFont font(pSettings->environment().interfaceFont(),
pSettings->environment().interfaceFontSize());
2021-06-20 09:27:37 +08:00
font.setStyleStrategy(QFont::PreferAntialias);
QApplication * app = dynamic_cast<QApplication*>(QApplication::instance());
app->setFont(font);
2021-06-20 22:54:16 +08:00
this->setFont(font);
2021-06-18 21:48:40 +08:00
}
2021-07-26 00:22:08 +08:00
void MainWindow::removeActiveBreakpoints()
{
for (int i=0;i<mEditorList->pageCount();i++) {
Editor* e= (*mEditorList)[i];
e->removeBreakpointFocus();
}
}
2021-07-26 18:22:09 +08:00
void MainWindow::setActiveBreakpoint(QString FileName, int Line, bool setFocus)
{
removeActiveBreakpoints();
// Then active the current line in the current file
FileName.replace('/',QDir::separator());
Editor *e = mEditorList->getEditorByFilename(FileName);
if (e!=nullptr) {
e->setActiveBreakpointFocus(Line,setFocus);
}
if (setFocus) {
this->activateWindow();
}
}
2021-07-26 00:22:08 +08:00
void MainWindow::updateAppTitle()
{
2021-07-26 11:47:54 +08:00
QString appName("Red Panda Dev-C++");
Editor *e = mEditorList->getEditor();
QString str;
QCoreApplication *app = QApplication::instance();
if (e && !e->inProject()) {
if (e->modified())
str = e->filename() + " [*]";
else
str = e->filename();
if (mDebugger->executing()) {
setWindowTitle(QString("%s - [%s] - %s %s").arg(str).arg(appName)
.arg(tr("Debugging")).arg(DEVCPP_VERSION));
app->setApplicationName(QString("%s - [%s] - %s").arg(str).arg(appName)
.arg(tr("Debugging")));
} else if (mCompilerManager->running()) {
setWindowTitle(QString("%s - [%s] - %s %s").arg(str).arg(appName)
.arg(tr("Running")).arg(DEVCPP_VERSION));
app->setApplicationName(QString("%s - [%s] - %s").arg(str).arg(appName)
.arg(tr("Running")));
} else if (mCompilerManager->compiling()) {
setWindowTitle(QString("%s - [%s] - %s %s").arg(str).arg(appName)
.arg(tr("Compiling")).arg(DEVCPP_VERSION));
app->setApplicationName(QString("%s - [%s] - %s").arg(str).arg(appName)
.arg(tr("Compiling")));
} else {
this->setWindowTitle(QString("%s - %s %s").arg(str).arg(appName).arg(DEVCPP_VERSION));
app->setApplicationName(QString("%s - %s").arg(str).arg(appName));
}
}
// else if Assigned(fProject) then begin
// if fDebugger.Executing then begin
// Caption := Format('%s - [%s] - [Debugging] - %s %s',
// [fProject.Name, ExtractFilename(fProject.Filename), appName, DEVCPP_VERSION]);
// Application.Title := Format('%s - [Debugging] - %s', [fProject.Name, appName]);
// end else if devExecutor.Running then begin
// Caption := Format('%s - [%s] - [Executing] - %s %s',
// [fProject.Name, ExtractFilename(fProject.Filename), appName, DEVCPP_VERSION]);
// Application.Title := Format('%s - [Executing] - %s', [fProject.Name, appName]);
// end else if fCompiler.Compiling then begin
// Caption := Format('%s - [%s] - [Compiling] - %s %s',
// [fProject.Name, ExtractFilename(fProject.Filename), appName, DEVCPP_VERSION]);
// Application.Title := Format('%s - [Compiling] - %s', [fProject.Name, appName]);
// end else begin
// Caption := Format('%s - [%s] - %s %s',
// [fProject.Name, ExtractFilename(fProject.Filename), appName, DEVCPP_VERSION]);
// Application.Title := Format('%s - %s', [fProject.Name, appName]);
// end;
else {
setWindowTitle(QString("%s %s").arg(appName).arg(DEVCPP_VERSION));
app->setApplicationName(QString("%s").arg(appName));
}
}
void MainWindow::addDebugOutput(const QString &text)
{
if (text.isEmpty()) {
ui->debugConsole->addLine("");
} else {
ui->debugConsole->addText(text);
}
2021-07-26 00:22:08 +08:00
}
void MainWindow::updateStatusbarForLineCol()
2021-06-07 11:02:03 +08:00
{
Editor* e = mEditorList->getEditor();
if (e!=nullptr) {
QString msg = tr("Line:%1 Col:%2 Selected:%3 Lines:%4 Length:%5")
.arg(e->caretY(),6)
.arg(e->caretX(),6)
.arg(e->selText().length(),6)
.arg(e->lines()->count(),6)
.arg(e->lines()->getTextLength(),6);
mFileInfoStatus->setText(msg);
} else {
mFileInfoStatus->setText("");
}
}
void MainWindow::updateForStatusbarModeInfo()
{
Editor* e = mEditorList->getEditor();
if (e!=nullptr) {
QString msg;
if (e->readOnly()) {
msg = tr("Read Only");
} else if (e->insertMode()) {
msg = tr("Insert");
} else {
msg = tr("Overwrite");
}
mFileModeStatus->setText(msg);
} else {
mFileModeStatus->setText("");
}
2021-06-07 11:02:03 +08:00
}
2021-04-11 21:33:08 +08:00
void MainWindow::openFiles(const QStringList &files)
{
mEditorList->beginUpdate();
auto end = finally([this] {
this->mEditorList->endUpdate();
});
2021-04-11 21:33:08 +08:00
for (QString file:files) {
openFile(file);
}
mEditorList->endUpdate();
}
void MainWindow::openFile(const QString &filename)
{
2021-04-29 20:54:44 +08:00
Editor* editor = mEditorList->getOpenedEditorByFilename(filename);
2021-04-11 21:33:08 +08:00
if (editor!=nullptr) {
editor->activate();
2021-04-11 21:33:08 +08:00
return;
}
editor = mEditorList->newEditor(filename,ENCODING_AUTO_DETECT,
false,false);
editor->activate();
this->updateForEncodingInfo();
2021-04-11 21:33:08 +08:00
}
2021-04-07 21:13:15 +08:00
void MainWindow::setupActions() {
}
2021-04-18 11:41:41 +08:00
void MainWindow::updateCompilerSet()
{
mCompilerSet->clear();
int index=pSettings->compilerSets().defaultIndex();
2021-06-07 11:02:03 +08:00
for (size_t i=0;i<pSettings->compilerSets().list().size();i++) {
2021-04-18 11:41:41 +08:00
mCompilerSet->addItem(pSettings->compilerSets().list()[i]->name());
}
if (index < 0 || index>=mCompilerSet->count()) {
index = 0;
}
mCompilerSet->setCurrentIndex(index);
}
2021-06-24 20:43:09 +08:00
void MainWindow::checkSyntaxInBack(Editor *e)
{
if (e==nullptr)
return;
// if not devEditor.AutoCheckSyntax then
// Exit;
//not c or cpp file
if (!e->highlighter() || e->highlighter()->getName()!=SYN_HIGHLIGHTER_CPP)
return;
if (mCompilerManager->backgroundSyntaxChecking())
return;
if (mCompilerManager->compiling())
return;
// if not Assigned(devCompilerSets.CompilationSet) then
// Exit;
// if fCompiler.Compiling then
// Exit;
// if fSyntaxChecker.Compiling then
// Exit;
if (mCheckSyntaxInBack)
return;
mCheckSyntaxInBack=true;
e->clearSyntaxIssues();
ui->tableIssues->clearIssues();
mCompilerManager->checkSyntax(e->filename(),e->lines()->text());
// if not PrepareForCompile(cttStdin,True) then begin
// fCheckSyntaxInBack:=False;
// Exit;
// end;
// if e.InProject then begin
// if not assigned(MainForm.fProject) then
// Exit;
// fSyntaxChecker.Project := MainForm.fProject;
// end;
2021-06-25 12:40:11 +08:00
// fSyntaxChecker.CheckSyntax(True);
}
bool MainWindow::compile(bool rebuild)
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
editor->clearSyntaxIssues();
ui->tableIssues->clearIssues();
if (editor->modified()) {
if (!editor->save(false,false))
return false;
}
if (mCompileSuccessionTask) {
mCompileSuccessionTask->filename = getCompiledExecutableName(editor->filename());
}
2021-07-01 19:44:38 +08:00
mCompilerManager->compile(editor->filename(),editor->fileEncoding(),rebuild);
updateCompileActions();
2021-06-25 12:40:11 +08:00
openCloseMessageSheet(true);
ui->tabMessages->setCurrentWidget(ui->tabCompilerOutput);
return true;
}
return false;
}
void MainWindow::runExecutable(const QString &exeName,const QString &filename)
{
// Check if it exists
if (!QFile(exeName).exists()) {
if (ui->actionCompile_Run->isEnabled()) {
if (QMessageBox::warning(this,tr("Confirm"),
tr("Source file is not compiled.")
+"<br /><br />"+tr("Compile now?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
ui->actionCompile_Run->trigger();
return;
}
} else {
QMessageBox::critical(this,"Error",
tr("Source file is not compiled."));
return;
}
} else {
if (!filename.isEmpty() && compareFileModifiedTime(filename,exeName)>=0) {
if (ui->actionCompile_Run->isEnabled()) {
if (QMessageBox::warning(this,tr("Confirm"),
tr("Source file is more recent than executable.")
+"<br /><br />"+tr("Recompile now?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
ui->actionCompile_Run->trigger();
return;
}
}
}
}
// Pause programs if they contain a console
// if devData.ConsolePause and ProgramHasConsole(FileToRun) then begin
// if fUseRunParams then
// Parameters := '"' + FileToRun + '" ' + fRunParams
// else
// Parameters := '"' + FileToRun + '"';
// FileToRun := devDirs.Exec + 'ConsolePauser.exe';
// end else begin
// if fUseRunParams then
// Parameters := fRunParams
// else
// Parameters := '';
// FileToRun := FileToRun;
// end;
// if devData.MinOnRun then
// Application.Minimize;
// devExecutor.ExecuteAndWatch(FileToRun, Parameters, ExtractFilePath(fSourceFile),
// True, UseInputFile,InputFile, INFINITE, RunTerminate);
// MainForm.UpdateAppTitle;
// end;
mCompilerManager->run(exeName,"",QFileInfo(exeName).absolutePath());
2021-07-01 19:44:38 +08:00
updateCompileActions();
if (pSettings->executor().minimizeOnRun()) {
showMinimized();
}
2021-06-25 12:40:11 +08:00
}
void MainWindow::runExecutable()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
if (editor->modified()) {
if (!editor->save(false,false))
return;
}
QString exeName= getCompiledExecutableName(editor->filename());
runExecutable(exeName,editor->filename());
}
2021-06-24 20:43:09 +08:00
}
2021-07-23 13:22:05 +08:00
void MainWindow::debug()
{
if (mCompilerManager->compiling())
return;
Settings::PCompilerSet compilerSet = pSettings->compilerSets().defaultSet();
if (!compilerSet)
return;
bool debugEnabled;
bool stripEnabled;
2021-07-25 13:03:46 +08:00
QString filePath;
QFileInfo debugFile;
2021-07-23 13:22:05 +08:00
switch(getCompileTarget()) {
case CompileTarget::Project:
break;
// cttProject: begin
// // Check if we enabled proper options
// DebugEnabled := fProject.GetCompilerOption('-g3') <> '0';
// StripEnabled := fProject.GetCompilerOption('-s') <> '0';
// // Ask the user if he wants to enable debugging...
// if (not DebugEnabled or StripEnabled) then begin
// if (MessageDlg(Lang[ID_MSG_NODEBUGSYMBOLS], mtConfirmation, [mbYes,
// mbNo], 0) = mrYes) then begin
// // Enable debugging, disable stripping
// fProject.SetCompilerOption('-g3', '1');
// fProject.SetCompilerOption('-s', '0');
// fCompSuccessAction := csaDebug;
// actRebuildExecute(nil);
// end;
// Exit;
// end;
// // Did we compile?
// if not FileExists(fProject.Executable) then begin
// if MessageDlg(Lang[ID_ERR_PROJECTNOTCOMPILEDSUGGEST], mtConfirmation, [mbYes, mbNo], 0) = mrYes then begin
// fCompSuccessAction := csaDebug;
// actCompileExecute(nil);
// end;
// Exit;
// end;
// // Did we choose a host application for our DLL?
// if fProject.Options.typ = dptDyn then begin
// if fProject.Options.HostApplication = '' then begin
// MessageDlg(Lang[ID_ERR_HOSTMISSING], mtWarning, [mbOK], 0);
// exit;
// end else if not FileExists(fProject.Options.HostApplication) then begin
// MessageDlg(Lang[ID_ERR_HOSTNOTEXIST], mtWarning, [mbOK], 0);
// exit;
// end;
// end;
// // Reset UI, remove invalid breakpoints
// PrepareDebugger;
// filepath := fProject.Executable;
// fDebugger.Start;
// fDebugger.SendCommand('file', '"' + StringReplace(filepath, '\', '/', [rfReplaceAll]) + '"');
// if fProject.Options.typ = dptDyn then
// fDebugger.SendCommand('exec-file', '"' + StringReplace(fProject.Options.HostApplication, '\', '/',
// [rfReplaceAll])
// + '"');
// for i:=0 to fProject.Units.Count-1 do begin
// fDebugger.SendCommand('dir', '"'+StringReplace(
// ExtractFilePath(fProject.Units[i].FileName),'\', '/',[rfReplaceAll])
// + '"');
// end;
// for i:=0 to fProject.Options.Includes.Count-1 do begin
// fDebugger.SendCommand('dir', '"'+StringReplace(
// fProject.Options.Includes[i],'\', '/',[rfReplaceAll])
// + '"');
// end;
// for i:=0 to fProject.Options.Libs.Count-1 do begin
// fDebugger.SendCommand('dir', '"'+StringReplace(
// fProject.Options.Includes[i],'\', '/',[rfReplaceAll])
// + '"');
// end;
// end;
case CompileTarget::File:
// Check if we enabled proper options
debugEnabled = compilerSet->getOptionValue("-g3")!='0';
stripEnabled = compilerSet->getOptionValue("-s")!=0;
// Ask the user if he wants to enable debugging...
if (((!debugEnabled) || stripEnabled) &&
(QMessageBox::question(this,
tr("Enable debugging"),
tr("You have not enabled debugging info (-g) and/or stripped it from the executable (-s) in Compiler Options.<BR /><BR />Do you want to correct this now?")
) == QMessageBox::Yes)) {
// Enable debugging, disable stripping
compilerSet->setOption("-g3",'1');
compilerSet->setOption("-s",'0');
// Save changes to compiler set
pSettings->compilerSets().saveSet(pSettings->compilerSets().defaultIndex());
mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
compile();
return;
}
Editor* e = mEditorList->getEditor();
if (e!=nullptr) {
// Did we saved?
if (e->modified()) {
// if file is modified,save it first
if (!e->save(false,false))
return;
}
// Did we compiled?
2021-07-25 13:03:46 +08:00
filePath = getCompiledExecutableName(e->filename());
debugFile.setFile(filePath);
if (!debugFile.exists()) {
2021-07-23 13:22:05 +08:00
if (QMessageBox::question(this,tr("Compile"),
tr("Source file is not compiled.")+"<BR /><BR />" + tr("Compile now?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::Yes) == QMessageBox::Yes) {
mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
compile();
return;
}
} else {
2021-07-25 13:03:46 +08:00
if (compareFileModifiedTime(e->filename(),filePath)>=0) {
2021-07-23 13:22:05 +08:00
if (QMessageBox::question(this,tr("Compile"),
tr("Source file is more recent than executable.")+"<BR /><BR />" + tr("Recompile?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::Yes) == QMessageBox::Yes) {
mCompileSuccessionTask=std::make_shared<CompileSuccessionTask>();
mCompileSuccessionTask->type = CompileSuccessionTaskType::Debug;
compile();
return;
}
}
}
prepareDebugger();
2021-07-25 13:03:46 +08:00
mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM);
2021-07-23 13:22:05 +08:00
mDebugger->start();
2021-07-25 13:03:46 +08:00
mDebugger->sendCommand("file", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/')));
2021-07-23 13:22:05 +08:00
}
break;
}
// Add library folders
for (QString dir:compilerSet->libDirs()) {
mDebugger->sendCommand("dir",
QString("\"%1\"").arg(dir.replace('\\','/')));
}
2021-07-25 13:03:46 +08:00
// Add include folders
for (QString dir:compilerSet->CIncludeDirs()) {
mDebugger->sendCommand("dir",
QString("\"%1\"").arg(dir.replace('\\','/')));
}
for (QString dir:compilerSet->CppIncludeDirs()) {
mDebugger->sendCommand("dir",
QString("\"%1\"").arg(dir.replace('\\','/')));
}
2021-07-23 13:22:05 +08:00
// Add breakpoints and watch vars
2021-07-26 18:22:09 +08:00
// for i := 0 to fDebugger.WatchVarList.Count - 1 do
// fDebugger.AddWatchVar(i);
mDebugger->sendAllWatchvarsToDebugger();
2021-07-25 13:03:46 +08:00
mDebugger->sendAllBreakpointsToDebugger();
2021-07-23 13:22:05 +08:00
// Run the debugger
2021-07-25 13:03:46 +08:00
mDebugger->sendCommand("set", "width 0"); // don't wrap output, very annoying
mDebugger->sendCommand("set", "new-console on");
mDebugger->sendCommand("set", "confirm off");
mDebugger->sendCommand("cd", excludeTrailingPathDelimiter(debugFile.path())); // restore working directory
if (!debugInferiorhasBreakpoint()) {
QString params;
switch(getCompileTarget()) {
case CompileTarget::None:
return;
case CompileTarget::File:
// if (mCompiler->useRunParams) {
// }
mDebugger->sendCommand("start",params);
2021-07-26 18:22:09 +08:00
mDebugger->updateDebugInfo();
2021-07-25 13:03:46 +08:00
break;
case CompileTarget::Project:
//params := '';
//if fCompiler.UseRunParams then
// params := params + ' ' + fProject.Options.CmdLineArgs;
//if fCompiler.UseInputFile then
// params := params + ' < "' + fCompiler.InputFile + '"';
//fDebugger.SendCommand('start', params);
//UpdateDebugInfo;
break;
}
} else {
QString params;
switch(getCompileTarget()) {
case CompileTarget::None:
return;
case CompileTarget::File:
// if (mCompiler->useRunParams) {
// }
mDebugger->sendCommand("run",params);
2021-07-26 18:22:09 +08:00
mDebugger->updateDebugInfo();
2021-07-25 13:03:46 +08:00
break;
case CompileTarget::Project:
//params := '';
//if fCompiler.UseRunParams then
// params := params + ' ' + fProject.Options.CmdLineArgs;
//if fCompiler.UseInputFile then
// params := params + ' < "' + fCompiler.InputFile + '"';
//fDebugger.SendCommand('run', params);
//UpdateDebugInfo;
break;
}
}
2021-07-23 13:22:05 +08:00
}
2021-06-23 22:38:02 +08:00
void MainWindow::openCloseMessageSheet(bool open)
{
// if Assigned(fReportToolWindow) then
// Exit;
if (mTabMessagesTogglingState)
return;
mTabMessagesTogglingState = true;
auto action = finally([this]{
mTabMessagesTogglingState = false;
});
2021-06-23 22:38:02 +08:00
// Switch between open and close
if (open) {
QList<int> sizes = ui->splitterMessages->sizes();
int tabHeight = ui->tabMessages->tabBar()->height();
ui->tabMessages->setMinimumHeight(tabHeight+5);
int totalSize = sizes[0] + sizes[1];
sizes[1] = mPreviousHeight;
sizes[0] = std::max(1,totalSize - sizes[1]);
ui->splitterMessages->setSizes(sizes);
} else {
QList<int> sizes = ui->splitterMessages->sizes();
mPreviousHeight = sizes[1];
int totalSize = sizes[0] + sizes[1];
int tabHeight = ui->tabMessages->tabBar()->height();
ui->tabMessages->setMinimumHeight(tabHeight);
sizes[1] = tabHeight;
sizes[0] = std::max(1,totalSize - sizes[1]);
ui->splitterMessages->setSizes(sizes);
}
QSplitterHandle* handle = ui->splitterMessages->handle(1);
handle->setEnabled(open);
int idxClose = ui->tabMessages->indexOf(ui->tabClose);
ui->tabMessages->setTabVisible(idxClose,open);
mTabMessagesTogglingState = false;
2021-06-23 22:38:02 +08:00
}
2021-07-23 13:22:05 +08:00
void MainWindow::prepareDebugger()
{
mDebugger->stop();
// Clear logs
ui->debugConsole->clear();
ui->txtEvalOutput->clear();
// Restore when no watch vars are shown
2021-07-26 18:22:09 +08:00
mDebugger->setLeftPageIndexBackup(ui->tabInfos->currentIndex());
2021-07-23 13:22:05 +08:00
// Focus on the debugging buttons
ui->tabInfos->setCurrentWidget(ui->tabWatch);
ui->tabMessages->setCurrentWidget(ui->tabDebug);
ui->debugViews->setCurrentWidget(ui->tabDebugConsole);
openCloseMessageSheet(true);
// Reset watch vars
2021-07-26 18:22:09 +08:00
// mDebugger->deleteWatchVars(false);
2021-07-23 13:22:05 +08:00
}
2021-07-26 18:22:09 +08:00
CPUDialog *MainWindow::cpuDialog() const
2021-07-26 11:47:54 +08:00
{
return mCPUDialog;
}
2021-04-07 21:13:15 +08:00
void MainWindow::on_actionNew_triggered()
{
2021-06-20 09:27:37 +08:00
try {
Editor * editor=mEditorList->newEditor("",ENCODING_AUTO_DETECT,false,true);
editor->activate();
updateForEncodingInfo();
} catch (FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
2021-04-07 21:13:15 +08:00
}
2021-04-07 22:44:08 +08:00
void MainWindow::on_EditorTabsLeft_tabCloseRequested(int index)
{
Editor* editor = mEditorList->getEditor(index);
mEditorList->closeEditor(editor);
}
void MainWindow::on_actionOpen_triggered()
{
2021-06-20 09:27:37 +08:00
try {
QString selectedFileFilter = pSystemConsts->defaultFileFilter();
QStringList files = QFileDialog::getOpenFileNames(pMainWindow,
tr("Open"), QString(), pSystemConsts->defaultFileFilters().join(";;"),
&selectedFileFilter);
openFiles(files);
} catch (FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
2021-04-07 22:44:08 +08:00
}
2021-04-09 17:48:25 +08:00
void MainWindow::closeEvent(QCloseEvent *event) {
2021-06-10 09:34:59 +08:00
if (!mEditorList->closeAll(false)) {
2021-04-09 17:48:25 +08:00
event->ignore();
return ;
}
delete mEditorList;
event->accept();
return;
}
void MainWindow::on_actionSave_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL) {
2021-06-20 09:27:37 +08:00
try {
editor->save();
} catch(FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
}
}
void MainWindow::on_actionSaveAs_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL) {
2021-06-20 09:27:37 +08:00
try {
editor->saveAs();
} catch(FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
}
}
2021-04-16 22:04:48 +08:00
void MainWindow::on_actionOptions_triggered()
{
SettingsDialog settingsDialog;
settingsDialog.exec();
}
2021-04-18 11:41:41 +08:00
void MainWindow::onCompilerSetChanged(int index)
{
if (index<0)
return;
pSettings->compilerSets().setDefaultIndex(index);
pSettings->compilerSets().saveDefaultIndex();
}
2021-04-20 22:24:33 +08:00
void MainWindow::onCompileLog(const QString &msg)
{
ui->txtCompilerOutput->appendPlainText(msg);
}
2021-04-24 15:57:45 +08:00
void MainWindow::onCompileIssue(PCompileIssue issue)
2021-04-20 22:24:33 +08:00
{
2021-04-24 15:57:45 +08:00
ui->tableIssues->addIssue(issue);
2021-06-23 22:38:02 +08:00
// Update tab caption
// if CompilerOutput.Items.Count = 1 then
// CompSheet.Caption := Lang[ID_SHEET_COMP] + ' (' + IntToStr(CompilerOutput.Items.Count) + ')';
if (issue->type == CompileIssueType::Error || issue->type ==
CompileIssueType::Warning) {
Editor* e = mEditorList->getOpenedEditorByFilename(issue->filename);
if (e!=nullptr && (issue->line>0)) {
int line = issue->line;
if (line > e->lines()->count())
return;
int col = std::min(issue->column,e->lines()->getString(line-1).length()+1);
if (col < 1)
col = e->lines()->getString(line-1).length()+1;
e->addSyntaxIssues(line,col,issue->endColumn,issue->type,issue->description);
2021-06-23 22:38:02 +08:00
}
}
}
void MainWindow::onCompileFinished()
{
// Update tab caption
int i = ui->tabMessages->indexOf(ui->tabIssues);
if (i==-1)
return;
ui->tabMessages->setTabText(i, tr("Issues") +
QString(" (%1)").arg(ui->tableIssues->model()->rowCount()));
// Close it if there's nothing to show
if (mCheckSyntaxInBack) {
// check syntax in back, don't change message panel
} else if (
(ui->tableIssues->count() == 0)
// and (ResourceOutput.Items.Count = 0)
// and devData.AutoCloseProgress
) {
openCloseMessageSheet(false);
// Or open it if there is anything to show
} else {
if (ui->tableIssues->count() > 0) {
if (ui->tabMessages->currentIndex() != i) {
ui->tabMessages->setCurrentIndex(i);
mMessageControlChanged = false;
}
// end else if (ResourceOutput.Items.Count > 0) then begin
// if MessageControl.ActivePage <> ResSheet then begin
// MessageControl.ActivePage := ResSheet;
// fMessageControlChanged := False;
// end;
// end;
openCloseMessageSheet(true);
}
}
Editor * e = mEditorList->getEditor();
if (e!=nullptr) {
2021-06-24 20:43:09 +08:00
e->invalidate();
2021-06-23 22:38:02 +08:00
}
// Jump to problem location, sorted by significance
if ((mCompilerManager->compileErrorCount() > 0) && (!mCheckSyntaxInBack)) {
// First try to find errors
for (int i=0;i<ui->tableIssues->count();i++) {
PCompileIssue issue = ui->tableIssues->issue(i);
if (issue->type == CompileIssueType::Error) {
ui->tableIssues->selectRow(i);
QModelIndex index =ui->tableIssues->model()->index(i,0);
ui->tableIssues->doubleClicked(index);
}
}
// Then try to find warnings
for (int i=0;i<ui->tableIssues->count();i++) {
PCompileIssue issue = ui->tableIssues->issue(i);
if (issue->type == CompileIssueType::Warning) {
ui->tableIssues->selectRow(i);
QModelIndex index =ui->tableIssues->model()->index(i,0);
ui->tableIssues->doubleClicked(index);
}
}
// Then try to find anything with a line number...
// for I := 0 to CompilerOutput.Items.Count - 1 do begin
// if not SameStr(CompilerOutput.Items[I].Caption, '') then begin
// CompilerOutput.Selected := CompilerOutput.Items[I];
// CompilerOutput.Selected.MakeVisible(False);
// CompilerOutputDblClick(CompilerOutput);
// Exit;
// end;
// end;
// Then try to find a resource error
// if ResourceOutput.Items.Count > 0 then begin
// ResourceOutput.Selected := ResourceOutput.Items[0];
// ResourceOutput.Selected.MakeVisible(False);
// CompilerOutputDblClick(ResourceOutput);
// end;
2021-06-25 12:40:11 +08:00
} else {
if (mCompileSuccessionTask) {
switch (mCompileSuccessionTask->type) {
case MainWindow::CompileSuccessionTaskType::Run:
runExecutable(mCompileSuccessionTask->filename);
2021-07-23 13:22:05 +08:00
break;
case MainWindow::CompileSuccessionTaskType::Debug:
debug();
break;
2021-06-25 12:40:11 +08:00
}
2021-07-23 13:22:05 +08:00
mCompileSuccessionTask.reset();
2021-06-25 12:40:11 +08:00
}
2021-06-23 22:38:02 +08:00
}
mCheckSyntaxInBack=false;
2021-07-01 19:44:38 +08:00
updateCompileActions();
2021-04-20 22:24:33 +08:00
}
void MainWindow::onCompileErrorOccured(const QString &reason)
{
QMessageBox::critical(this,tr("Compile Failed"),reason);
}
2021-06-25 12:40:11 +08:00
void MainWindow::onRunErrorOccured(const QString &reason)
{
QMessageBox::critical(this,tr("Run Failed"),reason);
}
void MainWindow::onRunFinished()
{
2021-07-01 19:44:38 +08:00
updateCompileActions();
if (pSettings->executor().minimizeOnRun()) {
showNormal();
}
2021-06-25 12:40:11 +08:00
}
2021-04-20 22:24:33 +08:00
void MainWindow::on_actionCompile_triggered()
{
2021-06-25 12:40:11 +08:00
mCompileSuccessionTask.reset();
compile();
2021-04-20 22:24:33 +08:00
}
void MainWindow::on_actionRun_triggered()
{
2021-06-25 12:40:11 +08:00
runExecutable();
}
void MainWindow::on_actionUndo_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->undo();
}
}
void MainWindow::on_actionRedo_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->redo();
}
}
void MainWindow::on_actionCut_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->cutToClipboard();
}
}
void MainWindow::on_actionSelectAll_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->selectAll();
}
}
void MainWindow::on_actionCopy_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->copyToClipboard();
}
}
void MainWindow::on_actionPaste_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->pasteFromClipboard();
}
}
void MainWindow::on_actionIndent_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->tab();
}
}
void MainWindow::on_actionUnIndent_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-06-07 11:02:03 +08:00
editor->untab();
}
}
2021-04-24 15:57:45 +08:00
void MainWindow::on_actionToggleComment_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
editor->toggleComment();
2021-04-24 15:57:45 +08:00
}
}
void MainWindow::on_actionUnfoldAll_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-05-24 00:41:00 +08:00
//editor->clearFolds();
2021-04-24 15:57:45 +08:00
}
}
void MainWindow::on_actionFoldAll_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
2021-05-24 00:41:00 +08:00
//editor->clearFolds();
//editor->foldAll();
2021-04-24 15:57:45 +08:00
}
}
2021-04-29 20:54:44 +08:00
void MainWindow::on_tableIssues_doubleClicked(const QModelIndex &index)
{
PCompileIssue issue = ui->tableIssues->issue(index);
if (!issue)
return;
Editor * editor = mEditorList->getEditorByFilename(issue->filename);
if (editor == nullptr)
return;
editor->setCaretPositionAndActivate(issue->line,issue->column);
2021-04-29 20:54:44 +08:00
}
void MainWindow::on_actionEncode_in_ANSI_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor == nullptr)
return;
2021-06-20 09:27:37 +08:00
try {
editor->setEncodingOption(ENCODING_SYSTEM_DEFAULT);
} catch(FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
}
void MainWindow::on_actionEncode_in_UTF_8_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor == nullptr)
return;
2021-06-20 09:27:37 +08:00
try {
editor->setEncodingOption(ENCODING_UTF8);
} catch(FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason());
2021-06-20 09:27:37 +08:00
}
}
void MainWindow::on_actionAuto_Detect_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor == nullptr)
return;
editor->setEncodingOption(ENCODING_AUTO_DETECT);
}
void MainWindow::on_actionConvert_to_ANSI_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor == nullptr)
return;
if (QMessageBox::warning(this,tr("Confirm Convertion"),
tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
.arg(QString(QTextCodec::codecForLocale()->name())),
QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
return;
editor->convertToEncoding(ENCODING_SYSTEM_DEFAULT);
}
void MainWindow::on_actionConvert_to_UTF_8_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor == nullptr)
return;
if (QMessageBox::warning(this,tr("Confirm Convertion"),
tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
.arg(ENCODING_UTF8),
QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
return;
editor->convertToEncoding(ENCODING_UTF8);
}
2021-06-23 22:38:02 +08:00
void MainWindow::on_tabMessages_tabBarClicked(int index)
{
if (index == ui->tabMessages->currentIndex()) {
openCloseMessageSheet(!ui->splitterMessages->handle(1)->isEnabled());
}
}
void MainWindow::on_tabMessages_currentChanged(int index)
{
2021-06-23 22:38:02 +08:00
int idxClose = ui->tabMessages->indexOf(ui->tabClose);
if (index == idxClose) {
openCloseMessageSheet(false);
} else {
openCloseMessageSheet(true);
}
}
void MainWindow::on_tabMessages_tabBarDoubleClicked(int index)
{
}
2021-06-25 12:40:11 +08:00
void MainWindow::on_actionCompile_Run_triggered()
{
mCompileSuccessionTask = std::make_shared<CompileSuccessionTask>();
mCompileSuccessionTask->type = CompileSuccessionTaskType::Run;
compile();
}
void MainWindow::on_actionRebuild_triggered()
{
mCompileSuccessionTask.reset();
compile(true);
}
void MainWindow::on_actionStop_Execution_triggered()
{
mCompilerManager->stopRun();
}
2021-07-20 15:16:52 +08:00
void MainWindow::on_actionDebug_triggered()
{
2021-07-23 13:22:05 +08:00
debug();
2021-07-20 15:16:52 +08:00
}
CompileTarget MainWindow::getCompileTarget()
{
// Check if the current file belongs to a project
CompileTarget target = CompileTarget::None;
Editor* e = mEditorList->getEditor();
if (e!=nullptr) {
// Treat makefiles as InProject files too
// if ((mProject) and (e.InProject or (fProject.MakeFileName = e.FileName)) then begin
// Result := cttProject;
// end else begin
// Result := cttFile;
// end;
target = CompileTarget::File;
}
// // No editors have been opened. Check if a project is open
// end else if Assigned(fProject) then begin
// Result := cttProject;
// // No project, no editor...
// end else begin
// Result := cttNone;
// end;
return target;
}
2021-07-25 13:03:46 +08:00
bool MainWindow::debugInferiorhasBreakpoint()
{
Editor * e = mEditorList->getEditor();
if (e==nullptr)
return false;
if (!e->inProject()) {
for (PBreakpoint breakpoint:mDebugger->breakpointModel()->breakpoints()) {
if (e->filename() == breakpoint->filename) {
return true;
}
}
} else {
for (PBreakpoint breakpoint:mDebugger->breakpointModel()->breakpoints()) {
Editor* e1 = mEditorList->getOpenedEditorByFilename(breakpoint->filename);
if (e1->inProject()) {
return true;
}
}
}
return false;
}