1 //=============================================================================
2 //
3 //   File : KviMainWindow.cpp
4 //   Creation date : Sun Jun 18 2000 17:59:02 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24 
25 #define _KVI_FRAME_CPP_
26 
27 #include "kvi_debug.h"
28 #include "KviApplication.h"
29 #include "kvi_settings.h"
30 #include "KviMainWindow.h"
31 #include "KviMenuBar.h"
32 #include "KviWindowStack.h"
33 #include "KviIconManager.h"
34 #include "KviWindow.h"
35 #include "KviWindowListBase.h"
36 #include "KviTreeWindowList.h"
37 #include "KviConsoleWindow.h"
38 #include "KviConfigurationFile.h"
39 #include "KviInternalCommand.h"
40 #include "KviTrayIcon.h"
41 #include "KviIrcToolBar.h"
42 #include "kvi_confignames.h"
43 #include "KviModule.h"
44 #include "KviMexToolBar.h"
45 #include "KviLocale.h"
46 #include "KviIrcContext.h"
47 #include "KviStatusBar.h"
48 #include "KviCustomToolBar.h"
49 #include "KviCustomToolBarManager.h"
50 #include "KviCustomToolBarDescriptor.h"
51 #include "KviActionManager.h"
52 #include "kvi_defaults.h"
53 #include "KviIrcView.h"
54 #include "KviKvsScript.h"
55 #include "KviKvsEventTriggers.h"
56 #include "KviTextIconManager.h"
57 #include "KviShortcut.h"
58 
59 #define _WANT_OPTION_FLAGS_
60 #include "KviOptions.h"
61 
62 #include <QCheckBox>
63 #include <QCloseEvent>
64 #include <QDesktopWidget>
65 #include <QEvent>
66 #include <QFile>
67 #include <QLayout>
68 #include <QLineEdit>
69 #include <QMenu>
70 #include <QMessageBox>
71 #include <QShortcut>
72 #include <QSplitter>
73 #include <QString>
74 #include <QTimer>
75 #include <QVariant>
76 #include <QWindowStateChangeEvent>
77 
78 #include <algorithm>
79 #include <ctime>
80 
81 #ifdef COMPILE_PSEUDO_TRANSPARENCY
82 #include <QPixmap>
83 // KviApplication.h
84 extern QPixmap * g_pShadedParentGlobalDesktopBackground;
85 extern QPixmap * g_pShadedChildGlobalDesktopBackground;
86 #endif
87 
88 #define KVI_DEFAULT_FRAME_CAPTION "KVIrc " KVI_VERSION " " KVI_RELEASE_NAME
89 
90 // Declared and managed by KviApplication (KviApplication.cpp)
91 extern KviConfigurationFile * g_pWinPropertiesConfig;
92 KVIRC_API KviMainWindow * g_pMainWindow = nullptr; // the one and only frame object
93 
KviMainWindow(QWidget * pParent)94 KviMainWindow::KviMainWindow(QWidget * pParent)
95     : KviTalMainWindow(pParent, "kvirc_frame")
96 {
97 	g_pMainWindow = this;
98 	setAttribute(Qt::WA_DeleteOnClose);
99 	setAutoFillBackground(false);
100 	setAttribute(Qt::WA_TranslucentBackground);
101 	//disable this flag that gets enabled by qt when using Qt::WA_TranslucentBackground
102 	setAttribute(Qt::WA_NoSystemBackground, false);
103 #if !(defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW) || defined(COMPILE_KDE_SUPPORT))
104 	// Under windows, the icon is builtin; under kde, KApplication sets it for us
105 	// We try to avois this as much as possible, since it forces the use of the low-res 16x16 icon
106 	setWindowIcon(*(g_pIconManager->getSmallIcon(KviIconManager::KVIrc)));
107 #endif
108 
109 	setWindowTitle(KVI_DEFAULT_FRAME_CAPTION);
110 
111 	m_pSplitter = new QSplitter(Qt::Horizontal, this);
112 	m_pSplitter->setObjectName("main_frame_splitter");
113 	m_pSplitter->setChildrenCollapsible(false);
114 
115 	setCentralWidget(m_pSplitter);
116 
117 	setIconSize(KVI_OPTION_UINT(KviOption_uintToolBarIconSize));
118 	setButtonStyle(KVI_OPTION_UINT(KviOption_uintToolBarButtonStyle));
119 
120 	m_pWindowStack = new KviWindowStack(m_pSplitter, "mdi_manager");
121 
122 	// This theoretically had to exists before KviWindowStack (that uses enterSdiMode)
123 	m_pMenuBar = new KviMenuBar(this, "main_menu_bar");
124 	setMenuWidget(m_pMenuBar);
125 #ifndef COMPILE_ON_MAC
126 	m_pMenuBar->setVisible(KVI_OPTION_BOOL(KviOption_boolMenuBarVisible));
127 #endif
128 
129 	if(KVI_OPTION_BOOL(KviOption_boolStatusBarVisible))
130 	{
131 		m_pStatusBar = new KviStatusBar(this);
132 		setStatusBar(m_pStatusBar);
133 		// torque: moved out of status bar constructor
134 		// because module init functions executed in load()
135 		// couldn't access the status bar via g_pMainWindow->mainStatusBar()
136 		// (assignment of m_pStatusBar happened after load() and
137 		// the init function)
138 		m_pStatusBar->load();
139 	}
140 
141 	createWindowList();
142 
143 	if((KVI_OPTION_RECT(KviOption_rectFrameGeometry).width() < 100) || (KVI_OPTION_RECT(KviOption_rectFrameGeometry).height() < 100) || (KVI_OPTION_RECT(KviOption_rectFrameGeometry).x() > g_pApp->desktop()->width()) || (KVI_OPTION_RECT(KviOption_rectFrameGeometry).y() > g_pApp->desktop()->height()))
144 	{
145 		// Try to find some reasonable defaults
146 		// prefer primary screen for first startup
147 		int primary_screen = g_pApp->desktop()->primaryScreen();
148 		QRect r = g_pApp->desktop()->screenGeometry(primary_screen);
149 		r.setLeft(r.left() + 10);
150 		r.setRight(r.right() - 100);
151 		r.setTop(r.top() + 10);
152 		r.setBottom(r.bottom() - 200);
153 		KVI_OPTION_RECT(KviOption_rectFrameGeometry) = r;
154 	}
155 
156 	resize(KVI_OPTION_RECT(KviOption_rectFrameGeometry).width(),
157 	    KVI_OPTION_RECT(KviOption_rectFrameGeometry).height());
158 	move(KVI_OPTION_RECT(KviOption_rectFrameGeometry).x(),
159 	    KVI_OPTION_RECT(KviOption_rectFrameGeometry).y());
160 
161 	if(KVI_OPTION_BOOL(KviOption_boolFrameIsMaximized))
162 		showMaximized();
163 
164 	applyOptions();
165 
166 	installAccelerators();
167 }
168 
~KviMainWindow()169 KviMainWindow::~KviMainWindow()
170 {
171 	KVI_OPTION_BOOL(KviOption_boolFrameIsMaximized) = isMaximized();
172 	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(), pos().y(),
173 	    size().width(), size().height());
174 
175 	KVI_OPTION_BOOL(KviOption_boolStatusBarVisible) = m_pStatusBar ? true : false;
176 
177 	KviCustomToolBarManager::instance()->storeVisibilityState();
178 
179 	saveToolBarPositions();
180 	saveModuleExtensionToolBars();
181 
182 	// Call the frame destructor callback AFTER saving the toolbar positions
183 	// This is because the destructor callback kills alls the KVS objects
184 	// and thus the eventual user toolbar objects too and their position
185 	// wouldn't be saved if they are shown at startup.
186 
187 	g_pApp->frameDestructorCallback();
188 
189 	// Now start killing stuff
190 
191 	// Explicitly kill all the module extension toolbars: qt has NOT to delete them: we must call their "die" method
192 	while(!m_pModuleExtensionToolBarList.empty())
193 	{
194 		auto & t = *m_pModuleExtensionToolBarList.begin();
195 		t->die();
196 	}
197 
198 	KVI_OPTION_BOOL(KviOption_boolShowDockExtension) = m_pTrayIcon != nullptr;
199 
200 	delete m_pTrayIcon;
201 	m_pTrayIcon = nullptr;
202 
203 	delete m_pStatusBar;
204 	m_pStatusBar = nullptr;
205 
206 	std::vector<KviWindow *> lWinListCopy(m_WinList.begin(), m_WinList.end());
207 	// Sort the console windows to the end so they are closed last
208 	std::sort(begin(lWinListCopy), end(lWinListCopy), [](KviWindow * a, KviWindow * b){
209 		return !a->isConsole() && b->isConsole();
210 	});
211 
212 	for(auto & i : lWinListCopy)
213 		closeWindow(i);
214 
215 	g_pMainWindow = nullptr;
216 }
217 
registerModuleExtensionToolBar(KviMexToolBar * t)218 void KviMainWindow::registerModuleExtensionToolBar(KviMexToolBar * t)
219 {
220 	m_pModuleExtensionToolBarList.insert(t);
221 }
222 
unregisterModuleExtensionToolBar(KviMexToolBar * t)223 void KviMainWindow::unregisterModuleExtensionToolBar(KviMexToolBar * t)
224 {
225 	m_pModuleExtensionToolBarList.erase(t);
226 }
227 
restoreModuleExtensionToolBars()228 void KviMainWindow::restoreModuleExtensionToolBars()
229 {
230 	for(auto szEntry : KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars))
231 	{
232 		int idx = szEntry.indexOf(':');
233 		if(idx != -1)
234 		{
235 			QString szMod = szEntry.left(idx);
236 			szEntry.remove(0, idx + 1);
237 			g_pModuleExtensionManager->allocateExtension("toolbar", KviCString(szEntry), firstConsole(), nullptr, nullptr, szMod);
238 		}
239 	}
240 }
241 
saveModuleExtensionToolBars()242 void KviMainWindow::saveModuleExtensionToolBars()
243 {
244 	KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).clear();
245 
246 	for(auto & t : m_pModuleExtensionToolBarList)
247 	{
248 		QString s = t->descriptor()->module()->name();
249 		s += ':';
250 		s += t->descriptor()->name().ptr();
251 
252 		KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).append(s);
253 	}
254 }
255 
moduleExtensionToolBar(int extensionId)256 KviMexToolBar * KviMainWindow::moduleExtensionToolBar(int extensionId)
257 {
258 	for(auto & t : m_pModuleExtensionToolBarList)
259 		if(extensionId == t->descriptor()->id())
260 			return t;
261 
262 	return nullptr;
263 }
264 
installAccelerators()265 void KviMainWindow::installAccelerators()
266 {
267 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_PREV, this, SLOT(switchToPrevWindow()), nullptr, Qt::ApplicationShortcut));
268 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_NEXT, this, SLOT(switchToNextWindow()), nullptr, Qt::ApplicationShortcut));
269 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_PREV_CONTEXT, this, SLOT(switchToPrevWindowInContext()), nullptr, Qt::ApplicationShortcut));
270 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_NEXT_CONTEXT, this, SLOT(switchToNextWindowInContext()), nullptr, Qt::ApplicationShortcut));
271 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_PREV_HIGHLIGHT, this, SLOT(switchToPrevHighlightedWindow()), nullptr, Qt::ApplicationShortcut));
272 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_NEXT_HIGHLIGHT, this, SLOT(switchToNextHighlightedWindow()), nullptr, Qt::ApplicationShortcut));
273 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_CLOSE, this, SLOT(closeActiveWindow()), nullptr, Qt::ApplicationShortcut));
274 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_PREV_TAB, this, SLOT(switchToPrevWindow()), nullptr, Qt::ApplicationShortcut));
275 	m_pAccellerators.push_back(KviShortcut::create(KVI_SHORTCUTS_WIN_NEXT_TAB, this, SLOT(switchToNextWindow()), nullptr, Qt::ApplicationShortcut));
276 
277 	static int accel_table[] = {
278 		Qt::Key_1 + Qt::ControlModifier, // script accels...
279 		Qt::Key_2 + Qt::ControlModifier,
280 		Qt::Key_3 + Qt::ControlModifier,
281 		Qt::Key_4 + Qt::ControlModifier,
282 		Qt::Key_5 + Qt::ControlModifier,
283 		Qt::Key_6 + Qt::ControlModifier,
284 		Qt::Key_7 + Qt::ControlModifier,
285 		Qt::Key_8 + Qt::ControlModifier,
286 		Qt::Key_9 + Qt::ControlModifier,
287 		Qt::Key_0 + Qt::ControlModifier,
288 		Qt::Key_F2,
289 		Qt::Key_F3,
290 		Qt::Key_F4,
291 		Qt::Key_F5,
292 		Qt::Key_F6,
293 		Qt::Key_F7,
294 		Qt::Key_F8,
295 		Qt::Key_F9,
296 		Qt::Key_F10,
297 		Qt::Key_F11,
298 		Qt::Key_F12,
299 		Qt::Key_F1 + Qt::ShiftModifier,
300 		Qt::Key_F2 + Qt::ShiftModifier,
301 		Qt::Key_F3 + Qt::ShiftModifier,
302 		Qt::Key_F4 + Qt::ShiftModifier,
303 		Qt::Key_F5 + Qt::ShiftModifier,
304 		Qt::Key_F6 + Qt::ShiftModifier,
305 		Qt::Key_F7 + Qt::ShiftModifier,
306 		Qt::Key_F8 + Qt::ShiftModifier,
307 		Qt::Key_F9 + Qt::ShiftModifier,
308 		Qt::Key_F10 + Qt::ShiftModifier,
309 		Qt::Key_F11 + Qt::ShiftModifier,
310 		Qt::Key_F12 + Qt::ShiftModifier
311 	};
312 
313 	for(auto key : accel_table)
314 		m_pAccellerators.push_back(KviShortcut::create(key, this, SLOT(accelActivated()), SLOT(accelActivated()), Qt::ApplicationShortcut));
315 }
316 
freeAccelleratorKeySequence(const QString & key)317 void KviMainWindow::freeAccelleratorKeySequence(const QString & key)
318 {
319 	QKeySequence kS(key);
320 	for(auto & pS : m_pAccellerators)
321 	{
322 		if(pS->key() == kS)
323 		{
324 			m_pAccellerators.erase(
325 				std::remove(m_pAccellerators.begin(), m_pAccellerators.end(), pS),
326 				m_pAccellerators.end()
327 			);
328 			return;
329 		}
330 	}
331 }
332 
accelActivated()333 void KviMainWindow::accelActivated()
334 {
335 	KVS_TRIGGER_EVENT_1(KviEvent_OnAccelKeyPressed, g_pActiveWindow, ((qobject_cast<QShortcut *>(sender()))->key()).toString());
336 }
337 
executeInternalCommand(int index)338 void KviMainWindow::executeInternalCommand(int index)
339 {
340 	KviConsoleWindow * pConsole = nullptr;
341 	if(activeContext() && activeContext()->console())
342 		pConsole = activeContext()->console();
343 	else
344 		pConsole = firstConsole();
345 	KviKvsScript::run(kvi_getInternalCommandBuffer(index), pConsole);
346 }
347 
saveWindowProperties(KviWindow * wnd,const QString & szSection)348 void KviMainWindow::saveWindowProperties(KviWindow * wnd, const QString & szSection)
349 {
350 	g_pWinPropertiesConfig->setGroup(szSection);
351 	g_pWinPropertiesConfig->writeEntry("EntryTimestamp", (unsigned int)time(nullptr));
352 
353 	// Allow max 80 window properties to be floating around
354 	while(g_pWinPropertiesConfig->groupsCount() > 80)
355 	{
356 		// Kill the oldest group
357 		KviConfigurationFileIterator it(*(g_pWinPropertiesConfig->dict()));
358 		QString minKey;
359 		unsigned int minVal = time(nullptr);
360 		while(it.current() && minVal)
361 		{
362 			QString * pVal = it.current()->find("EntryTimestamp");
363 			if(pVal)
364 			{
365 				bool bOk;
366 				unsigned int uVal = pVal->toUInt(&bOk);
367 				if(bOk)
368 				{
369 					if(uVal < minVal)
370 					{
371 						minVal = uVal;
372 						minKey = it.currentKey();
373 					}
374 				}
375 				else
376 				{
377 					minVal = 0;
378 					minKey = it.currentKey();
379 				}
380 			}
381 			else
382 			{
383 				minVal = 0;
384 				minKey = it.currentKey();
385 			}
386 			++it;
387 		}
388 
389 		if(!minKey.isEmpty())
390 			g_pWinPropertiesConfig->clearGroup(minKey);
391 		else
392 			qDebug("Oops! No minimum key found.");
393 	}
394 
395 	// The following line should NOT be needed...but just to be sure...
396 	g_pWinPropertiesConfig->setGroup(szSection);
397 
398 	g_pWinPropertiesConfig->writeEntry("IsDocked", wnd->isDocked());
399 
400 	wnd->saveProperties(g_pWinPropertiesConfig);
401 }
402 
closeActiveWindow()403 void KviMainWindow::closeActiveWindow()
404 {
405 	if(!g_pActiveWindow)
406 		return;
407 	// Don't directly call closeWindow(g_pActiveWindow)
408 	// as it won't handle last console closing.
409 	g_pActiveWindow->delayedClose();
410 }
411 
closeWindow(KviWindow * wnd)412 void KviMainWindow::closeWindow(KviWindow * wnd)
413 {
414 	if(wnd->isConsole() && consoleCount() <= 1)
415 	{
416 		KVS_TRIGGER_EVENT_0(KviEvent_OnFrameWindowDestroyed, wnd);
417 		KVS_TRIGGER_EVENT_0(KviEvent_OnKVIrcShutdown, wnd);
418 	}
419 	// notify the destruction
420 	wnd->triggerDestructionEvents();
421 
422 	// save it's properties
423 	if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties))
424 	{
425 		QString group;
426 		wnd->getConfigGroupName(group);
427 
428 		// not uses default settings : store it always
429 		saveWindowProperties(wnd, group);
430 	}
431 
432 	// forget it...
433 	const auto iter = std::find(m_WinList.begin(), m_WinList.end(), wnd);
434 	if (iter != m_WinList.end())
435 		m_WinList.erase(iter);
436 
437 	if(wnd == g_pActiveWindow)
438 	{
439 		if(!g_pApp->kviClosingDown())
440 		{
441 			qDebug("Have no active window: trying to pick one");
442 
443 			// this happens when there are only minimized windows in the Mdi area
444 			// just pick another window to be the active one
445 			bool bGotIt = false;
446 			for(auto & pOther : m_WinList)
447 			{
448 				if(wnd != pOther)
449 				{
450 					windowActivated(pOther);
451 					bGotIt = true;
452 					break;
453 				}
454 			}
455 
456 			if(!bGotIt)
457 			{
458 				g_pActiveWindow = nullptr;
459 				m_pActiveContext = nullptr;
460 			}
461 		}
462 		else
463 		{
464 			g_pActiveWindow = nullptr;
465 			m_pActiveContext = nullptr;
466 		}
467 	}
468 
469 	// and shut it down...
470 	// KviWindow will call childWindowDestroyed() here
471 	if(wnd->isDocked())
472 	{
473 		//this deletes the wnd, too
474 		m_pWindowStack->destroyWindow(wnd);
475 	}
476 	else
477 	{
478 		delete wnd;
479 	}
480 }
481 
addWindow(KviWindow * wnd,bool bShow)482 void KviMainWindow::addWindow(KviWindow * wnd, bool bShow)
483 {
484 	m_WinList.push_back(wnd);
485 	wnd->createWindowListItem(); // create the window WindowList item AFTER it has been constructed
486 
487 	QString group;
488 	wnd->getConfigGroupName(group);
489 
490 	bool bDefaultDocking = false;
491 
492 	if(g_pWinPropertiesConfig->hasGroup(group))
493 	{
494 		g_pWinPropertiesConfig->setGroup(group);
495 	}
496 	else if(wnd->isChannel() && g_pWinPropertiesConfig->hasGroup(group = wnd->windowName()))
497 	{
498 		// try to load pre-4.2 channel settings
499 		g_pWinPropertiesConfig->setGroup(group);
500 	}
501 	else
502 	{
503 		if(g_pWinPropertiesConfig->hasGroup(wnd->typeString()))
504 		{
505 			g_pWinPropertiesConfig->setGroup(wnd->typeString());
506 		}
507 		else
508 		{
509 			g_pWinPropertiesConfig->setGroup("no_settings_group");
510 			wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)
511 			bDefaultDocking = true;                      // no settings stored
512 		}
513 	}
514 
515 	wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)
516 
517 	if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties) && !bDefaultDocking)
518 	{
519 		bool bDocked = g_pWinPropertiesConfig->readBoolEntry("IsDocked", true);
520 
521 		if(bDocked)
522 		{
523 			// when group settings are used, we always cascade the windows
524 			// this means that windows that have no specialized config group name
525 			// are always cascaded : this is true for consoles, queries (and other windows) but not channels (and some other windows)
526 			// FIXME: Since the introduction of QMdiArea cascading (and positioning of windows in general) no longer works
527 			dockWindow(wnd);
528 			wnd->triggerCreationEvents();
529 			if(bShow)
530 			{
531 				m_pWindowStack->showAndActivate(wnd);
532 				// Handle the special case of this top level widget not being the active one.
533 				// In this situation the child will not get the focusInEvent
534 				// and thus will not call out windowActivated() method
535 				if(!isActiveWindow())
536 					windowActivated(wnd);
537 			}
538 		}
539 		else
540 		{
541 			wnd->triggerCreationEvents();
542 			if(bShow)
543 				wnd->show();
544 			wnd->youAreUndocked();
545 			if(bShow)
546 			{
547 				wnd->raise();
548 				wnd->setFocus();
549 			}
550 		}
551 	}
552 	else
553 	{
554 
555 		dockWindow(wnd);
556 		wnd->triggerCreationEvents();
557 		if(bShow)
558 		{
559 			m_pWindowStack->showAndActivate(wnd);
560 			// Handle the special case of this top level widget not being the active one.
561 			// In this situation the child will not get the focusInEvent
562 			// and thus will not call out windowActivated() method
563 			if(!isActiveWindow())
564 				windowActivated(wnd);
565 		}
566 	}
567 
568 	// we like to have an active window.. but don't trigger the events until it is really shown
569 	if(!g_pActiveWindow)
570 	{
571 		g_pActiveWindow = wnd;
572 		m_pActiveContext = wnd->context();
573 	}
574 }
575 
dockWindow(KviWindow * wnd)576 void KviMainWindow::dockWindow(KviWindow * wnd)
577 {
578 	if(wnd->parentWidget())
579 		return; // already docked
580 
581 	m_pWindowStack->addWindow(wnd);
582 	wnd->youAreDocked();
583 }
584 
undockWindow(KviWindow * wnd)585 void KviMainWindow::undockWindow(KviWindow * wnd)
586 {
587 	if(!(wnd->parentWidget()))
588 		return;
589 
590 	m_pWindowStack->removeWidget(wnd);
591 	wnd->setParent(nullptr);
592 
593 	wnd->show();
594 	wnd->youAreUndocked();
595 	wnd->raise();
596 	wnd->setFocus();
597 }
598 
newConsole()599 void KviMainWindow::newConsole()
600 {
601 	createNewConsole();
602 }
603 
createNewConsole(bool bFirstInFrame,bool bShowIt)604 KviConsoleWindow * KviMainWindow::createNewConsole(bool bFirstInFrame, bool bShowIt)
605 {
606 	// the first console must be created BEFORE the toolbars visible
607 	// at startup otherwise we cannot execute script code
608 	// which is necessary for the actions that are going to be added
609 	// to the toolbars
610 	KviConsoleWindow * c = new KviConsoleWindow(bFirstInFrame ? KVI_CONSOLE_FLAG_FIRSTINFRAME : 0);
611 	addWindow(c, bShowIt);
612 
613 	if(bFirstInFrame)
614 	{
615 		restoreModuleExtensionToolBars();
616 		KviCustomToolBarManager::instance()->createToolBarsVisibleAtStartup();
617 		KviActionManager::instance()->delayedRegisterAccelerators();
618 		restoreToolBarPositions();
619 	}
620 
621 	return c;
622 }
623 
consoleCount()624 int KviMainWindow::consoleCount()
625 {
626 	return std::count_if(begin(m_WinList), end(m_WinList), [](KviWindow * w){ return w->isConsole(); });
627 }
628 
firstConsole()629 KviConsoleWindow * KviMainWindow::firstConsole()
630 {
631 	for(auto & wnd : m_WinList)
632 		if(wnd->isConsole())
633 			return qobject_cast<KviConsoleWindow *>(wnd);
634 
635 	// We end up here when we have not console windows.
636 	// This may happen at early startup or late before shutdown.
637 	return nullptr;
638 }
639 
firstNotConnectedConsole()640 KviConsoleWindow * KviMainWindow::firstNotConnectedConsole()
641 {
642 	for(auto & wnd : m_WinList)
643 	{
644 		if(wnd->type() == KviWindow::Console)
645 		{
646 			if(!qobject_cast<KviConsoleWindow *>(wnd)->connectionInProgress())
647 				return qobject_cast<KviConsoleWindow *>(wnd);
648 		}
649 	}
650 	return nullptr;
651 }
652 
childWindowCloseRequest(KviWindow * wnd)653 void KviMainWindow::childWindowCloseRequest(KviWindow * wnd)
654 {
655 	closeWindow(wnd);
656 }
657 
setActiveWindow(KviWindow * wnd)658 void KviMainWindow::setActiveWindow(KviWindow * wnd)
659 {
660 	m_pWindowStack->showAndActivate(wnd);
661 }
662 
activeConnection()663 KviIrcConnection * KviMainWindow::activeConnection()
664 {
665 	return m_pActiveContext ? m_pActiveContext->connection() : nullptr;
666 }
667 
childWindowSelectionStateChange(KviWindow * pWnd,bool bGotSelectionNow)668 void KviMainWindow::childWindowSelectionStateChange(KviWindow * pWnd, bool bGotSelectionNow)
669 {
670 	if(pWnd != g_pActiveWindow)
671 		return;
672 	emit activeWindowSelectionStateChanged(bGotSelectionNow);
673 }
674 
childContextStateChange(KviIrcContext * c)675 void KviMainWindow::childContextStateChange(KviIrcContext * c)
676 {
677 	if(c != m_pActiveContext)
678 		return;
679 	emit activeContextStateChanged();
680 }
681 
childConnectionLagChange(KviIrcConnection * c)682 void KviMainWindow::childConnectionLagChange(KviIrcConnection * c)
683 {
684 	KviIrcContext * ctx = c->context();
685 	if(ctx != m_pActiveContext)
686 		return;
687 	emit activeConnectionLagChanged();
688 }
689 
childConnectionServerInfoChange(KviIrcConnection * c)690 void KviMainWindow::childConnectionServerInfoChange(KviIrcConnection * c)
691 {
692 	KviIrcContext * ctx = c->context();
693 	if(ctx != m_pActiveContext)
694 		return;
695 	emit activeConnectionServerInfoChanged();
696 }
697 
childConnectionNickNameChange(KviIrcConnection * c)698 void KviMainWindow::childConnectionNickNameChange(KviIrcConnection * c)
699 {
700 	KviIrcContext * ctx = c->context();
701 	if(ctx != m_pActiveContext)
702 		return;
703 	emit activeConnectionNickNameChanged();
704 }
705 
childConnectionAwayStateChange(KviIrcConnection * c)706 void KviMainWindow::childConnectionAwayStateChange(KviIrcConnection * c)
707 {
708 	KviIrcContext * ctx = c->context();
709 	if(ctx != m_pActiveContext)
710 		return;
711 	emit activeConnectionAwayStateChanged();
712 }
713 
childConnectionUserModeChange(KviIrcConnection * c)714 void KviMainWindow::childConnectionUserModeChange(KviIrcConnection * c)
715 {
716 	KviIrcContext * ctx = c->context();
717 	if(ctx != m_pActiveContext)
718 		return;
719 	emit activeConnectionUserModeChanged();
720 }
721 
windowActivated(KviWindow * wnd,bool bForce)722 void KviMainWindow::windowActivated(KviWindow * wnd, bool bForce)
723 {
724 	if(!wnd)
725 		return; // this can happen?
726 
727 	// unless we want to bForce the active window to be re-activated
728 	if(g_pActiveWindow == wnd && !bForce)
729 		return;
730 
731 	if(g_pActiveWindow != wnd)
732 	{
733 		if(g_pActiveWindow)
734 			g_pActiveWindow->lostUserFocus();
735 		g_pActiveWindow = wnd;
736 	}
737 
738 	updateWindowTitle(wnd);
739 
740 	m_pWindowList->setActiveItem(wnd->windowListItem());
741 
742 	bool bActiveContextChanged = (m_pActiveContext != wnd->context());
743 	m_pActiveContext = wnd->context();
744 
745 	if(g_pActiveWindow->view())
746 		g_pActiveWindow->view()->clearUnreaded();
747 
748 	emit activeWindowChanged();
749 	if(bActiveContextChanged)
750 		emit activeContextChanged();
751 
752 	KVS_TRIGGER_EVENT_0(KviEvent_OnWindowActivated, wnd);
753 }
754 
changeEvent(QEvent * e)755 void KviMainWindow::changeEvent(QEvent * e)
756 {
757 #ifndef COMPILE_ON_MAC
758 	// For Qt5 this should be used to minimize to tray
759 	if((e->type() == QEvent::WindowStateChange) && (windowState() & Qt::WindowMinimized) && KVI_OPTION_BOOL(KviOption_boolMinimizeInTray) && e->spontaneous())
760 	{
761 
762 		if(!trayIcon())
763 		{
764 			executeInternalCommand(KVI_INTERNALCOMMAND_TRAYICON_SHOW);
765 		}
766 		if(trayIcon())
767 		{
768 			QWindowStateChangeEvent * ev = static_cast<QWindowStateChangeEvent *>(e);
769 			KVI_OPTION_BOOL(KviOption_boolFrameIsMaximized) = ev->oldState() & Qt::WindowMaximized;
770 			QTimer::singleShot(0, this, &KviMainWindow::hide);
771 		}
772 		return;
773 	}
774 #endif
775 	if(e->type() == QEvent::ActivationChange)
776 	{
777 		//WINDOW (DE)ACTIVATION
778 		// if we have just been activated by the WM
779 		// then update the active window task bar item
780 		// It will then reset its highlight state
781 		// and hopefully make the dock widget work correctly
782 		// in this case.
783 		// This will also trigger the OnWindowActivated event :)
784 		if(g_pActiveWindow)
785 		{
786 			if(isActiveWindow())
787 				windowActivated(g_pActiveWindow, true);
788 			else
789 				g_pActiveWindow->lostUserFocus();
790 		}
791 	}
792 	KviTalMainWindow::changeEvent(e);
793 }
794 
closeEvent(QCloseEvent * e)795 void KviMainWindow::closeEvent(QCloseEvent * e)
796 {
797 	//check if the user just want us to minimize in tray; if we're not the sender
798 	//of this signal (sender!=0), it has been generated by a "quit" action in a menu
799 	if(KVI_OPTION_BOOL(KviOption_boolCloseInTray) && QObject::sender() == nullptr && e->spontaneous())
800 	{
801 		if(!trayIcon())
802 		{
803 			executeInternalCommand(KVI_INTERNALCOMMAND_TRAYICON_SHOW);
804 		}
805 		if(trayIcon())
806 		{
807 			e->ignore();
808 			KVI_OPTION_BOOL(KviOption_boolFrameIsMaximized) = isMaximized();
809 			QTimer::singleShot(0, this, &KviMainWindow::hide);
810 		}
811 		return;
812 	}
813 
814 	if(KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections))
815 	{
816 		// check for running connections
817 		bool bGotRunningConnection = false;
818 		for(auto & w : m_WinList)
819 		{
820 			if(w->isConsole() && qobject_cast<KviConsoleWindow *>(w)->connectionInProgress())
821 			{
822 				bGotRunningConnection = true;
823 				break;
824 			}
825 		}
826 
827 		if(bGotRunningConnection)
828 		{
829 			QString txt =  __tr2qs("There are active connections, are you sure you wish to quit KVIrc?");
830 
831 			switch(QMessageBox::warning(this, __tr2qs("Confirm Close - KVIrc"), txt, __tr2qs("&Yes"), __tr2qs("&Always"), __tr2qs("&No"), 2, 2))
832 			{
833 				case 0:
834 					// ok to close
835 					break;
836 				case 1:
837 					// ok to close but don't ask again
838 					KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections) = false;
839 					break;
840 				case 2:
841 					e->ignore();
842 					return;
843 					break;
844 			}
845 		}
846 	}
847 
848 	e->accept();
849 
850 	if(g_pApp)
851 	{
852 		g_pApp->setKviClosingDown();
853 		g_pApp->quit();
854 	}
855 }
856 
857 // For Qt4, see changeEvent method for Qt5
hideEvent(QHideEvent * e)858 void KviMainWindow::hideEvent(QHideEvent * e)
859 {
860 #ifndef COMPILE_ON_MAC
861 	if(KVI_OPTION_BOOL(KviOption_boolMinimizeInTray) && e->spontaneous())
862 	{
863 		if(!trayIcon())
864 		{
865 			executeInternalCommand(KVI_INTERNALCOMMAND_TRAYICON_SHOW);
866 		}
867 		if(trayIcon())
868 		{
869 			KVI_OPTION_BOOL(KviOption_boolFrameIsMaximized) = isMaximized();
870 			QTimer::singleShot(0, this, &KviMainWindow::hide);
871 		}
872 		return;
873 	}
874 #endif
875 }
876 
resizeEvent(QResizeEvent * e)877 void KviMainWindow::resizeEvent(QResizeEvent * e)
878 {
879 	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(), pos().y(),
880 	    size().width(), size().height());
881 	KviTalMainWindow::resizeEvent(e);
882 }
883 
contextMenuEvent(QContextMenuEvent *)884 void KviMainWindow::contextMenuEvent(QContextMenuEvent *)
885 {
886 	// do nothing! avoids builtin popup from qmainwindow
887 }
888 
updatePseudoTransparency()889 void KviMainWindow::updatePseudoTransparency()
890 {
891 #ifdef COMPILE_PSEUDO_TRANSPARENCY
892 	uint uOpacity = KVI_OPTION_UINT(KviOption_uintGlobalWindowOpacityPercent) < 50 ? 50 : KVI_OPTION_UINT(KviOption_uintGlobalWindowOpacityPercent);
893 	setWindowOpacity(uOpacity / 100.f);
894 #if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW)
895 #ifndef Q_WS_EX_LAYERED
896 #define Q_WS_EX_LAYERED WS_EX_LAYERED
897 #endif
898 	if(uOpacity < 100)
899 	{
900 		SetWindowLong(reinterpret_cast<HWND>(effectiveWinId()), GWL_EXSTYLE,
901 		    GetWindowLong(reinterpret_cast<HWND>(effectiveWinId()), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
902 	}
903 	else
904 	{
905 		SetWindowLong(reinterpret_cast<HWND>(effectiveWinId()), GWL_EXSTYLE,
906 		    GetWindowLong(reinterpret_cast<HWND>(effectiveWinId()), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
907 	}
908 #endif
909 	if(g_pShadedParentGlobalDesktopBackground)
910 		m_pWindowStack->update();
911 
912 	if(g_pShadedChildGlobalDesktopBackground)
913 	{
914 		for(auto & wnd : m_WinList)
915 			wnd->updateBackgrounds();
916 		m_pWindowList->updatePseudoTransparency();
917 	}
918 #endif
919 }
920 
moveEvent(QMoveEvent * e)921 void KviMainWindow::moveEvent(QMoveEvent * e)
922 {
923 	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(), pos().y(),
924 	    size().width(), size().height());
925 #ifdef COMPILE_PSEUDO_TRANSPARENCY
926 	updatePseudoTransparency();
927 #endif
928 	KviTalMainWindow::moveEvent(e);
929 }
930 
applyOptions()931 void KviMainWindow::applyOptions()
932 {
933 	m_pWindowStack->update();
934 
935 	for(auto & wnd : m_WinList)
936 		wnd->applyOptions();
937 
938 	m_pWindowList->applyOptions();
939 	g_pTextIconManager->applyOptions();
940 
941 #ifndef COMPILE_ON_MAC
942 	m_pMenuBar->setVisible(KVI_OPTION_BOOL(KviOption_boolMenuBarVisible));
943 #endif
944 }
945 
toggleStatusBar()946 void KviMainWindow::toggleStatusBar()
947 {
948 	if(m_pStatusBar)
949 	{
950 		delete m_pStatusBar;
951 		m_pStatusBar = nullptr;
952 	}
953 	else
954 	{
955 		m_pStatusBar = new KviStatusBar(this);
956 		m_pStatusBar->load();
957 		setStatusBar(m_pStatusBar);
958 		m_pStatusBar->show();
959 	}
960 }
961 
toggleMenuBar()962 void KviMainWindow::toggleMenuBar()
963 {
964 	if(KVI_OPTION_BOOL(KviOption_boolMenuBarVisible) == true)
965 	{
966 		if(KVI_OPTION_BOOL(KviOption_boolWarnAboutHidingMenuBar))
967 		{
968 			// ah, we need an abstraction for this setCheckBox() qt5 shiny stuff
969 			QMessageBox pMsgBox;
970 			QCheckBox cb(__tr2qs("Do not show this message again"));
971 			pMsgBox.setText(__tr2qs("This will hide the menu bar completely. "
972 			                        "You can show it again by pressing %1.").arg(QString(KVI_SHORTCUTS_TOGGLE_MENU_BAR)));
973 			pMsgBox.setWindowTitle(__tr2qs("Hide Menu Bar - KVIrc"));
974 			pMsgBox.setIcon(QMessageBox::Icon::Information);
975 			pMsgBox.addButton(QMessageBox::Ok);
976 			pMsgBox.addButton(QMessageBox::Cancel);
977 			pMsgBox.setDefaultButton(QMessageBox::Ok);
978 			pMsgBox.setCheckBox(&cb);
979 			if(pMsgBox.exec() == QMessageBox::Ok)
980 			{
981 				if(cb.isChecked())
982 				{
983 					KVI_OPTION_BOOL(KviOption_boolWarnAboutHidingMenuBar) = false;
984 				}
985 			}
986 			else
987 			{
988 				return;
989 			}
990 		}
991 		m_pMenuBar->hide();
992 		KVI_OPTION_BOOL(KviOption_boolMenuBarVisible) = false;
993 	}
994 	else
995 	{
996 		m_pMenuBar->show();
997 		KVI_OPTION_BOOL(KviOption_boolMenuBarVisible) = true;
998 	}
999 }
1000 
toggleWindowList()1001 void KviMainWindow::toggleWindowList()
1002 {
1003 	KVI_OPTION_BOOL(KviOption_boolUseTreeWindowList) = !KVI_OPTION_BOOL(KviOption_boolUseTreeWindowList);
1004 	recreateWindowList();
1005 	applyOptions();
1006 }
1007 
fillToolBarsPopup(QMenu * p)1008 void KviMainWindow::fillToolBarsPopup(QMenu * p)
1009 {
1010 	p->clear();
1011 
1012 	disconnect(p, &QMenu::triggered, this, &KviMainWindow::toolbarsPopupSelected); // just to be sure
1013 	connect(p, &QMenu::triggered, this, &KviMainWindow::toolbarsPopupSelected);
1014 
1015 	int cnt = 0;
1016 
1017 	KviModuleExtensionDescriptorList * l = g_pModuleExtensionManager->getExtensionList("toolbar");
1018 	if(l)
1019 	{
1020 		for(KviModuleExtensionDescriptor * d = l->first(); d; d = l->next())
1021 		{
1022 			QString label = __tr2qs("Show %1").arg(d->visibleName());
1023 			QAction * pAction;
1024 			if(d->icon())
1025 				pAction = p->addAction(*(d->icon()), label);
1026 			else
1027 				pAction = p->addAction(label);
1028 			pAction->setCheckable(true);
1029 			pAction->setChecked(moduleExtensionToolBar(d->id()));
1030 			pAction->setData(d->id());
1031 			cnt++;
1032 		}
1033 	}
1034 
1035 	// FIXME: Should this display "Hide %1" when the toolbar is already visible ?
1036 	KviPointerHashTableIterator<QString, KviCustomToolBarDescriptor> it2(*(KviCustomToolBarManager::instance()->descriptors()));
1037 	if(it2.current())
1038 	{
1039 		if(cnt > 0)
1040 			p->addSeparator();
1041 
1042 		while(KviCustomToolBarDescriptor * d = it2.current())
1043 		{
1044 			QString label = __tr2qs("Show %1").arg(d->label());
1045 			QString ico = d->iconId();
1046 			QAction * pAction;
1047 			if(!ico.isEmpty())
1048 			{
1049 				QPixmap * pix = g_pIconManager->getImage(d->iconId());
1050 				if(pix)
1051 					pAction = p->addAction(*pix, label);
1052 				else
1053 					pAction = p->addAction(label);
1054 			}
1055 			else
1056 			{
1057 				pAction = p->addAction(label);
1058 			}
1059 			pAction->setData(d->internalId());
1060 			pAction->setCheckable(true);
1061 			pAction->setChecked(d->toolBar());
1062 			++it2;
1063 			cnt++;
1064 		}
1065 	}
1066 
1067 	if(cnt > 0)
1068 		p->addSeparator();
1069 
1070 	p->addAction(
1071 	    *(g_pIconManager->getSmallIcon(KviIconManager::ToolBarEditor)),
1072 	    __tr2qs("Customize..."),
1073 	    this,
1074 	    SLOT(customizeToolBars()));
1075 }
1076 
customizeToolBars()1077 void KviMainWindow::customizeToolBars()
1078 {
1079 	KviKvsScript::run("toolbareditor.open -t", g_pActiveWindow);
1080 }
1081 
toolbarsPopupSelected(QAction * pAction)1082 void KviMainWindow::toolbarsPopupSelected(QAction * pAction)
1083 {
1084 	bool bOk;
1085 	int idext = pAction->data().toInt(&bOk);
1086 	if(!bOk)
1087 		return;
1088 
1089 	KviCustomToolBarDescriptor * dd = KviCustomToolBarManager::instance()->findDescriptorByInternalId(idext);
1090 	if(dd)
1091 	{
1092 		if(dd->toolBar())
1093 			dd->toolBar()->deleteLater();
1094 		else
1095 			dd->createToolBar();
1096 	}
1097 
1098 	if(KviMexToolBar * t = moduleExtensionToolBar(idext))
1099 		t->die();
1100 	else
1101 		g_pModuleExtensionManager->allocateExtension("toolbar", idext, firstConsole());
1102 }
1103 
iconSizePopupSelected(QAction * pAction)1104 void KviMainWindow::iconSizePopupSelected(QAction * pAction)
1105 {
1106 	if(!pAction)
1107 		return;
1108 
1109 	bool bOk;
1110 	uint uSize = pAction->data().toUInt(&bOk);
1111 	if(!bOk)
1112 		return;
1113 
1114 	setIconSize(uSize);
1115 	g_pApp->optionResetUpdate(KviOption_resetReloadImages);
1116 }
1117 
buttonStylePopupSelected(QAction * pAction)1118 void KviMainWindow::buttonStylePopupSelected(QAction * pAction)
1119 {
1120 	if(!pAction)
1121 		return;
1122 
1123 	bool bOk;
1124 	uint uStyle = pAction->data().toUInt(&bOk);
1125 	if(!bOk)
1126 		return;
1127 
1128 	setButtonStyle(uStyle);
1129 }
1130 
focusNextPrevChild(bool next)1131 bool KviMainWindow::focusNextPrevChild(bool next)
1132 {
1133 	if(QWidget * w = focusWidget(); w)
1134 	{
1135 		if(w->focusPolicy() == Qt::StrongFocus)
1136 			return false;
1137 		if(w->parent())
1138 		{
1139 			QVariant v = w->parent()->property("KviProperty_ChildFocusOwner");
1140 			if(v.isValid())
1141 				return false; // Do NOT change the focus widget!
1142 		}
1143 	}
1144 	return KviTalMainWindow::focusNextPrevChild(next);
1145 }
1146 
updateWindowTitle(KviWindow * wnd)1147 void KviMainWindow::updateWindowTitle(KviWindow * wnd)
1148 {
1149 	if(g_pActiveWindow == wnd)
1150 	{
1151 		QString szCaption = QString("%1 - %2").arg(wnd->windowTitle()).arg(KVI_DEFAULT_FRAME_CAPTION);
1152 		setWindowTitle(szCaption);
1153 	}
1154 }
1155 
1156 //
1157 // Toolbar positioning stuff
1158 //
1159 
saveToolBarPositions()1160 void KviMainWindow::saveToolBarPositions()
1161 {
1162 	QString szTemp;
1163 	g_pApp->getLocalKvircDirectory(szTemp, KviApplication::Config, KVI_CONFIGFILE_TOOLBARS);
1164 
1165 	QFile f(szTemp);
1166 	if(f.open(QIODevice::WriteOnly | QIODevice::Truncate))
1167 		f.write(saveState(1));
1168 }
1169 
restoreToolBarPositions()1170 void KviMainWindow::restoreToolBarPositions()
1171 {
1172 	QString szTemp;
1173 	g_pApp->getLocalKvircDirectory(szTemp, KviApplication::Config, KVI_CONFIGFILE_TOOLBARS);
1174 
1175 	QFile f(szTemp);
1176 
1177 	if(f.open(QIODevice::ReadOnly))
1178 	{
1179 		if(!restoreState(f.readAll(), 1))
1180 			qDebug("Error while restoring toolbars position");
1181 	}
1182 
1183 	if(m_pWindowList->inherits("KviTreeWindowList"))
1184 	{
1185 		// ensure that it is not too wide
1186 		m_pWindowList->setMaximumWidth(600);
1187 		if(m_pWindowList->width() > 600)
1188 			m_pWindowList->setFixedWidth(250);
1189 	}
1190 }
1191 
createWindowList()1192 void KviMainWindow::createWindowList()
1193 {
1194 	Qt::DockWidgetArea ePreviousArea = Qt::NoDockWidgetArea;
1195 
1196 	if(m_pWindowList)
1197 	{
1198 		ePreviousArea = m_pWindowList->currentDockArea();
1199 		delete m_pWindowList;
1200 	}
1201 
1202 	if(KVI_OPTION_BOOL(KviOption_boolUseTreeWindowList))
1203 	{
1204 		m_pWindowList = new KviTreeWindowList();
1205 		m_pWindowList->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1206 		if((ePreviousArea != Qt::LeftDockWidgetArea) && (ePreviousArea != Qt::RightDockWidgetArea))
1207 			ePreviousArea = Qt::LeftDockWidgetArea;
1208 	}
1209 	else
1210 	{
1211 		m_pWindowList = new KviClassicWindowList();
1212 		m_pWindowList->setAllowedAreas(Qt::AllDockWidgetAreas);
1213 		if(ePreviousArea == Qt::NoDockWidgetArea || ePreviousArea == Qt::LeftDockWidgetArea || ePreviousArea == Qt::RightDockWidgetArea)
1214 			ePreviousArea = Qt::BottomDockWidgetArea;
1215 	}
1216 	addDockWidget(ePreviousArea, m_pWindowList);
1217 }
1218 
recreateWindowList()1219 void KviMainWindow::recreateWindowList()
1220 {
1221 	for(auto & w : m_WinList)
1222 		w->destroyWindowListItem();
1223 
1224 	createWindowList();
1225 
1226 	for(auto & w : m_WinList)
1227 		w->createWindowListItem();
1228 
1229 	if(g_pActiveWindow)
1230 		m_pWindowList->setActiveItem(g_pActiveWindow->windowListItem());
1231 }
1232 
1233 //
1234 // Some accelerators
1235 //
1236 
switchToPrevWindow()1237 void KviMainWindow::switchToPrevWindow()
1238 {
1239 	m_pWindowList->switchWindow(false, false);
1240 }
1241 
switchToNextWindow()1242 void KviMainWindow::switchToNextWindow()
1243 {
1244 	m_pWindowList->switchWindow(true, false);
1245 }
1246 
switchToPrevHighlightedWindow()1247 void KviMainWindow::switchToPrevHighlightedWindow()
1248 {
1249 	m_pWindowList->switchWindow(false, false, true);
1250 }
1251 
switchToNextHighlightedWindow()1252 void KviMainWindow::switchToNextHighlightedWindow()
1253 {
1254 	m_pWindowList->switchWindow(true, false, true);
1255 }
1256 
switchToPrevWindowInContext()1257 void KviMainWindow::switchToPrevWindowInContext()
1258 {
1259 	m_pWindowList->switchWindow(false, true);
1260 }
1261 
switchToNextWindowInContext()1262 void KviMainWindow::switchToNextWindowInContext()
1263 {
1264 	m_pWindowList->switchWindow(true, true);
1265 }
1266 
setIconSize(unsigned int uSize)1267 void KviMainWindow::setIconSize(unsigned int uSize)
1268 {
1269 	if((uSize != 16) && (uSize != 22) && (uSize != 32) && (uSize != 48))
1270 		uSize = 22;
1271 
1272 	KVI_OPTION_UINT(KviOption_uintToolBarIconSize) = uSize;
1273 
1274 	QSize sSize(uSize, uSize);
1275 
1276 	KviTalMainWindow::setIconSize(sSize);
1277 
1278 	for(auto & t : m_pModuleExtensionToolBarList)
1279 	{
1280 		t->setIconSize(sSize);
1281 		t->update();
1282 	}
1283 
1284 	KviPointerHashTableIterator<QString, KviCustomToolBarDescriptor> it2(*(KviCustomToolBarManager::instance()->descriptors()));
1285 	if(it2.current())
1286 	{
1287 		while(KviCustomToolBarDescriptor * d = it2.current())
1288 		{
1289 			if(d->toolBar())
1290 			{
1291 				d->toolBar()->setIconSize(sSize);
1292 				d->toolBar()->update();
1293 			}
1294 			++it2;
1295 		}
1296 	}
1297 }
1298 
setButtonStyle(unsigned int uStyle)1299 void KviMainWindow::setButtonStyle(unsigned int uStyle)
1300 {
1301 
1302 	KVI_OPTION_UINT(KviOption_uintToolBarButtonStyle) = uStyle;
1303 
1304 	for(auto & t : m_pModuleExtensionToolBarList)
1305 	{
1306 		t->setToolButtonStyle((Qt::ToolButtonStyle)uStyle);
1307 		t->update();
1308 	}
1309 
1310 	KviPointerHashTableIterator<QString, KviCustomToolBarDescriptor> it2(*(KviCustomToolBarManager::instance()->descriptors()));
1311 	if(it2.current())
1312 	{
1313 		while(KviCustomToolBarDescriptor * d = it2.current())
1314 		{
1315 			if(d->toolBar())
1316 			{
1317 				d->toolBar()->setToolButtonStyle((Qt::ToolButtonStyle)uStyle);
1318 				d->toolBar()->update();
1319 			}
1320 			++it2;
1321 		}
1322 	}
1323 }
1324