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) )
72 MessagesDialog::MessagesDialog( intf_thread_t *_p_intf)
73 : QVLCFrame( _p_intf )
75 setWindowTitle( qtr( "Messages" ) );
76 setWindowRole( "vlc-messages" );
79 ui.bottomButtonsBox->addButton( new QPushButton( qtr("&Close"), this ),
80 QDialogButtonBox::RejectRole );
84 ui.modulesTree->setHeaderHidden( true );
86 /* Buttons and general layout */
87 ui.saveLogButton->setToolTip( qtr( "Saves all the displayed logs to a file" ) );
89 int verbosity = var_InheritInteger( p_intf, "verbose" );
90 vlc_atomic_set( &this->verbosity, verbosity );
91 ui.verbosityBox->setValue( verbosity );
93 char *objs = var_InheritString( p_intf, "verbose-objects" );
96 ui.vbobjectsEdit->setText( qfu(objs) );
100 ui.vbobjectsEdit->setToolTip( "verbose-objects usage: \n"
101 "--verbose-objects=+printthatobject,-dontprintthatone\n"
102 "(keyword 'all' to applies to all objects)");
104 updateButton = new QPushButton( QIcon(":/update"), "" );
105 updateButton->setToolTip( qtr("Update the tree") );
106 ui.mainTab->setCornerWidget( updateButton );
107 updateButton->setVisible( false );
108 updateButton->setFlat( true );
110 BUTTONACT( ui.clearButton, clear() );
111 BUTTONACT( updateButton, updateTree() );
112 BUTTONACT( ui.saveLogButton, save() );
113 CONNECT( ui.vbobjectsEdit, editingFinished(), this, updateConfig());
114 CONNECT( ui.bottomButtonsBox, rejected(), this, hide() );
115 CONNECT( ui.verbosityBox, valueChanged( int ),
116 this, changeVerbosity( int ) );
118 CONNECT( ui.mainTab, currentChanged( int ), this, tabChanged( int ) );
121 readSettings( "Messages", QSize( 600, 450 ) );
123 /* Hook up to LibVLC messaging */
124 sub = vlc_Subscribe( MsgCallback, this );
127 MessagesDialog::~MessagesDialog()
129 writeSettings( "Messages" );
130 vlc_Unsubscribe( sub );
133 void MessagesDialog::changeVerbosity( int verbosity )
135 vlc_atomic_set( &this->verbosity, verbosity );
138 void MessagesDialog::updateConfig()
140 const QString& objects = ui.vbobjectsEdit->text();
141 /* FIXME: config item should be part of Qt4 module */
142 config_PutPsz(p_intf, "verbose-objects", qtu(objects));
144 QStringList filterOut, filterIn;
145 /* If a filter is set, disable by default */
146 /* If no filters are set, enable */
147 filterDefault = objects.isEmpty();
148 foreach( const QString& elem, objects.split(QChar(',')) )
150 QString object = elem;
153 if( elem.startsWith(QChar('-')) )
156 object.remove( 0, 1 );
158 else if( elem.startsWith(QChar('+')) )
159 object.remove( 0, 1 );
161 if( object.compare(qfu("all"), Qt::CaseInsensitive) == 0 )
164 (add ? &filterIn : &filterOut)->append( object );
166 filter = filterDefault ? filterOut : filterIn;
167 filter.removeDuplicates();
170 void MessagesDialog::sinkMessage( const MsgEvent *msg )
172 if( (filter.contains(msg->module) || filter.contains(msg->object_type))
176 QTextEdit *messages = ui.messages;
177 /* Only scroll if the viewport is at the end.
178 Don't bug user by auto-changing/loosing viewport on insert(). */
179 bool b_autoscroll = ( messages->verticalScrollBar()->value()
180 + messages->verticalScrollBar()->pageStep()
181 >= messages->verticalScrollBar()->maximum() );
183 /* Copy selected text to the clipboard */
184 if( messages->textCursor().hasSelection() )
187 /* Fix selected text bug */
188 if( !messages->textCursor().atEnd() ||
189 messages->textCursor().anchor() != messages->textCursor().position() )
190 messages->moveCursor( QTextCursor::End );
192 messages->setFontItalic( true );
193 messages->setTextColor( "darkBlue" );
194 messages->insertPlainText( msg->module );
196 switch (msg->priority)
199 messages->setTextColor( "blue" );
200 messages->insertPlainText( " info: " );
203 messages->setTextColor( "red" );
204 messages->insertPlainText( " error: " );
207 messages->setTextColor( "green" );
208 messages->insertPlainText( " warning: " );
212 messages->setTextColor( "grey" );
213 messages->insertPlainText( " debug: " );
217 /* Add message Regular black Font */
218 messages->setFontItalic( false );
219 messages->setTextColor( "black" );
220 messages->insertPlainText( msg->text );
221 messages->insertPlainText( "\n" );
222 if ( b_autoscroll ) messages->ensureCursorVisible();
225 void MessagesDialog::customEvent( QEvent *event )
227 MsgEvent *msge = static_cast<MsgEvent *>(event);
233 void MessagesDialog::clear()
235 ui.messages->clear();
238 bool MessagesDialog::save()
240 QString saveLogFileName = QFileDialog::getSaveFileName(
241 this, qtr( "Save log file as..." ),
242 QVLCUserDir( VLC_DOCUMENTS_DIR ),
243 qtr( "Texts / Logs (*.log *.txt);; All (*.*) ") );
245 if( !saveLogFileName.isNull() )
247 QFile file( saveLogFileName );
248 if ( !file.open( QFile::WriteOnly | QFile::Text ) ) {
249 QMessageBox::warning( this, qtr( "Application" ),
250 qtr( "Cannot write to file %1:\n%2." )
251 .arg( saveLogFileName )
252 .arg( file.errorString() ) );
256 QTextStream out( &file );
257 out << ui.messages->toPlainText() << "\n";
264 void MessagesDialog::buildTree( QTreeWidgetItem *parentItem,
265 vlc_object_t *p_obj )
267 QTreeWidgetItem *item;
270 item = new QTreeWidgetItem( parentItem );
272 item = new QTreeWidgetItem( ui.modulesTree );
274 char *name = vlc_object_get_name( p_obj );
275 item->setText( 0, QString("%1%2 (0x%3)")
276 .arg( qfu( p_obj->psz_object_type ) )
277 .arg( ( name != NULL )
278 ? QString( " \"%1\"" ).arg( qfu( name ) )
280 .arg( (uintptr_t)p_obj, 0, 16 )
283 item->setExpanded( true );
285 vlc_list_t *l = vlc_list_children( p_obj );
286 for( int i=0; i < l->i_count; i++ )
287 buildTree( item, l->p_values[i].p_object );
288 vlc_list_release( l );
291 void MessagesDialog::updateTree()
293 ui.modulesTree->clear();
294 buildTree( NULL, VLC_OBJECT( p_intf->p_libvlc ) );
297 void MessagesDialog::tabChanged( int i )
299 updateButton->setVisible( i == 1 );
302 void MessagesDialog::MsgCallback( void *self, const msg_item_t *item )
304 MessagesDialog *dialog = (MessagesDialog *)self;
305 int verbosity = vlc_atomic_get( &dialog->verbosity );
307 if( verbosity < 0 || verbosity < (item->i_type - VLC_MSG_ERR) )
310 int canc = vlc_savecancel();
311 QApplication::postEvent( dialog, new MsgEvent( item ) );
312 vlc_restorecancel( canc );