Mercurial > hg > octave-nkf
changeset 14676:35512b788af2 gui
Editor can now handle multiple files in tabs.
* FileEditorInterface (new class): Interface class fpr the file editor.
* FileEditorTab (new class): File editor unit for editing a single file.
* MainWindow: Adjusted includes and method calls.
* FileEditor: Replaced code that allowed editing a file with code that manages tabs and delegates button clicks.
* src.pro: Added new files.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Wed, 23 May 2012 20:25:07 +0200 |
parents | 252a86f8fe62 |
children | 2fb96afd7b34 |
files | gui/src/MainWindow.cpp gui/src/MainWindow.h gui/src/editor/FileEditor.cpp gui/src/editor/FileEditor.h gui/src/editor/FileEditorInterface.h gui/src/editor/FileEditorTab.cpp gui/src/editor/FileEditorTab.h gui/src/src.pro |
diffstat | 8 files changed, 930 insertions(+), 527 deletions(-) [+] |
line wrap: on
line diff
--- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -43,31 +43,27 @@ } void -MainWindow::openExistingFile (QString fileName) +MainWindow::newFile () { - reportStatusMessage (tr ("Opening file..")); - newEditorWindow(fileName); + if (!m_fileEditor->isVisible ()) + { + m_fileEditor->show (); + } + m_fileEditor->requestNewFile (); + } void -MainWindow::newFile () -{ - newEditorWindow(QString()); -} - -void -MainWindow::newEditorWindow (QString fileName) +MainWindow::openFile () { - FileEditor *fileEditor = new FileEditor (m_terminalView, m_lexer, this); - fileEditor->setAttribute (Qt::WA_DeleteOnClose); + if (!m_fileEditor->isVisible ()) + { + m_fileEditor->show (); + } + m_fileEditor->requestOpenFile (); - if (fileName.isEmpty ()) - fileEditor->newFile (); - else - fileEditor->loadFile (fileName); } - void MainWindow::reportStatusMessage (QString statusMessage) { @@ -231,7 +227,7 @@ m_terminalView = new QTerminal(this); setCentralWidget (m_terminalView); - m_lexer = NULL; // initialise the empty lexer for the edtiors + m_fileEditor = new FileEditor (m_terminalView, this); QMenu *fileMenu = menuBar ()->addMenu (tr ("&File")); QAction *newFileAction @@ -250,25 +246,27 @@ QAction *cutAction = editMenu->addAction (QIcon::fromTheme ("edit-cut", style->standardIcon (QStyle::SP_FileIcon)), tr ("Cut")); - cutAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X)); + cutAction->setShortcut (QKeySequence::Cut); QAction *copyAction = editMenu->addAction (QIcon::fromTheme ("edit-copy", style->standardIcon (QStyle::SP_FileIcon)), tr ("Copy")); - copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); + copyAction->setShortcut (QKeySequence::Copy); QAction *pasteAction = editMenu->addAction (QIcon::fromTheme ("edit-paste", style->standardIcon (QStyle::SP_FileIcon)), tr ("Paste")); - pasteAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V)); + pasteAction->setShortcut (QKeySequence::Paste); QAction *undoAction = editMenu->addAction (QIcon::fromTheme ("edit-undo", style->standardIcon (QStyle::SP_FileIcon)), tr ("Undo")); + undoAction->setShortcut (QKeySequence::Undo); QAction *redoAction = editMenu->addAction (QIcon::fromTheme ("edit-redo", style->standardIcon (QStyle::SP_FileIcon)), tr ("Redo")); + redoAction->setShortcut (QKeySequence::Redo); //QMenu *debugMenu = menuBar ()->addMenu (tr ("De&bug")); //QMenu *parallelMenu = menuBar ()->addMenu (tr ("&Parallel")); @@ -296,7 +294,6 @@ QAction *aboutOctaveAction = helpMenu->addAction (tr ("About Octave")); // Toolbars - QToolBar *mainToolBar = addToolBar ("Main"); mainToolBar->addAction (newFileAction); mainToolBar->addAction (openFileAction); @@ -315,6 +312,7 @@ connect (settingsAction, SIGNAL (triggered ()), this, SLOT (processSettingsDialogRequest ())); connect (exitAction, SIGNAL (triggered ()), this, SLOT (close ())); connect (newFileAction, SIGNAL (triggered ()), this, SLOT (newFile ())); + connect (openFileAction, SIGNAL (triggered ()), this, SLOT (openFile ())); connect (reportBugAction, SIGNAL (triggered ()), this, SLOT (openBugTrackerPage ())); connect (agoraAction, SIGNAL (triggered ()), this, SLOT (openAgoraPage ())); connect (octaveForgeAction, SIGNAL (triggered ()), this, SLOT (openOctaveForgePage ())); @@ -331,7 +329,7 @@ //connect (this, SIGNAL (settingsChanged ()), m_historyDockWidget, SLOT (noticeSettings ())); connect (this, SIGNAL (settingsChanged ()), m_filesDockWidget, SLOT (noticeSettings ())); - connect (m_filesDockWidget, SIGNAL (openFile (QString)), this, SLOT (openExistingFile (QString))); + connect (m_filesDockWidget, SIGNAL (openFile (QString)), m_fileEditor, SLOT (requestOpenFile (QString))); connect (m_historyDockWidget, SIGNAL (information (QString)), this, SLOT (reportStatusMessage (QString))); connect (m_historyDockWidget, SIGNAL (commandDoubleClicked (QString)), this, SLOT (handleCommandDoubleClicked (QString))); connect (saveWorkspaceAction, SIGNAL (triggered ()), this, SLOT (handleSaveWorkspaceRequest ())); @@ -347,38 +345,6 @@ addDockWidget (Qt::RightDockWidgetArea, m_filesDockWidget); setStatusBar (m_statusBar); - // this has to be done only once, not for each editor - m_lexer = new LexerOctaveGui (); - - // Editor font (default or from settings) - QSettings *settings = ResourceManager::instance ()->settings (); - m_lexer->setDefaultFont (QFont ( - settings->value ("editor/fontName","Courier").toString (), - settings->value ("editor/fontSize",10).toInt ())); - - // TODO: Autoindent not working as it should - m_lexer->setAutoIndentStyle (QsciScintilla::AiMaintain || - QsciScintilla::AiOpening || - QsciScintilla::AiClosing); - - // The API info that is used for auto completion - // TODO: Where to store a file with API info (raw or prepared?)? - // TODO: Also provide infos on octave-forge functions? - // TODO: Also provide infos on function parameters? - // By now, use the keywords-list from syntax highlighting - m_lexerAPI = new QsciAPIs (m_lexer); - - QString keyword; - QStringList keywordList; - keyword = m_lexer->keywords (1); // get whole string with all keywords - keywordList = keyword.split (QRegExp ("\\s+")); // split into single strings - int i; - for (i=0; i<keywordList.size(); i++) - { - m_lexerAPI->add (keywordList.at (i)); // add single strings to the API - } - m_lexerAPI->prepare (); // prepare API info ... this make take some time - readSettings (); updateTerminalFont(); }
--- a/gui/src/MainWindow.h +++ b/gui/src/MainWindow.h @@ -30,9 +30,8 @@ #include <QCloseEvent> #include <QToolButton> -// QScintilla includes -#include <Qsci/qsciapis.h> -#include "lexeroctavegui.h" +// Editor includes +#include "FileEditorInterface.h" // QTerminal includes #include "QTerminal.h" @@ -77,14 +76,13 @@ void settingsChanged (); public slots: - void openExistingFile (QString fileName); void reportStatusMessage (QString statusMessage); void handleSaveWorkspaceRequest (); void handleLoadWorkspaceRequest (); void handleClearWorkspaceRequest (); void handleCommandDoubleClicked (QString command); void newFile (); - void newEditorWindow (QString fileName); + void openFile (); void openBugTrackerPage (); void openAgoraPage (); void openOctaveForgePage (); @@ -102,16 +100,13 @@ void establishOctaveLink (); QTerminal *m_terminalView; + FileEditorInterface *m_fileEditor; // Dock widgets. WorkspaceView *m_workspaceView; HistoryDockWidget *m_historyDockWidget; FilesDockWidget *m_filesDockWidget; - // Editor's lexer - LexerOctaveGui *m_lexer; - QsciAPIs *m_lexerAPI; - // Toolbars. QStatusBar *m_statusBar;
--- a/gui/src/editor/FileEditor.cpp +++ b/gui/src/editor/FileEditor.cpp @@ -25,331 +25,210 @@ #include <QStyle> #include <QTextStream> -FileEditor::FileEditor (QTerminal *terminalView, LexerOctaveGui *lexer, MainWindow *mainWindow) - : QWidget () +FileEditor::FileEditor (QTerminal *terminal, MainWindow *mainWindow) + : FileEditorInterface(terminal, mainWindow) { construct (); - m_editor->setLexer (lexer); - m_terminalView = terminalView; // for sending commands to octave - m_mainWindow = mainWindow; // get the MainWindow for chekcing state at subwindow close - show (); + + m_terminal = terminal; + m_mainWindow = mainWindow; + setVisible (false); } FileEditor::~FileEditor () { } +LexerOctaveGui * +FileEditor::lexer () +{ + return m_lexer; +} + +QTerminal * +FileEditor::terminal () +{ + return m_terminal; +} + +MainWindow * +FileEditor::mainWindow () +{ + return m_mainWindow; +} + void -FileEditor::closeEvent(QCloseEvent *event) +FileEditor::requestNewFile () { - if ( m_mainWindow->closing () ) + FileEditorTab *fileEditorTab = new FileEditorTab (this); + if (fileEditorTab) + { + addFileEditorTab (fileEditorTab); + fileEditorTab->newFile (); + } +} + +void +FileEditor::requestOpenFile () +{ + FileEditorTab *fileEditorTab = new FileEditorTab (this); + if (fileEditorTab) { - // close wohle application: save file or not if modified - checkFileModified ("Closing Octave", 0); // no cancel possible - event->accept (); + addFileEditorTab (fileEditorTab); + fileEditorTab->openFile (); + } +} + +void +FileEditor::requestOpenFile (QString fileName) +{ + FileEditorTab *fileEditorTab = new FileEditorTab (this); + if (fileEditorTab) + { + addFileEditorTab (fileEditorTab); + fileEditorTab->loadFile (fileName); } - else +} + +void +FileEditor::requestUndo () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->undo (); +} + +void +FileEditor::requestRedo () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->redo (); +} + +void +FileEditor::requestCopy () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->copy (); +} + +void +FileEditor::requestCut () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->cut (); +} + +void +FileEditor::requestPaste () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->paste (); +} + +void +FileEditor::requestSaveFile () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->saveFile (); +} + +void +FileEditor::requestSaveFileAs () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->saveFileAs (); +} + +void +FileEditor::requestRunFile () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->runFile (); +} + +void +FileEditor::requestToggleBookmark () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->toggleBookmark (); +} + +void +FileEditor::requestNextBookmark () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->nextBookmark (); +} + +void +FileEditor::requestPreviousBookmark () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->previousBookmark (); +} + +void +FileEditor::requestRemoveBookmark () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->removeBookmark (); +} + +void +FileEditor::requestCommentSelectedText () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->commentSelectedText (); +} + +void +FileEditor::requestUncommentSelectedText () +{ + FileEditorTab *activeFileEditorTab = activeEditorTab (); + if (activeFileEditorTab) + activeFileEditorTab->uncommentSelectedText (); +} + +void +FileEditor::handleFileNameChanged (QString fileName) +{ + QObject *senderObject = sender (); + FileEditorTab *fileEditorTab = dynamic_cast<FileEditorTab*> (senderObject); + if (fileEditorTab) { - // ignore close event if file is not saved and user cancels closing this window - if (checkFileModified ("Close File",QMessageBox::Cancel) == QMessageBox::Cancel) + for(int i = 0; i < m_tabWidget->count (); i++) { - event->ignore (); - } - else - { - event->accept(); + if (m_tabWidget->widget (i) == fileEditorTab) + { + m_tabWidget->setTabText (i, fileName); + } } } } void -FileEditor::handleMarginClicked(int margin, int line, Qt::KeyboardModifiers state) -{ - Q_UNUSED (state); - if ( margin == 1 ) // marker margin - { - unsigned int mask = m_editor->markersAtLine (line); - if (mask && (1 << MARKER_BOOKMARK)) - m_editor->markerDelete(line,MARKER_BOOKMARK); - else - m_editor->markerAdd(line,MARKER_BOOKMARK); - } -} - -void -FileEditor::newWindowTitle(bool modified) -{ - QString title(m_fileName); - if ( !m_longTitle ) - { - QFileInfo file(m_fileName); - title = file.fileName(); - } - if ( modified ) - { - setWindowTitle(title.prepend("* ")); - } - else - setWindowTitle (title); -} - -void -FileEditor::handleCopyAvailable(bool enableCopy) -{ - m_copyAction->setEnabled(enableCopy); - m_cutAction->setEnabled(enableCopy); -} - - -void -FileEditor::openFile () -{ - if (checkFileModified ("Open File",QMessageBox::Cancel)==QMessageBox::Cancel) - { - return; // existing file not saved and opening another file canceled by user - } - QString openFileName; - QFileDialog dlg(this); - dlg.setNameFilter(SAVE_FILE_FILTER); - dlg.setAcceptMode(QFileDialog::AcceptOpen); - dlg.setViewMode(QFileDialog::Detail); - if ( dlg.exec() ) - { - openFileName = dlg.selectedFiles().at(0); - if (openFileName.isEmpty ()) - return; - loadFile(openFileName); - } -} - -void -FileEditor::loadFile (QString fileName) -{ - QFile file (fileName); - if (!file.open (QFile::ReadOnly)) - { - QMessageBox::warning (this, tr ("File Editor"), - tr ("Cannot read file %1:\n%2.").arg (fileName). - arg (file.errorString ())); - return; - } - - QTextStream in (&file); - QApplication::setOverrideCursor (Qt::WaitCursor); - m_editor->setText (in.readAll ()); - QApplication::restoreOverrideCursor (); - - m_fileName = fileName; - newWindowTitle (false); // window title (no modification) - m_statusBar->showMessage (tr ("File loaded."), 2000); - m_editor->setModified (false); // loaded file is not modified yet -} - -void -FileEditor::newFile () -{ - if (checkFileModified ("Create New File",QMessageBox::Cancel)==QMessageBox::Cancel) - { - return; // existing file not saved and creating new file canceled by user - } - - m_fileName = UNNAMED_FILE; - newWindowTitle (false); // window title (no modification) - m_editor->setText (""); - m_editor->setModified (false); // new file is not modified yet -} - -int -FileEditor::checkFileModified (QString msg, int cancelButton) -{ - int decision = QMessageBox::Yes; - if (m_editor->isModified ()) - { - // file is modified but not saved, aks user what to do - decision = QMessageBox::warning (this, - msg, - tr ("The file %1\n" - "has been modified. Do you want to save the changes?"). - arg (m_fileName), - QMessageBox::Save, QMessageBox::Discard, cancelButton ); - if (decision == QMessageBox::Save) - { - saveFile (); - if (m_editor->isModified ()) - { - // If the user attempted to save the file, but it's still - // modified, then probably something went wrong, so return cancel - // for cancel this operation or try to save files as if cancel not - // possible - if ( cancelButton ) - return (QMessageBox::Cancel); - else - saveFileAs (); - } - } - } - return (decision); -} - -void -FileEditor::saveFile () -{ - saveFile(m_fileName); -} - -void -FileEditor::saveFile (QString saveFileName) +FileEditor::handleTabCloseRequest (int index) { - // it is a new file with the name "<unnamed>" -> call saveFielAs - if (saveFileName==UNNAMED_FILE || saveFileName.isEmpty ()) - { - saveFileAs(); - return; - } - - // open the file for writing - QFile file (saveFileName); - if (!file.open (QFile::WriteOnly)) - { - QMessageBox::warning (this, tr ("File Editor"), - tr ("Cannot write file %1:\n%2."). - arg (saveFileName).arg (file.errorString ())); - return; - } - - // save the contents into the file - QTextStream out (&file); - QApplication::setOverrideCursor (Qt::WaitCursor); - out << m_editor->text (); - QApplication::restoreOverrideCursor (); - m_fileName = saveFileName; // save file name for later use - newWindowTitle(false); // set the window title to actual file name (not modified) - m_statusBar->showMessage (tr ("File %1 saved").arg(m_fileName), 2000); - m_editor->setModified (false); // files is save -> not modified -} - -void -FileEditor::saveFileAs () -{ - QString saveFileName(m_fileName); - QFileDialog dlg(this); - if (saveFileName==UNNAMED_FILE || saveFileName.isEmpty ()) - { - saveFileName = QDir::homePath(); - dlg.setDirectory(saveFileName); - } - else - { - dlg.selectFile(saveFileName); - } - dlg.setNameFilter(SAVE_FILE_FILTER); - dlg.setDefaultSuffix("m"); - dlg.setAcceptMode(QFileDialog::AcceptSave); - dlg.setViewMode(QFileDialog::Detail); - if ( dlg.exec() ) - { - saveFileName = dlg.selectedFiles().at(0); - if (saveFileName.isEmpty ()) - return; - saveFile(saveFileName); - } -} - -// handle the run command -void -FileEditor::runFile () -{ - if (m_editor->isModified ()) - saveFile(m_fileName); - m_terminalView->sendText (QString ("run \'%1\'\n").arg (m_fileName)); - m_terminalView->setFocus (); -} - - -// (un)comment selected text -void -FileEditor::commentSelectedText () -{ - doCommentSelectedText (true); -} -void -FileEditor::uncommentSelectedText () -{ - doCommentSelectedText (false); -} -void -FileEditor::doCommentSelectedText (bool comment) -{ - if ( m_editor->hasSelectedText() ) - { - int lineFrom, lineTo, colFrom, colTo, i; - m_editor->getSelection (&lineFrom,&colFrom,&lineTo,&colTo); - if ( colTo == 0 ) // the beginning of last line is not selected - lineTo--; // stop at line above - m_editor->beginUndoAction (); - for ( i=lineFrom; i<=lineTo; i++ ) - { - if ( comment ) - m_editor->insertAt("%",i,0); - else - { - QString line(m_editor->text(i)); - if ( line.startsWith("%") ) - { - m_editor->setSelection(i,0,i,1); - m_editor->removeSelectedText(); - } - } - } - m_editor->endUndoAction (); - } -} - - -// remove bookmarks -void -FileEditor::removeBookmark () -{ - m_editor->markerDeleteAll(MARKER_BOOKMARK); -} -// toggle bookmark -void -FileEditor::toggleBookmark () -{ - int line,cur; - m_editor->getCursorPosition(&line,&cur); - if ( m_editor->markersAtLine (line) && (1 << MARKER_BOOKMARK) ) - m_editor->markerDelete(line,MARKER_BOOKMARK); - else - m_editor->markerAdd(line,MARKER_BOOKMARK); -} -// goto next bookmark -void -FileEditor::nextBookmark () -{ - int line,cur,nextline; - m_editor->getCursorPosition(&line,&cur); - if ( m_editor->markersAtLine(line) && (1 << MARKER_BOOKMARK) ) - line++; // we have a bookmark here, so start search from next line - nextline = m_editor->markerFindNext(line,(1 << MARKER_BOOKMARK)); - m_editor->setCursorPosition(nextline,0); -} -// goto previous bookmark -void -FileEditor::prevBookmark () -{ - int line,cur,prevline; - m_editor->getCursorPosition(&line,&cur); - if ( m_editor->markersAtLine(line) && (1 << MARKER_BOOKMARK) ) - line--; // we have a bookmark here, so start search from prev line - prevline = m_editor->markerFindPrevious(line,(1 << MARKER_BOOKMARK)); - m_editor->setCursorPosition(prevline,0); -} - -void -FileEditor::setModified (bool modified) -{ - m_modified = modified; + FileEditorTab *fileEditorTab = dynamic_cast <FileEditorTab*> (m_tabWidget->widget (index)); + if (fileEditorTab) + if (fileEditorTab->close ()) + { + m_tabWidget->removeTab (index); + delete fileEditorTab; + } } void @@ -361,104 +240,69 @@ m_menuBar = new QMenuBar (this); m_toolBar = new QToolBar (this); m_statusBar = new QStatusBar (this); - m_editor = new QsciScintilla (this); - - // markers - m_editor->setMarginType (1, QsciScintilla::SymbolMargin); - m_editor->setMarginSensitivity(1,true); - m_editor->markerDefine(QsciScintilla::RightTriangle,MARKER_BOOKMARK); - connect(m_editor,SIGNAL(marginClicked(int,int,Qt::KeyboardModifiers)), - this,SLOT(handleMarginClicked(int,int,Qt::KeyboardModifiers))); - - // line numbers - m_editor->setMarginsForegroundColor(QColor(96,96,96)); - m_editor->setMarginsBackgroundColor(QColor(232,232,220)); - if ( settings->value ("editor/showLineNumbers",true).toBool () ) - { - QFont marginFont( settings->value ("editor/fontName","Courier").toString () , - settings->value ("editor/fontSize",10).toInt () ); - m_editor->setMarginsFont( marginFont ); - QFontMetrics metrics(marginFont); - m_editor->setMarginType (2, QsciScintilla::TextMargin); - m_editor->setMarginWidth(2, metrics.width("99999")); - m_editor->setMarginLineNumbers(2, true); - } - // code folding - m_editor->setMarginType (3, QsciScintilla::SymbolMargin); - m_editor->setFolding (QsciScintilla::BoxedTreeFoldStyle , 3); - // other features - if ( settings->value ("editor/highlightCurrentLine",true).toBool () ) - { - m_editor->setCaretLineVisible(true); - m_editor->setCaretLineBackgroundColor(QColor(245,245,245)); - } - m_editor->setBraceMatching (QsciScintilla::StrictBraceMatch); - m_editor->setAutoIndent (true); - m_editor->setIndentationWidth (2); - m_editor->setIndentationsUseTabs (false); - if ( settings->value ("editor/codeCompletion",true).toBool () ) - { - m_editor->autoCompleteFromAll (); - m_editor->setAutoCompletionSource(QsciScintilla::AcsAll); - m_editor->setAutoCompletionThreshold (1); - } - m_editor->setUtf8 (true); - m_longTitle = settings->value ("editor/longWindowTitle",true).toBool (); - - // The Actions + m_tabWidget = new QTabWidget (this); + m_tabWidget->setTabsClosable (true); + //m_longTitle = settings->value ("editor/longWindowTitle",true).toBool (); // Theme icons with QStyle icons as fallback QAction *newAction = new QAction ( QIcon::fromTheme("document-new",style->standardIcon (QStyle::SP_FileIcon)), tr("&New File"), m_toolBar); + QAction *openAction = new QAction ( QIcon::fromTheme("document-open",style->standardIcon (QStyle::SP_DirOpenIcon)), tr("&Open File"), m_toolBar); + QAction *saveAction = new QAction ( QIcon::fromTheme("document-save",style->standardIcon (QStyle::SP_DriveHDIcon)), tr("&Save File"), m_toolBar); + QAction *saveAsAction = new QAction ( QIcon::fromTheme("document-save-as",style->standardIcon (QStyle::SP_DriveFDIcon)), tr("Save File &As"), m_toolBar); + QAction *undoAction = new QAction ( QIcon::fromTheme("edit-undo",style->standardIcon (QStyle::SP_ArrowLeft)), tr("&Undo"), m_toolBar); + QAction *redoAction = new QAction ( QIcon::fromTheme("edit-redo",style->standardIcon (QStyle::SP_ArrowRight)), tr("&Redo"), m_toolBar); - m_copyAction = new QAction (QIcon::fromTheme("edit-copy"),tr("&Copy"),m_toolBar); - m_cutAction = new QAction (QIcon::fromTheme("edit-cut"),tr("Cu&t"),m_toolBar); - QAction *pasteAction = new QAction (QIcon::fromTheme("edit-paste"),tr("&Paste"),m_toolBar); - QAction *nextBookmarkAction = new QAction (tr("&Next Bookmark"),m_toolBar); - QAction *prevBookmarkAction = new QAction (tr("Pre&vious Bookmark"),m_toolBar); - QAction *toggleBookmarkAction = new QAction (tr("Toggle &Bookmark"),m_toolBar); - QAction *removeBookmarkAction = new QAction (tr("&Remove All Bookmarks"),m_toolBar); - QAction *commentSelectedAction = new QAction (tr("&Comment Selected Text"),m_toolBar); - QAction *uncommentSelectedAction = new QAction (tr("&Uncomment Selected Text"),m_toolBar); + + m_copyAction = new QAction (QIcon::fromTheme("edit-copy"), tr("&Copy"),m_toolBar); + m_cutAction = new QAction (QIcon::fromTheme("edit-cut"), tr("Cu&t"),m_toolBar); + + QAction *pasteAction = new QAction (QIcon::fromTheme ("edit-paste"), tr ("&Paste"),m_toolBar); + QAction *nextBookmarkAction = new QAction (tr ("&Next Bookmark"),m_toolBar); + QAction *prevBookmarkAction = new QAction (tr ("Pre&vious Bookmark"),m_toolBar); + QAction *toggleBookmarkAction = new QAction (tr ("Toggle &Bookmark"),m_toolBar); + QAction *removeBookmarkAction = new QAction (tr ("&Remove All Bookmarks"),m_toolBar); + QAction *commentSelectedAction = new QAction (tr ("&Comment Selected Text"),m_toolBar); + QAction *uncommentSelectedAction = new QAction (tr ("&Uncomment Selected Text"),m_toolBar); + QAction *runAction = new QAction ( - QIcon::fromTheme("media-play",style->standardIcon (QStyle::SP_MediaPlay)), + QIcon::fromTheme ("media-play", style->standardIcon (QStyle::SP_MediaPlay)), tr("&Run File"), m_toolBar); // some actions are disabled from the beginning m_copyAction->setEnabled(false); m_cutAction->setEnabled(false); - connect(m_editor,SIGNAL(copyAvailable(bool)),this,SLOT(handleCopyAvailable(bool))); // short cuts - newAction->setShortcut(QKeySequence::New); - openAction->setShortcut(QKeySequence::Open); - saveAction->setShortcut(QKeySequence::Save); - saveAsAction->setShortcut(QKeySequence::SaveAs); - undoAction->setShortcut(QKeySequence::Undo); - redoAction->setShortcut(QKeySequence::Redo); - m_copyAction->setShortcut(QKeySequence::Copy); - m_cutAction->setShortcut(QKeySequence::Cut); - pasteAction->setShortcut(QKeySequence::Paste); - runAction->setShortcut(Qt::Key_F5); - nextBookmarkAction->setShortcut(Qt::Key_F2); - prevBookmarkAction->setShortcut(Qt::SHIFT + Qt::Key_F2); - toggleBookmarkAction->setShortcut(Qt::Key_F7); - commentSelectedAction->setShortcut(Qt::CTRL + Qt::Key_R); + newAction->setShortcut (QKeySequence::New); + openAction->setShortcut (QKeySequence::Open); + saveAction->setShortcut (QKeySequence::Save); + saveAsAction->setShortcut (QKeySequence::SaveAs); + undoAction->setShortcut (QKeySequence::Undo); + redoAction->setShortcut (QKeySequence::Redo); + m_copyAction->setShortcut (QKeySequence::Copy); + m_cutAction->setShortcut (QKeySequence::Cut); + pasteAction->setShortcut (QKeySequence::Paste); + runAction->setShortcut (Qt::Key_F5); + nextBookmarkAction->setShortcut (Qt::Key_F2); + prevBookmarkAction->setShortcut (Qt::SHIFT + Qt::Key_F2); + toggleBookmarkAction->setShortcut (Qt::Key_F7); + commentSelectedAction->setShortcut (Qt::CTRL + Qt::Key_R); uncommentSelectedAction->setShortcut(Qt::CTRL + Qt::Key_T); // toolbar @@ -466,74 +310,118 @@ m_toolBar->addAction (openAction); m_toolBar->addAction (saveAction); m_toolBar->addAction (saveAsAction); - m_toolBar->addSeparator(); + m_toolBar->addSeparator (); m_toolBar->addAction (undoAction); m_toolBar->addAction (redoAction); m_toolBar->addAction (m_copyAction); m_toolBar->addAction (m_cutAction); m_toolBar->addAction (pasteAction); - m_toolBar->addSeparator(); + m_toolBar->addSeparator (); m_toolBar->addAction (runAction); // menu bar - QMenu *fileMenu = new QMenu(tr("&File"),m_menuBar); - fileMenu->addAction(newAction); - fileMenu->addAction(openAction); - fileMenu->addAction(saveAction); - fileMenu->addAction(saveAsAction); - fileMenu->addSeparator(); - m_menuBar->addMenu(fileMenu); - QMenu *editMenu = new QMenu(tr("&Edit"),m_menuBar); - editMenu->addAction(undoAction); - editMenu->addAction(redoAction); - editMenu->addSeparator(); - editMenu->addAction(m_copyAction); - editMenu->addAction(m_cutAction); - editMenu->addAction(pasteAction); - editMenu->addSeparator(); - editMenu->addAction(commentSelectedAction); - editMenu->addAction(uncommentSelectedAction); - editMenu->addSeparator(); - editMenu->addAction(toggleBookmarkAction); - editMenu->addAction(nextBookmarkAction); - editMenu->addAction(prevBookmarkAction); - editMenu->addAction(removeBookmarkAction); - m_menuBar->addMenu(editMenu); - QMenu *runMenu = new QMenu(tr("&Run"),m_menuBar); - runMenu->addAction(runAction); - m_menuBar->addMenu(runMenu); + QMenu *fileMenu = new QMenu (tr ("&File"), m_menuBar); + fileMenu->addAction (newAction); + fileMenu->addAction (openAction); + fileMenu->addAction (saveAction); + fileMenu->addAction (saveAsAction); + fileMenu->addSeparator (); + m_menuBar->addMenu (fileMenu); + QMenu *editMenu = new QMenu (tr ("&Edit"), m_menuBar); + editMenu->addAction (undoAction); + editMenu->addAction (redoAction); + editMenu->addSeparator (); + editMenu->addAction (m_copyAction); + editMenu->addAction (m_cutAction); + editMenu->addAction (pasteAction); + editMenu->addSeparator (); + editMenu->addAction (commentSelectedAction); + editMenu->addAction (uncommentSelectedAction); + editMenu->addSeparator (); + editMenu->addAction (toggleBookmarkAction); + editMenu->addAction (nextBookmarkAction); + editMenu->addAction (prevBookmarkAction); + editMenu->addAction (removeBookmarkAction); + m_menuBar->addMenu (editMenu); + + QMenu *runMenu = new QMenu (tr ("&Run"), m_menuBar); + runMenu->addAction (runAction); + m_menuBar->addMenu (runMenu); QVBoxLayout *layout = new QVBoxLayout (); layout->addWidget (m_menuBar); layout->addWidget (m_toolBar); - layout->addWidget (m_editor); + layout->addWidget (m_tabWidget); layout->addWidget (m_statusBar); - layout->setMargin (2); + layout->setMargin (0); setLayout (layout); - connect (newAction, SIGNAL (triggered ()), this, SLOT (newFile ())); - connect (openAction, SIGNAL (triggered ()), this, SLOT (openFile ())); - connect (undoAction, SIGNAL (triggered ()), m_editor, SLOT (undo ())); - connect (redoAction, SIGNAL (triggered ()), m_editor, SLOT (redo ())); - connect (m_copyAction, SIGNAL (triggered ()), m_editor, SLOT (copy ())); - connect (m_cutAction, SIGNAL (triggered ()), m_editor, SLOT (cut ())); - connect (pasteAction, SIGNAL (triggered ()), m_editor, SLOT (paste ())); - connect (saveAction, SIGNAL (triggered ()), this, SLOT (saveFile ())); - connect (saveAsAction, SIGNAL (triggered ()), this, SLOT (saveFileAs ())); - connect (runAction, SIGNAL (triggered ()), this, SLOT (runFile ())); - connect (toggleBookmarkAction, SIGNAL (triggered ()), this, SLOT (toggleBookmark ())); - connect (nextBookmarkAction, SIGNAL (triggered ()), this, SLOT (nextBookmark ())); - connect (prevBookmarkAction, SIGNAL (triggered ()), this, SLOT (prevBookmark ())); - connect (removeBookmarkAction, SIGNAL (triggered ()), this, SLOT (removeBookmark ())); - connect (commentSelectedAction, SIGNAL (triggered ()), this, SLOT (commentSelectedText ())); - connect (uncommentSelectedAction, SIGNAL (triggered ()), this, SLOT (uncommentSelectedText ())); + connect (newAction, SIGNAL (triggered ()), this, SLOT (requestNewFile ())); + connect (openAction, SIGNAL (triggered ()), this, SLOT (requestOpenFile ())); + connect (undoAction, SIGNAL (triggered ()), this, SLOT (requestUndo ())); + connect (redoAction, SIGNAL (triggered ()), this, SLOT (requestRedo ())); + connect (m_copyAction, SIGNAL (triggered ()), this, SLOT (requestCopy ())); + connect (m_cutAction, SIGNAL (triggered ()), this, SLOT (requestCut ())); + connect (pasteAction, SIGNAL (triggered ()), this, SLOT (requestPaste ())); + connect (saveAction, SIGNAL (triggered ()), this, SLOT (requestSaveFile ())); + connect (saveAsAction, SIGNAL (triggered ()), this, SLOT (requestSaveFileAs ())); + connect (runAction, SIGNAL (triggered ()), this, SLOT (requestRunFile ())); + connect (toggleBookmarkAction, SIGNAL (triggered ()), this, SLOT (requestToggleBookmark ())); + connect (nextBookmarkAction, SIGNAL (triggered ()), this, SLOT (requestNextBookmark ())); + connect (prevBookmarkAction, SIGNAL (triggered ()), this, SLOT (requestPreviousBookmark ())); + connect (removeBookmarkAction, SIGNAL (triggered ()), this, SLOT (requestRemoveBookmark ())); + connect (commentSelectedAction, SIGNAL (triggered ()), this, SLOT (requestCommentSelectedText ())); + connect (uncommentSelectedAction, SIGNAL (triggered ()), this, SLOT (requestUncommentSelectedText ())); + connect (m_tabWidget, SIGNAL (tabCloseRequested (int)), this, SLOT (handleTabCloseRequest (int))); + + // this has to be done only once, not for each editor + m_lexer = new LexerOctaveGui (); + + // Editor font (default or from settings) + m_lexer->setDefaultFont (QFont ( + settings->value ("editor/fontName","Courier").toString (), + settings->value ("editor/fontSize",10).toInt ())); + + // TODO: Autoindent not working as it should + m_lexer->setAutoIndentStyle (QsciScintilla::AiMaintain || + QsciScintilla::AiOpening || + QsciScintilla::AiClosing); - - // connect modified signal - connect (m_editor, SIGNAL (modificationChanged(bool)), this, SLOT (newWindowTitle(bool)) ); + // The API info that is used for auto completion + // TODO: Where to store a file with API info (raw or prepared?)? + // TODO: Also provide infos on octave-forge functions? + // TODO: Also provide infos on function parameters? + // By now, use the keywords-list from syntax highlighting + m_lexerAPI = new QsciAPIs (m_lexer); - m_fileName = ""; - newWindowTitle (false); - setWindowIcon(QIcon::fromTheme("accessories-text-editor",style->standardIcon (QStyle::SP_FileIcon))); + QString keyword; + QStringList keywordList; + keyword = m_lexer->keywords (1); // get whole string with all keywords + keywordList = keyword.split (QRegExp ("\\s+")); // split into single strings + int i; + for (i = 0; i < keywordList.size (); i++) + { + m_lexerAPI->add (keywordList.at (i)); // add single strings to the API + } + m_lexerAPI->prepare (); // prepare API info ... this make take some time + resize (500, 400); + setWindowIcon (QIcon::fromTheme ("accessories-text-editor", style->standardIcon (QStyle::SP_FileIcon))); + setWindowTitle ("Octave Editor"); } + +void +FileEditor::addFileEditorTab (FileEditorTab *fileEditorTab) +{ + m_tabWidget->addTab (fileEditorTab, ""); + connect (fileEditorTab, SIGNAL(fileNameChanged(QString)), + this, SLOT(handleFileNameChanged(QString))); + + m_tabWidget->setCurrentWidget (fileEditorTab); +} + +FileEditorTab * +FileEditor::activeEditorTab () +{ + return dynamic_cast<FileEditorTab*> (m_tabWidget->currentWidget ()); +}
--- a/gui/src/editor/FileEditor.h +++ b/gui/src/editor/FileEditor.h @@ -19,14 +19,16 @@ #define FILEEDITORMDISUBWINDOW_H #include "MainWindow.h" +#include "FileEditorInterface.h" +#include "FileEditorTab.h" -#include <QWidget> #include <QToolBar> #include <QAction> #include <QMenuBar> #include <QStatusBar> #include <QCloseEvent> -#include <Qsci/qsciscintilla.h> +#include <QTabWidget> +#include <Qsci/qsciapis.h> // Not available in the Debian repos yet! // #include <Qsci/qscilexeroctave.h> #include "lexeroctavegui.h" @@ -39,58 +41,56 @@ MARKER_BREAKPOINT }; -class FileEditor : public QWidget +class FileEditor : public FileEditorInterface { Q_OBJECT public: - FileEditor (QTerminal *terminalView, LexerOctaveGui *lexer, MainWindow *mainWindow); + FileEditor (QTerminal *terminal, MainWindow *mainWindow); ~FileEditor (); void loadFile (QString fileName); + LexerOctaveGui *lexer (); + QTerminal *terminal (); + MainWindow *mainWindow (); public slots: + void requestNewFile (); + void requestOpenFile (); + void requestOpenFile (QString fileName); - void newFile (); - void openFile (); - void saveFile (); - void saveFile (QString fileName); - void saveFileAs (); + void requestUndo (); + void requestRedo (); + void requestCopy (); + void requestCut (); + void requestPaste (); + void requestSaveFile (); + void requestSaveFileAs (); + void requestRunFile (); + void requestToggleBookmark (); + void requestNextBookmark (); + void requestPreviousBookmark (); + void requestRemoveBookmark (); + void requestCommentSelectedText (); + void requestUncommentSelectedText (); - void setModified (bool modified); - -protected: - void closeEvent(QCloseEvent *event); + void handleFileNameChanged (QString fileName); + void handleTabCloseRequest (int index); private: - int checkFileModified (QString msg, int cancelButton); void construct (); - void doCommentSelectedText (bool comment); + void addFileEditorTab(FileEditorTab *fileEditorTab); + FileEditorTab *activeEditorTab(); + QMenuBar *m_menuBar; QToolBar *m_toolBar; - QsciScintilla *m_editor; QStatusBar *m_statusBar; - QString m_fileName; - QString m_fileNameShort; - QTerminal* m_terminalView; QAction* m_copyAction; QAction* m_cutAction; - MainWindow* m_mainWindow; + QTabWidget *m_tabWidget; int m_markerBookmark; - bool m_modified; - bool m_longTitle; -private slots: - void newWindowTitle(bool modified); - void handleMarginClicked(int line, int margin, Qt::KeyboardModifiers state); - void handleCopyAvailable(bool enableCopy); - void runFile(); - void removeBookmark (); - void toggleBookmark (); - void nextBookmark(); - void prevBookmark(); - void commentSelectedText(); - void uncommentSelectedText(); - + LexerOctaveGui *m_lexer; + QsciAPIs *m_lexerAPI; }; #endif // FILEEDITORMDISUBWINDOW_H
new file mode 100644 --- /dev/null +++ b/gui/src/editor/FileEditorInterface.h @@ -0,0 +1,49 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FILEEDITORINTERFACE_H +#define FILEEDITORINTERFACE_H + +#include <QWidget> + +class QTerminal; +class MainWindow; + +class FileEditorInterface : public QWidget +{ + Q_OBJECT + + public: + FileEditorInterface (QTerminal *terminal, MainWindow *mainWindow) + : QWidget () + { + m_terminal = terminal; + m_mainWindow = mainWindow; + } + + virtual ~FileEditorInterface () { } + public slots: + virtual void requestNewFile () = 0; + virtual void requestOpenFile () = 0; + virtual void requestOpenFile (QString fileName) = 0; + + protected: + QTerminal* m_terminal; + MainWindow* m_mainWindow; +}; + +#endif // FILEEDITORINTERFACE_H
new file mode 100644 --- /dev/null +++ b/gui/src/editor/FileEditorTab.cpp @@ -0,0 +1,422 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "FileEditorTab.h" +#include "FileEditor.h" +#include <QMessageBox> +#include <QVBoxLayout> + +FileEditorTab::FileEditorTab(FileEditor *fileEditor) + : QWidget ((QWidget*)fileEditor) +{ + QSettings *settings = ResourceManager::instance ()->settings (); + m_fileEditor = fileEditor; + m_fileName = ""; + m_editArea = new QsciScintilla (this); + m_editArea->setLexer (fileEditor->lexer ()); + + // markers + m_editArea->setMarginType (1, QsciScintilla::SymbolMargin); + m_editArea->setMarginSensitivity (1, true); + m_editArea->markerDefine (QsciScintilla::RightTriangle, MARKER_BOOKMARK); + connect (m_editArea, SIGNAL (marginClicked (int, int, Qt::KeyboardModifiers)), + this, SLOT (handleMarginClicked (int, int, Qt::KeyboardModifiers))); + + // line numbers + m_editArea->setMarginsForegroundColor(QColor(96,96,96)); + m_editArea->setMarginsBackgroundColor(QColor(232,232,220)); + if (settings->value ("editor/showLineNumbers",true).toBool ()) + { + QFont marginFont( settings->value ("editor/fontName","Courier").toString () , + settings->value ("editor/fontSize",10).toInt () ); + m_editArea->setMarginsFont( marginFont ); + QFontMetrics metrics(marginFont); + m_editArea->setMarginType (2, QsciScintilla::TextMargin); + m_editArea->setMarginWidth(2, metrics.width("99999")); + m_editArea->setMarginLineNumbers(2, true); + } + + // code folding + m_editArea->setMarginType (3, QsciScintilla::SymbolMargin); + m_editArea->setFolding (QsciScintilla::BoxedTreeFoldStyle , 3); + + // other features + if (settings->value ("editor/highlightCurrentLine",true).toBool ()) + { + m_editArea->setCaretLineVisible(true); + m_editArea->setCaretLineBackgroundColor(QColor(245,245,245)); + } + m_editArea->setBraceMatching (QsciScintilla::StrictBraceMatch); + m_editArea->setAutoIndent (true); + m_editArea->setIndentationWidth (2); + m_editArea->setIndentationsUseTabs (false); + if (settings->value ("editor/codeCompletion",true).toBool ()) + { + m_editArea->autoCompleteFromAll (); + m_editArea->setAutoCompletionSource(QsciScintilla::AcsAll); + m_editArea->setAutoCompletionThreshold (1); + } + m_editArea->setUtf8 (true); + + QVBoxLayout *layout = new QVBoxLayout (); + layout->addWidget (m_editArea); + setLayout (layout); + + // connect modified signal + connect (m_editArea, SIGNAL (modificationChanged (bool)), + this, SLOT (newTitle (bool))); + connect (m_editArea, SIGNAL (copyAvailable (bool)), + this, SLOT (handleCopyAvailable (bool))); + + m_fileName = ""; + newTitle (false); +} + +void +FileEditorTab::closeEvent(QCloseEvent *event) +{ + if (m_fileEditor->mainWindow ()->closing ()) + { + // close whole application: save file or not if modified + checkFileModified ("Closing Octave", 0); // no cancel possible + event->accept (); + } + else + { + // ignore close event if file is not saved and user cancels closing this window + if (checkFileModified ("Close File",QMessageBox::Cancel) == QMessageBox::Cancel) + { + event->ignore (); + } + else + { + event->accept(); + } + } +} + +void +FileEditorTab::handleMarginClicked(int margin, int line, Qt::KeyboardModifiers state) +{ + Q_UNUSED (state); + if (margin == 1) // marker margin + { + unsigned int mask = m_editArea->markersAtLine (line); + if (mask && (1 << MARKER_BOOKMARK)) + m_editArea->markerDelete(line,MARKER_BOOKMARK); + else + m_editArea->markerAdd(line,MARKER_BOOKMARK); + } +} + +void +FileEditorTab::commentSelectedText () +{ + doCommentSelectedText (true); +} + +void +FileEditorTab::uncommentSelectedText () +{ + doCommentSelectedText (false); +} + +void +FileEditorTab::doCommentSelectedText (bool comment) +{ + if ( m_editArea->hasSelectedText() ) + { + int lineFrom, lineTo, colFrom, colTo, i; + m_editArea->getSelection (&lineFrom,&colFrom,&lineTo,&colTo); + if ( colTo == 0 ) // the beginning of last line is not selected + lineTo--; // stop at line above + m_editArea->beginUndoAction (); + for ( i=lineFrom; i<=lineTo; i++ ) + { + if ( comment ) + m_editArea->insertAt("%",i,0); + else + { + QString line(m_editArea->text(i)); + if ( line.startsWith("%") ) + { + m_editArea->setSelection(i,0,i,1); + m_editArea->removeSelectedText(); + } + } + } + m_editArea->endUndoAction (); + } +} + +void +FileEditorTab::newTitle(bool modified) +{ + QString title(m_fileName); + if ( !m_longTitle ) + { + QFileInfo file(m_fileName); + title = file.fileName(); + } + + if ( modified ) + { + emit fileNameChanged (title.prepend("* ")); + } + else + emit fileNameChanged (title); +} + +void +FileEditorTab::handleCopyAvailable(bool enableCopy) +{ + /* + m_copyAction->setEnabled(enableCopy); + m_cutAction->setEnabled(enableCopy); + */ +} + +int +FileEditorTab::checkFileModified (QString msg, int cancelButton) +{ + int decision = QMessageBox::Yes; + if (m_editArea->isModified ()) + { + // file is modified but not saved, aks user what to do + decision = QMessageBox::warning (this, + msg, + tr ("The file %1\n" + "has been modified. Do you want to save the changes?"). + arg (m_fileName), + QMessageBox::Save, QMessageBox::Discard, cancelButton ); + if (decision == QMessageBox::Save) + { + saveFile (); + if (m_editArea->isModified ()) + { + // If the user attempted to save the file, but it's still + // modified, then probably something went wrong, so return cancel + // for cancel this operation or try to save files as if cancel not + // possible + if ( cancelButton ) + return (QMessageBox::Cancel); + else + saveFileAs (); + } + } + } + return (decision); +} + +void +FileEditorTab::removeBookmark () +{ + m_editArea->markerDeleteAll(MARKER_BOOKMARK); +} + +void +FileEditorTab::toggleBookmark () +{ + int line,cur; + m_editArea->getCursorPosition(&line,&cur); + if ( m_editArea->markersAtLine (line) && (1 << MARKER_BOOKMARK) ) + m_editArea->markerDelete(line,MARKER_BOOKMARK); + else + m_editArea->markerAdd(line,MARKER_BOOKMARK); +} + +void +FileEditorTab::nextBookmark () +{ + int line,cur,nextline; + m_editArea->getCursorPosition(&line,&cur); + if ( m_editArea->markersAtLine(line) && (1 << MARKER_BOOKMARK) ) + line++; // we have a bookmark here, so start search from next line + nextline = m_editArea->markerFindNext(line,(1 << MARKER_BOOKMARK)); + m_editArea->setCursorPosition(nextline,0); +} + +void +FileEditorTab::previousBookmark () +{ + int line,cur,prevline; + m_editArea->getCursorPosition(&line,&cur); + if ( m_editArea->markersAtLine(line) && (1 << MARKER_BOOKMARK) ) + line--; // we have a bookmark here, so start search from prev line + prevline = m_editArea->markerFindPrevious(line,(1 << MARKER_BOOKMARK)); + m_editArea->setCursorPosition(prevline,0); +} + +void +FileEditorTab::cut () +{ + m_editArea->cut (); +} + +void +FileEditorTab::copy () +{ + m_editArea->copy (); +} + +void +FileEditorTab::paste () +{ + m_editArea->paste (); +} + +void +FileEditorTab::undo () +{ + m_editArea->undo (); +} + +void +FileEditorTab::redo () +{ + m_editArea->redo (); +} + +void +FileEditorTab::setModified (bool modified) +{ + m_modified = modified; +} + +void +FileEditorTab::openFile () +{ + QString openFileName; + QFileDialog fileDialog(this); + fileDialog.setNameFilter(SAVE_FILE_FILTER); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setViewMode(QFileDialog::Detail); + if ( fileDialog.exec() ) + { + openFileName = fileDialog.selectedFiles().at(0); + if (openFileName.isEmpty ()) + return; + loadFile(openFileName); + } +} + +void +FileEditorTab::loadFile (QString fileName) +{ + QFile file (fileName); + if (!file.open (QFile::ReadOnly)) + { + QMessageBox::warning (this, tr ("Octave Editor"), + tr ("Could not open file %1 for read:\n%2.").arg (fileName). + arg (file.errorString ())); + return; + } + + QTextStream in (&file); + QApplication::setOverrideCursor (Qt::WaitCursor); + m_editArea->setText (in.readAll ()); + QApplication::restoreOverrideCursor (); + + m_fileName = fileName; + newTitle (false); // window title (no modification) + //m_statusBar->showMessage (tr ("File loaded."), 2000); + m_editArea->setModified (false); // loaded file is not modified yet +} + +void +FileEditorTab::newFile () +{ + m_fileName = UNNAMED_FILE; + newTitle (false); // window title (no modification) + m_editArea->setText (""); + m_editArea->setModified (false); // new file is not modified yet +} + +void +FileEditorTab::saveFile () +{ + saveFile (m_fileName); +} + +void +FileEditorTab::saveFile (QString saveFileName) +{ + // it is a new file with the name "<unnamed>" -> call saveFielAs + if (saveFileName == UNNAMED_FILE || saveFileName.isEmpty ()) + { + saveFileAs(); + return; + } + + // open the file for writing + QFile file (saveFileName); + if (!file.open (QFile::WriteOnly)) + { + QMessageBox::warning (this, tr ("Octave Editor"), + tr ("Could not open file %1 for write:\n%2."). + arg (saveFileName).arg (file.errorString ())); + return; + } + + // save the contents into the file + QTextStream out (&file); + QApplication::setOverrideCursor (Qt::WaitCursor); + out << m_editArea->text (); + QApplication::restoreOverrideCursor (); + m_fileName = saveFileName; // save file name for later use + newTitle (false); // set the window title to actual file name (not modified) + //m_statusBar->showMessage (tr ("File %1 saved").arg(m_fileName), 2000); + m_editArea->setModified (false); // files is save -> not modified +} + +void +FileEditorTab::saveFileAs () +{ + QString saveFileName(m_fileName); + QFileDialog fileDialog(this); + if (saveFileName == UNNAMED_FILE || saveFileName.isEmpty ()) + { + saveFileName = QDir::homePath (); + fileDialog.setDirectory (saveFileName); + } + else + { + fileDialog.selectFile (saveFileName); + } + fileDialog.setNameFilter (SAVE_FILE_FILTER); + fileDialog.setDefaultSuffix ("m"); + fileDialog.setAcceptMode (QFileDialog::AcceptSave); + fileDialog.setViewMode (QFileDialog::Detail); + + if (fileDialog.exec ()) + { + saveFileName = fileDialog.selectedFiles ().at (0); + if (saveFileName.isEmpty ()) + return; + saveFile (saveFileName); + } +} + +void +FileEditorTab::runFile () +{ + if (m_editArea->isModified ()) + saveFile(m_fileName); + + m_fileEditor->terminal ()->sendText (QString ("run \'%1\'\n").arg (m_fileName)); + m_fileEditor->terminal ()->setFocus (); +}
new file mode 100644 --- /dev/null +++ b/gui/src/editor/FileEditorTab.h @@ -0,0 +1,80 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FILEEDITORTAB_H +#define FILEEDITORTAB_H + +#include <Qsci/qsciscintilla.h> +#include <QWidget> +#include <QCloseEvent> + +class FileEditor; +class FileEditorTab : public QWidget +{ + Q_OBJECT +public: + FileEditorTab (FileEditor *fileEditor); + +public slots: + void newTitle(bool modified); + void handleCopyAvailable(bool enableCopy); + void handleMarginClicked (int line, int margin, Qt::KeyboardModifiers state); + void commentSelectedText (); + void uncommentSelectedText (); + void removeBookmark (); + void toggleBookmark (); + void nextBookmark (); + void previousBookmark (); + void cut (); + void copy (); + void paste (); + void undo (); + void redo (); + + void setModified (bool modified); + + void openFile (); + void loadFile (QString fileName); + void newFile (); + void saveFile (); + void saveFile (QString saveFileName); + void saveFileAs (); + void runFile (); + +signals: + void fileNameChanged(QString fileName); + +protected: + void closeEvent(QCloseEvent *event); + +private: + int checkFileModified (QString msg, int cancelButton); + void doCommentSelectedText (bool comment); + + FileEditor *m_fileEditor; + QsciScintilla *m_editArea; + + QString m_fileName; + QString m_fileNameShort; + + bool m_modified; + bool m_longTitle; + + // TODO: Use QFileSystemWatcher to sync with disc. +}; + +#endif // FILEEDITORTAB_H
--- a/gui/src/src.pro +++ b/gui/src/src.pro @@ -86,7 +86,8 @@ backend/OctaveMainThread.cpp \ WelcomeWizard.cpp \ editor/FileEditor.cpp \ - WorkspaceModel.cpp + WorkspaceModel.cpp \ + editor/FileEditorTab.cpp HEADERS += \ editor/lexeroctavegui.h \ @@ -100,7 +101,9 @@ backend/OctaveMainThread.h \ WelcomeWizard.h \ editor/FileEditor.h \ - WorkspaceModel.h + WorkspaceModel.h \ + editor/FileEditorInterface.h \ + editor/FileEditorTab.h FORMS += \ SettingsDialog.ui \