1 // Copyright (C) 2015-2016 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_SettingsDlg.h"
28 #include "SUIT_Session.h"
29 #include "SUIT_ResourceMgr.h"
31 #include "QtxAction.h"
32 #include "QtxActionToolMgr.h"
34 #include <QApplication>
35 #include <QFileDialog>
36 #include <QMessageBox>
37 #include <QTextStream>
40 \class PyViewer_ViewWindow
41 \brief Python view window.
46 \param desktop SALOME desktop window
48 PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) :
49 SUIT_ViewWindow( desktop )
51 // Create editor and set it as a central widget.
52 myTextEditor = new PyEditor_Editor( this );
53 setCentralWidget( myTextEditor );
56 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
60 action = new QtxAction( tr( "TTP_NEW" ),
61 resMgr->loadPixmap( "PyViewer", tr( "ICON_NEW" ) ),
62 tr( "ACT_NEW" ), 0, this );
63 action->setStatusTip( tr( "DSC_NEW" ) );
64 action->setShortcut( QKeySequence::New );
65 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onNew() ) );
66 toolMgr()->registerAction( action, NewId );
69 action = new QtxAction( tr( "TTP_OPEN" ),
70 resMgr->loadPixmap( "PyViewer", tr( "ICON_OPEN" ) ),
71 tr( "ACT_OPEN" ), 0, this );
72 action->setStatusTip( tr( "DSC_OPEN" ) );
73 action->setShortcut( QKeySequence::Open );
74 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onOpen() ) );
75 toolMgr()->registerAction( action, OpenId );
78 action = new QtxAction( tr( "TTP_SAVE" ),
79 resMgr->loadPixmap( "PyViewer", tr( "ICON_SAVE" ) ),
80 tr( "ACT_SAVE" ), 0, this );
81 action->setStatusTip( tr( "DSC_SAVE" ) );
82 action->setShortcut( QKeySequence::Save );
83 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) );
84 action->setEnabled( false );
85 connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ),
86 action, SLOT( setEnabled( bool ) ) );
87 toolMgr()->registerAction( action, SaveId );
90 action = new QtxAction( tr( "TTP_SAVEAS" ),
91 resMgr->loadPixmap( "PyViewer", tr( "ICON_SAVEAS" ) ),
92 tr( "ACT_SAVEAS" ), 0, this );
93 action->setStatusTip( tr( "DSC_SAVEAS" ) );
94 action->setShortcut( QKeySequence::SaveAs );
95 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAs() ) );
96 toolMgr()->registerAction( action, SaveAsId );
99 action = new QtxAction( tr( "TTP_UNDO" ),
100 resMgr->loadPixmap( "PyViewer", tr( "ICON_UNDO" ) ),
101 tr( "ACT_UNDO" ), 0, this );
102 action->setStatusTip( tr( "DSC_UNDO" ) );
103 action->setShortcut( QKeySequence::Undo );
104 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( undo() ) );
105 action->setEnabled( false );
106 connect( myTextEditor->document(), SIGNAL( undoAvailable( bool ) ),
107 action, SLOT( setEnabled( bool ) ) );
108 toolMgr()->registerAction( action, UndoId );
111 action = new QtxAction( tr( "TTP_REDO" ),
112 resMgr->loadPixmap( "PyViewer", tr( "ICON_REDO" ) ),
113 tr( "ACT_REDO" ), 0, this );
114 action->setStatusTip( tr( "DSC_REDO" ) );
115 action->setShortcut( QKeySequence::Redo );
116 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( redo() ) );
117 action->setEnabled( false );
118 connect( myTextEditor->document(), SIGNAL( redoAvailable( bool ) ),
119 action, SLOT( setEnabled( bool ) ) );
120 toolMgr()->registerAction( action, RedoId );
123 action = new QtxAction( tr( "TTP_CUT" ),
124 resMgr->loadPixmap( "PyViewer", tr( "ICON_CUT" ) ),
125 tr( "ACT_CUT" ), 0, this );
126 action->setStatusTip( tr( "DSC_CUT" ) );
127 action->setShortcut( QKeySequence::Cut );
128 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( cut() ) );
129 action->setEnabled( false );
130 connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
131 action, SLOT( setEnabled( bool ) ) );
132 toolMgr()->registerAction( action, CutId );
135 action = new QtxAction( tr( "TTP_COPY" ),
136 resMgr->loadPixmap( "PyViewer", tr( "ICON_COPY" ) ),
137 tr( "ACT_COPY" ), 0, this );
138 action->setStatusTip( tr( "DSC_COPY" ) );
139 action->setShortcut( QKeySequence::Copy );
140 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( copy() ) );
141 action->setEnabled( false );
142 connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
143 action, SLOT( setEnabled( bool ) ) );
144 toolMgr()->registerAction( action, CopyId );
147 action = new QtxAction( tr( "TTP_PASTE" ),
148 resMgr->loadPixmap( "PyViewer", tr( "ICON_PASTE" ) ),
149 tr( "ACT_PASTE" ), 0, this );
150 action->setStatusTip( tr( "DSC_PASTE" ) );
151 action->setShortcut( QKeySequence::Paste );
152 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( paste() ) );
153 toolMgr()->registerAction( action, PasteId );
156 action = new QtxAction( tr( "TTP_DELETE" ),
157 resMgr->loadPixmap( "PyViewer", tr( "ICON_DELETE" ) ),
158 tr( "ACT_DELETE" ), 0, this );
159 action->setStatusTip( tr( "DSC_DELETE" ) );
160 action->setShortcut( QKeySequence::Delete );
161 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( deleteSelected() ) );
162 action->setEnabled( false );
163 connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
164 action, SLOT( setEnabled( bool ) ) );
165 toolMgr()->registerAction( action, DeleteId );
168 action = new QtxAction( tr( "TTP_SELECT_ALL" ),
169 resMgr->loadPixmap( "PyViewer", tr( "ICON_SELECT_ALL" ) ),
170 tr( "ACT_SELECT_ALL" ), 0, this );
171 action->setStatusTip( tr( "DSC_SELECT_ALL" ) );
172 action->setShortcut( QKeySequence::SelectAll );
173 connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( selectAll() ) );
174 toolMgr()->registerAction( action, SelectAllId );
177 action = new QtxAction( tr( "TTP_PREFERENCES" ),
178 resMgr->loadPixmap( "PyViewer", tr( "ICON_PREFERENCES" ) ),
179 tr( "ACT_PREFERENCES" ), 0, this );
180 action->setStatusTip( tr( "DSC_PREFERENCES" ) );
181 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onPreferences() ) );
182 toolMgr()->registerAction( action, PreferencesId );
185 action = new QtxAction( tr( "TTP_HELP" ),
186 resMgr->loadPixmap( "PyViewer", tr( "ICON_HELP" ) ),
187 tr( "ACT_HELP" ), 0, this );
188 action->setStatusTip( tr( "DSC_HELP" ) );
189 connect( action, SIGNAL( triggered() ), this, SLOT( onHelp() ) );
190 toolMgr()->registerAction( action, HelpId );
193 int idTB = toolMgr()->createToolBar( tr("TOOLBAR_LABEL"), QString( "PythonEditor" ), false );
194 toolMgr()->append( NewId, idTB );
195 toolMgr()->append( OpenId, idTB );
196 toolMgr()->append( SaveId, idTB );
197 toolMgr()->append( SaveAsId, idTB );
198 toolMgr()->append( toolMgr()->separator(), idTB );
199 toolMgr()->append( UndoId, idTB );
200 toolMgr()->append( RedoId, idTB );
201 toolMgr()->append( toolMgr()->separator(), idTB );
202 toolMgr()->append( CutId, idTB );
203 toolMgr()->append( CopyId, idTB );
204 toolMgr()->append( PasteId, idTB );
205 toolMgr()->append( DeleteId, idTB );
206 toolMgr()->append( SelectAllId, idTB );
207 toolMgr()->append( toolMgr()->separator(), idTB );
208 toolMgr()->append( PreferencesId, idTB );
209 toolMgr()->append( toolMgr()->separator(), idTB );
210 toolMgr()->append( HelpId, idTB );
213 setCurrentFile( QString() );
219 PyViewer_ViewWindow::~PyViewer_ViewWindow()
224 \brief Manage window close request.
225 \param event close event
227 void PyViewer_ViewWindow::closeEvent( QCloseEvent* event )
236 SLOT: Create new document
238 void PyViewer_ViewWindow::onNew()
242 myTextEditor->clear();
243 setCurrentFile( QString() );
248 SLOT: Open existing Python file
250 void PyViewer_ViewWindow::onOpen()
254 QString filter = tr( "TIT_PY_FILES" );
256 QString aFilePath = QFileDialog::getOpenFileName( this,
257 tr( "TIT_DLG_OPEN" ),
261 if ( !aFilePath.isEmpty() )
262 loadFile( aFilePath );
267 SLOT: Save current document
269 bool PyViewer_ViewWindow::onSave()
271 if ( myURL.isEmpty() )
274 return saveFile( myURL );
279 SLOT: Save current document under a new name
281 bool PyViewer_ViewWindow::onSaveAs()
283 QString filter = tr( "TIT_PY_FILES" );
285 QString url = myURL.isEmpty() ? defaultName() : myURL;
286 QString aFilePath = QFileDialog::getSaveFileName( this,
287 tr( "TIT_DLG_SAVE" ),
291 if ( !aFilePath.isEmpty() )
292 return saveFile( aFilePath );
298 SLOT: Open preferences dialog
300 void PyViewer_ViewWindow::onPreferences()
302 PyEditor_SettingsDlg dlg( myTextEditor, true, this );
303 connect( &dlg, SIGNAL( help() ), this, SLOT( onHelp() ) );
308 \brief Associate \a filePath with the current document
309 \param filePath document's file path
311 void PyViewer_ViewWindow::setCurrentFile( const QString& filePath )
314 myTextEditor->document()->setModified( false );
318 \brief Check whether the file is modified.
319 If it has the modifications then ask the user to save it.
320 \return true if the document is saved.
322 bool PyViewer_ViewWindow::whetherSave()
324 if ( myTextEditor->document()->isModified() )
326 QMessageBox::StandardButton answer = QMessageBox::warning( this,
327 tr( "NAME_PYEDITOR" ),
328 tr( "WRN_SAVE_FILE" ),
330 QMessageBox::Discard |
331 QMessageBox::Cancel );
334 case QMessageBox::Save:
336 case QMessageBox::Cancel:
347 \param filePath file path
349 void PyViewer_ViewWindow::loadFile( const QString& filePath )
351 QFile aFile( filePath );
352 if ( !aFile.open(QFile::ReadOnly | QFile::Text) )
354 QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
355 tr( "WRN_READ_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
359 QTextStream anInput( &aFile );
360 QApplication::setOverrideCursor( Qt::WaitCursor );
361 myTextEditor->setPlainText( anInput.readAll() );
362 QApplication::restoreOverrideCursor();
364 setCurrentFile( filePath );
371 \param theFilePath file path
373 bool PyViewer_ViewWindow::saveFile( const QString& filePath )
375 QFile aFile( filePath );
376 if ( !aFile.open( QFile::WriteOnly | QFile::Text ) )
378 QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
379 tr( "WRN_WRITE_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
383 QTextStream anOutput( &aFile );
384 QApplication::setOverrideCursor( Qt::WaitCursor );
385 anOutput << myTextEditor->toPlainText();
386 QApplication::restoreOverrideCursor();
388 setCurrentFile( filePath );
395 Slot, called when user clicks "Help" button in "Preferences" dialog box.
397 void PyViewer_ViewWindow::onHelp()
399 SUIT_Application* app = SUIT_Session::session()->activeApplication();
401 QString page = "python_viewer_page.html";
402 if ( qobject_cast<QWidget*>( sender() ) )
403 page += "#custom_python_preferences";
404 app->onHelpContextModule( "GUI", page );
409 Get default name for Python file
412 QString PyViewer_ViewWindow::defaultName() const
414 return tr( "NONAME" );