1 // Copyright (C) 2015 OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : PyViewer_ViewWindow.cxx
20 // Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
23 #include "PyViewer_ViewWindow.h"
25 #include "PyEditor_Editor.h"
26 #include "PyEditor_Settings.h"
27 #include "PyEditor_SettingsDlg.h"
29 #include <SUIT_Session.h>
30 #include <SUIT_ResourceMgr.h>
32 #include <QtxAction.h>
33 #include <QtxActionToolMgr.h>
34 #include <QtxMultiAction.h>
40 \class PyViewer_ViewWindow
41 \brief Python view window.
46 \param theParent parent widget
48 PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* theDesktop , PyViewer_Viewer* theModel ) :
49 SUIT_ViewWindow(theDesktop),
52 my_IsExternal = (theDesktop == NULL);
58 void PyViewer_ViewWindow::initLayout()
60 my_TextEditor = new PyEditor_Editor( my_IsExternal ,SUIT_Session::session()->resourceMgr(), this );
61 setCentralWidget( my_TextEditor );
65 setCurrentFile( QString() );
69 connect( my_TextEditor->document(), SIGNAL( modificationChanged( bool ) ),
70 this, SLOT( setWindowModified( bool ) ) );
72 statusBar()->showMessage( tr("STS_READY") );
79 PyViewer_ViewWindow::~PyViewer_ViewWindow()
81 my_CurrentFile.clear();
86 \return \c true if the application is external
88 bool PyViewer_ViewWindow::isExternal()
94 \brief Creates actions of Python view window.
96 void PyViewer_ViewWindow::createActions()
98 QtxActionToolMgr* aMgr = toolMgr();
101 // 1. File operations
102 // 1.1. Create New action
103 anAction = new QtxAction( tr( "MNU_PY_NEW" ), QIcon( ":/images/py_new.png" ),
104 tr( "MNU_PY_NEW" ), 0, this );
105 anAction->setStatusTip( tr( "DSC_PY_NEW" ) );
106 anAction->setShortcuts( QKeySequence::New );
107 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onNew() ) );
108 aMgr->registerAction( anAction, NewId );
110 // 1.2 Create Open action
111 anAction = new QtxAction( tr( "MNU_PY_OPEN" ), QIcon( ":/images/py_open.png" ),
112 tr( "MNU_PY_OPEN" ), 0, this );
113 anAction->setStatusTip( tr( "DSC_PY_OPEN" ) );
114 anAction->setShortcuts( QKeySequence::Open );
115 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onOpen() ) );
116 aMgr->registerAction( anAction, OpenId );
118 // 1.3. Create Save action
119 anAction = new QtxAction( tr( "MNU_PY_SAVE" ), QIcon( ":/images/py_save.png" ),
120 tr( "MNU_PY_SAVE" ), 0, this );
121 anAction->setStatusTip( tr( "DSC_PY_SAVE" ) );
122 anAction->setShortcuts( QKeySequence::Save );
123 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) );
124 aMgr->registerAction( anAction, SaveId );
125 // Set default statement for Save action
126 anAction->setEnabled( my_TextEditor->document()->isModified() );
127 connect( my_TextEditor->document(), SIGNAL( modificationChanged( bool ) ),
128 anAction, SLOT( setEnabled( bool ) ) );
130 // 1.4. Create SaveAs action
131 anAction = new QtxAction( tr( "MNU_PY_SAVEAS" ), QIcon( ":/images/py_save_as.png" ),
132 tr( "MNU_PY_SAVEAS" ), 0, this );
133 anAction->setStatusTip( tr( "DSC_PY_SAVEAS" ) );
134 anAction->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_S );
135 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAs() ) );
136 aMgr->registerAction( anAction, SaveAsId );
138 // 1.5 Create multi-action for file operations
139 /*QtxMultiAction* aFileAction = new QtxMultiAction( this );
140 aFileAction->insertAction( aMgr->action( NewId ) );
141 aFileAction->insertAction( aMgr->action( OpenId ) );
142 aFileAction->insertAction( aMgr->action( SaveId ) );
143 aFileAction->insertAction( aMgr->action( SaveAsId ) );
144 aMgr->registerAction( aFileAction, FileOpId );*/
146 // 1.6. Create Close action
149 anAction = new QtxAction( tr( "MNU_PY_CLOSE" ), QIcon( ":/images/py_close.png" ),
150 tr( "MNU_PY_CLOSE" ), 0, this );
151 anAction->setStatusTip( tr( "DSC_PY_CLOSE" ) );
152 anAction->setShortcut( Qt::CTRL + Qt::Key_Q );
153 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( close() ) );
154 aMgr->registerAction( anAction, CloseId );
157 // 2. Edit operations
158 // 2.1. Create Undo action
159 anAction = new QtxAction( tr( "MNU_PY_UNDO" ), QIcon( ":/images/py_undo.png" ),
160 tr( "MNU_PY_UNDO" ), 0, this );
161 anAction->setStatusTip( tr( "DSC_PY_UNDO" ) );
162 anAction->setShortcuts( QKeySequence::Undo );
163 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( undo() ) );
164 aMgr->registerAction( anAction, UndoId );
165 // Set default statement for Undo action
166 anAction->setEnabled( my_TextEditor->document()->isUndoAvailable() );
167 connect( my_TextEditor->document(), SIGNAL( undoAvailable( bool ) ),
168 anAction, SLOT( setEnabled( bool ) ) );
170 // 2.2. Create Redo action
171 anAction = new QtxAction( tr( "MNU_PY_REDO" ), QIcon( ":/images/py_redo.png" ),
172 tr( "MNU_PY_REDO" ), 0, this );
173 anAction->setStatusTip( tr( "DSC_PY_REDO" ) );
174 anAction->setShortcuts( QKeySequence::Redo );
175 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( redo() ) );
176 aMgr->registerAction( anAction, RedoId );
177 // Set default statement for Redo action
178 anAction->setEnabled( my_TextEditor->document()->isRedoAvailable() );
179 connect( my_TextEditor->document(), SIGNAL( redoAvailable( bool ) ),
180 anAction, SLOT( setEnabled( bool ) ) );
182 // 2.3. Create Cut action
183 anAction = new QtxAction( tr( "MNU_PY_CUT" ), QIcon( ":/images/py_cut.png" ),
184 tr( "MNU_PY_CUT" ), 0, this );
185 anAction->setStatusTip( tr( "DSC_PY_CUT" ) );
186 anAction->setShortcuts( QKeySequence::Cut );
187 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( cut() ) );
188 aMgr->registerAction( anAction, CutId );
189 // Set default statement for Cut action
190 anAction->setEnabled( false );
191 connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
192 anAction, SLOT( setEnabled( bool ) ) );
194 // 2.4. Create Copy action
195 anAction = new QtxAction( tr( "MNU_PY_COPY" ), QIcon( ":/images/py_copy.png" ),
196 tr( "MNU_PY_COPY" ), 0, this );
197 anAction->setStatusTip( tr( "DSC_PY_COPY" ) );
198 anAction->setShortcuts( QKeySequence::Copy );
199 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( copy() ) );
200 aMgr->registerAction( anAction, CopyId );
201 // Set default statement for Copy action
202 anAction->setEnabled( false );
203 connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
204 anAction, SLOT( setEnabled( bool ) ) );
206 // 2.5. Create Paste action
207 anAction = new QtxAction( tr( "MNU_PY_PASTE" ), QIcon( ":/images/py_paste.png" ),
208 tr( "MNU_PY_PASTE" ), 0, this );
209 anAction->setStatusTip( tr( "DSC_PY_PASTE" ) );
210 anAction->setShortcuts( QKeySequence::Paste );
211 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( paste() ) );
212 aMgr->registerAction( anAction, PasteId );
214 // 2.6. Create Delete action
215 anAction = new QtxAction( tr( "MNU_PY_DELETE" ), QIcon( ":/images/py_delete.png" ),
216 tr( "MNU_PY_DELETE" ), 0, this );
217 anAction->setStatusTip( tr( "DSC_PY_DELETE" ) );
218 anAction->setShortcuts( QKeySequence::Delete );
219 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( deleteSelected() ) );
220 aMgr->registerAction( anAction, DeleteId );
221 // Set default statement for Delete action
222 anAction->setEnabled( false );
223 connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
224 anAction, SLOT( setEnabled( bool ) ) );
226 // 2.7. Create SelectAll action
227 anAction = new QtxAction( tr( "MNU_PY_SELECTALL" ), QIcon( ":/images/py_select_all.png" ),
228 tr( "MNU_PY_SELECTALL" ), 0, this );
229 anAction->setStatusTip( tr( "DSC_PY_SELECT_ALL" ) );
230 anAction->setShortcuts( QKeySequence::SelectAll );
231 connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( selectAll() ) );
232 aMgr->registerAction( anAction, SelectAllId );
234 // 2.8. Create multi-action for edit operations
235 /*QtxMultiAction* anEditAction = new QtxMultiAction( this );
236 anEditAction->insertAction( aMgr->action( UndoId ) );
237 anEditAction->insertAction( aMgr->action( RedoId ) );
238 anEditAction->insertAction( aMgr->action( CutId ) );
239 anEditAction->insertAction( aMgr->action( CopyId ) );
240 anEditAction->insertAction( aMgr->action( PasteId ) );
241 anEditAction->insertAction( aMgr->action( DeleteId ) );
242 anEditAction->insertAction( aMgr->action( SelectAllId ) );
243 aMgr->registerAction( anEditAction, EditOpId );*/
245 // 3. Create Preference action
246 anAction = new QtxAction( tr( "MNU_PY_PREFERENCES" ), QIcon( ":/images/py_preferences.png" ),
247 tr( "MNU_PY_PREFERENCES" ), 0, this );
248 anAction->setStatusTip( tr( "DSC_PY_PREFERENCES" ) );
249 connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onPreferences() ) );
250 aMgr->registerAction( anAction, PreferencesId );
252 // 4. Help operations
254 // 4.1. Create Help action
255 anAction = new QtxAction( tr( "MNU_PY_BROWSER" ), QIcon( ":/images/py_browser.png" ),
256 tr( "MNU_PY_BROWSER" ), 0, this );
257 anAction->setStatusTip( tr( "DSC_PY_BROWSER" ) );
258 connect( anAction, SIGNAL( triggered() ), this, SLOT( onBrowser() ) );
259 aMgr->registerAction( anAction, BrowserId );
261 // 4.2. Create multi-action for help operations
262 /*QtxMultiAction* aHelpAction = new QtxMultiAction( this );
263 aHelpAction->insertAction( aMgr->action( BrowserId ) );
264 aMgr->registerAction( aHelpAction, HelpOpId );*/
268 \brief Create toolbar for the python view window.
270 void PyViewer_ViewWindow::createToolBar()
272 QtxActionToolMgr* aMgr = toolMgr();
273 int idTB = aMgr->createToolBar( tr("LBL_TOOLBAR_LABEL"), // title (language-dependent)
274 QString( "PyEditorOperations" ), // name (language-independent)
275 false ); // disable floatable toolbar
276 aMgr->append( NewId, idTB );
277 aMgr->append( OpenId, idTB );
278 aMgr->append( SaveId, idTB );
279 aMgr->append( SaveAsId, idTB );
281 aMgr->append( CloseId, idTB );
282 aMgr->append( aMgr->separator(), idTB );
283 aMgr->append( UndoId, idTB );
284 aMgr->append( RedoId, idTB );
285 aMgr->append( aMgr->separator(), idTB );
286 aMgr->append( CutId, idTB );
287 aMgr->append( CopyId, idTB );
288 aMgr->append( PasteId, idTB );
289 aMgr->append( DeleteId, idTB );
290 aMgr->append( SelectAllId, idTB );
291 aMgr->append( aMgr->separator(), idTB );
292 aMgr->append( PreferencesId, idTB );
293 aMgr->append( aMgr->separator(), idTB );
294 aMgr->append( BrowserId, idTB );
299 \brief Reimplemented class is to receive a window close request.
300 \param theEvent event
302 void PyViewer_ViewWindow::closeEvent( QCloseEvent* theEvent )
311 SLOT: Creates a new document
313 void PyViewer_ViewWindow::onNew()
317 my_TextEditor->clear();
318 setCurrentFile( QString() );
323 SLOT: Open an existing python file
325 void PyViewer_ViewWindow::onOpen()
329 QString aFilePath = QFileDialog::getOpenFileName(
330 this, tr( "TIT_DLG_OPEN" ), QDir::currentPath(), "Python Files (*.py)" );
332 if ( !aFilePath.isEmpty() )
333 loadFile( aFilePath );
338 SLOT: Save the current file
340 bool PyViewer_ViewWindow::onSave()
342 if ( my_CurrentFile.isEmpty() )
345 return saveFile( my_CurrentFile );
350 SLOT: Save the current file under a new name
352 bool PyViewer_ViewWindow::onSaveAs()
354 QString aFilePath = QFileDialog::getSaveFileName(
355 this, tr( "TIT_DLG_SAVEAS" ), QDir::currentPath(), "Python Files (*.py)" );
357 if ( !aFilePath.isEmpty() )
358 return saveFile( aFilePath );
364 SLOT: Open preferences dialog
366 void PyViewer_ViewWindow::onPreferences()
368 PyEditor_SettingsDlg aPage( my_TextEditor, this );
373 \brief Set preferece values for view.
375 void PyViewer_ViewWindow::setPreferences()
377 my_TextEditor->settings()->readSettings();
378 my_TextEditor->updateStatement();
382 \brief Associates the theFilePath with the python view.
383 \param theFilePath file path
385 void PyViewer_ViewWindow::setCurrentFile( const QString &theFilePath )
387 my_CurrentFile = theFilePath;
388 my_TextEditor->document()->setModified( false );
392 setWindowModified( false );
394 QString aShownName = my_CurrentFile;
395 if ( my_CurrentFile.isEmpty() )
396 aShownName = "untitled.py";
397 setWindowFilePath( aShownName );
399 // Set window title with associated file path
400 QFileInfo anInfo( aShownName );
401 setWindowTitle( "Python Viewer - " + anInfo.fileName() + "[*]" );
406 \brief Checks whether the file is modified.
407 If it has the modifications then ask the user to save it.
408 \return true if the document is saved.
410 bool PyViewer_ViewWindow::whetherSave()
412 if ( my_TextEditor->document()->isModified() )
414 QMessageBox::StandardButton aReturn;
415 aReturn = QMessageBox::warning(
416 this, tr( "TIT_DLG_SAVE" ),tr( "WRN_PY_SAVE_FILE" ),
417 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel );
419 if ( aReturn == QMessageBox::Save )
421 else if ( aReturn == QMessageBox::Cancel )
429 \param theFilePath file path
431 void PyViewer_ViewWindow::loadFile( const QString &theFilePath )
433 QFile aFile( theFilePath );
434 if ( !aFile.open(QFile::ReadOnly | QFile::Text) )
436 QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
437 tr( "WRN_PY_READ_FILE" ).arg( theFilePath ).arg( aFile.errorString() ) );
441 QTextStream anInput( &aFile );
442 QApplication::setOverrideCursor( Qt::WaitCursor );
443 my_TextEditor->setPlainText( anInput.readAll() );
444 QApplication::restoreOverrideCursor();
446 setCurrentFile( theFilePath );
449 statusBar()->showMessage( tr( "STS_F_LOADED" ), 2000 );
454 \param theFilePath file path
456 bool PyViewer_ViewWindow::saveFile( const QString &theFilePath )
458 QFile aFile( theFilePath );
459 if ( !aFile.open( QFile::WriteOnly | QFile::Text ) )
461 QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
462 tr( "WRN_PY_WRITE_FILE" ).arg( theFilePath ).arg( aFile.errorString() ) );
466 QTextStream anOutput( &aFile );
467 QApplication::setOverrideCursor( Qt::WaitCursor );
468 anOutput << my_TextEditor->toPlainText();
469 QApplication::restoreOverrideCursor();
471 setCurrentFile( theFilePath );
475 statusBar()->showMessage( tr( "STS_F_SAVED" ), 2000 );
481 \brief Opens help browser with python view help information.
483 void PyViewer_ViewWindow::onBrowser()
485 QDir appDir = QApplication::applicationDirPath();
486 QStringList parameters;
487 parameters << QString( "--file=%1" ).arg( appDir.filePath( "pyeditor.html" ) );
488 QProcess::startDetached( "HelpBrowser", parameters );