1 /*****************************************************************************
2 * messages.cpp : Information about an item
3 ****************************************************************************
4 * Copyright (C) 2006-2011 the VideoLAN team
7 * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
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. See the
17 * GNU General Public License for more details.
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
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
27 #include "dialogs/messages.hpp"
30 #include <QTextCursor>
31 #include <QFileDialog>
32 #include <QTextStream>
33 #include <QMessageBox>
35 #include <QTreeWidget>
36 #include <QTreeWidgetItem>
44 MsgEvent_Type = QEvent::User + MsgEventType + 1,
47 class MsgEvent : public QEvent
50 MsgEvent( int, const msg_item_t *, const char * );
60 MsgEvent::MsgEvent( int type, const msg_item_t *msg, const char *text )
61 : QEvent( (QEvent::Type)MsgEvent_Type ),
63 object_id( msg->i_object_id ),
64 object_type( qfu(msg->psz_object_type) ),
65 header( qfu(msg->psz_header) ),
66 module( qfu(msg->psz_module) ),
71 MessagesDialog::MessagesDialog( intf_thread_t *_p_intf)
72 : QVLCFrame( _p_intf )
74 setWindowTitle( qtr( "Messages" ) );
75 setWindowRole( "vlc-messages" );
78 ui.bottomButtonsBox->addButton( new QPushButton( qtr("&Close"), this ),
79 QDialogButtonBox::RejectRole );
83 ui.modulesTree->setHeaderHidden( true );
85 /* Buttons and general layout */
86 ui.saveLogButton->setToolTip( qtr( "Saves all the displayed logs to a file" ) );
88 int i_verbosity = var_InheritInteger( p_intf, "verbose" );
89 changeVerbosity( i_verbosity );
90 ui.verbosityBox->setValue( i_verbosity );
92 char *objs = var_InheritString( p_intf, "verbose-objects" );
95 ui.vbobjectsEdit->setText( qfu(objs) );
99 ui.vbobjectsEdit->setToolTip( "verbose-objects usage: \n"
100 "--verbose-objects=+printthatobject,-dontprintthatone\n"
101 "(keyword 'all' to applies to all objects)");
103 updateButton = new QPushButton( QIcon(":/update"), "" );
104 updateButton->setToolTip( qtr("Update the tree") );
105 ui.mainTab->setCornerWidget( updateButton );
106 updateButton->setVisible( false );
107 updateButton->setFlat( true );
109 BUTTONACT( ui.clearButton, clear() );
110 BUTTONACT( updateButton, updateTree() );
111 BUTTONACT( ui.saveLogButton, save() );
112 CONNECT( ui.vbobjectsEdit, editingFinished(), this, updateConfig());
113 CONNECT( ui.bottomButtonsBox, rejected(), this, hide() );
114 CONNECT( ui.verbosityBox, valueChanged( int ),
115 this, changeVerbosity( int ) );
117 CONNECT( ui.mainTab, currentChanged( int ), this, tabChanged( int ) );
120 readSettings( "Messages", QSize( 600, 450 ) );
122 /* Hook up to LibVLC messaging */
123 vlc_Subscribe( &sub, MsgCallback, this );
126 MessagesDialog::~MessagesDialog()
128 writeSettings( "Messages" );
129 vlc_Unsubscribe( &sub );
132 void MessagesDialog::changeVerbosity( int i_verbosity )
134 vlc_atomic_set( &this->verbosity, i_verbosity );
137 void MessagesDialog::updateConfig()
139 const QString& objects = ui.vbobjectsEdit->text();
140 /* FIXME: config item should be part of Qt4 module */
141 config_PutPsz(p_intf, "verbose-objects", qtu(objects));
143 QStringList filterOut, filterIn;
144 /* If a filter is set, disable by default */
145 /* If no filters are set, enable */
146 filterDefault = objects.isEmpty();
147 foreach( const QString& elem, objects.split(QChar(',')) )
149 QString object = elem;
152 if( elem.startsWith(QChar('-')) )
155 object.remove( 0, 1 );
157 else if( elem.startsWith(QChar('+')) )
158 object.remove( 0, 1 );
160 if( object.compare(qfu("all"), Qt::CaseInsensitive) == 0 )
163 (add ? &filterIn : &filterOut)->append( object );
165 filter = filterDefault ? filterOut : filterIn;
166 filter.removeDuplicates();
169 void MessagesDialog::sinkMessage( const MsgEvent *msg )
171 if( (filter.contains(msg->module) || filter.contains(msg->object_type))
175 QTextEdit *messages = ui.messages;
176 /* Only scroll if the viewport is at the end.
177 Don't bug user by auto-changing/losing viewport on insert(). */
178 bool b_autoscroll = ( messages->verticalScrollBar()->value()
179 + messages->verticalScrollBar()->pageStep()
180 >= messages->verticalScrollBar()->maximum() );
182 /* Copy selected text to the clipboard */
183 if( messages->textCursor().hasSelection() )
186 /* Fix selected text bug */
187 if( !messages->textCursor().atEnd() ||
188 messages->textCursor().anchor() != messages->textCursor().position() )
189 messages->moveCursor( QTextCursor::End );
191 messages->setFontItalic( true );
192 messages->setTextColor( "darkBlue" );
193 messages->insertPlainText( msg->module );
195 switch (msg->priority)
198 messages->setTextColor( "blue" );
199 messages->insertPlainText( " info: " );
202 messages->setTextColor( "red" );
203 messages->insertPlainText( " error: " );
206 messages->setTextColor( "green" );
207 messages->insertPlainText( " warning: " );
211 messages->setTextColor( "grey" );
212 messages->insertPlainText( " debug: " );
216 /* Add message Regular black Font */
217 messages->setFontItalic( false );
218 messages->setTextColor( "black" );
219 messages->insertPlainText( msg->text );
220 messages->insertPlainText( "\n" );
221 if ( b_autoscroll ) messages->ensureCursorVisible();
224 void MessagesDialog::customEvent( QEvent *event )
226 MsgEvent *msge = static_cast<MsgEvent *>(event);
232 void MessagesDialog::clear()
234 ui.messages->clear();
237 bool MessagesDialog::save()
239 QString saveLogFileName = QFileDialog::getSaveFileName(
240 this, qtr( "Save log file as..." ),
241 QVLCUserDir( VLC_DOCUMENTS_DIR ),
242 qtr( "Texts / Logs (*.log *.txt);; All (*.*) ") );
244 if( !saveLogFileName.isNull() )
246 QFile file( saveLogFileName );
247 if ( !file.open( QFile::WriteOnly | QFile::Text ) ) {
248 QMessageBox::warning( this, qtr( "Application" ),
249 qtr( "Cannot write to file %1:\n%2." )
250 .arg( saveLogFileName )
251 .arg( file.errorString() ) );
255 QTextStream out( &file );
256 out << ui.messages->toPlainText() << "\n";
263 void MessagesDialog::buildTree( QTreeWidgetItem *parentItem,
264 vlc_object_t *p_obj )
266 QTreeWidgetItem *item;
269 item = new QTreeWidgetItem( parentItem );
271 item = new QTreeWidgetItem( ui.modulesTree );
273 char *name = vlc_object_get_name( p_obj );
274 item->setText( 0, QString("%1%2 (0x%3)")
275 .arg( qfu( p_obj->psz_object_type ) )
276 .arg( ( name != NULL )
277 ? QString( " \"%1\"" ).arg( qfu( name ) )
279 .arg( (uintptr_t)p_obj, 0, 16 )
282 item->setExpanded( true );
284 vlc_list_t *l = vlc_list_children( p_obj );
285 for( int i=0; i < l->i_count; i++ )
286 buildTree( item, l->p_values[i].p_object );
287 vlc_list_release( l );
290 void MessagesDialog::updateTree()
292 ui.modulesTree->clear();
293 buildTree( NULL, VLC_OBJECT( p_intf->p_libvlc ) );
296 void MessagesDialog::tabChanged( int i )
298 updateButton->setVisible( i == 1 );
301 void MessagesDialog::MsgCallback( void *self, int type, const msg_item_t *item,
302 const char *format, va_list ap )
304 MessagesDialog *dialog = (MessagesDialog *)self;
306 int verbosity = vlc_atomic_get( &dialog->verbosity );
308 if( verbosity < 0 || verbosity < (type - VLC_MSG_ERR)
309 || unlikely(vasprintf( &str, format, ap ) == -1) )
312 int canc = vlc_savecancel();
313 QApplication::postEvent( dialog, new MsgEvent( type, item, str ) );
314 vlc_restorecancel( canc );