1 #ifndef _KVI_WINDOW_H_
2 #define _KVI_WINDOW_H_
3 //=============================================================================
4 //
5 // File : KviWindow.h
6 // Creation date : Tue Jul 6 1999 14:52:20 by Szymon Stefanek
7 //
8 // This file is part of the KVIrc IRC client distribution
9 // Copyright (C) 1999-2010 Szymon Stefanek (pragma at kvirc dot net)
10 //
11 // This program is FREE software. You can redistribute it and/or
12 // modify it under the terms of the GNU General Public License
13 // as published by the Free Software Foundation; either version 2
14 // of the License, or (at your option) any later version.
15 //
16 // This program is distributed in the HOPE that it will be USEFUL,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 // See the GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, write to the Free Software Foundation,
23 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 //=============================================================================
26
27 /**
28 * \file KviWindow.h
29 * \brief Contains the KviWindow class
30 */
31
32 #include "kvi_settings.h"
33 #include "KviApplication.h"
34 #include "KviCString.h"
35 #include "KviQString.h"
36 #include "KviIrcContext.h"
37 #include "KviIrcConnection.h"
38 #include "KviInput.h"
39 #include "KviTalHBox.h"
40 #include "KviTalSplitter.h"
41 #include "KviIconManager.h"
42
43 #include <QFrame>
44 #include <QWidget>
45 #include <QToolButton>
46 #include <QTextEncoder>
47 #include <QByteArray>
48 #include <QDateTime>
49
50 class QPushButton;
51 class QPixmap;
52 class QTextCodec;
53 class KviMainWindow;
54 class KviWindowListItem;
55 class KviConfigurationFile;
56 class KviIrcView;
57 class KviConsoleWindow;
58 class KviIrcConnection;
59 class KviWindowToolPageButton;
60 class QMenu;
61 class KviTalHBox;
62
63 #ifdef COMPILE_CRYPT_SUPPORT
64 class KviCryptController;
65 class KviCryptSessionInfo;
66 #endif
67
68 #define KVI_WINDOW_TYPE_USER 10000
69
70 /**
71 * \class KviWindow
72 * \brief Base class for all windows in KVIrc
73 */
74 class KVIRC_API KviWindow : public QWidget
75 {
76 friend class KviInput;
77 friend class KviMainWindow;
78 friend class KviWindowStack;
79 friend class KviWindowListItem;
80 friend class KviWindowListButton;
81 friend class KviTreeWindowListItem;
82 friend class KviTreeWindowList;
83 friend class KviTreeWindowListItemDelegate;
84 Q_PROPERTY(int KviProperty_ChildFocusOwner READ type)
85 Q_OBJECT
86 public:
87 /**
88 * \enum ActivityValue
89 * \brief Holds the activity meter in value scale
90 */
91 enum ActivityValue
92 {
93 None = 0, /**< None */
94 VeryLow = 1, /**< Very low */
95 Low = 2, /**< Low */
96 Medium = 3, /**< Medium */
97 High = 4, /**< High */
98 VeryHigh = 5 /**< Very high */
99 };
100
101 /**
102 * \enum ActivityTemperature
103 * \brief Holds the activity meter in temperature scale
104 */
105 enum ActivityTemperature
106 {
107 Ice = 0, /**< Ice */
108 VeryCold = 1, /**< Very cold */
109 Cold = 2, /**< Cold */
110 Undefined = 3, /**< Undefined */
111 Hot = 4, /**< Hot */
112 VeryHot = 5, /**< Very hot */
113 Fire = 6 /**< Fire */
114 };
115
116 /**
117 * \enum AttentionLevel
118 * \brief attention levels usable in hasAttention()
119 */
120 enum AttentionLevel
121 {
122 VisibleAndActive = 0, /**< The window is visible and active (aka: has user focus) */
123 MainWindowIsVisible = 1 /**< The kvirc frame is visible but the window is not the active one */
124 };
125 /**
126 * \enum Type
127 * \brief Holds the types of a window; these are used by the KVIrc core and distributed modules
128 * \note If you add a new type, insert it just before Unknown
129 */
130 enum Type
131 {
132 Console = 0,
133 Channel = 1,
134 Query = 2,
135 DeadChannel = 3,
136 DeadQuery = 4,
137 Editor = 5,
138 Help = 6,
139 Terminal = 7,
140 SocketSpy = 8,
141 Links = 9,
142 List = 10,
143 DccChat = 11,
144 DccTransfer = 12,
145 DccCanvas = 13,
146 DccVoice = 14,
147 DccVideo = 15,
148 UserWindow = 16,
149 Tool = 17,
150 IOGraph = 18,
151 DirBrowser = 19, //!\ no longer exists please reuse entry
152 ScriptEditor = 20,
153 ScriptObject = 21,
154 LogView = 22,
155 Offer = 23,
156 Debug = 24,
157 Unknown = 25,
158 TypeCount = 26
159 };
160
161 /**
162 * \brief Constructs the window object
163 * \param eType The type of the window
164 * \param lpFrm The main window
165 * \param szName The name of the window
166 * \param pConsole The parent console
167 * \return KviWindow
168 */
169 KviWindow(Type eType, const QString & szName, KviConsoleWindow * pConsole = nullptr);
170
171 /**
172 * \brief Destroys the window object
173 */
174 ~KviWindow();
175
176 protected: // almost private: don't touch :D
177 QString m_szName; // the current window name (usually also the target)
178 KviConsoleWindow * m_pConsole;
179 Type m_eType;
180 KviWindowListItem * m_pWindowListItem;
181 QWidget * m_pFocusHandler;
182 QString m_szPlainTextCaption;
183 KviIrcView * m_pIrcView;
184 KviInput * m_pInput;
185 KviTalSplitter * m_pSplitter;
186 KviTalHBox * m_pButtonBox;
187 unsigned long int m_uId;
188 QString m_szTextEncoding;
189 #ifdef COMPILE_CRYPT_SUPPORT
190 KviWindowToolPageButton * m_pCryptControllerButton;
191 KviCryptController * m_pCryptController;
192 KviCryptSessionInfo * m_pCryptSessionInfo;
193 #endif
194 QToolButton * m_pTextEncodingButton;
195 QToolButton * m_pHideToolsButton;
196 QWidget * m_pLastFocusedChild;
197 static const char * m_typeTable[TypeCount];
198 // text encoding and decoding
199 //unsigned int m_uTextEncoding;
200 QTextCodec * m_pTextCodec;
201 //KviToolWindowsContainer * m_pEditorsContainer;
202 bool m_bIsDocked;
203 bool m_bProcessingInputEvent;
204
205 public:
isDocked()206 bool isDocked() const { return m_bIsDocked; }
207
208 /**
209 * \brief Returns the global ID of this window
210 *
211 * This is unique in the application
212 * \return QString
213 */
id()214 QString id() const { return QString("%1").arg(m_uId); }
215
216 /**
217 * \brief Returns the global ID of this window
218 *
219 * This is unique in the application
220 * \return QString
221 */
numericId()222 unsigned long int numericId() const { return m_uId; }
223
224 /**
225 * \brief Returns the name of this window
226 * \return const QString &
227 */
windowName()228 const QString & windowName() const { return m_szName; }
229
230 /**
231 * \brief Sets the name of the window
232 * \param szName The name of the window
233 * \return void
234 */
235 void setWindowName(const QString & szName);
236
237 /**
238 * \brief Sets the progress for the WindowList item
239 *
240 * If "progress" makes sense in your window, well, use this
241 * \param iProgress The progress to set
242 * \return void
243 */
244 void setProgress(int iProgress);
245
246 /**
247 * \brief Returns the type of the window
248 * \return Type
249 */
type()250 Type type() const { return m_eType; }
251
252 /**
253 * Returns true if the window is a channel
254 */
isChannel()255 bool isChannel() const { return m_eType == Channel; }
256
257 /**
258 * Returns true if the window is a query
259 */
isQuery()260 bool isQuery() const { return m_eType == Query; }
261
262 /**
263 * Returns true if the window is a console
264 */
isConsole()265 bool isConsole() const { return m_eType == Console; }
266
267 /**
268 * \brief Returns a descriptive name of the window type
269 * \return const char *
270 */
271 virtual const char * typeString();
272
textCodec()273 QTextCodec * textCodec() { return m_pTextCodec ? m_pTextCodec : defaultTextCodec(); }
274 void forceTextCodec(QTextCodec * pCodec);
275
276 /**
277 * \brief Returns the KviIrcView of this window
278 *
279 * May be nullptr if the window has no KviIrcView (and thus supports no direct output)
280 * \return KviIrcView *
281 */
view()282 KviIrcView * view() const { return m_pIrcView; }
283
284 /**
285 * \brief Returns the KviIrcView that was last clicked in this window
286 *
287 * Acts as view() except for split view windows
288 * See also: view()
289 * \return KviIrcView *
290 */
lastClickedView()291 virtual KviIrcView * lastClickedView() const { return m_pIrcView; };
292
293 /**
294 * \brief Returns the console that this window belongs to
295 *
296 * May be null for windows that aren't bound to irc contexts
297 * \return KviConsoleWindow *
298 */
console()299 KviConsoleWindow * console() const { return m_pConsole; }
300
301 KviIrcContext * context();
302
303 /**
304 * \brief Returns the current IRC connection (if any)
305 * \return KviIrcConnection *
306 */
307 KviIrcConnection * connection();
308
309 /**
310 * \brief Returns the splitter of this window
311 *
312 * It *shouldn't* be null... but... well... who knows ? :D ...better check it
313 * \return KviTalSplitter *
314 */
splitter()315 KviTalSplitter * splitter() const { return m_pSplitter; }
316
317 /**
318 * \brief Returns the windowList item
319 *
320 * The window has ALWAYS a WindowList item
321 * \return KviWindowListItem *
322 */
windowListItem()323 KviWindowListItem * windowListItem() const { return m_pWindowListItem; }
324
325 // The window *might* have a button container
buttonContainer()326 virtual QFrame * buttonContainer() { return (QFrame *)m_pButtonBox; };
327 virtual void toggleButtonContainer();
328
329 // The window *might* have an output proxy: if it has no view() for example
330 virtual KviWindow * outputProxy();
331
332 // The window input widget
input()333 KviInput * input() const { return m_pInput; }
334
335 // The target of this window: empty when it makes no sense :D
target()336 virtual const QString & target() { return KviQString::Empty; };
337
338 // The local nickname bound to this window: might be empty when a local nickname makes no sense
localNick()339 virtual const QString & localNick() { return KviQString::Empty; };
340
341 #ifdef COMPILE_CRYPT_SUPPORT
cryptSessionInfo()342 KviCryptSessionInfo * cryptSessionInfo()
343 {
344 return m_pCryptSessionInfo;
345 };
346 void setCryptSessionInfo(KviCryptSessionInfo * pInfo);
347 #endif
348
349 virtual bool activityMeter(unsigned int * puActivityValue, unsigned int * puActivityTemperature);
350
351 //* \param puValue Highlight level
352 virtual bool highlightMeter(unsigned int * puValue);
353 virtual bool highlightMe(unsigned int uValue);
354
355 void unhighlight();
356
getWindowListTipText(QString & szBuffer)357 virtual void getWindowListTipText(QString & szBuffer) { szBuffer = m_szPlainTextCaption; }
358
359 // This is meaningful only if view() is non nullptr
360 const QString & lastLineOfText();
361 const QString & lastMessageText();
362
textEncoding()363 const QString & textEncoding() const { return m_szTextEncoding; }
364 // returns true if the encoding could be successfully set
365 bool setTextEncoding(const QString & szTextEncoding);
366 // this must return a default text codec suitable for this window
367 virtual QTextCodec * defaultTextCodec();
368 // encode the text from szSource by using m_uTextEncoding
369 QByteArray encodeText(const QString & szText);
370 QString decodeText(const char * pcText);
371 //return a text encoder
372 QTextEncoder * makeEncoder();
373
374 void contextPopup();
375 // Raises the window (after a light delay to prevent focus pingpongs)
376 void delayedAutoRaise();
377
378 // Retrieves the default log file name: this is pre-build
379 void getDefaultLogFileName(QString & szBuffer);
380 void getDefaultLogFileName(QString & szBuffer, QDate date, bool bGzip, unsigned int uDatetimeFormat);
381
382 void delayedClose(); // close that jumps out of the current event loop
383
384 // Interesting overridables:
385 virtual void getConfigGroupName(QString & szBuffer);
386 virtual void getBaseLogFileName(QString & szBuffer);
387 virtual void updateCaption();
388 virtual void applyOptions();
389 virtual void updateIcon();
390 virtual void ownMessage(const QString &, bool = true){};
ownAction(const QString &)391 virtual void ownAction(const QString &){};
plainTextCaption()392 virtual const QString & plainTextCaption() { return m_szPlainTextCaption; };
393
394 void internalOutput(KviIrcView * pView, int iMsgType, const kvi_wchar_t * pwText, int iFlags = 0, const QDateTime & datetime = QDateTime());
395 // You *might* want to override these too.. but better don't touch them :D
396 virtual void output(int iMsgType, const char * pcFormat, ...);
397 virtual void output(int iMsgType, const kvi_wchar_t * pwFormat, ...);
398 virtual void output(int iMsgType, QString szFmt, ...);
399 void output(int iMsgType, const QDateTime & datetime, const char * pcFormat, ...);
400 void output(int iMsgType, const QDateTime & datetime, const kvi_wchar_t * pwFormat, ...);
401 void output(int iMsgType, const QDateTime & datetime, QString szFmt, ...);
402 virtual void outputNoFmt(int iMsgType, const char * pcText, int iFlags = 0, const QDateTime & datetime = QDateTime());
403 virtual void outputNoFmt(int iMsgType, const kvi_wchar_t * pwText, int iFlags = 0, const QDateTime & datetime = QDateTime()) { internalOutput(m_pIrcView, iMsgType, pwText, iFlags, datetime); };
404 virtual void outputNoFmt(int iMsgType, const QString & szText, int iFlags = 0, const QDateTime & datetime = QDateTime()); // <-- iFlags are KviIrcView::AppendTextFlags
405 // Just helpers.. FIXME: might be redesigned in some other way
406 void updateBackgrounds(QObject * pObj = nullptr);
407
408 /**
409 * \brief Notify the window manager that this window demands attention
410 *
411 * Depending on the os/window manager, this method uses different approaches to
412 * trigger a notification that typically makes the application entry flash
413 * on the application bar.
414 * \return void
415 */
416 void demandAttention();
417
418 /**
419 * \brief Returns whether this window is the active one
420 *
421 * This method is useful because it takes in consideration that this window
422 * can be either docked or undocked, and takes a parameter that defines the strictness
423 * of the checks used.
424 * Level MainWindowIsVisible is fine to check if we needs to trigger the notifier
425 * Level VisibleAndActive is useful to trigger highlights
426 * @param eLevel the level of checks to be done
427 * \return bool
428 */
429 bool hasAttention(AttentionLevel eLevel = VisibleAndActive);
430
431 // This should die, probably
432 void listWindowTypes();
433
434 // call this in the constructor if your caption is fixed:
435 // it will set m_szPlainTextCaption to szCaption and it will
436 // automatically use it without the need of overriding fillCaptionBuffers
setFixedCaption(const QString & szCaption)437 void setFixedCaption(const QString & szCaption) { m_szPlainTextCaption = szCaption; }
438
439 void setWindowTitle(QString & szTitle);
440
441 /**
442 * \brief Pastes the most recent channel log into the buffer
443 *
444 * It searches for the most recent channel log of the channel we have just
445 * joined, and pastes into the buffer the last N lines, where N is get from
446 * the options
447 * \return void
448 */
449 void pasteLastLog();
450
451 private:
452 /**
453 * \brief Loads a log file
454 *
455 * It opens a logfile, gzipped or not, and returns the content in a buffer
456 * \param szFileName The filename of the log file
457 * \param bGzip Whether the log file is gzipped
458 * \return QByteArray
459 */
460 QByteArray loadLogFile(const QString & szFileName, bool bGzip);
461
462 protected:
463 // Loading and saving of properties
464 // Protected: only KviMainWindow can call these
465 virtual void saveProperties(KviConfigurationFile * pCfg);
466 virtual void loadProperties(KviConfigurationFile * pCfg);
467 // Creation and destruction events: overridden in windows that have script events bound to creation and destruction
triggerCreationEvents()468 virtual void triggerCreationEvents(){};
triggerDestructionEvents()469 virtual void triggerDestructionEvents(){};
470 // Internal: do not touch :D (KviMainWindow)
471 virtual void createWindowListItem();
472 virtual void destroyWindowListItem();
473 // called by KviMainWindow
474 // either lost the active window status or the frame is no longer active (but we're still the active kvirc's subwindow)
475 virtual void lostUserFocus();
476 // this by default calls fillSingleColorCaptionBuffer(plainTextCaption());
477 virtual void fillCaptionBuffers();
478 // protected helper
fillSingleColorCaptionBuffers(const QString & szName)479 void fillSingleColorCaptionBuffers(const QString & szName) { m_szPlainTextCaption = szName; }
480 // Virtual events that signal dock state change
481 virtual void youAreDocked();
482 virtual void youAreUndocked();
483 // Reimplement to show a special icon in the WindowList items and captions
484 virtual QPixmap * myIconPtr();
485 // Sets the type of this window: be careful with this
setType(Type eType)486 void setType(Type eType) { m_eType = eType; };
487
488 bool eventFilter(QObject * pObject, QEvent * pEvent) override;
489
490 // Virtuals overridden to manage the internal layouts...
491 void moveEvent(QMoveEvent * pEvent) override;
492 void closeEvent(QCloseEvent * pEvent) override;
493 void childEvent(QChildEvent * pEvent) override;
494 void focusInEvent(QFocusEvent *) override;
495 void inputMethodEvent(QInputMethodEvent * e) override;
496
497 void childInserted(QWidget * pObject);
498 void childRemoved(QWidget * pObject);
499
500 // Internal helpers
501 void createCryptControllerButton(QWidget * pPar);
502 void createTextEncodingButton(QWidget * pPar);
503 void createSystemTextEncodingPopup();
504
505 QToolButton * createToolButton(QWidget * pPar, const char * pcName, KviIconManager::SmallIcon eIcon, const QString & szToolTip, bool bOn);
506 // This is called by KviInput: actually it links the widgetAdded
507 virtual void childrenTreeChanged(QWidget * pAdded);
508
509 bool focusNextPrevChild(bool bNext) override;
510
511 virtual void preprocessMessage(QString & szMessage);
512 public slots:
513 void dock();
514 void undock();
515 void autoRaise();
516 void reloadImages();
517 void savePropertiesAsDefault();
518 protected slots:
519 void toggleCryptController(); // This has to be here even if the crypt support is enabled...moc does not support conditionals
520 void cryptControllerFinished(); // same as above
521 void cryptSessionInfoDestroyed(); // same as above
522 void textEncodingButtonClicked();
523 void systemTextEncodingPopupActivated(QAction * pAction);
524 void childDestroyed();
525 signals:
526 void windowNameChanged();
527 };
528
529 #ifndef _KVI_WINDOW_CPP_
530 // The active window:
531 // This is almost always non null
532 // The exception is the startup (when there are no windows at all)
533 // and the last phase of the destructor.
534 // You usually shouldn't care of checking this pointer for nullptr unless
535 // you're running very early at startup or very late at shutdown
536 extern KVIRC_API KviWindow * g_pActiveWindow;
537 #endif
538
encodeText(const QString & szText)539 inline QByteArray KviWindow::encodeText(const QString & szText)
540 {
541 if(m_pTextCodec)
542 return m_pTextCodec->fromUnicode(szText);
543 else
544 return defaultTextCodec()->fromUnicode(szText);
545 }
546
decodeText(const char * pcText)547 inline QString KviWindow::decodeText(const char * pcText)
548 {
549 if(m_pTextCodec)
550 return m_pTextCodec->toUnicode(pcText);
551 else
552 return defaultTextCodec()->toUnicode(pcText);
553 }
554
555 #endif //_KVI_WINDOW_H_
556