Mercurial > hg > octave-nkf
comparison libqterminal/unix/TerminalModel.cpp @ 15651:845cebf281aa
Added files of QConsole.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Mon, 30 Jan 2012 11:23:13 +0100 |
parents | |
children | 35c891dce299 |
comparison
equal
deleted
inserted
replaced
15650:ba360324035e | 15651:845cebf281aa |
---|---|
1 /* | |
2 This file is part of Konsole | |
3 | |
4 Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com> | |
5 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> | |
6 | |
7 Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 | |
8 Copyright (C) 2012 Jacob Dawid <jacob.dawid@googlemail.com> | |
9 | |
10 This program is free software; you can redistribute it and/or modify | |
11 it under the terms of the GNU General Public License as published by | |
12 the Free Software Foundation; either version 2 of the License, or | |
13 (at your option) any later version. | |
14 | |
15 This program is distributed in the hope that it will be useful, | |
16 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 GNU General Public License for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with this program; if not, write to the Free Software | |
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
23 02110-1301 USA. | |
24 */ | |
25 | |
26 // Own | |
27 #include "TerminalModel.h" | |
28 | |
29 // Standard | |
30 #include <assert.h> | |
31 #include <stdlib.h> | |
32 | |
33 // Qt | |
34 #include <QtGui/QApplication> | |
35 #include <QtCore/QByteRef> | |
36 #include <QtCore/QDir> | |
37 #include <QtCore/QFile> | |
38 #include <QtCore/QRegExp> | |
39 #include <QtCore/QStringList> | |
40 #include <QtCore> | |
41 | |
42 #include "TerminalView.h" | |
43 #include "Vt102Emulation.h" | |
44 | |
45 TerminalModel::TerminalModel(KPty *kpty) : | |
46 _shellProcess(0) | |
47 , _emulation(0) | |
48 , _monitorActivity(false) | |
49 , _monitorSilence(false) | |
50 , _notifiedActivity(false) | |
51 , _autoClose(true) | |
52 , _wantedClose(false) | |
53 , _silenceSeconds(10) | |
54 , _addToUtmp(false) | |
55 , _fullScripting(false) | |
56 , _hasDarkBackground(false) | |
57 { | |
58 _kpty = kpty; | |
59 | |
60 //create emulation backend | |
61 _emulation = new Vt102Emulation(); | |
62 connect( _emulation, SIGNAL( stateSet(int) ), | |
63 this, SLOT( activityStateSet(int) ) ); | |
64 connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ), | |
65 this, SIGNAL( changeTabTextColorRequest( int ) ) ); | |
66 connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)), | |
67 this, SIGNAL( profileChangeCommandReceived(const QString&)) ); | |
68 // TODO | |
69 // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this , | |
70 // SLOT(onEmulationSizeChange(int,int)) ); | |
71 | |
72 _selfListener = new SelfListener(kpty->masterFd()); | |
73 _selfListener->start(); | |
74 connect( _selfListener, SIGNAL(recvData(const char*,int)), | |
75 this, SLOT(onReceiveBlock(const char*,int)), Qt::BlockingQueuedConnection); | |
76 | |
77 connect( _emulation, SIGNAL(sendData(const char*,int)) | |
78 ,this,SLOT(sendData(const char*,int))); | |
79 | |
80 //connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) ); | |
81 //connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) ); | |
82 | |
83 | |
84 //connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) ); | |
85 | |
86 //setup timer for monitoring session activity | |
87 _monitorTimer = new QTimer(this); | |
88 _monitorTimer->setSingleShot(true); | |
89 connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone())); | |
90 } | |
91 | |
92 void TerminalModel::setDarkBackground(bool darkBackground) | |
93 { | |
94 _hasDarkBackground = darkBackground; | |
95 } | |
96 bool TerminalModel::hasDarkBackground() const | |
97 { | |
98 return _hasDarkBackground; | |
99 } | |
100 | |
101 void TerminalModel::setCodec(QTextCodec* codec) | |
102 { | |
103 emulation()->setCodec(codec); | |
104 } | |
105 | |
106 QList<TerminalView*> TerminalModel::views() const | |
107 { | |
108 return _views; | |
109 } | |
110 | |
111 void TerminalModel::addView(TerminalView* widget) | |
112 { | |
113 Q_ASSERT( !_views.contains(widget) ); | |
114 | |
115 _views.append(widget); | |
116 | |
117 if ( _emulation != 0 ) | |
118 { | |
119 // connect emulation - view signals and slots | |
120 connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation , | |
121 SLOT(sendKeyEvent(QKeyEvent*)) ); | |
122 connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation , | |
123 SLOT(sendMouseEvent(int,int,int,int)) ); | |
124 connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation , | |
125 SLOT(sendString(const char*)) ); | |
126 | |
127 // allow emulation to notify view when the foreground process | |
128 // indicates whether or not it is interested in mouse signals | |
129 connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget , | |
130 SLOT(setUsesMouse(bool)) ); | |
131 | |
132 widget->setUsesMouse( _emulation->programUsesMouse() ); | |
133 | |
134 widget->setScreenWindow(_emulation->createWindow()); | |
135 } | |
136 | |
137 //connect view signals and slots | |
138 QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this, | |
139 SLOT(onViewSizeChange(int,int))); | |
140 | |
141 QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this , | |
142 SLOT(viewDestroyed(QObject*)) ); | |
143 //slot for close | |
144 //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close())); | |
145 } | |
146 | |
147 void TerminalModel::viewDestroyed(QObject* view) | |
148 { | |
149 TerminalView* display = (TerminalView*)view; | |
150 | |
151 Q_ASSERT( _views.contains(display) ); | |
152 | |
153 removeView(display); | |
154 } | |
155 | |
156 void TerminalModel::sendData(const char *buf, int len) | |
157 { | |
158 ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len); | |
159 (void)bytesWritten; | |
160 } | |
161 | |
162 void TerminalModel::removeView(TerminalView* widget) | |
163 { | |
164 _views.removeAll(widget); | |
165 | |
166 disconnect(widget,0,this,0); | |
167 | |
168 if ( _emulation != 0 ) | |
169 { | |
170 // disconnect | |
171 // - key presses signals from widget | |
172 // - mouse activity signals from widget | |
173 // - string sending signals from widget | |
174 // | |
175 // ... and any other signals connected in addView() | |
176 disconnect( widget, 0, _emulation, 0); | |
177 | |
178 // disconnect state change signals emitted by emulation | |
179 disconnect( _emulation , 0 , widget , 0); | |
180 } | |
181 | |
182 // close the session automatically when the last view is removed | |
183 if ( _views.count() == 0 ) | |
184 { | |
185 close(); | |
186 } | |
187 } | |
188 | |
189 void TerminalModel::run() | |
190 { | |
191 emit started(); | |
192 } | |
193 | |
194 void TerminalModel::monitorTimerDone() | |
195 { | |
196 //FIXME: The idea here is that the notification popup will appear to tell the user than output from | |
197 //the terminal has stopped and the popup will disappear when the user activates the session. | |
198 // | |
199 //This breaks with the addition of multiple views of a session. The popup should disappear | |
200 //when any of the views of the session becomes active | |
201 | |
202 | |
203 //FIXME: Make message text for this notification and the activity notification more descriptive. | |
204 if (_monitorSilence) { | |
205 // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(), | |
206 // QApplication::activeWindow(), | |
207 // KNotification::CloseWhenWidgetActivated); | |
208 emit stateChanged(NOTIFYSILENCE); | |
209 } | |
210 else | |
211 { | |
212 emit stateChanged(NOTIFYNORMAL); | |
213 } | |
214 | |
215 _notifiedActivity=false; | |
216 } | |
217 | |
218 void TerminalModel::activityStateSet(int state) | |
219 { | |
220 if (state==NOTIFYBELL) | |
221 { | |
222 emit bellRequest(""); | |
223 } | |
224 else if (state==NOTIFYACTIVITY) | |
225 { | |
226 if (_monitorSilence) { | |
227 _monitorTimer->start(_silenceSeconds*1000); | |
228 } | |
229 | |
230 if ( _monitorActivity ) { | |
231 //FIXME: See comments in Session::monitorTimerDone() | |
232 if (!_notifiedActivity) { | |
233 // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(), | |
234 // QApplication::activeWindow(), | |
235 // KNotification::CloseWhenWidgetActivated); | |
236 _notifiedActivity=true; | |
237 } | |
238 } | |
239 } | |
240 | |
241 if ( state==NOTIFYACTIVITY && !_monitorActivity ) | |
242 state = NOTIFYNORMAL; | |
243 if ( state==NOTIFYSILENCE && !_monitorSilence ) | |
244 state = NOTIFYNORMAL; | |
245 | |
246 emit stateChanged(state); | |
247 } | |
248 | |
249 void TerminalModel::onViewSizeChange(int /*height*/, int /*width*/) | |
250 { | |
251 updateTerminalSize(); | |
252 } | |
253 void TerminalModel::onEmulationSizeChange(int lines , int columns) | |
254 { | |
255 setSize( QSize(lines,columns) ); | |
256 } | |
257 | |
258 void TerminalModel::updateTerminalSize() | |
259 { | |
260 QListIterator<TerminalView*> viewIter(_views); | |
261 | |
262 int minLines = -1; | |
263 int minColumns = -1; | |
264 | |
265 // minimum number of lines and columns that views require for | |
266 // their size to be taken into consideration ( to avoid problems | |
267 // with new view widgets which haven't yet been set to their correct size ) | |
268 const int VIEW_LINES_THRESHOLD = 2; | |
269 const int VIEW_COLUMNS_THRESHOLD = 2; | |
270 | |
271 //select largest number of lines and columns that will fit in all visible views | |
272 while ( viewIter.hasNext() ) | |
273 { | |
274 TerminalView* view = viewIter.next(); | |
275 if ( view->isHidden() == false && | |
276 view->lines() >= VIEW_LINES_THRESHOLD && | |
277 view->columns() >= VIEW_COLUMNS_THRESHOLD ) | |
278 { | |
279 minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() ); | |
280 minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() ); | |
281 } | |
282 } | |
283 | |
284 // backend emulation must have a _terminal of at least 1 column x 1 line in size | |
285 if ( minLines > 0 && minColumns > 0 ) | |
286 { | |
287 _emulation->setImageSize( minLines , minColumns ); | |
288 //_shellProcess->setWindowSize( minLines , minColumns ); | |
289 } | |
290 } | |
291 | |
292 void TerminalModel::refresh() | |
293 { | |
294 } | |
295 | |
296 void TerminalModel::close() | |
297 { | |
298 _autoClose = true; | |
299 _wantedClose = true; | |
300 } | |
301 | |
302 void TerminalModel::sendText(const QString &text) const | |
303 { | |
304 _emulation->sendText(text); | |
305 } | |
306 | |
307 TerminalModel::~TerminalModel() | |
308 { | |
309 delete _emulation; | |
310 } | |
311 | |
312 void TerminalModel::setProfileKey(const QString& key) | |
313 { | |
314 _profileKey = key; | |
315 emit profileChanged(key); | |
316 } | |
317 QString TerminalModel::profileKey() const { return _profileKey; } | |
318 | |
319 void TerminalModel::done(int) | |
320 { | |
321 emit finished(); | |
322 } | |
323 | |
324 Emulation* TerminalModel::emulation() const | |
325 { | |
326 return _emulation; | |
327 } | |
328 | |
329 QString TerminalModel::keyBindings() const | |
330 { | |
331 return _emulation->keyBindings(); | |
332 } | |
333 | |
334 void TerminalModel::setKeyBindings(const QString &id) | |
335 { | |
336 _emulation->setKeyBindings(id); | |
337 } | |
338 | |
339 void TerminalModel::setHistoryType(const HistoryType &hType) | |
340 { | |
341 _emulation->setHistory(hType); | |
342 } | |
343 | |
344 const HistoryType& TerminalModel::historyType() const | |
345 { | |
346 return _emulation->history(); | |
347 } | |
348 | |
349 void TerminalModel::clearHistory() | |
350 { | |
351 _emulation->clearHistory(); | |
352 } | |
353 | |
354 // unused currently | |
355 bool TerminalModel::isMonitorActivity() const { return _monitorActivity; } | |
356 // unused currently | |
357 bool TerminalModel::isMonitorSilence() const { return _monitorSilence; } | |
358 | |
359 void TerminalModel::setMonitorActivity(bool _monitor) | |
360 { | |
361 _monitorActivity=_monitor; | |
362 _notifiedActivity=false; | |
363 | |
364 activityStateSet(NOTIFYNORMAL); | |
365 } | |
366 | |
367 void TerminalModel::setMonitorSilence(bool _monitor) | |
368 { | |
369 if (_monitorSilence==_monitor) | |
370 return; | |
371 | |
372 _monitorSilence=_monitor; | |
373 if (_monitorSilence) | |
374 { | |
375 _monitorTimer->start(_silenceSeconds*1000); | |
376 } | |
377 else | |
378 _monitorTimer->stop(); | |
379 | |
380 activityStateSet(NOTIFYNORMAL); | |
381 } | |
382 | |
383 void TerminalModel::setMonitorSilenceSeconds(int seconds) | |
384 { | |
385 _silenceSeconds=seconds; | |
386 if (_monitorSilence) { | |
387 _monitorTimer->start(_silenceSeconds*1000); | |
388 } | |
389 } | |
390 | |
391 void TerminalModel::setAddToUtmp(bool set) | |
392 { | |
393 _addToUtmp = set; | |
394 } | |
395 | |
396 void TerminalModel::onReceiveBlock(const char* buf, int len ) | |
397 { | |
398 _emulation->receiveData( buf, len ); | |
399 emit receivedData( QString::fromLatin1( buf, len ) ); | |
400 } | |
401 | |
402 QSize TerminalModel::size() | |
403 { | |
404 return _emulation->imageSize(); | |
405 } | |
406 | |
407 void TerminalModel::setSize(const QSize& size) | |
408 { | |
409 if ((size.width() <= 1) || (size.height() <= 1)) | |
410 return; | |
411 | |
412 emit resizeRequest(size); | |
413 } |