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"
28 #include <vlc_atomic.h>
31 #include <QTextCursor>
32 #include <QFileDialog>
33 #include <QTextStream>
34 #include <QMessageBox>
36 #include <QTreeWidget>
37 #include <QTreeWidgetItem>
45 MsgEvent_Type = QEvent::User + MsgEventType + 1,
48 class MsgEvent : public QEvent
51 MsgEvent( const msg_item_t * );
61 MsgEvent::MsgEvent( const msg_item_t *msg )
62 : QEvent( (QEvent::Type)MsgEvent_Type ),
63 priority( msg->i_type ),
64 object_id( msg->i_object_id ),
65 object_type( qfu(msg->psz_object_type) ),
66 header( qfu(msg->psz_header) ),
67 module( qfu(msg->psz_module) ),
68 text( qfu(msg->psz_msg) )
77 MessagesDialog::MessagesDialog( intf_thread_t *_p_intf)
78 : QVLCFrame( _p_intf )
80 setWindowTitle( qtr( "Messages" ) );
81 setWindowRole( "vlc-messages" );
84 ui.bottomButtonsBox->addButton( new QPushButton( qtr("&Close"), this ),
85 QDialogButtonBox::RejectRole );
89 ui.modulesTree->setHeaderHidden( true );
91 /* Buttons and general layout */
92 ui.saveLogButton->setToolTip( qtr( "Saves all the displayed logs to a file" ) );
94 int verbosity = var_InheritInteger( p_intf, "verbose" );
95 vlc_atomic_set( &this->verbosity, verbosity );
96 ui.verbosityBox->setValue( verbosity );
98 char *objs = var_InheritString( p_intf, "verbose-objects" );
101 ui.vbobjectsEdit->setText( qfu(objs) );
105 ui.vbobjectsEdit->setToolTip( "verbose-objects usage: \n"
106 "--verbose-objects=+printthatobject,-dontprintthatone\n"
107 "(keyword 'all' to applies to all objects)");
109 updateButton = new QPushButton( QIcon(":/update"), "" );
110 updateButton->setToolTip( qtr("Update the tree") );
111 ui.mainTab->setCornerWidget( updateButton );
112 updateButton->setVisible( false );
113 updateButton->setFlat( true );
115 BUTTONACT( ui.clearButton, clear() );
116 BUTTONACT( updateButton, updateTree() );
117 BUTTONACT( ui.saveLogButton, save() );
118 CONNECT( ui.vbobjectsEdit, editingFinished(), this, updateConfig());
119 CONNECT( ui.bottomButtonsBox, rejected(), this, hide() );
120 CONNECT( ui.verbosityBox, valueChanged( int ),
121 this, changeVerbosity( int ) );
123 CONNECT( ui.mainTab, currentChanged( int ), this, tabChanged( int ) );
126 readSettings( "Messages", QSize( 600, 450 ) );
128 /* Hook up to LibVLC messaging */
129 cbData = new msg_cb_data_t;
131 sub = vlc_Subscribe( MsgCallback, cbData );
134 MessagesDialog::~MessagesDialog()
136 writeSettings( "Messages" );
137 vlc_Unsubscribe( sub );
141 void MessagesDialog::changeVerbosity( int verbosity )
143 vlc_atomic_set( &this->verbosity, verbosity );
146 void MessagesDialog::updateConfig()
148 const QString& objects = ui.vbobjectsEdit->text();
149 /* FIXME: config item should be part of Qt4 module */
150 config_PutPsz(p_intf, "verbose-objects", qtu(objects));
152 QStringList filterOut, filterIn;
153 /* If a filter is set, disable by default */
154 /* If no filters are set, enable */
155 filterDefault = objects.isEmpty();
156 foreach( const QString& elem, objects.split(QChar(',')) )
158 QString object = elem;
161 if( elem.startsWith(QChar('-')) )
164 object.remove( 0, 1 );
166 else if( elem.startsWith(QChar('+')) )
167 object.remove( 0, 1 );
169 if( object.compare(qfu("all"), Qt::CaseInsensitive) == 0 )
172 (add ? &filterIn : &filterOut)->append( object );
174 filter = filterDefault ? filterOut : filterIn;
175 filter.removeDuplicates();
178 void MessagesDialog::sinkMessage( const MsgEvent *msg )
180 if( (filter.contains(msg->module) || filter.contains(msg->object_type))
184 QTextEdit *messages = ui.messages;
185 /* Only scroll if the viewport is at the end.
186 Don't bug user by auto-changing/loosing viewport on insert(). */
187 bool b_autoscroll = ( messages->verticalScrollBar()->value()
188 + messages->verticalScrollBar()->pageStep()
189 >= messages->verticalScrollBar()->maximum() );
191 /* Copy selected text to the clipboard */
192 if( messages->textCursor().hasSelection() )
195 /* Fix selected text bug */
196 if( !messages->textCursor().atEnd() ||
197 messages->textCursor().anchor() != messages->textCursor().position() )
198 messages->moveCursor( QTextCursor::End );
200 messages->setFontItalic( true );
201 messages->setTextColor( "darkBlue" );
202 messages->insertPlainText( msg->module );
204 switch (msg->priority)
207 messages->setTextColor( "blue" );
208 messages->insertPlainText( " info: " );
211 messages->setTextColor( "red" );
212 messages->insertPlainText( " error: " );
215 messages->setTextColor( "green" );
216 messages->insertPlainText( " warning: " );
220 messages->setTextColor( "grey" );
221 messages->insertPlainText( " debug: " );
225 /* Add message Regular black Font */
226 messages->setFontItalic( false );
227 messages->setTextColor( "black" );
228 messages->insertPlainText( msg->text );
229 messages->insertPlainText( "\n" );
230 if ( b_autoscroll ) messages->ensureCursorVisible();
233 void MessagesDialog::customEvent( QEvent *event )
235 MsgEvent *msge = static_cast<MsgEvent *>(event);
241 void MessagesDialog::clear()
243 ui.messages->clear();
246 bool MessagesDialog::save()
248 QString saveLogFileName = QFileDialog::getSaveFileName(
249 this, qtr( "Save log file as..." ),
250 QVLCUserDir( VLC_DOCUMENTS_DIR ),
251 qtr( "Texts / Logs (*.log *.txt);; All (*.*) ") );
253 if( !saveLogFileName.isNull() )
255 QFile file( saveLogFileName );
256 if ( !file.open( QFile::WriteOnly | QFile::Text ) ) {
257 QMessageBox::warning( this, qtr( "Application" ),
258 qtr( "Cannot write to file %1:\n%2." )
259 .arg( saveLogFileName )
260 .arg( file.errorString() ) );
264 QTextStream out( &file );
265 out << ui.messages->toPlainText() << "\n";
272 void MessagesDialog::buildTree( QTreeWidgetItem *parentItem,
273 vlc_object_t *p_obj )
275 QTreeWidgetItem *item;
278 item = new QTreeWidgetItem( parentItem );
280 item = new QTreeWidgetItem( ui.modulesTree );
282 char *name = vlc_object_get_name( p_obj );
283 item->setText( 0, QString("%1%2 (0x%3)")
284 .arg( qfu( p_obj->psz_object_type ) )
285 .arg( ( name != NULL )
286 ? QString( " \"%1\"" ).arg( qfu( name ) )
288 .arg( (uintptr_t)p_obj, 0, 16 )
291 item->setExpanded( true );
293 vlc_list_t *l = vlc_list_children( p_obj );
294 for( int i=0; i < l->i_count; i++ )
295 buildTree( item, l->p_values[i].p_object );
296 vlc_list_release( l );
299 void MessagesDialog::updateTree()
301 ui.modulesTree->clear();
302 buildTree( NULL, VLC_OBJECT( p_intf->p_libvlc ) );
305 void MessagesDialog::tabChanged( int i )
307 updateButton->setVisible( i == 1 );
310 void MessagesDialog::MsgCallback( msg_cb_data_t *data, const msg_item_t *item )
312 MessagesDialog *dialog = data->self;
313 int verbosity = vlc_atomic_get( &dialog->verbosity );
315 if( verbosity < 0 || verbosity < (item->i_type - VLC_MSG_ERR) )
318 int canc = vlc_savecancel();
319 QApplication::postEvent( dialog, new MsgEvent( item ) );
320 vlc_restorecancel( canc );