2
* client_manager.cpp - implementation of client-manager (partly based on qt-clientManager-example)
5
* Copyright (c) 2004-2005 Tobias Doerffel <tobias@doerffel.de>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public
18
* License along with this program (see COPYING); if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
26
#include <qmessagebox.h>
28
#include <qfiledialog.h>
29
#include <qpopupmenu.h>
31
#include <qworkspace.h>
33
#include <qtoolbutton.h>
34
#include <qsplitter.h>
35
#include <qwhatsthis.h>
36
#include <qdatetime.h>
37
#if QT_VERSION >= 0x030200
38
#include <qsplashscreen.h>
42
#include "client_manager.h"
44
#include "client_properties_edit.h"
45
#include "cmd_input_dialog.h"
46
#include "msg_input_dialog.h"
47
#include "text_input_dialog.h"
51
#include "progress_information.h"
52
#include "italc_side_bar.h"
53
#include "system_environment.h"
54
#include "qt3_compat.h"
56
#include "client_manager.moc"
60
inline T roundCorrect( T _val )
62
if( _val-floor( _val ) < 0.5 )
64
return( floor( _val ) );
66
return( ceil( _val ) );
72
const int widths[] = { 128, 192, 256, 320, 384, 448, 512, /*576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, */0 };
76
QPixmap * classRoomItem::s_clientPixmap = NULL;
77
QPixmap * classRoomItem::s_clientObservedPixmap = NULL;
80
clientManager * clientManager::s_instOfMe = NULL;
83
clientManager::clientManager() :
84
sideBarWidget( tr( "Client-Manager" ), embed::getIconPixmap( "client_manager" ), italc::inst()->m_splitter ),
85
m_personalConfiguration( QDir::home().path() + "/" + QString( ITALC_CONFIG_PATH ) + "/personal-config.xml" ),
86
m_globalClientConfiguration( QDir::home().path() + "/" + QString( ITALC_CONFIG_PATH ) + "/global-client-config.xml" ),
87
m_quickSwitchMenu( new QPopupMenu( this ) ),
88
m_clientUpdateInterval( 1 )
92
m_list = new QListView( contentParent() );
93
QWhatsThis::add( m_list, tr( "In this list clients and classrooms are managed. You can add clients or "
94
"classrooms by clicking with the right mousebutton in this list." ) );
96
m_list->addColumn( tr("Clients") );
97
m_list->addColumn( tr("IP-address") );
98
m_list->setSelectionMode( QListView::Extended );
99
m_list->setTreeStepSize( 12 );
100
m_list->setDefaultRenameAction( QListView::Accept );
101
m_list->setSorting( 0 );
102
m_list->setRootIsDecorated( TRUE );
103
m_list->setShowToolTips( TRUE );
104
m_list->setCaption( tr( "Client-Manager" ) );
105
#if QT_VERSION >= 0x030200
106
connect( m_list, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ), this,
107
SLOT( itemDoubleClicked( QListViewItem *, const QPoint &, int ) ) );
109
connect( m_list, SIGNAL( doubleClicked( QListViewItem * ) ), this,
110
SLOT( itemDoubleClicked( QListViewItem * ) ) );
112
connect( m_list, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ), this,
113
SLOT( contextMenuRequest( QListViewItem *, const QPoint &, int ) ) );
117
f.setPixelSize( 12 );
118
QLabel * help_txt = new QLabel( tr( "Use the context-menu (right mouse-button) for adding/removing clients and/or "
119
"classrooms. Once you added clients you can show or hide them by "
120
"double-clicking them. You can also show or hide a whole classroom by "
121
"clicking right at it and selecting \"Show/hide all clients in room\"." ),
123
help_txt->setAlignment( help_txt->alignment()|WordBreak );
124
help_txt->setFont( f );
126
loadGlobalClientConfig();
127
loadPersonalConfig();
135
clientManager::~clientManager()
142
void clientManager::doCleanupWork( void )
144
while( m_clientsToRemove.size() )
146
delete m_clientsToRemove[0];
147
m_clientsToRemove.erase( m_clientsToRemove.begin() );
150
while( m_classRoomsToRemove.size() )
152
QValueVector<classRoom *>::iterator it = qFind( m_classRooms.begin(), m_classRooms.end(),
153
m_classRoomsToRemove[0] );
154
if( it != m_classRooms.end() )
156
m_classRooms.erase( it );
158
delete m_classRoomsToRemove[0];
159
m_classRoomsToRemove.erase( m_classRoomsToRemove.begin() );
161
savePersonalConfig();
162
saveGlobalClientConfig();
170
void clientManager::saveGlobalClientConfig( void )
172
QDomDocument doc( "italc-config-file" );
174
QDomElement italc_config = doc.createElement( "globalclientconfig" );
175
italc_config.setAttribute( "version", VER_STRING );
176
doc.appendChild( italc_config );
178
QDomElement root = doc.createElement( "body" );
179
italc_config.appendChild( root );
181
QListViewItem * lvi = m_list->firstChild();
183
for( int i = 0; i < m_list->childCount(); ++i )
185
saveSettingsOfChildren( doc, root, lvi, TRUE );
186
lvi = lvi->nextSibling();
189
#if QT_VERSION >= 0x030100
190
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString( 2 );
192
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString();
194
if( italc::ensureConfigPathExists() == FALSE )
196
qFatal( "Could not read/write or create directory " + QString( ITALC_CONFIG_PATH ) + "! For running iTALC, make sure you have "
197
"write-access to your home-directory and to " + QString( ITALC_CONFIG_PATH ) + " (if already existing)." );
200
QFile outfile( m_globalClientConfiguration );
201
outfile.open( IO_WriteOnly | IO_Truncate );
203
outfile.writeBlock( xml.ascii(), xml.length() );
210
void clientManager::savePersonalConfig( void )
212
QDomDocument doc( "italc-config-file" );
214
QDomElement italc_config = doc.createElement( "personalconfig" );
215
italc_config.setAttribute( "version", VER_STRING );
216
doc.appendChild( italc_config );
218
QDomElement head = doc.createElement( "head" );
219
italc_config.appendChild( head );
221
QDomElement globalsettings = doc.createElement( "globalsettings" );
222
globalsettings.setAttribute( "client-update-interval", m_clientUpdateInterval );
223
globalsettings.setAttribute( "use-big-icons", italc::inst()->usesBigPixmaps() );
224
globalsettings.setAttribute( "win-width", italc::inst()->width() );
225
globalsettings.setAttribute( "win-height", italc::inst()->height() );
226
globalsettings.setAttribute( "opened-tab", italc::inst()->m_sideBar->openedTab() );
228
QTextStream ts( m_winCfg, IO_WriteOnly );
229
ts << *( italc::inst() );
230
globalsettings.setAttribute( "wincfg", m_winCfg );
232
QMap<QString, QString> ip_addr_map = systemEnvironment::localIPAddresses();
233
int idx = ip_addr_map.values().findIndex( MASTER_HOST );
236
globalsettings.setAttribute( "net-iface", ip_addr_map.keys()[idx] );
239
head.appendChild( globalsettings );
242
QDomElement root = doc.createElement( "body" );
243
italc_config.appendChild( root );
245
QListViewItem * lvi = m_list->firstChild();
247
for( int i = 0; i < m_list->childCount(); ++i )
249
saveSettingsOfChildren( doc, root, lvi, FALSE );
250
lvi = lvi->nextSibling();
254
#if QT_VERSION >= 0x030100
255
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString( 2 );
257
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString();
259
if( italc::ensureConfigPathExists() == FALSE )
261
qFatal( "Could not read/write or create directory " + QString( ITALC_CONFIG_PATH ) + "! For running iTALC, make sure you have "
262
"write-access to your home-directory and to " + QString( ITALC_CONFIG_PATH ) + " (if already existing)." );
265
QFile outfile( m_personalConfiguration );
266
outfile.open( IO_WriteOnly | IO_Truncate );
268
outfile.writeBlock( xml.ascii(), xml.length() );
275
void clientManager::saveSettingsOfChildren( QDomDocument & _doc, QDomElement & _root, QListViewItem * _parent, bool _is_global_config )
277
QDomElement classroom = _doc.createElement( "classroom" );
278
classroom.setAttribute( "name", _parent->text( 0 ) );
279
_root.appendChild( classroom );
281
QListViewItem * lvi = _parent->firstChild();
283
for( int i = 0; i < _parent->childCount(); ++i )
285
if( lvi->childCount() || dynamic_cast<classRoom *>( lvi ) != NULL )
287
saveSettingsOfChildren( _doc, classroom, lvi, _is_global_config );
291
if( dynamic_cast<classRoomItem *>( lvi ) != NULL )
293
client * c = dynamic_cast<classRoomItem *>( lvi )->getClient();
294
QDomElement client_element = _doc.createElement( "client" );
295
client_element.setAttribute( "id", c->id() );
296
if( _is_global_config == TRUE )
298
client_element.setAttribute( "name", c->name() );
299
client_element.setAttribute( "ip", c->ip() );
300
client_element.setAttribute( "mac", c->mac() );
304
client_element.setAttribute( "visible", ( c->isShown() == TRUE ) ? "yes" : "no" );
307
client_element.setAttribute( "x", QString::number( static_cast<int>( c->m_rasterX ) ) );
308
client_element.setAttribute( "y", QString::number( static_cast<int>( c->m_rasterY ) ) );
312
client_element.setAttribute( "x", QString::number( c->parentWidget()->pos().x() ) );
313
client_element.setAttribute( "y", QString::number( c->parentWidget()->pos().y() ) );
314
client_element.setAttribute( "w", QString::number( c->width() ) );
315
client_element.setAttribute( "h", QString::number( c->height() ) );
318
classroom.appendChild( client_element );
321
lvi = lvi->nextSibling();
328
// routine that returns m_list of all visible clients
329
QValueVector<client *> clientManager::visibleClients( void ) const
331
QValueVector<client *> vv;
332
QListViewItem * lvi = m_list->firstChild();
334
for( int i = 0; i < m_list->childCount(); ++i )
336
getVisibleClients( lvi, vv );
337
lvi = lvi->nextSibling();
346
void clientManager::getVisibleClients( QListViewItem * _p, QValueVector<client *> & _vv )
348
QListViewItem * lvi = _p->firstChild();
350
classRoomItem * l = NULL;
352
for( int i = 0; i < _p->childCount(); ++i )
354
if( lvi->childCount() )
356
getVisibleClients( lvi, _vv );
358
else if( ( l = dynamic_cast<classRoomItem *>( lvi ) ) != NULL && l->getClient()->isShown() )
360
_vv.push_back( l->getClient() );
362
lvi = lvi->nextSibling();
369
void clientManager::getHeaderInformation( const QDomElement & _header )
371
QDomNode node = _header.firstChild();
373
while( !node.isNull() )
375
if( node.isElement() && node.nodeName() == "globalsettings" )
377
m_clientUpdateInterval = node.toElement().attribute( "client-update-interval" ).toInt();
378
if( node.toElement().attribute( "use-big-icons" ) != QString::null )
380
italc::inst()->setUsesBigPixmaps( node.toElement().attribute( "use-big-icons" ).toInt() );
382
if( node.toElement().attribute( "win-width" ) != QString::null &&
383
node.toElement().attribute( "win-height" ) != QString::null )
385
italc::inst()->resize( node.toElement().attribute( "win-width" ).toInt(),
386
node.toElement().attribute( "win-height" ).toInt() );
388
if( node.toElement().attribute( "opened-tab" ) != QString::null )
390
italc::inst()->m_openedTabInSideBar = node.toElement().attribute( "opened-tab" ).toInt();
392
if( node.toElement().attribute( "wincfg" ) != QString::null )
394
m_winCfg = node.toElement().attribute( "wincfg" );
397
// get list with all network-interfaces with according IP-addresses
398
QMap<QString, QString> ip_addr_map = systemEnvironment::localIPAddresses();
400
for( int i = 0; i < ip_addr_map.count(); ++i )
402
printf( "%s: %s\n", ip_addr_map.keys()[i].ascii(), ip_addr_map.values()[i].ascii() );
405
// iface already set in configuration?
406
if( node.toElement().attribute( "net-iface" ) != QString::null && ip_addr_map.count() &&
407
ip_addr_map.find( node.toElement().attribute( "net-iface" ) ) != ip_addr_map.end() )
409
MASTER_HOST = ip_addr_map[node.toElement().attribute( "net-iface" )];
411
else if( ip_addr_map.count() )
413
if( ip_addr_map.find( "eth0" ) != ip_addr_map.end() )
415
MASTER_HOST = ip_addr_map["eth0"];
419
MASTER_HOST = ip_addr_map.values()[0];
424
// the guy running iTALC seems to have no network-ifaces configured, not even loopback!!!
425
qFatal( "You have no network-interfaces configured!!! iTALC can't run without at least a "
426
"local loopback-interface.\n" );
429
// if the attr did not exist, we got zero as value, which is not acceptable
430
if( m_clientUpdateInterval < 1 )
432
m_clientUpdateInterval = 1;
435
node = node.nextSibling();
442
void clientManager::loadTree( classRoom * _parent_item, const QDomElement & _parent_element, bool _is_global_config )
444
for( QDomNode node = _parent_element.firstChild(); node.isNull() == FALSE; node = node.nextSibling() )
446
if( node.isElement() == FALSE )
451
if( node.nodeName() == "classroom"
452
#warning TODO: remove this compat-code
453
|| node.nodeName() == "clientgroup"
456
classRoom * cur_item = NULL;
457
if( _is_global_config == TRUE )
460
QString name = node.toElement().attribute( "name" );
461
if( _parent_item == NULL )
463
cur_item = new classRoom( m_list, name );
467
cur_item = new classRoom( _parent_item, name );
470
if( node.toElement().attribute( "opened" ) == "yes" )
472
cur_item->setOpen( TRUE );
475
m_classRooms.push_back( cur_item );
478
// recursive build of the tree
479
loadTree( cur_item, node.toElement(), _is_global_config );
481
else if( node.nodeName() == "client" )
483
if( _is_global_config == TRUE )
486
QString ip = node.toElement().attribute( "ip" );
487
QString mac = node.toElement().attribute( "mac" );
488
QString name = node.toElement().attribute( "name" );
491
(void) new client( ip, mac, name, _parent_item, node.toElement().attribute( "id" ).toInt() );
495
client * c = client::clientFromID( node.toElement().attribute( "id" ).toInt() );
500
QPoint pos = c->mapFrom( c->parentWidget()->parentWidget(),
501
QPoint( node.toElement().attribute("x").toInt(),
502
node.toElement().attribute("y").toInt() ) );
503
// workaround for Qt-Bug
509
//c->parentWidget()->move (node.toElement().attribute("x").toInt(), node.toElement().attribute("y").toInt());
510
c->m_rasterX = node.toElement().attribute( "x" ).toInt();
511
c->m_rasterY = node.toElement().attribute( "y" ).toInt();
512
c->setFixedSize( node.toElement().attribute( "w" ).toInt(),
513
node.toElement().attribute( "h" ).toInt() );
514
//c->setFixedSize( m_stdWidth, m_stdWidth*3/4 );
516
if( node.toElement().attribute( "visible" ) == "yes" )
532
void clientManager::loadGlobalClientConfig( void )
536
// read the XML file and create DOM tree
537
QFile cfg_file( m_globalClientConfiguration );
538
if( !cfg_file.open( IO_ReadOnly ) )
540
#if QT_VERSION >= 0x030200
541
if( splashScreen != NULL )
543
splashScreen->close();
546
QMessageBox::warning( this, tr( "No configuration-file found" ), tr( "Could not open configuration file %1.\n"
547
"You will have to add at least one "
548
"classroom and clients by using the "
549
"context-menu in the client-manager."
550
).arg( m_globalClientConfiguration ) );
554
if( !m_domTree.setContent( &cfg_file ) )
556
#if QT_VERSION >= 0x030200
557
if( splashScreen != NULL )
559
splashScreen->close();
562
QMessageBox::critical( 0, tr( "Error in configuration-file" ), tr( "Error while parsing configuration-file %1.\n"
563
"Please edit it. Otherwise you should "
564
"delete this file and have to add all "
565
"classrooms and clients again."
566
).arg( m_globalClientConfiguration ) );
573
// get the head information from the DOM
574
QDomElement root = m_domTree.documentElement();
575
QDomNode node = root.firstChild();
577
// create the tree view out of the DOM
578
node = root.firstChild();
579
while( !node.isNull() )
581
if( node.isElement() && node.nodeName() == "body" )
583
loadTree( NULL, node.toElement(), TRUE );
586
node = node.nextSibling();
593
void clientManager::loadPersonalConfig( void )
595
// read the XML file and create DOM tree
596
QFile cfg_file( m_personalConfiguration );
597
if( !cfg_file.open( IO_ReadOnly ) )
602
if( !m_domTree.setContent( &cfg_file ) )
604
#if QT_VERSION >= 0x030200
605
if( splashScreen != NULL )
607
splashScreen->close();
610
QMessageBox::critical( 0, tr( "Error in configuration-file" ), tr( "Error while parsing configuration-file %1.\n"
611
"Please edit it. Otherwise you should "
613
).arg( m_personalConfiguration ) );
620
// get the head information from the DOM
621
QDomElement root = m_domTree.documentElement();
622
QDomNode node = root.firstChild();
624
while( !node.isNull() )
626
if( node.isElement() && node.nodeName() == "head" )
628
getHeaderInformation( node.toElement() );
631
node = node.nextSibling();
634
// create the tree view out of the DOM
635
node = root.firstChild();
636
while( !node.isNull() )
638
if( node.isElement() && node.nodeName() == "body" )
640
loadTree( NULL, node.toElement(), FALSE );
643
node = node.nextSibling();
649
void clientManager::createActionMenu( QPopupMenu * _m )
651
QListViewItem * lvi = m_list->firstChild();
653
for( int i = 0; i < m_list->childCount(); ++i )
655
if( lvi->childCount() )
657
createActionMenu( lvi, _m );
659
lvi = lvi->nextSibling();
666
void clientManager::createActionMenu( QListViewItem * _p, QPopupMenu * _m )
668
QPopupMenu * root = new QPopupMenu( _m );
669
_m->insertItem( _p->text( 0 ), root );
671
QListViewItem * lvi = _p->firstChild();
672
classRoomItem * l = NULL;
674
for( int i = 0; i < _p->childCount(); ++i )
676
if( lvi->childCount() )
678
createActionMenu( lvi, root );
680
else if( ( l = dynamic_cast<classRoomItem *>( lvi ) ) != NULL )
682
QPopupMenu * client_submenu = new QPopupMenu( root );
683
l->getClient()->createActionMenu( client_submenu );
684
root->insertItem( l->getClient()->fullName(), client_submenu );
686
lvi = lvi->nextSibling();
693
void clientManager::createActionMenuForClassRooms( QPopupMenu * _m )
695
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
697
m_classRooms[i]->createActionMenu( _m );
704
bool clientManager::demoRunning( void ) const
706
QValueVector<client *> vc = visibleClients();
708
for( unsigned int i = 0; i < vc.size(); ++i )
710
if( vc[i]->demoRunning() )
719
void clientManager::updateClients( void )
721
QValueVector<client *> clients = visibleClients();
723
//unsigned int cur_client = static_cast<unsigned int>( clients.size() * ( rand() * ( 1.0f/RAND_MAX ) ) );
725
// loop through all clients
726
for( unsigned int cl = 0; cl < clients.size(); ++cl )
728
/* if( m_rotating && cl == cur_client )
730
// set focus -> client zoomes automatically if zoom-res. != standard-res.
731
clients[cl]->setFocus();
735
// update current client
736
clients[cl]->update();
740
//QTimer::singleShot (50, this, SLOT(updateClients()));
741
QTimer::singleShot( m_clientUpdateInterval*1000, this, SLOT( updateClients() ) );
750
inline void clientManager::cmdToActiveClients( client::clientCmds _cmd, const QString & _u_data )
752
QValueVector<client *> clients = visibleClients();
753
for( unsigned int cl = 0; cl < clients.size(); ++cl )
755
clients[cl]->processCmd( _cmd, _u_data );
756
// there're sometimes problems, when action on all clients are started simulanous (especially demo, because all clients
757
// connect to the same IVS on master), so add a little delay between each client...
760
while( t.elapsed() < 300 )
770
void clientManager::startDemo( void )
772
progressInformation pi( tr( "Please wait, while the demo is started." ) );
773
cmdToActiveClients( client::START_DEMO );
779
void clientManager::startFullScreenDemo( void )
781
progressInformation pi( tr( "Please wait, while the demo is started." ) );
782
cmdToActiveClients( client::START_FULLSCREEN_DEMO );
788
void clientManager::stopDemo(void )
790
progressInformation pi( tr( "Please wait, while the demo is stopped." ) );
791
cmdToActiveClients( client::STOP_DEMO );
797
void clientManager::powerOnClients( void )
799
progressInformation pi( tr( "Please wait, while the clients are being turned on." ) );
800
cmdToActiveClients( client::POWER_ON );
806
void clientManager::rebootClients( void )
808
if( QMessageBox::question( this, tr( "Reboot clients" ), tr( "Are you sure want to reboot all visible clients?" ),
809
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
811
progressInformation pi( tr( "Please wait, while the clients are being rebooted." ) );
812
cmdToActiveClients( client::REBOOT );
819
void clientManager::powerOffClients( void )
821
if( QMessageBox::question( this, tr( "Power off clients" ), tr( "Are you sure want to power off all visible clients?" ),
822
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
824
progressInformation pi( tr( "Please wait, while the clients are being powered off." ) );
825
cmdToActiveClients( client::POWER_OFF );
832
void clientManager::lockScreens( void )
834
// if (QMessageBox::question(this, tr("Lock screen on clients"), tr("Are you sure want to lock the screen on all visible clients?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
836
progressInformation pi( tr( "Please wait, while the screens are locked." ) );
837
cmdToActiveClients( client::LOCK_X );
843
void clientManager::unlockScreens( void )
845
// if (QMessageBox::question(this, tr("Unlock screen on all clients"), tr("Are you sure want to unlock the screen on all visible clients?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
847
progressInformation pi( tr( "Please wait, while the screens are unlocked." ) );
848
cmdToActiveClients( client::UNLOCK_X );
854
void clientManager::killGames( void )
856
progressInformation pi( tr( "Please wait, while games are killed." ) );
857
cmdToActiveClients( client::KILL_GAMES );
863
void clientManager::killBrowsers( void )
865
if( QMessageBox::question( this, tr( "Kill Mozilla/FireFox on clients" ), tr( "Are you sure want to kill Mozilla/FireFox on all "
866
"visible clients?" ), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
868
progressInformation pi( tr( "Please wait, while browsers are killed." ) );
869
cmdToActiveClients( client::KILL_BROWSERS );
876
void clientManager::execCmds( void )
880
cmdInputDialog cmd_input_dialog( cmds, this );
881
if( cmd_input_dialog.exec() == QDialog::Accepted && cmds != "" )
883
cmdToActiveClients( client::EXEC_CMDS, cmds );
889
void clientManager::sendMessage( void )
893
msgInputDialog msg_input_dialog( msg, this );
894
if( msg_input_dialog.exec() == QDialog::Accepted && msg != "" )
896
progressInformation pi( tr( "Please wait, while the message is being sent." ) );
897
cmdToActiveClients( client::SEND_MESSAGE, msg );
903
void clientManager::distributeFile( void )
905
/* QMessageBox::information (this, tr("Function not implemented yet."), tr("This function is not completely implemented yet. This is why it is disabled at the moment."), QMessageBox::Ok);
908
QFileDialog ofd( QDir::home().path(), QString::null, this, "", TRUE );
909
ofd.setMode( QFileDialog::ExistingFile );
910
ofd.setCaption( client::tr( "Select file to distribute" ) );
911
if( ofd.exec() == QDialog::Accepted )
913
cmdToActiveClients( client::DISTRIBUTE_FILE, ofd.selectedFile() );
920
void clientManager::collectFiles( void )
922
/* QMessageBox::information (this, tr("Function not implemented yet."), tr("This function is not completely implemented yet. This is why it is disabled at the moment."), QMessageBox::Ok);
926
textInputDialog file_name_input( client::tr( "Please enter the name(s) of the file(s) to be collected (wildcards are "
927
"allowed).\nThe base-directory is HOME/PUBLIC." ), fn, this );
928
file_name_input.setCaption( client::tr( "Collect files" ) );
930
if( file_name_input.exec() == QDialog::Accepted && fn != "" )
932
cmdToActiveClients( client::COLLECT_FILES, fn );
940
void clientManager::restartX( void )
942
if( QMessageBox::question( this, tr( "Restart X on clients" ), tr( "Are you sure want to restart X on all visible clients?" ),
943
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
945
cmdToActiveClients( client::RESTART_X );
952
const int decor_w = 4;
953
const int decor_h = 22;
956
void clientManager::optimizeClientSize( void )
958
QValueVector<client *> vc = visibleClients();
961
const int avail_w = italc::inst()->workspace()->width();
962
const int avail_h = italc::inst()->workspace()->height();
963
float cw = vc[0]->width()+decor_w; // add width of decoration
964
float ch = vc[0]->height()+decor_h; // add height of titlebar
966
// later we divide by cw, so assume standard-value if zero
967
if( static_cast<int>( cw ) == 0 )
971
// later we divide by ch, so assume standard-value if zero
972
if( static_cast<int>( ch ) == 0 )
976
int x_offset = vc[0]->parentWidget()->pos().x();
977
int y_offset = vc[0]->parentWidget()->pos().y();
979
for( unsigned int i = 0; i < vc.size(); ++i )
981
if( vc[i]->parentWidget()->pos().x() < x_offset )
983
x_offset = vc[i]->parentWidget()->pos().x();
985
if( vc[i]->parentWidget()->pos().y() < y_offset )
987
y_offset = vc[i]->parentWidget()->pos().y();
993
for( unsigned int i = 0; i < vc.size(); ++i )
995
vc[i]->m_rasterX = roundCorrect( ( vc[i]->parentWidget()->pos().x()-x_offset ) / cw );
996
vc[i]->m_rasterY = roundCorrect( ( vc[i]->parentWidget()->pos().y()-y_offset ) / ch );
997
if( vc[i]->m_rasterX > max_rx )
999
max_rx = vc[i]->m_rasterX;
1001
if( vc[i]->m_rasterY > max_ry )
1003
max_ry = vc[i]->m_rasterY;
1008
// now we have length of col and length of row and can calculate a width and a height (independent from each other)
1009
// divide available width by max length of rows
1010
int nw = static_cast<int>( floor( avail_w / max_rx ) );
1011
// calculate according height
1012
int nh = (nw-decor_w)*3/4+decor_h;
1013
// is this height fit max_ry times into available height?
1014
if( nh*max_ry >= avail_h )
1016
// no, then divide available height by max length of cols
1017
nh = static_cast<int>( floor( avail_h / max_ry ) );
1018
// and calculate according width
1019
nw = (nh-decor_h)*4/3+decor_w;
1021
for( unsigned int i = 0; i < vc.size(); ++i )
1023
vc[i]->setFixedSize( nw-decor_w, nh-decor_h );
1024
vc[i]->parentWidget()->move( static_cast<int>( vc[i]->m_rasterX*nw ), static_cast<int>( vc[i]->m_rasterY*nh ) );
1032
void clientManager::resizeClients( const int _new_width )
1034
QValueVector<client *> vc = visibleClients();
1038
const int _new_height = _new_width*3/4;
1039
float cw = vc[0]->width()+decor_w; // add width of decoration
1040
float ch = vc[0]->height()+decor_h; // add height of titlebar
1041
// later we divide by cw, so assume standard-value if zero
1042
if( static_cast<int>( cw ) == 0 )
1044
// later we divide by ch, so assume standard-value if zero
1045
if( static_cast<int>( ch )== 0 )
1048
int x_offset = vc[0]->parentWidget()->pos().x();
1049
int y_offset = vc[0]->parentWidget()->pos().y();
1051
for( unsigned int i = 0; i < vc.size(); ++i )
1053
if( vc[i]->parentWidget()->pos().x() < x_offset )
1055
x_offset = vc[i]->parentWidget()->pos().x();
1057
if( vc[i]->parentWidget()->pos().y() < y_offset )
1059
y_offset = vc[i]->parentWidget()->pos().y();
1063
for( unsigned int i = 0; i < vc.size(); ++i )
1065
vc[i]->setFixedSize( _new_width, _new_height );
1066
const int xp = static_cast<int>( ( vc[i]->parentWidget()->pos().x() - x_offset ) / cw *
1067
( _new_width + decor_w ) ) + x_offset;
1068
const int yp = static_cast<int>( ( vc[i]->parentWidget()->pos().y() - y_offset ) / ch *
1069
( _new_height + decor_h ) ) + y_offset;
1070
vc[i]->parentWidget()->move( xp, yp );
1078
void clientManager::increaseClientSize( void )
1080
QValueVector<client *> vc = visibleClients();
1084
const int cw = vc[0]->width();
1086
// seek to first width which is greater than current client-width
1087
while( widths[i] > 0 && cw >= widths[i] )
1093
resizeClients( widths[i] );
1101
void clientManager::decreaseClientSize( void )
1103
QValueVector<client *> vc = visibleClients();
1107
const int cw = vc[0]->width();
1109
// seek to last width
1110
while( widths[i] > 0 )
1115
// seek to first width which is smaller than current client-width
1116
while( i > 0 && cw <= widths[i] )
1120
if( i >= 0 && widths[i] > 0 )
1122
resizeClients( widths[i] );
1130
void clientManager::updateIntervalChanged( int _value )
1132
m_clientUpdateInterval = _value;
1138
void clientManager::closeEvent( QCloseEvent * _ce )
1146
#if QT_VERSION >= 0x030200
1148
void clientManager::itemDoubleClicked( QListViewItem * _i )
1152
void clientManager::itemDoubleClicked( QListViewItem * _i, const QPoint &, int )
1156
void clientManager::itemDoubleClicked( QListViewItem * _i, const QPoint &, int )
1159
void clientManager::itemDoubleClicked( QListViewItem * _i )
1163
classRoomItem * cri = dynamic_cast<classRoomItem *>( _i );
1167
if( cri->getClient()->isShown() )
1169
cri->getClient()->hide();
1173
cri->getClient()->show();
1181
void clientManager::contextMenuRequest( QListViewItem * _i, const QPoint &, int )
1183
QPopupMenu * context_menu = new QPopupMenu( this );
1185
classRoomItem * cri = dynamic_cast<classRoomItem *>( _i );
1186
classRoom * cr = dynamic_cast<classRoom *>( _i );
1190
context_menu->insertItem( embed::getIconPixmap( "client_show" ), tr( "Show/hide" ), this, SLOT( showHideClient() ) );
1191
context_menu->insertItem( embed::getIconPixmap( "client_settings" ), tr( "Edit properties" ), this,
1192
SLOT( editClientProperties() ) );
1193
context_menu->insertItem( embed::getIconPixmap( "client_remove" ), tr( "Remove" ), this, SLOT( removeClient() ) );
1194
context_menu->insertSeparator();
1196
QPopupMenu * single_clients_submenu = new QPopupMenu( context_menu );
1198
cri->getClient()->createActionMenu( single_clients_submenu );
1200
context_menu->insertItem( embed::getIconPixmap( "client" ), tr( "Actions" ), single_clients_submenu );
1201
context_menu->insertSeparator();
1203
else if( cr != NULL )
1205
context_menu->insertItem( embed::getIconPixmap( "classroom_show" ), tr( "Show all clients in classroom" ), this,
1206
SLOT( showSelectedClassRooms() ) );
1207
context_menu->insertItem( embed::getIconPixmap( "classroom_closed" ), tr( "Hide all clients in classroom" ), this,
1208
SLOT( hideSelectedClassRooms() ) );
1209
context_menu->insertItem( embed::getIconPixmap( "client_settings" ), tr( "Edit name" ), this, SLOT( editClassRoomName() ) );
1210
context_menu->insertItem( embed::getIconPixmap( "classroom_remove" ), tr("Remove classroom" ), this,
1211
SLOT( removeClassRoom() ) );
1213
context_menu->insertSeparator();
1215
QPopupMenu * actions_for_classroom_submenu = new QPopupMenu( context_menu );
1217
cr->createActionMenu( actions_for_classroom_submenu, FALSE );
1219
context_menu->insertItem( embed::getIconPixmap( "classroom_opened" ), tr( "Actions for %1" ).arg( cr->text( 0 ) ),
1220
actions_for_classroom_submenu );
1221
context_menu->insertSeparator();
1225
QPopupMenu * actions_for_classroom_submenu = new QPopupMenu( context_menu );
1227
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1229
m_classRooms[i]->createActionMenu( actions_for_classroom_submenu );
1232
context_menu->insertItem( embed::getIconPixmap( "classroom_closed" ), italc::tr( "Action for whole classroom" ),
1233
actions_for_classroom_submenu );
1234
context_menu->insertSeparator();
1237
context_menu->insertItem( embed::getIconPixmap( "client_add" ), tr( "Add client" ), this, SLOT( addClient() ) );
1238
context_menu->insertItem( embed::getIconPixmap( "classroom_add" ), tr( "Add classroom" ), this, SLOT( addClassRoom() ) );
1240
context_menu->exec( QCursor::pos() );
1242
delete context_menu;
1248
QValueVector<classRoomItem *> clientManager::selectedItems( void )
1250
QValueVector<classRoomItem *> vv;
1251
QListViewItem * lvi = m_list->firstChild();
1253
for( int i = 0; i < m_list->childCount(); ++i )
1255
getSelectedItems( lvi, vv );
1256
lvi = lvi->nextSibling();
1265
void clientManager::getSelectedItems( QListViewItem * _p, QValueVector<classRoomItem *> & _vv, bool _add_all )
1267
QListViewItem * lvi = _p->firstChild();
1269
for( int i = 0; i < _p->childCount(); ++i )
1271
if( lvi->childCount() )
1273
getSelectedItems( lvi, _vv, m_list->isSelected( lvi ) );
1275
else if( _add_all || ( dynamic_cast<classRoomItem *>( lvi ) != NULL && m_list->isSelected( lvi ) ) )
1277
_vv.push_back( dynamic_cast<classRoomItem *>( lvi ) );
1279
lvi = lvi->nextSibling();
1286
// slots for client-actions in context-menu
1287
void clientManager::showHideClient( void )
1289
QValueVector<classRoomItem *> si = selectedItems();
1293
bool all_shown = TRUE;
1294
for( unsigned int i = 0; i < si.size(); ++i )
1296
if( si[i]->getClient()->isShown() == FALSE )
1302
for( unsigned int i = 0; i < si.size(); ++i )
1306
si[i]->getClient()->hide();
1310
si[i]->getClient()->show();
1319
void clientManager::editClientProperties( void )
1321
QValueVector<classRoomItem *> si = selectedItems();
1325
for( unsigned int i = 0; i < si.size(); ++i )
1327
clientPropertiesEdit edit( si[i]->getClient(), si[i]->parent()->text( 0 ), this );
1336
void clientManager::removeClient( void )
1338
QValueVector<classRoomItem *> si = selectedItems();
1342
for( unsigned int i = 0; i < si.size(); ++i )
1344
si[i]->getClient()->hide();
1345
m_clientsToRemove.push_back( si[i]->getClient() );
1346
si[i]->setVisible (FALSE);
1354
void clientManager::setStateOfClassRoom( classRoom * _cr, bool _shown )
1356
QListViewItem * cri = _cr->firstChild();
1358
// If all clients are shown, we hide them all. Otherwise we show all.
1359
for( int i = 0; i < _cr->childCount(); ++i )
1361
if( dynamic_cast<classRoomItem *>( cri ) != NULL )
1365
dynamic_cast<classRoomItem *>( cri )->getClient()->show();
1369
dynamic_cast<classRoomItem *>( cri )->getClient()->hide();
1372
cri = cri->nextSibling();
1379
int clientManager::addClassRoomToQuickSwitchMenu( classRoom * _cr )
1381
return( m_quickSwitchMenu->insertItem( _cr->text( 0 ), _cr, SLOT( switchToClassRoom() ) ) );
1387
void clientManager::removeClassRoomFromQuickSwitchMenu( int _id )
1389
m_quickSwitchMenu->removeItem( _id );
1395
void clientManager::showSelectedClassRooms( void )
1397
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1399
classRoom * cr = NULL;
1400
if( m_list->isSelected( m_classRooms[i] ) )
1402
cr = m_classRooms[i];
1405
if( cr != NULL && cr->childCount() )
1407
setStateOfClassRoom( cr, TRUE );
1415
void clientManager::hideSelectedClassRooms( void )
1417
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1419
if( m_list->isSelected( m_classRooms[i] ) && m_classRooms[i]->childCount() )
1421
setStateOfClassRoom( m_classRooms[i], FALSE );
1429
void clientManager::hideAllClassRooms( void )
1431
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1433
setStateOfClassRoom( m_classRooms[i], FALSE );
1440
void clientManager::editClassRoomName( void )
1442
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1444
classRoom * cr = NULL;
1445
if( m_list->isSelected( m_classRooms[i] ) )
1447
cr = m_classRooms[i];
1452
QString classroom_name = cr->text( 0 );
1454
textInputDialog classroom_name_input( tr( "Please enter a new name for classroom \"%1\"."
1455
).arg( classroom_name ), classroom_name, this );
1456
classroom_name_input.setCaption( tr( "New name for classroom" ) );
1457
if( classroom_name_input.exec() == QDialog::Accepted && classroom_name != "" )
1459
cr->setText( 0, classroom_name );
1468
void clientManager::removeClassRoom( void )
1470
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1472
classRoom * cr = NULL;
1473
if( m_list->isSelected( m_classRooms[i] ) )
1475
cr = m_classRooms[i];
1479
if( QMessageBox::question( this, tr( "Remove classroom" ),
1480
tr( "Are you sure want to remove classroom \"%1\"?\nAll clients in it will also be "
1481
"removed!" ).arg( cr->text( 0 ) ), QMessageBox::Yes, QMessageBox::No )
1482
== QMessageBox::No )
1487
cr->setVisible( FALSE );
1489
QValueVector<client *> vv;
1490
getVisibleClients( cr, vv );
1491
for( unsigned int i = 0; i < vv.size(); ++i )
1494
m_clientsToRemove.push_back( vv[i] );
1496
m_classRoomsToRemove.push_back( cr );
1504
// slots for general actions in context-menu
1505
void clientManager::addClient( void )
1507
if( m_classRooms.size() == 0 )
1509
QMessageBox::information( this, tr( "Missing classroom" ), tr( "Before you add clients, please add at least one "
1510
"classroom!" ), QMessageBox::Ok );
1514
QString classroom_name = "";
1516
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1518
if( m_list->isSelected( m_classRooms[i] ) )
1520
classroom_name = m_classRooms[i]->text( 0 );
1525
clientPropertiesEdit edit( NULL, classroom_name, this );
1526
edit.setCaption( tr( "Add client" ) );
1533
void clientManager::addClassRoom( void )
1535
QString classroom_name = tr( "New classroom" );
1537
textInputDialog classroom_name_input( tr( "Please enter the name of the classroom you want to create." ), classroom_name, this );
1538
classroom_name_input.setCaption( tr( "Name for new classroom" ) );
1540
if( classroom_name_input.exec() == QDialog::Accepted && classroom_name != "" )
1542
classRoom * cr = NULL;
1543
for( unsigned int i = 0; i < m_classRooms.size(); ++i )
1545
if( m_list->isSelected( m_classRooms[i] ) )
1547
cr = m_classRooms[i];
1553
m_classRooms.push_back( new classRoom( cr, classroom_name ) );
1557
m_classRooms.push_back( new classRoom( m_list, classroom_name ) );
1568
/*****************************************************************************
1572
*****************************************************************************/
1575
QPixmap * classRoom::s_classRoomClosedPixmap = NULL;
1576
QPixmap * classRoom::s_classRoomOpenedPixmap = NULL;
1579
classRoom::classRoom( QListViewItem * _parent, const QString & _name ) :
1580
QListViewItem(_parent, _name ),
1582
m_qsMenuId( clientManager::inst()->addClassRoomToQuickSwitchMenu( this ) )
1590
classRoom::classRoom( QListView * _parent, const QString & _name ) :
1591
QListViewItem( _parent, _name ),
1593
m_qsMenuId( clientManager::inst()->addClassRoomToQuickSwitchMenu( this ) )
1601
classRoom::~classRoom()
1603
clientManager::inst()->removeClassRoomFromQuickSwitchMenu( m_qsMenuId );
1609
void classRoom::initPixmaps( void )
1611
if( s_classRoomClosedPixmap == NULL )
1613
s_classRoomClosedPixmap = new QPixmap( embed::getIconPixmap( "classroom_closed" ) );
1616
if( s_classRoomOpenedPixmap == NULL )
1618
s_classRoomOpenedPixmap = new QPixmap( embed::getIconPixmap( "classroom_opened" ) );
1621
setPixmap( s_classRoomClosedPixmap );
1627
void classRoom::createActionMenu( QPopupMenu * _m, bool _add_sub_menu )
1629
QPopupMenu * this_classroom_submenu = _m;
1630
QPopupMenu * orig_root = _m;
1632
if( _add_sub_menu == TRUE )
1634
this_classroom_submenu = new QPopupMenu( _m );
1635
orig_root = this_classroom_submenu;
1636
_m->insertItem( text( 0 ), this_classroom_submenu );
1638
QPopupMenu * admin_submenu = new QPopupMenu( this_classroom_submenu );
1640
for( int i = client::START_FULLSCREEN_DEMO; i < client::CMD_COUNT; ++i )
1642
if( i >= client::EXEC_CMDS )
1643
this_classroom_submenu = admin_submenu;
1645
int id = this_classroom_submenu->insertItem( embed::getIconPixmap( client::s_commands[i].m_icon ),
1646
client::tr( client::s_commands[i].m_name ), this, SLOT( processCmdOnAllClients( int ) ) );
1647
this_classroom_submenu->setItemParameter( id, i );
1649
if( client::s_commands[i].m_insertSep == TRUE )
1651
this_classroom_submenu->insertSeparator();
1655
orig_root->insertItem( embed::getIconPixmap( "client_settings" ), tr( "Administation" ), admin_submenu );
1661
void classRoom::processCmdOnAllClients( int _cmd )
1663
QValueVector<client *> vv;
1665
// get all visible clients for this classroom
1666
clientManager::getVisibleClients( this, vv );
1668
QString u_data = CONFIRM_NO;
1670
// may be we have to do something (e.g. confirm) before executing cmd
1671
switch( static_cast<client::clientCmds>( _cmd ) )
1673
case client::SEND_MESSAGE:
1675
msgInputDialog msg_input_dialog( u_data, NULL );
1676
if( msg_input_dialog.exec() != QDialog::Accepted || u_data == "" )
1682
case client::RESTART_X:
1684
if( QMessageBox::question( NULL, clientManager::tr( "Restart X on clients" ),
1685
clientManager::tr( "Are you sure want to restart X on all visible clients?" ),
1686
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1692
case client::KILL_BROWSERS:
1694
if( QMessageBox::question( NULL, clientManager::tr( "Kill Mozilla/FireFox on clients" ),
1695
clientManager::tr( "Are you sure want to kill Mozilla/FireFox on all visible clients?" ),
1696
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1702
case client::EXEC_CMDS:
1704
cmdInputDialog cmd_input_dialog( u_data, NULL );
1705
if( cmd_input_dialog.exec() != QDialog::Accepted || u_data == "" )
1711
case client::RUN_X_APP:
1713
textInputDialog app_input( client::tr( "Please enter the name of the application you want to run "
1714
"and redirect." ), u_data, NULL );
1715
app_input.setCaption( client::tr( "Run application..." ) );
1716
if( app_input.exec() != QDialog::Accepted || u_data == "" )
1722
case client::SSH_LOGIN:
1725
textInputDialog user_input( client::tr( "Please enter the user-name you want to login with." ), u_data, NULL );
1726
user_input.setCaption( client::tr( "SSH-Login" ) );
1727
if( user_input.exec() != QDialog::Accepted || u_data == "" )
1733
case client::REBOOT:
1735
if( QMessageBox::question( NULL, clientManager::tr( "Reboot clients" ),
1736
clientManager::tr( "Are you sure want to reboot all visible clients?" ),
1737
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1743
case client::POWER_OFF:
1745
if( QMessageBox::question( NULL, clientManager::tr( "Power off clients" ),
1746
clientManager::tr( "Are you sure want to power off all visible clients?" ),
1747
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1757
for( unsigned int i = 0; i < vv.size(); ++i )
1759
vv[i]->processCmd( static_cast<client::clientCmds>( _cmd ), u_data );
1766
void classRoom::setPixmap( QPixmap * _pix )
1779
void classRoom::setOpen( bool _o )
1783
setPixmap( s_classRoomOpenedPixmap );
1787
setPixmap( s_classRoomClosedPixmap );
1790
QListViewItem::setOpen( _o );
1796
void classRoom::setup( void )
1798
setExpandable( TRUE );
1799
QListViewItem::setup();
1805
void classRoom::switchToClassRoom( void )
1807
clientManager::inst()->hideAllClassRooms();
1808
clientManager::inst()->setStateOfClassRoom( this, TRUE );
1820
classRoomItem::classRoomItem( client * _client, QListViewItem * _parent, const QString & _name ) :
1821
QListViewItem( _parent, _name ),
1824
if( s_clientPixmap == NULL )
1826
s_clientPixmap = new QPixmap( embed::getIconPixmap( "client" ) );
1828
if( s_clientObservedPixmap == NULL )
1830
s_clientObservedPixmap = new QPixmap( embed::getIconPixmap( "client_observed" ) );
1833
m_pix = s_clientPixmap;
1834
setText( 1, m_client->ip() );
1840
classRoomItem::~classRoomItem()
1842
m_client->setClassRoomItem( NULL );
1848
void classRoomItem::setObserved( bool _obs )
1852
setPixmap( s_clientPixmap );
1856
setPixmap( s_clientObservedPixmap );
1863
void classRoomItem::setPixmap( QPixmap * _pix )