console_widget.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the name of Willow Garage, Inc. nor the names of its
00017 #    contributors may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 
00033 import os
00034 
00035 from python_qt_binding import loadUi
00036 from python_qt_binding.QtGui import QApplication, QCursor, QFileDialog, QIcon, QItemSelectionModel, QMenu, QMessageBox, QTableView, QWidget
00037 from python_qt_binding.QtCore import QRect, QRegExp, Qt, qWarning
00038 
00039 import time
00040 import datetime
00041 
00042 from .filters.custom_filter import CustomFilter
00043 from .filters.location_filter import LocationFilter
00044 from .filters.message_filter import MessageFilter
00045 from .filters.node_filter import NodeFilter
00046 from .filters.severity_filter import SeverityFilter
00047 from .filters.time_filter import TimeFilter
00048 from .filters.topic_filter import TopicFilter
00049 
00050 from .filters.custom_filter_widget import CustomFilterWidget
00051 from .filters.filter_wrapper_widget import FilterWrapperWidget
00052 from .filters.list_filter_widget import ListFilterWidget
00053 from .filters.text_filter_widget import TextFilterWidget
00054 from .filters.time_filter_widget import TimeFilterWidget
00055 from .filters.filter_utils import pack, unpack
00056 
00057 from .text_browse_dialog import TextBrowseDialog
00058 
00059 
00060 class ConsoleTableView(QTableView):
00061     def __init__(self, parent=None):
00062         super(ConsoleTableView, self).__init__()
00063 
00064 
00065 class ConsoleWidget(QWidget):
00066     """
00067     Primary widget for the rqt_console plugin.
00068     """
00069     def __init__(self, proxymodel, minimal=False):
00070         """
00071         :param proxymodel: the proxy model to display in the widget,''QSortFilterProxyModel''
00072         :param minimal: if true the load, save and column buttons will be hidden as well as the filter splitter, ''bool''
00073         """
00074         super(ConsoleWidget, self).__init__()
00075         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'console_widget.ui')
00076         loadUi(ui_file, self, {'ConsoleTableView': ConsoleTableView})
00077 
00078         if minimal:
00079             self.load_button.hide()
00080             self.save_button.hide()
00081             self.column_resize_button.hide()
00082         self.setObjectName('ConsoleWidget')
00083         self.table_view.setModel(proxymodel)
00084         self._proxymodel = proxymodel
00085         self._datamodel = proxymodel.sourceModel()
00086 
00087         self._columnwidth = (600, 140, 200, 430, 200, 600)
00088         for idx, width in enumerate(self._columnwidth):
00089             self.table_view.horizontalHeader().resizeSection(idx, width)
00090         self.table_view.sortByColumn(3, Qt.DescendingOrder)
00091 
00092         self.add_exclude_button.setIcon(QIcon.fromTheme('list-add'))
00093         self.add_highlight_button.setIcon(QIcon.fromTheme('list-add'))
00094         self._pauseicon = QIcon.fromTheme('media-playback-pause')
00095         self._recordicon = QIcon.fromTheme('media-record')
00096         self.pause_button.setIcon(self._pauseicon)
00097         self.load_button.setIcon(QIcon.fromTheme('document-open'))
00098         self.save_button.setIcon(QIcon.fromTheme('document-save'))
00099         self.highlight_exclude_button.setIcon(QIcon.fromTheme('format-text-strikethrough'))
00100 
00101         self.pause_button.clicked[bool].connect(self._handle_pause_clicked)
00102         self.load_button.clicked[bool].connect(self._handle_load_clicked)
00103         self.save_button.clicked[bool].connect(self._handle_save_clicked)
00104         self.column_resize_button.clicked[bool].connect(self._handle_column_resize_clicked)
00105         self.clear_button.clicked[bool].connect(self._handle_clear_button_clicked)
00106 
00107         self.table_view.mouseDoubleClickEvent = self._handle_mouse_double_click
00108         self.table_view.mousePressEvent = self._handle_mouse_press
00109         self.table_view.keyPressEvent = self._handle_custom_keypress
00110         self.severitylist = self._datamodel.get_severity_list()
00111 
00112         # These are lists of Tuples = (,)
00113         self._exclude_filters = []
00114         self._highlight_filters = []
00115 
00116         self.highlight_exclude_button.clicked[bool].connect(self._proxymodel.set_show_highlighted_only)
00117 
00118         self.add_highlight_button.clicked.connect(self._add_highlight_filter)
00119         self.add_exclude_button.clicked.connect(self._add_exclude_filter)
00120 
00121         # Filter factory dictionary:
00122         # index 0 is a label describing the widget, index 1 is the class that provides filtering logic
00123         # index 2 is the widget that sets the data in the filter class, index 3 are the arguments for the widget class constructor
00124         self.filter_factory = {'message': (self.tr('Message Filter'), MessageFilter, TextFilterWidget, []),
00125                                'severity': (self.tr('Severity Filter'), SeverityFilter, ListFilterWidget, [self._datamodel.get_severity_list]),
00126                                'node': (self.tr('Node Filter'), NodeFilter, ListFilterWidget, [self._datamodel.get_unique_col_data, 2]),
00127                                'time': (self.tr('Time Filter'), TimeFilter, TimeFilterWidget, [self.get_time_range_from_selection]),
00128                                'topic': (self.tr('Topic Filter'), TopicFilter, ListFilterWidget, [self._datamodel.get_unique_col_data, 4]),
00129                                'location': (self.tr('Location Filter'), LocationFilter, TextFilterWidget, []),
00130                                'custom': (self.tr('Custom Filter'), CustomFilter, CustomFilterWidget, [self._datamodel.get_severity_list, self._datamodel.get_unique_col_data, 2, self._datamodel.get_unique_col_data, 4])}
00131 
00132         # list of TextBrowserDialogs to close when cleaning up
00133         self._browsers = []
00134 
00135         # This defaults the filters panel to start by taking 50% of the available space
00136         if(minimal):
00137             self.table_splitter.setSizes([1, 0])
00138         else:
00139             self.table_splitter.setSizes([1, 1])
00140         self.exclude_table.resizeColumnsToContents()
00141         self.highlight_table.resizeColumnsToContents()
00142 
00143     def get_message_summary(self, start_time_offset=None, end_time_offset=None):
00144         """
00145         :param start_time: number of seconds before now to start, ''int'' (optional)
00146         :param end_time: number of seconds before now to end, ''int'' (optional)
00147         :returns: summary of message numbers within time
00148         """
00149         current_time = time.mktime(datetime.datetime.now().timetuple())
00150         if start_time_offset is None:
00151             start_time = current_time - 240
00152         else:
00153             start_time = current_time - start_time_offset
00154         if end_time_offset is not None:
00155             end_time = current_time - end_time_offset
00156         else:
00157             end_time = None
00158 
00159         message_subset = self._datamodel.get_message_list(start_time, end_time)
00160 
00161         class Message_Summary(object):
00162             __slots__ = 'fatal', 'error', 'warn', 'info', 'debug'
00163 
00164             def __init__(self, messages):
00165                 self.fatal = 0
00166                 self.error = 0
00167                 self.warn = 0
00168                 self.info = 0
00169                 self.debug = 0
00170                 for message in messages:
00171                     severity = message.get_data(1)
00172                     if severity == 'Debug':
00173                         self.debug += 1
00174                     elif severity == 'Info':
00175                         self.info += 1
00176                     elif severity == 'Warn':
00177                         self.warn += 1
00178                     elif severity == 'Error':
00179                         self.error += 1
00180                     elif severity == 'Fatal':
00181                         self.fatal += 1
00182 
00183         return Message_Summary(message_subset)
00184 
00185     def get_time_range_from_selection(self):
00186         """
00187         :returns: the range of time of messages in the current table selection (min, max), ''tuple(str,str)''
00188         """
00189         rowlist = []
00190         indexes = self.table_view.selectionModel().selectedIndexes()
00191 
00192         if len(indexes) != 0:
00193             for current in indexes:
00194                 rowlist.append(self._proxymodel.mapToSource(current).row())
00195             rowlist = list(set(rowlist))
00196             rowlist.sort()
00197 
00198             mintime, maxtime = self._datamodel.get_time_range(rowlist)
00199             return (mintime, maxtime)
00200         return (-1, -1)
00201 
00202     def _delete_highlight_filter(self):
00203         """
00204         Deletes any highlight filters which have a checked delete button
00205         """
00206         for index, item in enumerate(self._highlight_filters):
00207             if item[1].delete_button.isChecked():
00208                 if self._proxymodel.delete_highlight_filter(index):
00209                     self.highlight_table.removeCellWidget(index, 0)
00210                     self.highlight_table.removeRow(index)
00211                     item[0].filter_changed_signal.disconnect(self._proxymodel.handle_filters_changed)
00212                     item[1].delete_button.clicked.disconnect(self._delete_highlight_filter)
00213                     del self._highlight_filters[index]
00214 
00215     def _delete_exclude_filter(self):
00216         """
00217         Deletes any exclude filters which have a checked delete button
00218         """
00219         for index, item in enumerate(self._exclude_filters):
00220             if item[1].delete_button.isChecked():
00221                 if self._proxymodel.delete_exclude_filter(index):
00222                     self.exclude_table.removeCellWidget(index, 0)
00223                     self.exclude_table.removeRow(index)
00224                     item[0].filter_changed_signal.disconnect(self._proxymodel.handle_filters_changed)
00225                     item[1].delete_button.clicked.disconnect(self._delete_exclude_filter)
00226                     del self._exclude_filters[index]
00227 
00228     def _add_highlight_filter(self, filter_index=False):
00229         """
00230         :param filter_index: if false then this function shows a QMenu to allow the user to choose a type of message filter. ''bool''
00231         OR
00232         :param filter_index: the index of the filter to be added, ''int''
00233         :return: if a filter was added then the index is returned, ''int''
00234         OR
00235         :return: if no filter was added then None is returned, ''NoneType''
00236         """
00237         if filter_index is False:
00238             filter_index = -1
00239             filter_select_menu = QMenu()
00240             for index, item in self.filter_factory.items():
00241                 # flattens the _highlight filters list and only adds the item if it doesn't already exist
00242                 if self.filter_factory[index][0] == self.tr('Message Filter') or not self.filter_factory[index][1] in [type(item) for sublist in self._highlight_filters for item in sublist]:
00243                     filter_select_menu.addAction(self.filter_factory[index][0])
00244             action = filter_select_menu.exec_(QCursor.pos())
00245             if action is None:
00246                 return
00247             for index, item in self.filter_factory.items():
00248                 if self.filter_factory[index][0] == action.text():
00249                     filter_index = index
00250             if filter_index == -1:
00251                 return
00252 
00253         index = len(self._highlight_filters)
00254         newfilter = self.filter_factory[filter_index][1]()
00255         newwidget = self.filter_factory[filter_index][2](newfilter, self.filter_factory[filter_index][3])
00256 
00257         # pack the new filter tuple onto the filter list
00258         self._highlight_filters.append((newfilter, FilterWrapperWidget(newwidget, self.filter_factory[filter_index][0]), filter_index))
00259         self._proxymodel.add_highlight_filter(newfilter)
00260         newfilter.filter_changed_signal.connect(self._proxymodel.handle_filters_changed)
00261         self._highlight_filters[index][1].delete_button.clicked.connect(self._delete_highlight_filter)
00262         self._datamodel.rowsInserted.connect(self._highlight_filters[index][1].repopulate)
00263 
00264         # place the widget in the proper location
00265         self.highlight_table.insertRow(index)
00266         self.highlight_table.setCellWidget(index, 0, self._highlight_filters[index][1])
00267         self.highlight_table.resizeColumnsToContents()
00268         self.highlight_table.resizeRowsToContents()
00269         newfilter.filter_changed_signal.emit()
00270         return index
00271 
00272     def _add_exclude_filter(self, filter_index=False):
00273         """
00274         :param filter_index: if false then this function shows a QMenu to allow the user to choose a type of message filter. ''bool''
00275         OR
00276         :param filter_index: the index of the filter to be added, ''int''
00277         :return: if a filter was added then the index is returned, ''int''
00278         OR
00279         :return: if no filter was added then None is returned, ''NoneType''
00280         """
00281         if filter_index is False:
00282             filter_index = -1
00283             filter_select_menu = QMenu()
00284             for index, item in self.filter_factory.items():
00285                 # flattens the _exclude filters list and only adds the item if it doesn't already exist
00286                 if self.filter_factory[index][0] == self.tr('Message Filter') or not self.filter_factory[index][1] in [type(item) for sublist in self._exclude_filters for item in sublist]:
00287                     filter_select_menu.addAction(self.filter_factory[index][0])
00288             action = filter_select_menu.exec_(QCursor.pos())
00289             if action is None:
00290                 return None
00291             for index, item in self.filter_factory.items():
00292                 if self.filter_factory[index][0] == action.text():
00293                     filter_index = index
00294             if filter_index == -1:
00295                 return None
00296 
00297         index = len(self._exclude_filters)
00298         newfilter = self.filter_factory[filter_index][1]()
00299         newwidget = self.filter_factory[filter_index][2](newfilter, self.filter_factory[filter_index][3])
00300 
00301         # pack the new filter tuple onto the filter list
00302         self._exclude_filters.append((newfilter, FilterWrapperWidget(newwidget, self.filter_factory[filter_index][0]), filter_index))
00303         self._proxymodel.add_exclude_filter(newfilter)
00304         newfilter.filter_changed_signal.connect(self._proxymodel.handle_filters_changed)
00305         self._exclude_filters[index][1].delete_button.clicked.connect(self._delete_exclude_filter)
00306         self._datamodel.rowsInserted.connect(self._exclude_filters[index][1].repopulate)
00307 
00308         # place the widget in the proper location
00309         self.exclude_table.insertRow(index)
00310         self.exclude_table.setCellWidget(index, 0, self._exclude_filters[index][1])
00311         self.exclude_table.resizeColumnsToContents()
00312         self.exclude_table.resizeRowsToContents()
00313         newfilter.filter_changed_signal.emit()
00314         return index
00315 
00316     def _process_highlight_exclude_filter(self, selection, selectiontype, exclude=False):
00317         """
00318         Modifies the relevant filters (based on selectiontype) to remove (exclude=True)
00319         or highlight (exclude=False) the selection from the dataset in the tableview.
00320         :param selection: the actual selection, ''str''
00321         :param selectiontype: the type of selection, ''str''
00322         :param exclude: If True process as an exclude filter, False process as an highlight filter, ''bool''
00323         """
00324         types = {self.tr('Node'): 2, self.tr('Topic'): 4, self.tr('Severity'): 1, self.tr('Message'): 0}
00325         try:
00326             col = types[selectiontype]
00327         except:
00328             raise RuntimeError("Bad Column name in ConsoleWidget._process_highlight_exclude_filter()")
00329 
00330         if col == 0:
00331             unique_messages = set()
00332             selected_indexes = self.table_view.selectionModel().selectedIndexes()
00333             num_selected = len(selected_indexes) / 6
00334             for index in range(num_selected):
00335                 unique_messages.add(selected_indexes[num_selected * col + index].data())
00336             unique_messages = list(unique_messages)
00337             for message in unique_messages:
00338                 message = message.replace('\\', '\\\\')
00339                 message = message.replace('.', '\\.')
00340                 if exclude:
00341                     filter_index = self._add_exclude_filter(selectiontype.lower())
00342                     filter_widget = self._exclude_filters[filter_index][1].findChildren(QWidget, QRegExp('.*FilterWidget.*'))[0]
00343                     filter_widget.set_regex(True)
00344                     filter_widget.set_text('^' + message + '$')
00345                 else:
00346                     filter_index = self._add_highlight_filter(col)
00347                     filter_widget = self._highlight_filters[filter_index][1].findChildren(QWidget, QRegExp('.*FilterWidget.*'))[0]
00348                     filter_widget.set_regex(True)
00349                     filter_widget.set_text('^' + message + '$')
00350 
00351         else:
00352             if exclude:
00353                 # Test if the filter we are adding already exists if it does use the existing filter
00354                 if self.filter_factory[selectiontype.lower()][1] not in [type(item) for sublist in self._exclude_filters for item in sublist]:
00355                     filter_index = self._add_exclude_filter(selectiontype.lower())
00356                 else:
00357                     for index, item in enumerate(self._exclude_filters):
00358                         if type(item[0]) == self.filter_factory[selectiontype.lower()][1]:
00359                             filter_index = index
00360             else:
00361                 # Test if the filter we are adding already exists if it does use the existing filter
00362                 if self.filter_factory[selectiontype.lower()][1] not in [type(item) for sublist in self._highlight_filters for item in sublist]:
00363                     filter_index = self._add_highlight_filter(col)
00364                 else:
00365                     for index, item in enumerate(self._highlight_filters):
00366                         if type(item[0]) == self.filter_factory[selectiontype.lower()][1]:
00367                             filter_index = index
00368 
00369             if exclude:
00370                 filter_widget = self._exclude_filters[filter_index][1].findChildren(QWidget, QRegExp('.*FilterWidget.*'))[0]
00371                 filter_widget.select_item(selection)
00372             else:
00373                 filter_widget = self._highlight_filters[filter_index][1].findChildren(QWidget, QRegExp('.*FilterWidget.*'))[0]
00374                 filter_widget.select_item(selection)
00375 
00376     def _rightclick_menu(self, event):
00377         """
00378         Dynamically builds the rightclick menu based on the unique column data
00379         from the passed in datamodel and then launches it modally
00380         :param event: the mouse event object, ''QMouseEvent''
00381         """
00382         severities = self._datamodel.get_unique_col_data(1)
00383         nodes = self._datamodel.get_unique_col_data(2)
00384         topics = self._datamodel.get_unique_col_data(4)
00385         temp = []
00386         for topic in topics:
00387             if topic.find(', ') == -1:
00388                 temp.append(topic)
00389             else:
00390                 temp = temp + topic.split(', ')
00391         topics = list(set(temp))
00392 
00393         columns = list(self._datamodel.message_members())
00394         for index in range(len(columns)):
00395             columns[index] = [columns[index][1:].capitalize()]
00396 
00397         # menutext entries turned into
00398         menutext = []
00399         menutext.append([self.tr('Exclude'), [[self.tr('Severity'), severities], [self.tr('Node'), nodes], [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]])
00400         menutext.append([self.tr('Highlight'), [[self.tr('Severity'), severities], [self.tr('Node'), nodes], [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]])
00401         menutext.append([self.tr('Copy Selected')])
00402         menutext.append([self.tr('Browse Selected')])
00403 
00404         menu = QMenu()
00405         submenus = []
00406         subsubmenus = []
00407         for item in menutext:
00408             if len(item) > 1:
00409                 submenus.append(QMenu(item[0], menu))
00410                 for subitem in item[1]:
00411                     if len(subitem) > 1:
00412                         subsubmenus.append(QMenu(subitem[0], submenus[-1]))
00413                         for subsubitem in subitem[1]:
00414                             subsubmenus[-1].addAction(subsubitem)
00415                         submenus[-1].addMenu(subsubmenus[-1])
00416                     else:
00417                         submenus[-1].addAction(subitem[0])
00418                 menu.addMenu(submenus[-1])
00419             else:
00420                 menu.addAction(item[0])
00421         action = menu.exec_(event.globalPos())
00422 
00423         if action is None or action == 0:
00424             return
00425         elif action.text() == self.tr('Browse Selected'):
00426             self._show_browsers()
00427         elif action.text() == self.tr('Copy Selected'):
00428             rowlist = []
00429             for current in self.table_view.selectionModel().selectedIndexes():
00430                 rowlist.append(self._proxymodel.mapToSource(current).row())
00431             copytext = self._datamodel.get_selected_text(rowlist)
00432             if copytext is not None:
00433                 clipboard = QApplication.clipboard()
00434                 clipboard.setText(copytext)
00435         elif action.text() == self.tr('Selected Message(s)'):
00436             if action.parentWidget().title() == self.tr('Highlight'):
00437                 self._process_highlight_exclude_filter(action.text(), 'Message', False)
00438             elif action.parentWidget().title() == self.tr('Exclude'):
00439                 self._process_highlight_exclude_filter(action.text(), 'Message', True)
00440             else:
00441                 raise RuntimeError("Menu format corruption in ConsoleWidget._rightclick_menu()")
00442         else:
00443             # This processes the dynamic list entries (severity, node and topic)
00444             try:
00445                 roottitle = action.parentWidget().parentWidget().title()
00446             except:
00447                 raise RuntimeError("Menu format corruption in ConsoleWidget._rightclick_menu()")
00448 
00449             if roottitle == self.tr('Highlight'):
00450                 self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), False)
00451             elif roottitle == self.tr('Exclude'):
00452                 self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), True)
00453             else:
00454                 raise RuntimeError("Unknown Root Action %s selected in ConsoleWidget._rightclick_menu()" % roottitle)
00455         self.update_status()
00456 
00457     def update_status(self):
00458         """
00459         Sets the message display label to the current value
00460         """
00461         if self._datamodel.rowCount() == self._proxymodel.rowCount():
00462             tip = self.tr('Displaying %d messages') % (self._datamodel.rowCount())
00463         else:
00464             tip = self.tr('Displaying %d of %d messages') % (self._proxymodel.rowCount(), self._datamodel.rowCount())
00465         self.messages_label.setText(tip)
00466 
00467     def cleanup_browsers_on_close(self):
00468         for browser in self._browsers:
00469             browser.close()
00470 
00471     def _show_browsers(self):
00472         rowlist = []
00473         for current in self.table_view.selectionModel().selectedIndexes():
00474             rowlist.append(self._proxymodel.mapToSource(current).row())
00475         browsetext = self._datamodel.get_selected_text(rowlist)
00476         if browsetext is not None:
00477             self._browsers.append(TextBrowseDialog(browsetext))
00478             self._browsers[-1].show()
00479 
00480     def _handle_clear_button_clicked(self, checked):
00481         self.table_view.setSelection(QRect(0, 0, self._datamodel._message_limit, self._datamodel._message_limit), QItemSelectionModel.Select)
00482         self._delete_selected_rows()
00483 
00484     def _handle_load_clicked(self, checked):
00485         filename = QFileDialog.getOpenFileName(self, self.tr('Load from File'), '.', self.tr('rqt_console message file {.csv} (*.csv)'))
00486         if filename[0] != '':
00487             try:
00488                 handle = open(filename[0])
00489             except IOError as e:
00490                 qWarning(str(e))
00491                 return
00492             self.pause_button.setChecked(True)
00493             self._handle_pause_clicked(True)
00494             self._datamodel.load_from_file(handle)
00495             handle.close()
00496             self.update_status()
00497 
00498     def _handle_save_clicked(self, checked):
00499         filename = QFileDialog.getSaveFileName(self, 'Save to File', '.', self.tr('rqt_console msg file {.csv} (*.csv)'))
00500         if filename[0] != '':
00501             filename = filename[0]
00502             if filename[-4:] != '.csv':
00503                 filename += '.csv'
00504             try:
00505                 handle = open(filename, 'w')
00506             except IOError as e:
00507                 qWarning(str(e))
00508                 return
00509             self._proxymodel.save_to_file(handle)
00510             handle.close()
00511             self.update_status()
00512 
00513     def _handle_pause_clicked(self, checked):
00514         self._datamodel._paused = checked
00515         if self._datamodel._paused:
00516             self.pause_button.setIcon(self._recordicon)
00517             self.pause_button.setText(self.tr('Resume'))
00518         else:
00519             self.pause_button.setIcon(self._pauseicon)
00520             self.pause_button.setText(self.tr('Pause'))
00521 
00522     def _handle_column_resize_clicked(self):
00523         self.table_view.resizeColumnsToContents()
00524 
00525     def _delete_selected_rows(self):
00526         rowlist = []
00527         for current in self.table_view.selectionModel().selectedIndexes():
00528             rowlist.append(self._proxymodel.mapToSource(current).row())
00529         rowlist = list(set(rowlist))
00530         return self._datamodel.remove_rows(rowlist)
00531 
00532     def _handle_custom_keypress(self, event, old_keyPressEvent=QTableView.keyPressEvent):
00533         """
00534         Handles the delete key.
00535         The delete key removes the tableview's selected rows from the datamodel
00536         """
00537         if event.key() == Qt.Key_Delete and len(self._datamodel.get_message_list()) > 0:
00538             delete = QMessageBox.Yes
00539             if len(self.table_view.selectionModel().selectedIndexes()) == 0:
00540                 delete = QMessageBox.question(self, self.tr('Message'), self.tr("Are you sure you want to delete all messages?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
00541             if delete == QMessageBox.Yes and event.key() == Qt.Key_Delete and event.modifiers() == Qt.NoModifier:
00542                 if self._delete_selected_rows():
00543                     self.update_status()
00544                     event.accept()
00545         return old_keyPressEvent(self.table_view, event)
00546 
00547     def _handle_mouse_double_click(self, event, old_doubleclickevent=QTableView.mouseDoubleClickEvent):
00548         if event.buttons() & Qt.LeftButton and event.modifiers() == Qt.NoModifier:
00549             self._show_browsers()
00550             event.accept()
00551         return old_doubleclickevent(self.table_view, event)
00552 
00553     def _handle_mouse_press(self, event, old_pressEvent=QTableView.mousePressEvent):
00554         if event.buttons() & Qt.RightButton and event.modifiers() == Qt.NoModifier:
00555             self._rightclick_menu(event)
00556             event.accept()
00557         return old_pressEvent(self.table_view, event)
00558 
00559     def save_settings(self, plugin_settings, instance_settings):
00560         instance_settings.set_value('settings_exist', True)
00561 
00562         instance_settings.set_value('table_splitter', self.table_splitter.saveState())
00563         instance_settings.set_value('filter_splitter', self.filter_splitter.saveState())
00564 
00565         instance_settings.set_value('paused', self.pause_button.isChecked())
00566         instance_settings.set_value('show_highlighted_only', self.highlight_exclude_button.isChecked())
00567 
00568         exclude_filters = []
00569         for index, item in enumerate(self._exclude_filters):
00570             exclude_filters.append(item[2])
00571             filter_settings = instance_settings.get_settings('exclude_filter_' + str(index))
00572             item[1].save_settings(filter_settings)
00573         instance_settings.set_value('exclude_filters', pack(exclude_filters))
00574 
00575         highlight_filters = []
00576         for index, item in enumerate(self._highlight_filters):
00577             highlight_filters.append(item[2])
00578             filter_settings = instance_settings.get_settings('highlight_filter_' + str(index))
00579             item[1].save_settings(filter_settings)
00580         instance_settings.set_value('highlight_filters', pack(highlight_filters))
00581 
00582     def restore_settings(self, pluggin_settings, instance_settings):
00583         if instance_settings.contains('table_splitter'):
00584             self.table_splitter.restoreState(instance_settings.value('table_splitter'))
00585         else:
00586             self.table_splitter.setSizes([1000, 100])
00587         if instance_settings.contains('filter_splitter'):
00588             self.filter_splitter.restoreState(instance_settings.value('filter_splitter'))
00589         else:
00590             self.table_splitter.setSizes([500, 500])
00591 
00592         self.pause_button.setChecked(instance_settings.value('paused') in [True, 'true'])
00593         self._handle_pause_clicked(self.pause_button.isChecked())
00594         self.highlight_exclude_button.setChecked(instance_settings.value('show_highlighted_only') in [True, 'true'])
00595         self._proxymodel.set_show_highlighted_only(self.highlight_exclude_button.isChecked())
00596 
00597         for item in self._exclude_filters:
00598             item[1].delete_button.setChecked(True)
00599         self._delete_exclude_filter()
00600         if instance_settings.contains('exclude_filters'):
00601             exclude_filters = unpack(instance_settings.value('exclude_filters'))
00602             if exclude_filters is not None:
00603                 for index, item in enumerate(exclude_filters):
00604                     self._add_exclude_filter(item)
00605                     filter_settings = instance_settings.get_settings('exclude_filter_' + str(index))
00606                     self._exclude_filters[-1][1].restore_settings(filter_settings)
00607         else:
00608             self._add_exclude_filter('severity')
00609 
00610         for item in self._highlight_filters:
00611             item[1].delete_button.setChecked(True)
00612         self._delete_highlight_filter()
00613         if instance_settings.contains('highlight_filters'):
00614             highlight_filters = unpack(instance_settings.value('highlight_filters'))
00615             if highlight_filters is not None:
00616                 for index, item in enumerate(highlight_filters):
00617                     self._add_highlight_filter(item)
00618                     filter_settings = instance_settings.get_settings('highlight_filter_' + str(index))
00619                     self._highlight_filters[-1][1].restore_settings(filter_settings)
00620         else:
00621             self._add_highlight_filter('message')


rqt_console
Author(s): Aaron Blasdel
autogenerated on Fri Jan 3 2014 11:54:30